diff mbox

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

Message ID 1390819752-21233-10-git-send-email-valentin.longchamp@keymile.com
State Accepted
Delegated to: York Sun
Headers show

Commit Message

Valentin Longchamp Jan. 27, 2014, 10:49 a.m. UTC
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@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(-)

Comments

York Sun Feb. 3, 2014, 8:25 p.m. UTC | #1
On 01/27/2014 02:49 AM, Valentin Longchamp wrote:
> 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@keymile.com>
> ---
> 
> Changes in v2: None
> 

Applied to u-boot-mpc85xx master branch.

York
diff mbox

Patch

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);
 }