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