]>
Commit | Line | Data |
---|---|---|
877bfe37 VL |
1 | /* |
2 | * (C) Copyright 2013 Keymile AG | |
3 | * Valentin Longchamp <valentin.longchamp@keymile.com> | |
4 | * | |
5 | * Copyright 2011,2012 Freescale Semiconductor, Inc. | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
11 | #include <command.h> | |
12 | #include <netdev.h> | |
13 | #include <linux/compiler.h> | |
14 | #include <asm/mmu.h> | |
15 | #include <asm/processor.h> | |
16 | #include <asm/cache.h> | |
17 | #include <asm/immap_85xx.h> | |
18 | #include <asm/fsl_law.h> | |
19 | #include <asm/fsl_serdes.h> | |
20 | #include <asm/fsl_portals.h> | |
21 | #include <asm/fsl_liodn.h> | |
22 | #include <fm_eth.h> | |
23 | ||
24 | #include "../common/common.h" | |
25 | #include "kmp204x.h" | |
26 | ||
27 | DECLARE_GLOBAL_DATA_PTR; | |
28 | ||
0fdb6ead VL |
29 | static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN]; |
30 | ||
877bfe37 VL |
31 | int checkboard(void) |
32 | { | |
33 | printf("Board: Keymile %s\n", CONFIG_KM_BOARD_NAME); | |
34 | ||
35 | return 0; | |
36 | } | |
37 | ||
f3e74d0a RB |
38 | /* I2C deblocking uses the algorithm defined in board/keymile/common/common.c |
39 | * 2 dedicated QRIO GPIOs externally pull the SCL and SDA lines | |
40 | * For I2C only the low state is activly driven and high state is pulled-up | |
41 | * by a resistor. Therefore the deblock GPIOs are used | |
42 | * -> as an active output to drive a low state | |
43 | * -> as an open-drain input to have a pulled-up high state | |
44 | */ | |
45 | ||
46 | /* QRIO GPIOs used for deblocking */ | |
47 | #define DEBLOCK_PORT1 GPIO_A | |
48 | #define DEBLOCK_SCL1 20 | |
49 | #define DEBLOCK_SDA1 21 | |
50 | ||
51 | /* By default deblock GPIOs are floating */ | |
52 | static void i2c_deblock_gpio_cfg(void) | |
53 | { | |
54 | /* set I2C bus 1 deblocking GPIOs input, but 0 value for open drain */ | |
55 | qrio_gpio_direction_input(DEBLOCK_PORT1, DEBLOCK_SCL1); | |
56 | qrio_gpio_direction_input(DEBLOCK_PORT1, DEBLOCK_SDA1); | |
57 | ||
58 | qrio_set_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1, 0); | |
59 | qrio_set_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1, 0); | |
60 | } | |
61 | ||
62 | void set_sda(int state) | |
63 | { | |
64 | qrio_set_opendrain_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1, state); | |
65 | } | |
66 | ||
67 | void set_scl(int state) | |
68 | { | |
69 | qrio_set_opendrain_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1, state); | |
70 | } | |
71 | ||
72 | int get_sda(void) | |
73 | { | |
74 | return qrio_get_gpio(DEBLOCK_PORT1, DEBLOCK_SDA1); | |
75 | } | |
76 | ||
77 | int get_scl(void) | |
877bfe37 | 78 | { |
f3e74d0a | 79 | return qrio_get_gpio(DEBLOCK_PORT1, DEBLOCK_SCL1); |
877bfe37 VL |
80 | } |
81 | ||
f3e74d0a | 82 | |
877bfe37 | 83 | #define ZL30158_RST 8 |
af47faf6 | 84 | #define BFTIC4_RST 0 |
a09f470d BR |
85 | #define RSTRQSR1_WDT_RR 0x00200000 |
86 | #define RSTRQSR1_SW_RR 0x00100000 | |
877bfe37 VL |
87 | |
88 | int board_early_init_f(void) | |
89 | { | |
90 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
a09f470d | 91 | bool cpuwd_flag = false; |
877bfe37 | 92 | |
e3917b21 BR |
93 | /* configure mode for uP reset request */ |
94 | qrio_uprstreq(UPREQ_CORE_RST); | |
95 | ||
877bfe37 VL |
96 | /* board only uses the DDR_MCK0, so disable the DDR_MCK1/2/3 */ |
97 | setbits_be32(&gur->ddrclkdr, 0x001f000f); | |
98 | ||
a09f470d BR |
99 | /* set reset reason according CPU register */ |
100 | if ((gur->rstrqsr1 & (RSTRQSR1_WDT_RR | RSTRQSR1_SW_RR)) == | |
101 | RSTRQSR1_WDT_RR) | |
102 | cpuwd_flag = true; | |
103 | ||
104 | qrio_cpuwd_flag(cpuwd_flag); | |
105 | /* clear CPU bits by writing 1 */ | |
106 | setbits_be32(&gur->rstrqsr1, RSTRQSR1_WDT_RR | RSTRQSR1_SW_RR); | |
107 | ||
af47faf6 VL |
108 | /* set the BFTIC's prstcfg to reset at power-up and unit reset only */ |
109 | qrio_prstcfg(BFTIC4_RST, PRSTCFG_POWUP_UNIT_RST); | |
110 | /* and enable WD on it */ | |
111 | qrio_wdmask(BFTIC4_RST, true); | |
877bfe37 | 112 | |
f3839179 VL |
113 | /* set the ZL30138's prstcfg to reset at power-up only */ |
114 | qrio_prstcfg(ZL30158_RST, PRSTCFG_POWUP_RST); | |
af47faf6 VL |
115 | /* and take it out of reset as soon as possible (needed for Hooper) */ |
116 | qrio_prst(ZL30158_RST, false, false); | |
877bfe37 VL |
117 | |
118 | return 0; | |
119 | } | |
120 | ||
121 | int board_early_init_r(void) | |
122 | { | |
27c78e06 | 123 | int ret = 0; |
877bfe37 VL |
124 | /* Flush d-cache and invalidate i-cache of any FLASH data */ |
125 | flush_dcache(); | |
126 | invalidate_icache(); | |
127 | ||
128 | set_liodns(); | |
44262327 | 129 | setup_qbman_portals(); |
877bfe37 | 130 | |
27c78e06 VL |
131 | ret = trigger_fpga_config(); |
132 | if (ret) | |
133 | printf("error triggering PCIe FPGA config\n"); | |
134 | ||
a53e65d0 SB |
135 | /* enable the Unit LED (red) & Boot LED (on) */ |
136 | qrio_set_leds(); | |
137 | ||
4921a149 SB |
138 | /* enable Application Buffer */ |
139 | qrio_enable_app_buffer(); | |
140 | ||
27c78e06 | 141 | return ret; |
877bfe37 VL |
142 | } |
143 | ||
144 | unsigned long get_board_sys_clk(unsigned long dummy) | |
145 | { | |
146 | return 66666666; | |
147 | } | |
148 | ||
af47faf6 VL |
149 | #define ETH_FRONT_PHY_RST 15 |
150 | #define QSFP2_RST 11 | |
151 | #define QSFP1_RST 10 | |
152 | #define ZL30343_RST 9 | |
153 | ||
f3e74d0a RB |
154 | int misc_init_f(void) |
155 | { | |
156 | /* configure QRIO pis for i2c deblocking */ | |
157 | i2c_deblock_gpio_cfg(); | |
158 | ||
af47faf6 VL |
159 | /* configure the front phy's prstcfg and take it out of reset */ |
160 | qrio_prstcfg(ETH_FRONT_PHY_RST, PRSTCFG_POWUP_UNIT_CORE_RST); | |
161 | qrio_prst(ETH_FRONT_PHY_RST, false, false); | |
162 | ||
f3839179 VL |
163 | /* set the ZL30343 prstcfg to reset at power-up only */ |
164 | qrio_prstcfg(ZL30343_RST, PRSTCFG_POWUP_RST); | |
af47faf6 VL |
165 | /* and enable the WD on it */ |
166 | qrio_wdmask(ZL30343_RST, true); | |
167 | ||
168 | /* set the QSFPs' prstcfg to reset at power-up and unit rst only */ | |
169 | qrio_prstcfg(QSFP1_RST, PRSTCFG_POWUP_UNIT_RST); | |
170 | qrio_prstcfg(QSFP2_RST, PRSTCFG_POWUP_UNIT_RST); | |
171 | ||
172 | /* and enable the WD on them */ | |
173 | qrio_wdmask(QSFP1_RST, true); | |
174 | qrio_wdmask(QSFP2_RST, true); | |
175 | ||
f3e74d0a RB |
176 | return 0; |
177 | } | |
178 | ||
877bfe37 | 179 | #define NUM_SRDS_BANKS 2 |
877bfe37 VL |
180 | |
181 | int misc_init_r(void) | |
182 | { | |
183 | serdes_corenet_t *regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; | |
184 | u32 expected[NUM_SRDS_BANKS] = {SRDS_PLLCR0_RFCK_SEL_100, | |
185 | SRDS_PLLCR0_RFCK_SEL_125}; | |
186 | unsigned int i; | |
187 | ||
188 | /* check SERDES reference clocks */ | |
189 | for (i = 0; i < NUM_SRDS_BANKS; i++) { | |
190 | u32 actual = in_be32(®s->bank[i].pllcr0); | |
191 | actual &= SRDS_PLLCR0_RFCK_SEL_MASK; | |
192 | if (actual != expected[i]) { | |
193 | printf("Warning: SERDES bank %u expects reference \ | |
194 | clock %sMHz, but actual is %sMHz\n", i + 1, | |
195 | serdes_clock_to_string(expected[i]), | |
196 | serdes_clock_to_string(actual)); | |
197 | } | |
198 | } | |
199 | ||
60c4ae00 | 200 | ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN); |
877bfe37 VL |
201 | return 0; |
202 | } | |
203 | ||
204 | #if defined(CONFIG_HUSH_INIT_VAR) | |
205 | int hush_init_var(void) | |
206 | { | |
0fdb6ead | 207 | ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN); |
877bfe37 VL |
208 | return 0; |
209 | } | |
210 | #endif | |
211 | ||
212 | #if defined(CONFIG_LAST_STAGE_INIT) | |
af47faf6 | 213 | |
877bfe37 VL |
214 | int last_stage_init(void) |
215 | { | |
4921a149 SB |
216 | #if defined(CONFIG_KMCOGE4) |
217 | /* on KMCOGE4, the BFTIC4 is on the LBAPP2 */ | |
218 | struct bfticu_iomap *bftic4 = | |
219 | (struct bfticu_iomap *)CONFIG_SYS_LBAPP2_BASE; | |
220 | u8 dip_switch = in_8((u8 *)&(bftic4->mswitch)) & BFTICU_DIPSWITCH_MASK; | |
221 | ||
222 | if (dip_switch != 0) { | |
223 | /* start bootloader */ | |
224 | puts("DIP: Enabled\n"); | |
382bee57 | 225 | env_set("actual_bank", "0"); |
4921a149 SB |
226 | } |
227 | #endif | |
877bfe37 | 228 | set_km_env(); |
af47faf6 | 229 | |
877bfe37 VL |
230 | return 0; |
231 | } | |
232 | #endif | |
233 | ||
234 | #ifdef CONFIG_SYS_DPAA_FMAN | |
235 | void fdt_fixup_fman_mac_addresses(void *blob) | |
236 | { | |
237 | int node, i, ret; | |
238 | char *tmp, *end; | |
239 | unsigned char mac_addr[6]; | |
240 | ||
241 | /* get the mac addr from env */ | |
00caae6d | 242 | tmp = env_get("ethaddr"); |
877bfe37 VL |
243 | if (!tmp) { |
244 | printf("ethaddr env variable not defined\n"); | |
245 | return; | |
246 | } | |
247 | for (i = 0; i < 6; i++) { | |
248 | mac_addr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; | |
249 | if (tmp) | |
250 | tmp = (*end) ? end+1 : end; | |
251 | } | |
252 | ||
253 | /* find the correct fdt ethernet path and correct it */ | |
254 | node = fdt_path_offset(blob, "/soc/fman/ethernet@e8000"); | |
255 | if (node < 0) { | |
256 | printf("no /soc/fman/ethernet path offset\n"); | |
257 | return; | |
258 | } | |
259 | ret = fdt_setprop(blob, node, "local-mac-address", &mac_addr, 6); | |
260 | if (ret) { | |
261 | printf("error setting local-mac-address property\n"); | |
262 | return; | |
263 | } | |
264 | } | |
265 | #endif | |
266 | ||
e895a4b0 | 267 | int ft_board_setup(void *blob, bd_t *bd) |
877bfe37 VL |
268 | { |
269 | phys_addr_t base; | |
270 | phys_size_t size; | |
271 | ||
272 | ft_cpu_setup(blob, bd); | |
273 | ||
723806cc SG |
274 | base = env_get_bootm_low(); |
275 | size = env_get_bootm_size(); | |
877bfe37 VL |
276 | |
277 | fdt_fixup_memory(blob, (u64)base, (u64)size); | |
278 | ||
279 | #if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) | |
a5c289b9 | 280 | fsl_fdt_fixup_dr_usb(blob, bd); |
877bfe37 VL |
281 | #endif |
282 | ||
283 | #ifdef CONFIG_PCI | |
284 | pci_of_setup(blob, bd); | |
285 | #endif | |
286 | ||
287 | fdt_fixup_liodn(blob); | |
288 | #ifdef CONFIG_SYS_DPAA_FMAN | |
289 | fdt_fixup_fman_ethernet(blob); | |
290 | fdt_fixup_fman_mac_addresses(blob); | |
291 | #endif | |
e895a4b0 SG |
292 | |
293 | return 0; | |
877bfe37 | 294 | } |
18794944 VL |
295 | |
296 | #if defined(CONFIG_POST) | |
297 | ||
298 | /* DIC26_SELFTEST GPIO used to start factory test sw */ | |
299 | #define SELFTEST_PORT GPIO_A | |
300 | #define SELFTEST_PIN 31 | |
301 | ||
302 | int post_hotkeys_pressed(void) | |
303 | { | |
304 | qrio_gpio_direction_input(SELFTEST_PORT, SELFTEST_PIN); | |
305 | return qrio_get_gpio(SELFTEST_PORT, SELFTEST_PIN); | |
306 | } | |
307 | #endif |