]> git.sur5r.net Git - u-boot/blob - board/xilinx/zynqmp/zynqmp.c
ARM64: zynqmp: Add support for DFU from SPL
[u-boot] / board / xilinx / zynqmp / zynqmp.c
1 /*
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>
9 #include <sata.h>
10 #include <ahci.h>
11 #include <scsi.h>
12 #include <malloc.h>
13 #include <asm/arch/clk.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/arch/sys_proto.h>
16 #include <asm/io.h>
17 #include <usb.h>
18 #include <dwc3-uboot.h>
19 #include <i2c.h>
20 #include <g_dnl.h>
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 int board_init(void)
25 {
26         printf("EL Level:\tEL%d\n", current_el());
27
28         return 0;
29 }
30
31 int board_early_init_r(void)
32 {
33         u32 val;
34
35         if (current_el() == 3) {
36                 val = readl(&crlapb_base->timestamp_ref_ctrl);
37                 val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
38                 writel(val, &crlapb_base->timestamp_ref_ctrl);
39
40                 /* Program freq register in System counter */
41                 writel(zynqmp_get_system_timer_freq(),
42                        &iou_scntr_secure->base_frequency_id_register);
43                 /* And enable system counter */
44                 writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
45                        &iou_scntr_secure->counter_control_register);
46         }
47         /* Program freq register in System counter and enable system counter */
48         writel(gd->cpu_clk, &iou_scntr->base_frequency_id_register);
49         writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_HDBG |
50                ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
51                &iou_scntr->counter_control_register);
52
53         return 0;
54 }
55
56 int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
57 {
58 #if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
59     defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
60     defined(CONFIG_ZYNQ_EEPROM_BUS)
61         i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
62
63         if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
64                         CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
65                         ethaddr, 6))
66                 printf("I2C EEPROM MAC address read failed\n");
67 #endif
68
69         return 0;
70 }
71
72 #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
73 /*
74  * fdt_get_reg - Fill buffer by information from DT
75  */
76 static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
77                                const u32 *cell, int n)
78 {
79         int i = 0, b, banks;
80         int parent_offset = fdt_parent_offset(fdt, nodeoffset);
81         int address_cells = fdt_address_cells(fdt, parent_offset);
82         int size_cells = fdt_size_cells(fdt, parent_offset);
83         char *p = buf;
84         u64 val;
85         u64 vals;
86
87         debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
88               __func__, address_cells, size_cells, buf, cell);
89
90         /* Check memory bank setup */
91         banks = n % (address_cells + size_cells);
92         if (banks)
93                 panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
94                       n, address_cells, size_cells);
95
96         banks = n / (address_cells + size_cells);
97
98         for (b = 0; b < banks; b++) {
99                 debug("%s: Bank #%d:\n", __func__, b);
100                 if (address_cells == 2) {
101                         val = cell[i + 1];
102                         val <<= 32;
103                         val |= cell[i];
104                         val = fdt64_to_cpu(val);
105                         debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
106                               __func__, val, p, &cell[i]);
107                         *(phys_addr_t *)p = val;
108                 } else {
109                         debug("%s: addr32=%x, ptr=%p\n",
110                               __func__, fdt32_to_cpu(cell[i]), p);
111                         *(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
112                 }
113                 p += sizeof(phys_addr_t);
114                 i += address_cells;
115
116                 debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
117                       sizeof(phys_addr_t));
118
119                 if (size_cells == 2) {
120                         vals = cell[i + 1];
121                         vals <<= 32;
122                         vals |= cell[i];
123                         vals = fdt64_to_cpu(vals);
124
125                         debug("%s: size64=%llx, ptr=%p, cell=%p\n",
126                               __func__, vals, p, &cell[i]);
127                         *(phys_size_t *)p = vals;
128                 } else {
129                         debug("%s: size32=%x, ptr=%p\n",
130                               __func__, fdt32_to_cpu(cell[i]), p);
131                         *(phys_size_t *)p = fdt32_to_cpu(cell[i]);
132                 }
133                 p += sizeof(phys_size_t);
134                 i += size_cells;
135
136                 debug("%s: ps=%p, i=%x, size=%zu\n",
137                       __func__, p, i, sizeof(phys_size_t));
138         }
139
140         /* Return the first address size */
141         return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
142 }
143
144 #define FDT_REG_SIZE  sizeof(u32)
145 /* Temp location for sharing data for storing */
146 /* Up to 64-bit address + 64-bit size */
147 static u8 tmp[CONFIG_NR_DRAM_BANKS * 16];
148
149 void dram_init_banksize(void)
150 {
151         int bank;
152
153         memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
154
155         for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
156                 debug("Bank #%d: start %llx\n", bank,
157                       (unsigned long long)gd->bd->bi_dram[bank].start);
158                 debug("Bank #%d: size %llx\n", bank,
159                       (unsigned long long)gd->bd->bi_dram[bank].size);
160         }
161 }
162
163 int dram_init(void)
164 {
165         int node, len;
166         const void *blob = gd->fdt_blob;
167         const u32 *cell;
168
169         memset(&tmp, 0, sizeof(tmp));
170
171         /* find or create "/memory" node. */
172         node = fdt_subnode_offset(blob, 0, "memory");
173         if (node < 0) {
174                 printf("%s: Can't get memory node\n", __func__);
175                 return node;
176         }
177
178         /* Get pointer to cells and lenght of it */
179         cell = fdt_getprop(blob, node, "reg", &len);
180         if (!cell) {
181                 printf("%s: Can't get reg property\n", __func__);
182                 return -1;
183         }
184
185         gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
186
187         debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
188
189         return 0;
190 }
191 #else
192 int dram_init(void)
193 {
194         gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
195
196         return 0;
197 }
198 #endif
199
200 void reset_cpu(ulong addr)
201 {
202 }
203
204 #ifdef CONFIG_SCSI_AHCI_PLAT
205 void scsi_init(void)
206 {
207 #if defined(CONFIG_SATA_CEVA)
208         init_sata(0);
209 #endif
210         ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR);
211         scsi_scan(1);
212 }
213 #endif
214
215 int board_late_init(void)
216 {
217         u32 reg = 0;
218         u8 bootmode;
219         const char *mode;
220         char *new_targets;
221
222         if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
223                 debug("Saved variables - Skipping\n");
224                 return 0;
225         }
226
227         reg = readl(&crlapb_base->boot_mode);
228         bootmode = reg & BOOT_MODES_MASK;
229
230         puts("Bootmode: ");
231         switch (bootmode) {
232         case USB_MODE:
233                 puts("USB_MODE\n");
234                 mode = "usb";
235                 break;
236         case JTAG_MODE:
237                 puts("JTAG_MODE\n");
238                 mode = "pxe dhcp";
239                 break;
240         case QSPI_MODE_24BIT:
241         case QSPI_MODE_32BIT:
242                 mode = "qspi0";
243                 puts("QSPI_MODE\n");
244                 break;
245         case EMMC_MODE:
246                 puts("EMMC_MODE\n");
247                 mode = "mmc0";
248                 break;
249         case SD_MODE:
250                 puts("SD_MODE\n");
251                 mode = "mmc0";
252                 break;
253         case SD_MODE1:
254                 puts("SD_MODE1\n");
255 #if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
256                 mode = "mmc1";
257 #else
258                 mode = "mmc0";
259 #endif
260                 break;
261         case NAND_MODE:
262                 puts("NAND_MODE\n");
263                 mode = "nand0";
264                 break;
265         default:
266                 mode = "";
267                 printf("Invalid Boot Mode:0x%x\n", bootmode);
268                 break;
269         }
270
271         /*
272          * One terminating char + one byte for space between mode
273          * and default boot_targets
274          */
275         new_targets = calloc(1, strlen(mode) +
276                                 strlen(getenv("boot_targets")) + 2);
277
278         sprintf(new_targets, "%s %s", mode, getenv("boot_targets"));
279         setenv("boot_targets", new_targets);
280
281         return 0;
282 }
283
284 int checkboard(void)
285 {
286         puts("Board: Xilinx ZynqMP\n");
287         return 0;
288 }
289
290 #ifdef CONFIG_USB_DWC3
291 static struct dwc3_device dwc3_device_data0 = {
292         .maximum_speed = USB_SPEED_HIGH,
293         .base = ZYNQMP_USB0_XHCI_BASEADDR,
294         .dr_mode = USB_DR_MODE_PERIPHERAL,
295         .index = 0,
296 };
297
298 static struct dwc3_device dwc3_device_data1 = {
299         .maximum_speed = USB_SPEED_HIGH,
300         .base = ZYNQMP_USB1_XHCI_BASEADDR,
301         .dr_mode = USB_DR_MODE_PERIPHERAL,
302         .index = 1,
303 };
304
305 int usb_gadget_handle_interrupts(int index)
306 {
307         dwc3_uboot_handle_interrupt(index);
308         return 0;
309 }
310
311 int board_usb_init(int index, enum usb_init_type init)
312 {
313         debug("%s: index %x\n", __func__, index);
314
315         switch (index) {
316         case 0:
317                 return dwc3_uboot_init(&dwc3_device_data0);
318         case 1:
319                 return dwc3_uboot_init(&dwc3_device_data1);
320         };
321
322         return -1;
323 }
324
325 int board_usb_cleanup(int index, enum usb_init_type init)
326 {
327         dwc3_uboot_exit(index);
328         return 0;
329 }
330 #endif
331
332 void reset_misc(void)
333 {
334         psci_system_reset(true);
335 }