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

Valentin Longchamp
2014-01-27T10:49:12Z

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(-)

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