]> git.ipfire.org Git - thirdparty/u-boot.git/blame - board/xilinx/zynqmp/zynqmp.c
SPDX: Convert all of our single license tags to Linux Kernel style
[thirdparty/u-boot.git] / board / xilinx / zynqmp / zynqmp.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
84c7204b
MS
2/*
3 * (C) Copyright 2014 - 2015 Xilinx, Inc.
4 * Michal Simek <michal.simek@xilinx.com>
84c7204b
MS
5 */
6
7#include <common.h>
679b994a 8#include <sata.h>
6fe6f135
MS
9#include <ahci.h>
10#include <scsi.h>
b72894f1 11#include <malloc.h>
0785dfd8 12#include <asm/arch/clk.h>
84c7204b
MS
13#include <asm/arch/hardware.h>
14#include <asm/arch/sys_proto.h>
2ad341ed 15#include <asm/arch/psu_init_gpl.h>
84c7204b 16#include <asm/io.h>
16fa00a7
SDPP
17#include <usb.h>
18#include <dwc3-uboot.h>
47e60cbd 19#include <zynqmppl.h>
6919b4bf 20#include <i2c.h>
9feff385 21#include <g_dnl.h>
84c7204b
MS
22
23DECLARE_GLOBAL_DATA_PTR;
24
47e60cbd
MS
25#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
26 !defined(CONFIG_SPL_BUILD)
27static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
28
29static const struct {
8ebdf9ef 30 u32 id;
494fffe7 31 u32 ver;
47e60cbd 32 char *name;
83bf2ff0 33 bool evexists;
47e60cbd
MS
34} zynqmp_devices[] = {
35 {
36 .id = 0x10,
37 .name = "3eg",
38 },
494fffe7
MS
39 {
40 .id = 0x10,
41 .ver = 0x2c,
42 .name = "3cg",
43 },
47e60cbd
MS
44 {
45 .id = 0x11,
46 .name = "2eg",
47 },
494fffe7
MS
48 {
49 .id = 0x11,
50 .ver = 0x2c,
51 .name = "2cg",
52 },
47e60cbd
MS
53 {
54 .id = 0x20,
55 .name = "5ev",
83bf2ff0 56 .evexists = 1,
47e60cbd 57 },
494fffe7
MS
58 {
59 .id = 0x20,
60 .ver = 0x100,
61 .name = "5eg",
83bf2ff0 62 .evexists = 1,
494fffe7
MS
63 },
64 {
65 .id = 0x20,
66 .ver = 0x12c,
67 .name = "5cg",
68 },
47e60cbd
MS
69 {
70 .id = 0x21,
71 .name = "4ev",
83bf2ff0 72 .evexists = 1,
47e60cbd 73 },
494fffe7
MS
74 {
75 .id = 0x21,
76 .ver = 0x100,
77 .name = "4eg",
83bf2ff0 78 .evexists = 1,
494fffe7
MS
79 },
80 {
81 .id = 0x21,
82 .ver = 0x12c,
83 .name = "4cg",
84 },
47e60cbd
MS
85 {
86 .id = 0x30,
87 .name = "7ev",
83bf2ff0 88 .evexists = 1,
47e60cbd 89 },
494fffe7
MS
90 {
91 .id = 0x30,
92 .ver = 0x100,
93 .name = "7eg",
83bf2ff0 94 .evexists = 1,
494fffe7
MS
95 },
96 {
97 .id = 0x30,
98 .ver = 0x12c,
99 .name = "7cg",
100 },
47e60cbd
MS
101 {
102 .id = 0x38,
103 .name = "9eg",
104 },
494fffe7
MS
105 {
106 .id = 0x38,
107 .ver = 0x2c,
108 .name = "9cg",
109 },
47e60cbd
MS
110 {
111 .id = 0x39,
112 .name = "6eg",
113 },
494fffe7
MS
114 {
115 .id = 0x39,
116 .ver = 0x2c,
117 .name = "6cg",
118 },
47e60cbd
MS
119 {
120 .id = 0x40,
121 .name = "11eg",
122 },
494fffe7
MS
123 { /* For testing purpose only */
124 .id = 0x50,
125 .ver = 0x2c,
126 .name = "15cg",
127 },
47e60cbd
MS
128 {
129 .id = 0x50,
130 .name = "15eg",
131 },
132 {
133 .id = 0x58,
134 .name = "19eg",
135 },
136 {
137 .id = 0x59,
138 .name = "17eg",
139 },
b030fedf
MS
140 {
141 .id = 0x61,
142 .name = "21dr",
143 },
144 {
145 .id = 0x63,
146 .name = "23dr",
147 },
148 {
149 .id = 0x65,
150 .name = "25dr",
151 },
152 {
153 .id = 0x64,
154 .name = "27dr",
155 },
156 {
157 .id = 0x60,
158 .name = "28dr",
159 },
160 {
161 .id = 0x62,
162 .name = "29dr",
163 },
47e60cbd 164};
74ba69db 165#endif
47e60cbd 166
f52bf5a3 167int chip_id(unsigned char id)
47e60cbd
MS
168{
169 struct pt_regs regs;
db3123b4 170 int val = -EINVAL;
47e60cbd 171
74ba69db
SDPP
172 if (current_el() != 3) {
173 regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
174 regs.regs[1] = 0;
175 regs.regs[2] = 0;
176 regs.regs[3] = 0;
177
178 smc_call(&regs);
179
180 /*
181 * SMC returns:
182 * regs[0][31:0] = status of the operation
183 * regs[0][63:32] = CSU.IDCODE register
184 * regs[1][31:0] = CSU.version register
494fffe7 185 * regs[1][63:32] = CSU.IDCODE2 register
74ba69db
SDPP
186 */
187 switch (id) {
188 case IDCODE:
189 regs.regs[0] = upper_32_bits(regs.regs[0]);
190 regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
191 ZYNQMP_CSU_IDCODE_SVD_MASK;
192 regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
193 val = regs.regs[0];
194 break;
195 case VERSION:
196 regs.regs[1] = lower_32_bits(regs.regs[1]);
197 regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
198 val = regs.regs[1];
199 break;
494fffe7
MS
200 case IDCODE2:
201 regs.regs[1] = lower_32_bits(regs.regs[1]);
202 regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
203 val = regs.regs[1];
204 break;
74ba69db
SDPP
205 default:
206 printf("%s, Invalid Req:0x%x\n", __func__, id);
207 }
208 } else {
209 switch (id) {
210 case IDCODE:
211 val = readl(ZYNQMP_CSU_IDCODE_ADDR);
212 val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
213 ZYNQMP_CSU_IDCODE_SVD_MASK;
214 val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
215 break;
216 case VERSION:
217 val = readl(ZYNQMP_CSU_VER_ADDR);
218 val &= ZYNQMP_CSU_SILICON_VER_MASK;
219 break;
220 default:
221 printf("%s, Invalid Req:0x%x\n", __func__, id);
222 }
db3123b4 223 }
0cba6abb 224
db3123b4 225 return val;
47e60cbd
MS
226}
227
83bf2ff0
SDPP
228#define ZYNQMP_VERSION_SIZE 9
229#define ZYNQMP_PL_STATUS_BIT 9
230#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
231#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
232
74ba69db
SDPP
233#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
234 !defined(CONFIG_SPL_BUILD)
47e60cbd
MS
235static char *zynqmp_get_silicon_idcode_name(void)
236{
494fffe7 237 u32 i, id, ver;
83bf2ff0
SDPP
238 char *buf;
239 static char name[ZYNQMP_VERSION_SIZE];
47e60cbd 240
db3123b4 241 id = chip_id(IDCODE);
494fffe7
MS
242 ver = chip_id(IDCODE2);
243
47e60cbd 244 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
83bf2ff0
SDPP
245 if ((zynqmp_devices[i].id == id) &&
246 (zynqmp_devices[i].ver == (ver &
247 ZYNQMP_CSU_VERSION_MASK))) {
248 strncat(name, "zu", 2);
249 strncat(name, zynqmp_devices[i].name,
250 ZYNQMP_VERSION_SIZE - 3);
251 break;
252 }
47e60cbd 253 }
83bf2ff0
SDPP
254
255 if (i >= ARRAY_SIZE(zynqmp_devices))
256 return "unknown";
257
258 if (!zynqmp_devices[i].evexists)
259 return name;
260
261 if (ver & ZYNQMP_PL_STATUS_MASK)
262 return name;
263
264 if (strstr(name, "eg") || strstr(name, "ev")) {
265 buf = strstr(name, "e");
266 *buf = '\0';
267 }
268
269 return name;
47e60cbd
MS
270}
271#endif
272
fb4000e8
MS
273int board_early_init_f(void)
274{
f32e79f1 275 int ret = 0;
fb4000e8
MS
276#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP)
277 zynqmp_pmufw_version();
278#endif
55de0929 279
88f05a92 280#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
f32e79f1 281 ret = psu_init();
55de0929
MS
282#endif
283
f32e79f1 284 return ret;
fb4000e8
MS
285}
286
84c7204b
MS
287int board_init(void)
288{
a0736efb
MS
289 printf("EL Level:\tEL%d\n", current_el());
290
47e60cbd
MS
291#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
292 !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
293 defined(CONFIG_SPL_BUILD))
294 if (current_el() != 3) {
83bf2ff0 295 zynqmppl.name = zynqmp_get_silicon_idcode_name();
47e60cbd
MS
296 printf("Chip ID:\t%s\n", zynqmppl.name);
297 fpga_init();
298 fpga_add(fpga_xilinx, &zynqmppl);
299 }
300#endif
301
84c7204b
MS
302 return 0;
303}
304
305int board_early_init_r(void)
306{
307 u32 val;
308
ec60a279
SDPP
309 if (current_el() != 3)
310 return 0;
311
90a35db4
MS
312 val = readl(&crlapb_base->timestamp_ref_ctrl);
313 val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
314
ec60a279 315 if (!val) {
0785dfd8
MS
316 val = readl(&crlapb_base->timestamp_ref_ctrl);
317 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
318 writel(val, &crlapb_base->timestamp_ref_ctrl);
84c7204b 319
0785dfd8
MS
320 /* Program freq register in System counter */
321 writel(zynqmp_get_system_timer_freq(),
322 &iou_scntr_secure->base_frequency_id_register);
323 /* And enable system counter */
324 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
325 &iou_scntr_secure->counter_control_register);
326 }
84c7204b
MS
327 return 0;
328}
329
6919b4bf
MS
330int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
331{
332#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
333 defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
334 defined(CONFIG_ZYNQ_EEPROM_BUS)
335 i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
336
337 if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
338 CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
339 ethaddr, 6))
340 printf("I2C EEPROM MAC address read failed\n");
341#endif
342
343 return 0;
344}
345
51916864
NJ
346unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
347 char * const argv[])
348{
349 int ret = 0;
350
351 if (current_el() > 1) {
352 smp_kick_all_cpus();
353 dcache_disable();
354 armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
355 ES_TO_AARCH64);
356 } else {
357 printf("FAIL: current EL is not above EL1\n");
358 ret = EINVAL;
359 }
360 return ret;
361}
362
8d59d7f6 363#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
76b00aca 364int dram_init_banksize(void)
361a8799 365{
da3f003b 366 return fdtdec_setup_memory_banksize();
8a5db0ab 367}
8d59d7f6 368
361a8799 369int dram_init(void)
8a5db0ab 370{
950f86ca
NR
371 if (fdtdec_setup_memory_size() != 0)
372 return -EINVAL;
8a5db0ab 373
361a8799 374 return 0;
8d59d7f6
MS
375}
376#else
84c7204b
MS
377int dram_init(void)
378{
61dc92a2
MS
379 gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
380 CONFIG_SYS_SDRAM_SIZE);
84c7204b
MS
381
382 return 0;
383}
8d59d7f6 384#endif
84c7204b 385
84c7204b
MS
386void reset_cpu(ulong addr)
387{
388}
389
84c7204b
MS
390int board_late_init(void)
391{
392 u32 reg = 0;
393 u8 bootmode;
b72894f1
MS
394 const char *mode;
395 char *new_targets;
01c42d3d 396 char *env_targets;
d1db89f4 397 int ret;
b72894f1
MS
398
399 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
400 debug("Saved variables - Skipping\n");
401 return 0;
402 }
84c7204b 403
d1db89f4
SDPP
404 ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
405 if (ret)
406 return -EINVAL;
407
47359a03
MS
408 if (reg >> BOOT_MODE_ALT_SHIFT)
409 reg >>= BOOT_MODE_ALT_SHIFT;
410
84c7204b
MS
411 bootmode = reg & BOOT_MODES_MASK;
412
fb90917c 413 puts("Bootmode: ");
84c7204b 414 switch (bootmode) {
d58fc12e
MS
415 case USB_MODE:
416 puts("USB_MODE\n");
417 mode = "usb";
07656ba5 418 env_set("modeboot", "usb_dfu_spl");
d58fc12e 419 break;
0a5bcc8c 420 case JTAG_MODE:
fb90917c 421 puts("JTAG_MODE\n");
b72894f1 422 mode = "pxe dhcp";
07656ba5 423 env_set("modeboot", "jtagboot");
0a5bcc8c
SDPP
424 break;
425 case QSPI_MODE_24BIT:
426 case QSPI_MODE_32BIT:
b72894f1 427 mode = "qspi0";
fb90917c 428 puts("QSPI_MODE\n");
07656ba5 429 env_set("modeboot", "qspiboot");
0a5bcc8c 430 break;
39c56f55 431 case EMMC_MODE:
78678fee 432 puts("EMMC_MODE\n");
b72894f1 433 mode = "mmc0";
07656ba5 434 env_set("modeboot", "emmcboot");
78678fee
MS
435 break;
436 case SD_MODE:
fb90917c 437 puts("SD_MODE\n");
b72894f1 438 mode = "mmc0";
07656ba5 439 env_set("modeboot", "sdboot");
84c7204b 440 break;
e1992276
SDPP
441 case SD1_LSHFT_MODE:
442 puts("LVL_SHFT_");
443 /* fall through */
af813acd 444 case SD_MODE1:
fb90917c 445 puts("SD_MODE1\n");
2d9925bc 446#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
b72894f1 447 mode = "mmc1";
07656ba5 448 env_set("sdbootdev", "1");
b72894f1
MS
449#else
450 mode = "mmc0";
2d9925bc 451#endif
07656ba5 452 env_set("modeboot", "sdboot");
af813acd
MS
453 break;
454 case NAND_MODE:
fb90917c 455 puts("NAND_MODE\n");
b72894f1 456 mode = "nand0";
07656ba5 457 env_set("modeboot", "nandboot");
af813acd 458 break;
84c7204b 459 default:
b72894f1 460 mode = "";
84c7204b
MS
461 printf("Invalid Boot Mode:0x%x\n", bootmode);
462 break;
463 }
464
b72894f1
MS
465 /*
466 * One terminating char + one byte for space between mode
467 * and default boot_targets
468 */
01c42d3d
SDPP
469 env_targets = env_get("boot_targets");
470 if (env_targets) {
471 new_targets = calloc(1, strlen(mode) +
472 strlen(env_targets) + 2);
473 sprintf(new_targets, "%s %s", mode, env_targets);
474 } else {
475 new_targets = calloc(1, strlen(mode) + 2);
476 sprintf(new_targets, "%s", mode);
477 }
b72894f1 478
382bee57 479 env_set("boot_targets", new_targets);
b72894f1 480
84c7204b
MS
481 return 0;
482}
84696ff5
SDPP
483
484int checkboard(void)
485{
5af08556 486 puts("Board: Xilinx ZynqMP\n");
84696ff5
SDPP
487 return 0;
488}
16fa00a7
SDPP
489
490#ifdef CONFIG_USB_DWC3
275bd6d1 491static struct dwc3_device dwc3_device_data0 = {
16fa00a7
SDPP
492 .maximum_speed = USB_SPEED_HIGH,
493 .base = ZYNQMP_USB0_XHCI_BASEADDR,
494 .dr_mode = USB_DR_MODE_PERIPHERAL,
495 .index = 0,
496};
497
275bd6d1
MS
498static struct dwc3_device dwc3_device_data1 = {
499 .maximum_speed = USB_SPEED_HIGH,
500 .base = ZYNQMP_USB1_XHCI_BASEADDR,
501 .dr_mode = USB_DR_MODE_PERIPHERAL,
502 .index = 1,
503};
504
9feff385 505int usb_gadget_handle_interrupts(int index)
16fa00a7 506{
9feff385 507 dwc3_uboot_handle_interrupt(index);
16fa00a7
SDPP
508 return 0;
509}
510
511int board_usb_init(int index, enum usb_init_type init)
512{
275bd6d1
MS
513 debug("%s: index %x\n", __func__, index);
514
8ecd50c8
MS
515#if defined(CONFIG_USB_GADGET_DOWNLOAD)
516 g_dnl_set_serialnumber(CONFIG_SYS_CONFIG_NAME);
517#endif
518
275bd6d1
MS
519 switch (index) {
520 case 0:
521 return dwc3_uboot_init(&dwc3_device_data0);
522 case 1:
523 return dwc3_uboot_init(&dwc3_device_data1);
524 };
525
526 return -1;
16fa00a7
SDPP
527}
528
529int board_usb_cleanup(int index, enum usb_init_type init)
530{
531 dwc3_uboot_exit(index);
532 return 0;
533}
534#endif