]>
Commit | Line | Data |
---|---|---|
e84a324b AK |
1 | /* |
2 | * Copyright 2017 NXP | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | #include <common.h> | |
7 | #include <i2c.h> | |
8 | #include <malloc.h> | |
9 | #include <errno.h> | |
10 | #include <netdev.h> | |
11 | #include <fsl_ifc.h> | |
12 | #include <fsl_ddr.h> | |
13 | #include <fsl_sec.h> | |
14 | #include <asm/io.h> | |
15 | #include <fdt_support.h> | |
16 | #include <libfdt.h> | |
17 | #include <fsl-mc/fsl_mc.h> | |
18 | #include <environment.h> | |
19 | #include <asm/arch-fsl-layerscape/soc.h> | |
20 | #include <asm/arch/ppa.h> | |
21 | ||
22 | #include "../common/qixis.h" | |
23 | #include "ls1088a_qixis.h" | |
24 | ||
25 | DECLARE_GLOBAL_DATA_PTR; | |
26 | ||
27 | unsigned long long get_qixis_addr(void) | |
28 | { | |
29 | unsigned long long addr; | |
30 | ||
31 | if (gd->flags & GD_FLG_RELOC) | |
32 | addr = QIXIS_BASE_PHYS; | |
33 | else | |
34 | addr = QIXIS_BASE_PHYS_EARLY; | |
35 | ||
36 | /* | |
37 | * IFC address under 256MB is mapped to 0x30000000, any address above | |
38 | * is mapped to 0x5_10000000 up to 4GB. | |
39 | */ | |
40 | addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000; | |
41 | ||
42 | return addr; | |
43 | } | |
44 | ||
45 | int checkboard(void) | |
46 | { | |
47 | char buf[64]; | |
48 | u8 sw; | |
49 | static const char *const freq[] = {"100", "125", "156.25", | |
50 | "100 separate SSCG"}; | |
51 | int clock; | |
52 | ||
7769776a AK |
53 | #ifdef CONFIG_TARGET_LS1088AQDS |
54 | printf("Board: LS1088A-QDS, "); | |
55 | #else | |
e84a324b | 56 | printf("Board: LS1088A-RDB, "); |
7769776a | 57 | #endif |
e84a324b AK |
58 | |
59 | sw = QIXIS_READ(arch); | |
60 | printf("Board Arch: V%d, ", sw >> 4); | |
61 | ||
7769776a AK |
62 | #ifdef CONFIG_TARGET_LS1088AQDS |
63 | printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1); | |
64 | #else | |
e84a324b | 65 | printf("Board version: %c, boot from ", (sw & 0xf) + 'A'); |
7769776a | 66 | #endif |
e84a324b AK |
67 | |
68 | memset((u8 *)buf, 0x00, ARRAY_SIZE(buf)); | |
69 | ||
70 | sw = QIXIS_READ(brdcfg[0]); | |
71 | sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; | |
72 | ||
73 | #ifdef CONFIG_SD_BOOT | |
74 | puts("SD card\n"); | |
75 | #endif | |
76 | switch (sw) { | |
7769776a | 77 | #ifdef CONFIG_TARGET_LS1088AQDS |
e84a324b | 78 | case 0: |
7769776a AK |
79 | case 1: |
80 | case 2: | |
81 | case 3: | |
82 | case 4: | |
83 | case 5: | |
84 | case 6: | |
85 | case 7: | |
86 | printf("vBank: %d\n", sw); | |
87 | break; | |
88 | case 8: | |
89 | puts("PromJet\n"); | |
90 | break; | |
91 | case 15: | |
92 | puts("IFCCard\n"); | |
93 | break; | |
94 | case 14: | |
95 | #else | |
96 | case 0: | |
97 | #endif | |
e84a324b AK |
98 | puts("QSPI:"); |
99 | sw = QIXIS_READ(brdcfg[0]); | |
100 | sw = (sw & QIXIS_QMAP_MASK) >> QIXIS_QMAP_SHIFT; | |
101 | if (sw == 0 || sw == 4) | |
102 | puts("0\n"); | |
103 | else if (sw == 1) | |
104 | puts("1\n"); | |
105 | else | |
106 | puts("EMU\n"); | |
107 | break; | |
108 | ||
109 | default: | |
110 | printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); | |
111 | break; | |
112 | } | |
113 | ||
7769776a AK |
114 | #ifdef CONFIG_TARGET_LS1088AQDS |
115 | printf("FPGA: v%d (%s), build %d", | |
116 | (int)QIXIS_READ(scver), qixis_read_tag(buf), | |
117 | (int)qixis_read_minor()); | |
118 | /* the timestamp string contains "\n" at the end */ | |
119 | printf(" on %s", qixis_read_time(buf)); | |
120 | #else | |
e84a324b | 121 | printf("CPLD: v%d.%d\n", QIXIS_READ(scver), QIXIS_READ(tagdata)); |
7769776a | 122 | #endif |
e84a324b AK |
123 | |
124 | /* | |
125 | * Display the actual SERDES reference clocks as configured by the | |
126 | * dip switches on the board. Note that the SWx registers could | |
127 | * technically be set to force the reference clocks to match the | |
128 | * values that the SERDES expects (or vice versa). For now, however, | |
129 | * we just display both values and hope the user notices when they | |
130 | * don't match. | |
131 | */ | |
132 | puts("SERDES1 Reference : "); | |
133 | sw = QIXIS_READ(brdcfg[2]); | |
134 | clock = (sw >> 6) & 3; | |
135 | printf("Clock1 = %sMHz ", freq[clock]); | |
136 | clock = (sw >> 4) & 3; | |
137 | printf("Clock2 = %sMHz", freq[clock]); | |
138 | ||
139 | puts("\nSERDES2 Reference : "); | |
140 | clock = (sw >> 2) & 3; | |
141 | printf("Clock1 = %sMHz ", freq[clock]); | |
142 | clock = (sw >> 0) & 3; | |
143 | printf("Clock2 = %sMHz\n", freq[clock]); | |
144 | ||
145 | return 0; | |
146 | } | |
147 | ||
148 | bool if_board_diff_clk(void) | |
149 | { | |
7769776a AK |
150 | #ifdef CONFIG_TARGET_LS1088AQDS |
151 | u8 diff_conf = QIXIS_READ(brdcfg[11]); | |
152 | return diff_conf & 0x40; | |
153 | #else | |
e84a324b AK |
154 | u8 diff_conf = QIXIS_READ(dutcfg[11]); |
155 | return diff_conf & 0x80; | |
7769776a | 156 | #endif |
e84a324b AK |
157 | } |
158 | ||
159 | unsigned long get_board_sys_clk(void) | |
160 | { | |
161 | u8 sysclk_conf = QIXIS_READ(brdcfg[1]); | |
162 | ||
163 | switch (sysclk_conf & 0x0f) { | |
164 | case QIXIS_SYSCLK_83: | |
165 | return 83333333; | |
166 | case QIXIS_SYSCLK_100: | |
167 | return 100000000; | |
168 | case QIXIS_SYSCLK_125: | |
169 | return 125000000; | |
170 | case QIXIS_SYSCLK_133: | |
171 | return 133333333; | |
172 | case QIXIS_SYSCLK_150: | |
173 | return 150000000; | |
174 | case QIXIS_SYSCLK_160: | |
175 | return 160000000; | |
176 | case QIXIS_SYSCLK_166: | |
177 | return 166666666; | |
178 | } | |
179 | ||
180 | return 66666666; | |
181 | } | |
182 | ||
183 | unsigned long get_board_ddr_clk(void) | |
184 | { | |
185 | u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); | |
186 | ||
187 | if (if_board_diff_clk()) | |
188 | return get_board_sys_clk(); | |
189 | switch ((ddrclk_conf & 0x30) >> 4) { | |
190 | case QIXIS_DDRCLK_100: | |
191 | return 100000000; | |
192 | case QIXIS_DDRCLK_125: | |
193 | return 125000000; | |
194 | case QIXIS_DDRCLK_133: | |
195 | return 133333333; | |
196 | } | |
197 | ||
198 | return 66666666; | |
199 | } | |
200 | ||
201 | int select_i2c_ch_pca9547(u8 ch) | |
202 | { | |
203 | int ret; | |
204 | ||
205 | ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); | |
206 | if (ret) { | |
207 | puts("PCA: failed to select proper channel\n"); | |
208 | return ret; | |
209 | } | |
210 | ||
211 | return 0; | |
212 | } | |
213 | ||
214 | void board_retimer_init(void) | |
215 | { | |
216 | u8 reg; | |
217 | ||
218 | /* Retimer is connected to I2C1_CH5 */ | |
219 | select_i2c_ch_pca9547(I2C_MUX_CH5); | |
220 | ||
221 | /* Access to Control/Shared register */ | |
222 | reg = 0x0; | |
223 | i2c_write(I2C_RETIMER_ADDR, 0xff, 1, ®, 1); | |
224 | ||
225 | /* Read device revision and ID */ | |
226 | i2c_read(I2C_RETIMER_ADDR, 1, 1, ®, 1); | |
227 | debug("Retimer version id = 0x%x\n", reg); | |
228 | ||
229 | /* Enable Broadcast. All writes target all channel register sets */ | |
230 | reg = 0x0c; | |
231 | i2c_write(I2C_RETIMER_ADDR, 0xff, 1, ®, 1); | |
232 | ||
233 | /* Reset Channel Registers */ | |
234 | i2c_read(I2C_RETIMER_ADDR, 0, 1, ®, 1); | |
235 | reg |= 0x4; | |
236 | i2c_write(I2C_RETIMER_ADDR, 0, 1, ®, 1); | |
237 | ||
238 | /* Set data rate as 10.3125 Gbps */ | |
239 | reg = 0x90; | |
240 | i2c_write(I2C_RETIMER_ADDR, 0x60, 1, ®, 1); | |
241 | reg = 0xb3; | |
242 | i2c_write(I2C_RETIMER_ADDR, 0x61, 1, ®, 1); | |
243 | reg = 0x90; | |
244 | i2c_write(I2C_RETIMER_ADDR, 0x62, 1, ®, 1); | |
245 | reg = 0xb3; | |
246 | i2c_write(I2C_RETIMER_ADDR, 0x63, 1, ®, 1); | |
247 | reg = 0xcd; | |
248 | i2c_write(I2C_RETIMER_ADDR, 0x64, 1, ®, 1); | |
249 | ||
250 | /* Select VCO Divider to full rate (000) */ | |
251 | i2c_read(I2C_RETIMER_ADDR, 0x2F, 1, ®, 1); | |
252 | reg &= 0x0f; | |
253 | reg |= 0x70; | |
254 | i2c_write(I2C_RETIMER_ADDR, 0x2F, 1, ®, 1); | |
255 | ||
7769776a AK |
256 | #ifdef CONFIG_TARGET_LS1088AQDS |
257 | /* Retimer is connected to I2C1_CH5 */ | |
258 | select_i2c_ch_pca9547(I2C_MUX_CH5); | |
259 | ||
260 | /* Access to Control/Shared register */ | |
261 | reg = 0x0; | |
262 | i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); | |
e84a324b | 263 | |
7769776a AK |
264 | /* Read device revision and ID */ |
265 | i2c_read(I2C_RETIMER_ADDR2, 1, 1, ®, 1); | |
266 | debug("Retimer version id = 0x%x\n", reg); | |
267 | ||
268 | /* Enable Broadcast. All writes target all channel register sets */ | |
269 | reg = 0x0c; | |
270 | i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); | |
271 | ||
272 | /* Reset Channel Registers */ | |
273 | i2c_read(I2C_RETIMER_ADDR2, 0, 1, ®, 1); | |
274 | reg |= 0x4; | |
275 | i2c_write(I2C_RETIMER_ADDR2, 0, 1, ®, 1); | |
276 | ||
277 | /* Set data rate as 10.3125 Gbps */ | |
278 | reg = 0x90; | |
279 | i2c_write(I2C_RETIMER_ADDR2, 0x60, 1, ®, 1); | |
280 | reg = 0xb3; | |
281 | i2c_write(I2C_RETIMER_ADDR2, 0x61, 1, ®, 1); | |
282 | reg = 0x90; | |
283 | i2c_write(I2C_RETIMER_ADDR2, 0x62, 1, ®, 1); | |
284 | reg = 0xb3; | |
285 | i2c_write(I2C_RETIMER_ADDR2, 0x63, 1, ®, 1); | |
286 | reg = 0xcd; | |
287 | i2c_write(I2C_RETIMER_ADDR2, 0x64, 1, ®, 1); | |
288 | ||
289 | /* Select VCO Divider to full rate (000) */ | |
290 | i2c_read(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); | |
291 | reg &= 0x0f; | |
292 | reg |= 0x70; | |
293 | i2c_write(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); | |
294 | #endif | |
e84a324b AK |
295 | /*return the default channel*/ |
296 | select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); | |
297 | } | |
298 | ||
299 | int board_init(void) | |
300 | { | |
301 | init_final_memctl_regs(); | |
302 | #if defined(CONFIG_TARGET_LS1088ARDB) && defined(CONFIG_FSL_MC_ENET) | |
303 | u32 __iomem *irq_ccsr = (u32 __iomem *)ISC_BASE; | |
304 | #endif | |
305 | ||
306 | select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); | |
307 | board_retimer_init(); | |
308 | ||
309 | #ifdef CONFIG_ENV_IS_NOWHERE | |
310 | gd->env_addr = (ulong)&default_environment[0]; | |
311 | #endif | |
312 | ||
313 | #if defined(CONFIG_TARGET_LS1088ARDB) && defined(CONFIG_FSL_MC_ENET) | |
314 | /* invert AQR105 IRQ pins polarity */ | |
315 | out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR105_IRQ_MASK); | |
316 | #endif | |
317 | ||
318 | #ifdef CONFIG_FSL_LS_PPA | |
319 | ppa_init(); | |
320 | #endif | |
321 | return 0; | |
322 | } | |
323 | ||
324 | int board_early_init_f(void) | |
325 | { | |
326 | fsl_lsch3_early_init_f(); | |
327 | return 0; | |
328 | } | |
329 | ||
330 | void detail_board_ddr_info(void) | |
331 | { | |
332 | puts("\nDDR "); | |
333 | print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); | |
334 | print_ddr_info(0); | |
335 | } | |
336 | ||
337 | #if defined(CONFIG_ARCH_MISC_INIT) | |
338 | int arch_misc_init(void) | |
339 | { | |
340 | #ifdef CONFIG_FSL_CAAM | |
341 | sec_init(); | |
342 | #endif | |
343 | return 0; | |
344 | } | |
345 | #endif | |
346 | ||
347 | #ifdef CONFIG_FSL_MC_ENET | |
348 | void fdt_fixup_board_enet(void *fdt) | |
349 | { | |
350 | int offset; | |
351 | ||
352 | offset = fdt_path_offset(fdt, "/fsl-mc"); | |
353 | ||
354 | if (offset < 0) | |
355 | offset = fdt_path_offset(fdt, "/fsl,dprc@0"); | |
356 | ||
357 | if (offset < 0) { | |
358 | printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n", | |
359 | __func__, offset); | |
360 | return; | |
361 | } | |
362 | ||
363 | if (get_mc_boot_status() == 0) | |
364 | fdt_status_okay(fdt, offset); | |
365 | else | |
366 | fdt_status_fail(fdt, offset); | |
367 | } | |
368 | #endif | |
369 | ||
370 | #ifdef CONFIG_OF_BOARD_SETUP | |
6b6b7e8a AK |
371 | void fsl_fdt_fixup_flash(void *fdt) |
372 | { | |
373 | int offset; | |
374 | ||
375 | /* | |
376 | * IFC-NOR and QSPI are muxed on SoC. | |
377 | * So disable IFC node in dts if QSPI is enabled or | |
378 | * disable QSPI node in dts in case QSPI is not enabled. | |
379 | */ | |
380 | ||
381 | #ifdef CONFIG_FSL_QSPI | |
382 | offset = fdt_path_offset(fdt, "/soc/ifc/nor"); | |
383 | ||
384 | if (offset < 0) | |
385 | offset = fdt_path_offset(fdt, "/ifc/nor"); | |
386 | #else | |
387 | offset = fdt_path_offset(fdt, "/soc/quadspi"); | |
388 | ||
389 | if (offset < 0) | |
390 | offset = fdt_path_offset(fdt, "/quadspi"); | |
391 | #endif | |
392 | if (offset < 0) | |
393 | return; | |
394 | ||
395 | fdt_status_disabled(fdt, offset); | |
396 | } | |
397 | ||
e84a324b AK |
398 | int ft_board_setup(void *blob, bd_t *bd) |
399 | { | |
400 | int err, i; | |
401 | u64 base[CONFIG_NR_DRAM_BANKS]; | |
402 | u64 size[CONFIG_NR_DRAM_BANKS]; | |
403 | ||
404 | ft_cpu_setup(blob, bd); | |
405 | ||
406 | /* fixup DT for the two GPP DDR banks */ | |
407 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
408 | base[i] = gd->bd->bi_dram[i].start; | |
409 | size[i] = gd->bd->bi_dram[i].size; | |
410 | } | |
411 | ||
412 | #ifdef CONFIG_RESV_RAM | |
413 | /* reduce size if reserved memory is within this bank */ | |
414 | if (gd->arch.resv_ram >= base[0] && | |
415 | gd->arch.resv_ram < base[0] + size[0]) | |
416 | size[0] = gd->arch.resv_ram - base[0]; | |
417 | else if (gd->arch.resv_ram >= base[1] && | |
418 | gd->arch.resv_ram < base[1] + size[1]) | |
419 | size[1] = gd->arch.resv_ram - base[1]; | |
420 | #endif | |
421 | ||
422 | fdt_fixup_memory_banks(blob, base, size, CONFIG_NR_DRAM_BANKS); | |
423 | ||
6b6b7e8a AK |
424 | fsl_fdt_fixup_flash(blob); |
425 | ||
e84a324b AK |
426 | #ifdef CONFIG_FSL_MC_ENET |
427 | fdt_fixup_board_enet(blob); | |
428 | err = fsl_mc_ldpaa_exit(bd); | |
429 | if (err) | |
430 | return err; | |
431 | #endif | |
432 | ||
433 | return 0; | |
434 | } | |
435 | #endif |