Commit 27c78e06f2b42bd6285ed104ece23f6c69e42e6f
Committed by
York Sun
1 parent
47c1180c02
Exists in
master
and in
49 other branches
kmp204x: initial support for PCIe FPGA configuration
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>
Showing 2 changed files with 91 additions and 1 deletions Side-by-side Diff
board/keymile/kmp204x/kmp204x.c
... | ... | @@ -101,6 +101,7 @@ |
101 | 101 | |
102 | 102 | int board_early_init_r(void) |
103 | 103 | { |
104 | + int ret = 0; | |
104 | 105 | /* Flush d-cache and invalidate i-cache of any FLASH data */ |
105 | 106 | flush_dcache(); |
106 | 107 | invalidate_icache(); |
... | ... | @@ -108,7 +109,11 @@ |
108 | 109 | set_liodns(); |
109 | 110 | setup_portals(); |
110 | 111 | |
111 | - return 0; | |
112 | + ret = trigger_fpga_config(); | |
113 | + if (ret) | |
114 | + printf("error triggering PCIe FPGA config\n"); | |
115 | + | |
116 | + return ret; | |
112 | 117 | } |
113 | 118 | |
114 | 119 | unsigned long get_board_sys_clk(unsigned long dummy) |
board/keymile/kmp204x/pci.c
... | ... | @@ -14,18 +14,103 @@ |
14 | 14 | #include <libfdt.h> |
15 | 15 | #include <fdt_support.h> |
16 | 16 | #include <asm/fsl_serdes.h> |
17 | +#include <asm/errno.h> | |
17 | 18 | |
18 | 19 | #include "kmp204x.h" |
19 | 20 | |
21 | +#define PROM_SEL_L 11 | |
22 | +/* control the PROM_SEL_L signal*/ | |
23 | +static void toggle_fpga_eeprom_bus(bool cpu_own) | |
24 | +{ | |
25 | + qrio_gpio_direction_output(GPIO_A, PROM_SEL_L, !cpu_own); | |
26 | +} | |
27 | + | |
28 | +#define CONF_SEL_L 10 | |
29 | +#define FPGA_PROG_L 19 | |
30 | +#define FPGA_DONE 18 | |
31 | +#define FPGA_INIT_L 17 | |
32 | + | |
33 | +int trigger_fpga_config(void) | |
34 | +{ | |
35 | + int ret = 0, init_l; | |
36 | + /* approx 10ms */ | |
37 | + u32 timeout = 10000; | |
38 | + | |
39 | + /* make sure the FPGA_can access the EEPROM */ | |
40 | + toggle_fpga_eeprom_bus(false); | |
41 | + | |
42 | + /* assert CONF_SEL_L to be able to drive FPGA_PROG_L */ | |
43 | + qrio_gpio_direction_output(GPIO_A, CONF_SEL_L, 0); | |
44 | + | |
45 | + /* trigger the config start */ | |
46 | + qrio_gpio_direction_output(GPIO_A, FPGA_PROG_L, 0); | |
47 | + | |
48 | + /* small delay for INIT_L line */ | |
49 | + udelay(10); | |
50 | + | |
51 | + /* wait for FPGA_INIT to be asserted */ | |
52 | + do { | |
53 | + init_l = qrio_get_gpio(GPIO_A, FPGA_INIT_L); | |
54 | + if (timeout-- == 0) { | |
55 | + printf("FPGA_INIT timeout\n"); | |
56 | + ret = -EFAULT; | |
57 | + break; | |
58 | + } | |
59 | + udelay(10); | |
60 | + } while (init_l); | |
61 | + | |
62 | + /* deassert FPGA_PROG, config should start */ | |
63 | + qrio_set_gpio(GPIO_A, FPGA_PROG_L, 1); | |
64 | + | |
65 | + return ret; | |
66 | +} | |
67 | + | |
68 | +/* poll the FPGA_DONE signal and give the EEPROM back to the QorIQ */ | |
69 | +static int wait_for_fpga_config(void) | |
70 | +{ | |
71 | + int ret = 0, done; | |
72 | + /* approx 5 s */ | |
73 | + u32 timeout = 500000; | |
74 | + | |
75 | + printf("PCIe FPGA config:"); | |
76 | + do { | |
77 | + done = qrio_get_gpio(GPIO_A, FPGA_DONE); | |
78 | + if (timeout-- == 0) { | |
79 | + printf(" FPGA_DONE timeout\n"); | |
80 | + ret = -EFAULT; | |
81 | + goto err_out; | |
82 | + } | |
83 | + udelay(10); | |
84 | + } while (!done); | |
85 | + | |
86 | + printf(" done\n"); | |
87 | + | |
88 | +err_out: | |
89 | + /* deactive CONF_SEL and give the CPU conf EEPROM access */ | |
90 | + qrio_set_gpio(GPIO_A, CONF_SEL_L, 1); | |
91 | + toggle_fpga_eeprom_bus(true); | |
92 | + | |
93 | + return ret; | |
94 | +} | |
95 | + | |
20 | 96 | #define PCIE_SW_RST 14 |
97 | +#define PEXHC_SW_RST 13 | |
21 | 98 | #define HOOPER_SW_RST 12 |
22 | 99 | |
23 | 100 | void pci_init_board(void) |
24 | 101 | { |
102 | + /* first wait for the PCIe FPGA to be configured | |
103 | + * it has been triggered earlier in board_early_init_r */ | |
104 | + int ret = wait_for_fpga_config(); | |
105 | + if (ret) | |
106 | + printf("error finishing PCIe FPGA config\n"); | |
107 | + | |
25 | 108 | qrio_prst(PCIE_SW_RST, false, false); |
109 | + qrio_prst(PEXHC_SW_RST, false, false); | |
26 | 110 | qrio_prst(HOOPER_SW_RST, false, false); |
27 | 111 | /* Hooper is not direcly PCIe capable */ |
28 | 112 | mdelay(50); |
113 | + | |
29 | 114 | fsl_pcie_init_board(0); |
30 | 115 | } |
31 | 116 |