blob: 566b5e8d2afa4915bb13b6754ef43b323a1240d5 [file] [log] [blame]
Michal Simek04b7e622015-01-15 10:01:51 +01001/*
2 * (C) Copyright 2014 - 2015 Xilinx, Inc.
3 * Michal Simek <michal.simek@xilinx.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
Michal Simekd54b1af2015-09-30 17:26:55 +02009#include <sata.h>
Michal Simekb216cc12015-07-23 13:27:40 +020010#include <ahci.h>
11#include <scsi.h>
Michal Simekecfb6dc2016-04-22 14:28:54 +020012#include <malloc.h>
Michal Simekc23d3f82015-11-05 08:34:35 +010013#include <asm/arch/clk.h>
Michal Simek04b7e622015-01-15 10:01:51 +010014#include <asm/arch/hardware.h>
15#include <asm/arch/sys_proto.h>
16#include <asm/io.h>
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +053017#include <usb.h>
18#include <dwc3-uboot.h>
Michal Simek8111aff2016-02-01 15:05:58 +010019#include <zynqmppl.h>
Michal Simekeec32f62016-04-22 11:48:49 +020020#include <i2c.h>
Michal Simek76d0a772016-09-01 11:16:40 +020021#include <g_dnl.h>
Michal Simek04b7e622015-01-15 10:01:51 +010022
23DECLARE_GLOBAL_DATA_PTR;
24
Michal Simek8111aff2016-02-01 15:05:58 +010025#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
26 !defined(CONFIG_SPL_BUILD)
27static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
28
29static const struct {
30 uint32_t id;
31 char *name;
32} zynqmp_devices[] = {
33 {
34 .id = 0x10,
35 .name = "3eg",
36 },
37 {
38 .id = 0x11,
39 .name = "2eg",
40 },
41 {
42 .id = 0x20,
43 .name = "5ev",
44 },
45 {
46 .id = 0x21,
47 .name = "4ev",
48 },
49 {
50 .id = 0x30,
51 .name = "7ev",
52 },
53 {
54 .id = 0x38,
55 .name = "9eg",
56 },
57 {
58 .id = 0x39,
59 .name = "6eg",
60 },
61 {
62 .id = 0x40,
63 .name = "11eg",
64 },
65 {
66 .id = 0x50,
67 .name = "15eg",
68 },
69 {
70 .id = 0x58,
71 .name = "19eg",
72 },
73 {
74 .id = 0x59,
75 .name = "17eg",
76 },
77};
78
79static int chip_id(void)
80{
81 struct pt_regs regs;
82 regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
83 regs.regs[1] = 0;
84 regs.regs[2] = 0;
85 regs.regs[3] = 0;
86
87 smc_call(&regs);
88
89 return regs.regs[0];
90}
91
92static char *zynqmp_get_silicon_idcode_name(void)
93{
94 uint32_t i, id;
95
96 id = chip_id();
97 for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
98 if (zynqmp_devices[i].id == id)
99 return zynqmp_devices[i].name;
100 }
101 return "unknown";
102}
103#endif
104
105#define ZYNQMP_VERSION_SIZE 9
106
Michal Simek04b7e622015-01-15 10:01:51 +0100107int board_init(void)
108{
Michal Simekfb7242d2015-06-22 14:31:06 +0200109 printf("EL Level:\tEL%d\n", current_el());
110
Michal Simek8111aff2016-02-01 15:05:58 +0100111#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
112 !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
113 defined(CONFIG_SPL_BUILD))
114 if (current_el() != 3) {
115 static char version[ZYNQMP_VERSION_SIZE];
116
117 strncat(version, "xczu", ZYNQMP_VERSION_SIZE);
118 zynqmppl.name = strncat(version,
119 zynqmp_get_silicon_idcode_name(),
120 ZYNQMP_VERSION_SIZE);
121 printf("Chip ID:\t%s\n", zynqmppl.name);
122 fpga_init();
123 fpga_add(fpga_xilinx, &zynqmppl);
124 }
125#endif
126
Michal Simek04b7e622015-01-15 10:01:51 +0100127 return 0;
128}
129
130int board_early_init_r(void)
131{
132 u32 val;
133
Michal Simekc23d3f82015-11-05 08:34:35 +0100134 if (current_el() == 3) {
135 val = readl(&crlapb_base->timestamp_ref_ctrl);
136 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
137 writel(val, &crlapb_base->timestamp_ref_ctrl);
Michal Simek04b7e622015-01-15 10:01:51 +0100138
Michal Simekc23d3f82015-11-05 08:34:35 +0100139 /* Program freq register in System counter */
140 writel(zynqmp_get_system_timer_freq(),
141 &iou_scntr_secure->base_frequency_id_register);
142 /* And enable system counter */
143 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
144 &iou_scntr_secure->counter_control_register);
145 }
Michal Simek04b7e622015-01-15 10:01:51 +0100146 /* Program freq register in System counter and enable system counter */
147 writel(gd->cpu_clk, &iou_scntr->base_frequency_id_register);
148 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_HDBG |
149 ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
150 &iou_scntr->counter_control_register);
151
152 return 0;
153}
154
Michal Simekeec32f62016-04-22 11:48:49 +0200155int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
156{
157#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
158 defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
159 defined(CONFIG_ZYNQ_EEPROM_BUS)
160 i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
161
162 if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
163 CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
164 ethaddr, 6))
165 printf("I2C EEPROM MAC address read failed\n");
166#endif
167
168 return 0;
169}
170
Michal Simek8faa66a2016-02-08 09:34:53 +0100171#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
172/*
173 * fdt_get_reg - Fill buffer by information from DT
174 */
175static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
176 const u32 *cell, int n)
177{
178 int i = 0, b, banks;
179 int parent_offset = fdt_parent_offset(fdt, nodeoffset);
180 int address_cells = fdt_address_cells(fdt, parent_offset);
181 int size_cells = fdt_size_cells(fdt, parent_offset);
182 char *p = buf;
Michal Simeka8c0bf32016-04-01 15:55:47 +0200183 u64 val;
184 u64 vals;
Michal Simek8faa66a2016-02-08 09:34:53 +0100185
186 debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
187 __func__, address_cells, size_cells, buf, cell);
188
189 /* Check memory bank setup */
190 banks = n % (address_cells + size_cells);
191 if (banks)
192 panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
193 n, address_cells, size_cells);
194
195 banks = n / (address_cells + size_cells);
196
197 for (b = 0; b < banks; b++) {
198 debug("%s: Bank #%d:\n", __func__, b);
199 if (address_cells == 2) {
200 val = cell[i + 1];
201 val <<= 32;
202 val |= cell[i];
203 val = fdt64_to_cpu(val);
204 debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
205 __func__, val, p, &cell[i]);
206 *(phys_addr_t *)p = val;
207 } else {
208 debug("%s: addr32=%x, ptr=%p\n",
209 __func__, fdt32_to_cpu(cell[i]), p);
210 *(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
211 }
212 p += sizeof(phys_addr_t);
213 i += address_cells;
214
215 debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
216 sizeof(phys_addr_t));
217
218 if (size_cells == 2) {
219 vals = cell[i + 1];
220 vals <<= 32;
221 vals |= cell[i];
222 vals = fdt64_to_cpu(vals);
223
224 debug("%s: size64=%llx, ptr=%p, cell=%p\n",
225 __func__, vals, p, &cell[i]);
226 *(phys_size_t *)p = vals;
227 } else {
228 debug("%s: size32=%x, ptr=%p\n",
229 __func__, fdt32_to_cpu(cell[i]), p);
230 *(phys_size_t *)p = fdt32_to_cpu(cell[i]);
231 }
232 p += sizeof(phys_size_t);
233 i += size_cells;
234
235 debug("%s: ps=%p, i=%x, size=%zu\n",
236 __func__, p, i, sizeof(phys_size_t));
237 }
238
239 /* Return the first address size */
240 return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
241}
242
243#define FDT_REG_SIZE sizeof(u32)
244/* Temp location for sharing data for storing */
245/* Up to 64-bit address + 64-bit size */
246static u8 tmp[CONFIG_NR_DRAM_BANKS * 16];
247
248void dram_init_banksize(void)
249{
250 int bank;
251
252 memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
253
254 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
255 debug("Bank #%d: start %llx\n", bank,
256 (unsigned long long)gd->bd->bi_dram[bank].start);
257 debug("Bank #%d: size %llx\n", bank,
258 (unsigned long long)gd->bd->bi_dram[bank].size);
259 }
260}
261
262int dram_init(void)
263{
264 int node, len;
265 const void *blob = gd->fdt_blob;
266 const u32 *cell;
267
268 memset(&tmp, 0, sizeof(tmp));
269
270 /* find or create "/memory" node. */
271 node = fdt_subnode_offset(blob, 0, "memory");
272 if (node < 0) {
273 printf("%s: Can't get memory node\n", __func__);
274 return node;
275 }
276
277 /* Get pointer to cells and lenght of it */
278 cell = fdt_getprop(blob, node, "reg", &len);
279 if (!cell) {
280 printf("%s: Can't get reg property\n", __func__);
281 return -1;
282 }
283
284 gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
285
Michal Simeka8c0bf32016-04-01 15:55:47 +0200286 debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
Michal Simek8faa66a2016-02-08 09:34:53 +0100287
288 return 0;
289}
290#else
Michal Simek04b7e622015-01-15 10:01:51 +0100291int dram_init(void)
292{
293 gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
294
295 return 0;
296}
Michal Simek8faa66a2016-02-08 09:34:53 +0100297#endif
Michal Simek04b7e622015-01-15 10:01:51 +0100298
Michal Simek04b7e622015-01-15 10:01:51 +0100299void reset_cpu(ulong addr)
300{
301}
302
Michal Simekb216cc12015-07-23 13:27:40 +0200303#ifdef CONFIG_SCSI_AHCI_PLAT
304void scsi_init(void)
305{
Michal Simekd54b1af2015-09-30 17:26:55 +0200306#if defined(CONFIG_SATA_CEVA)
307 init_sata(0);
308#endif
Michal Simekb216cc12015-07-23 13:27:40 +0200309 ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR);
310 scsi_scan(1);
311}
312#endif
313
Michal Simek04b7e622015-01-15 10:01:51 +0100314int board_late_init(void)
315{
316 u32 reg = 0;
317 u8 bootmode;
Michal Simekecfb6dc2016-04-22 14:28:54 +0200318 const char *mode;
319 char *new_targets;
320
321 if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
322 debug("Saved variables - Skipping\n");
323 return 0;
324 }
Michal Simek04b7e622015-01-15 10:01:51 +0100325
326 reg = readl(&crlapb_base->boot_mode);
327 bootmode = reg & BOOT_MODES_MASK;
328
Michal Simekc5d95232015-09-20 17:20:42 +0200329 puts("Bootmode: ");
Michal Simek04b7e622015-01-15 10:01:51 +0100330 switch (bootmode) {
Michal Simek12398ea2016-08-19 14:14:52 +0200331 case USB_MODE:
332 puts("USB_MODE\n");
333 mode = "usb";
334 break;
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530335 case JTAG_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200336 puts("JTAG_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200337 mode = "pxe dhcp";
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530338 break;
339 case QSPI_MODE_24BIT:
340 case QSPI_MODE_32BIT:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200341 mode = "qspi0";
Michal Simekc5d95232015-09-20 17:20:42 +0200342 puts("QSPI_MODE\n");
Siva Durga Prasad Paladugu30f0fc72015-03-13 11:10:26 +0530343 break;
Michal Simek02d66cd2015-04-15 15:02:28 +0200344 case EMMC_MODE:
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200345 puts("EMMC_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200346 mode = "mmc0";
Michal Simekdf7ff0a2015-10-05 15:59:38 +0200347 break;
348 case SD_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200349 puts("SD_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200350 mode = "mmc0";
Michal Simek04b7e622015-01-15 10:01:51 +0100351 break;
Michal Simek108e1842015-10-05 10:51:12 +0200352 case SD_MODE1:
Michal Simekc5d95232015-09-20 17:20:42 +0200353 puts("SD_MODE1\n");
Michal Simek6d902452015-11-06 10:22:37 +0100354#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
Michal Simekecfb6dc2016-04-22 14:28:54 +0200355 mode = "mmc1";
356#else
357 mode = "mmc0";
Michal Simek6d902452015-11-06 10:22:37 +0100358#endif
Michal Simek108e1842015-10-05 10:51:12 +0200359 break;
360 case NAND_MODE:
Michal Simekc5d95232015-09-20 17:20:42 +0200361 puts("NAND_MODE\n");
Michal Simekecfb6dc2016-04-22 14:28:54 +0200362 mode = "nand0";
Michal Simek108e1842015-10-05 10:51:12 +0200363 break;
Michal Simek04b7e622015-01-15 10:01:51 +0100364 default:
Michal Simekecfb6dc2016-04-22 14:28:54 +0200365 mode = "";
Michal Simek04b7e622015-01-15 10:01:51 +0100366 printf("Invalid Boot Mode:0x%x\n", bootmode);
367 break;
368 }
369
Michal Simekecfb6dc2016-04-22 14:28:54 +0200370 /*
371 * One terminating char + one byte for space between mode
372 * and default boot_targets
373 */
374 new_targets = calloc(1, strlen(mode) +
375 strlen(getenv("boot_targets")) + 2);
376
377 sprintf(new_targets, "%s %s", mode, getenv("boot_targets"));
378 setenv("boot_targets", new_targets);
379
Michal Simek04b7e622015-01-15 10:01:51 +0100380 return 0;
381}
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530382
383int checkboard(void)
384{
Michal Simek47ce9362016-01-25 11:04:21 +0100385 puts("Board: Xilinx ZynqMP\n");
Siva Durga Prasad Paladugu650e0a32015-08-04 13:01:05 +0530386 return 0;
387}
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +0530388
389#ifdef CONFIG_USB_DWC3
Michal Simekea526be2016-08-08 10:11:26 +0200390static struct dwc3_device dwc3_device_data0 = {
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +0530391 .maximum_speed = USB_SPEED_HIGH,
392 .base = ZYNQMP_USB0_XHCI_BASEADDR,
393 .dr_mode = USB_DR_MODE_PERIPHERAL,
394 .index = 0,
395};
396
Michal Simekea526be2016-08-08 10:11:26 +0200397static struct dwc3_device dwc3_device_data1 = {
398 .maximum_speed = USB_SPEED_HIGH,
399 .base = ZYNQMP_USB1_XHCI_BASEADDR,
400 .dr_mode = USB_DR_MODE_PERIPHERAL,
401 .index = 1,
402};
403
Michal Simek76d0a772016-09-01 11:16:40 +0200404int usb_gadget_handle_interrupts(int index)
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +0530405{
Michal Simek76d0a772016-09-01 11:16:40 +0200406 dwc3_uboot_handle_interrupt(index);
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +0530407 return 0;
408}
409
410int board_usb_init(int index, enum usb_init_type init)
411{
Michal Simekea526be2016-08-08 10:11:26 +0200412 debug("%s: index %x\n", __func__, index);
413
414 switch (index) {
415 case 0:
416 return dwc3_uboot_init(&dwc3_device_data0);
417 case 1:
418 return dwc3_uboot_init(&dwc3_device_data1);
419 };
420
421 return -1;
Siva Durga Prasad Paladuguba1f68e2015-08-04 13:03:26 +0530422}
423
424int board_usb_cleanup(int index, enum usb_init_type init)
425{
426 dwc3_uboot_exit(index);
427 return 0;
428}
429#endif
Michal Simek6a900952016-07-27 13:40:19 +0200430
431void reset_misc(void)
432{
433 psci_system_reset(true);
434}