[U-Boot] [PATCH v2 9/9] kmp204x: initial support for PCIe FPGA configuration

Valentin Longchamp valentin.longchamp at keymile.com
Mon Jan 27 11:49:12 CET 2014


The PEXHC PCIe configuration mechanism ensures that the FPGA get
configured at power-up. Since all the PCIe devices should be configured
when the kernel start, u-boot has to take care that the FPGA gets
configured also in other reset scenarios, mostly because of possible
configuration change.

The used mechanism is taken from the km_kirkwood design and adapted to
the kmp204x case (slightly different HW and PCIe configuration).

Signed-off-by: Valentin Longchamp <valentin.longchamp at keymile.com>
---

Changes in v2: None

 board/keymile/kmp204x/kmp204x.c |  7 +++-
 board/keymile/kmp204x/pci.c     | 85 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c
index 8d6eecb..17d35a4 100644
--- a/board/keymile/kmp204x/kmp204x.c
+++ b/board/keymile/kmp204x/kmp204x.c
@@ -101,6 +101,7 @@ int board_early_init_f(void)
 
 int board_early_init_r(void)
 {
+	int ret = 0;
 	/* Flush d-cache and invalidate i-cache of any FLASH data */
 	flush_dcache();
 	invalidate_icache();
@@ -108,7 +109,11 @@ int board_early_init_r(void)
 	set_liodns();
 	setup_portals();
 
-	return 0;
+	ret = trigger_fpga_config();
+	if (ret)
+		printf("error triggering PCIe FPGA config\n");
+
+	return ret;
 }
 
 unsigned long get_board_sys_clk(unsigned long dummy)
diff --git a/board/keymile/kmp204x/pci.c b/board/keymile/kmp204x/pci.c
index ec20c8a..a484eb5 100644
--- a/board/keymile/kmp204x/pci.c
+++ b/board/keymile/kmp204x/pci.c
@@ -14,18 +14,103 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <asm/fsl_serdes.h>
+#include <asm/errno.h>
 
 #include "kmp204x.h"
 
+#define PROM_SEL_L	11
+/* control the PROM_SEL_L signal*/
+static void toggle_fpga_eeprom_bus(bool cpu_own)
+{
+	qrio_gpio_direction_output(GPIO_A, PROM_SEL_L, !cpu_own);
+}
+
+#define CONF_SEL_L	10
+#define FPGA_PROG_L	19
+#define FPGA_DONE	18
+#define FPGA_INIT_L	17
+
+int trigger_fpga_config(void)
+{
+	int ret = 0, init_l;
+	/* approx 10ms */
+	u32 timeout = 10000;
+
+	/* make sure the FPGA_can access the EEPROM */
+	toggle_fpga_eeprom_bus(false);
+
+	/* assert CONF_SEL_L to be able to drive FPGA_PROG_L */
+	qrio_gpio_direction_output(GPIO_A, CONF_SEL_L, 0);
+
+	/* trigger the config start */
+	qrio_gpio_direction_output(GPIO_A, FPGA_PROG_L, 0);
+
+	/* small delay for INIT_L line */
+	udelay(10);
+
+	/* wait for FPGA_INIT to be asserted */
+	do {
+		init_l = qrio_get_gpio(GPIO_A, FPGA_INIT_L);
+		if (timeout-- == 0) {
+			printf("FPGA_INIT timeout\n");
+			ret = -EFAULT;
+			break;
+		}
+		udelay(10);
+	} while (init_l);
+
+	/* deassert FPGA_PROG, config should start */
+	qrio_set_gpio(GPIO_A, FPGA_PROG_L, 1);
+
+	return ret;
+}
+
+/* poll the FPGA_DONE signal and give the EEPROM back to the QorIQ */
+static int wait_for_fpga_config(void)
+{
+	int ret = 0, done;
+	/* approx 5 s */
+	u32 timeout = 500000;
+
+	printf("PCIe FPGA config:");
+	do {
+		done = qrio_get_gpio(GPIO_A, FPGA_DONE);
+		if (timeout-- == 0) {
+			printf(" FPGA_DONE timeout\n");
+			ret = -EFAULT;
+			goto err_out;
+		}
+		udelay(10);
+	} while (!done);
+
+	printf(" done\n");
+
+err_out:
+	/* deactive CONF_SEL and give the CPU conf EEPROM access */
+	qrio_set_gpio(GPIO_A, CONF_SEL_L, 1);
+	toggle_fpga_eeprom_bus(true);
+
+	return ret;
+}
+
 #define PCIE_SW_RST	14
+#define PEXHC_SW_RST	13
 #define HOOPER_SW_RST	12
 
 void pci_init_board(void)
 {
+	/* first wait for the PCIe FPGA to be configured
+	 * it has been triggered earlier in board_early_init_r */
+	int ret = wait_for_fpga_config();
+	if (ret)
+		printf("error finishing PCIe FPGA config\n");
+
 	qrio_prst(PCIE_SW_RST, false, false);
+	qrio_prst(PEXHC_SW_RST, false, false);
 	qrio_prst(HOOPER_SW_RST, false, false);
 	/* Hooper is not direcly PCIe capable */
 	mdelay(50);
+
 	fsl_pcie_init_board(0);
 }
 
-- 
1.8.0.1



More information about the U-Boot mailing list