kmp204x: initial support for PCIe FPGA configuration
authorValentin Longchamp <valentin.longchamp@keymile.com>
Mon, 27 Jan 2014 10:49:12 +0000 (11:49 +0100)
committerYork Sun <yorksun@freescale.com>
Mon, 3 Feb 2014 16:38:51 +0000 (08:38 -0800)
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>
Reviewed-by: York Sun <yorksun@freescale.com>
board/keymile/kmp204x/kmp204x.c
board/keymile/kmp204x/pci.c

index a6c23a2c35879fc77f076dd86fc1125b31474029..95a19cdb2c1869c880e850b25648339530010c85 100644 (file)
@@ -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)
index ec20c8afb4e55ea185da1004059f34b5ab47e869..a484eb574955ad6afc1de8f9c66ed292a12f46ed 100644 (file)
 #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);
 }