]>
Commit | Line | Data |
---|---|---|
31cbf933 JCD |
1 | /* |
2 | * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net> | |
3 | * | |
4 | * i.MX6UL SOC emulation. | |
5 | * | |
6 | * Based on hw/arm/fsl-imx7.c | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | */ | |
18 | ||
19 | #include "qemu/osdep.h" | |
20 | #include "qapi/error.h" | |
31cbf933 JCD |
21 | #include "hw/arm/fsl-imx6ul.h" |
22 | #include "hw/misc/unimp.h" | |
17372bd8 | 23 | #include "hw/usb/imx-usb-phy.h" |
cc7d44c2 | 24 | #include "hw/boards.h" |
31cbf933 JCD |
25 | #include "sysemu/sysemu.h" |
26 | #include "qemu/error-report.h" | |
0b8fa32f | 27 | #include "qemu/module.h" |
31cbf933 JCD |
28 | |
29 | #define NAME_SIZE 20 | |
30 | ||
31 | static void fsl_imx6ul_init(Object *obj) | |
32 | { | |
33 | FslIMX6ULState *s = FSL_IMX6UL(obj); | |
34 | char name[NAME_SIZE]; | |
35 | int i; | |
36 | ||
bc8c2ecf | 37 | object_initialize_child(obj, "cpu0", &s->cpu, sizeof(s->cpu), |
8a863c81 | 38 | ARM_CPU_TYPE_NAME("cortex-a7"), &error_abort, NULL); |
31cbf933 JCD |
39 | |
40 | /* | |
41 | * A7MPCORE | |
42 | */ | |
43 | sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, sizeof(s->a7mpcore), | |
44 | TYPE_A15MPCORE_PRIV); | |
45 | ||
46 | /* | |
47 | * CCM | |
48 | */ | |
49 | sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX6UL_CCM); | |
50 | ||
51 | /* | |
52 | * SRC | |
53 | */ | |
54 | sysbus_init_child_obj(obj, "src", &s->src, sizeof(s->src), TYPE_IMX6_SRC); | |
55 | ||
56 | /* | |
57 | * GPCv2 | |
58 | */ | |
59 | sysbus_init_child_obj(obj, "gpcv2", &s->gpcv2, sizeof(s->gpcv2), | |
60 | TYPE_IMX_GPCV2); | |
61 | ||
62 | /* | |
63 | * SNVS | |
64 | */ | |
65 | sysbus_init_child_obj(obj, "snvs", &s->snvs, sizeof(s->snvs), | |
66 | TYPE_IMX7_SNVS); | |
67 | ||
68 | /* | |
69 | * GPR | |
70 | */ | |
71 | sysbus_init_child_obj(obj, "gpr", &s->gpr, sizeof(s->gpr), | |
72 | TYPE_IMX7_GPR); | |
73 | ||
74 | /* | |
75 | * GPIOs 1 to 5 | |
76 | */ | |
77 | for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) { | |
78 | snprintf(name, NAME_SIZE, "gpio%d", i); | |
79 | sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]), | |
80 | TYPE_IMX_GPIO); | |
81 | } | |
82 | ||
83 | /* | |
84 | * GPT 1, 2 | |
85 | */ | |
86 | for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) { | |
87 | snprintf(name, NAME_SIZE, "gpt%d", i); | |
88 | sysbus_init_child_obj(obj, name, &s->gpt[i], sizeof(s->gpt[i]), | |
89 | TYPE_IMX7_GPT); | |
90 | } | |
91 | ||
92 | /* | |
93 | * EPIT 1, 2 | |
94 | */ | |
95 | for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) { | |
96 | snprintf(name, NAME_SIZE, "epit%d", i + 1); | |
97 | sysbus_init_child_obj(obj, name, &s->epit[i], sizeof(s->epit[i]), | |
98 | TYPE_IMX_EPIT); | |
99 | } | |
100 | ||
101 | /* | |
102 | * eCSPI | |
103 | */ | |
104 | for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) { | |
105 | snprintf(name, NAME_SIZE, "spi%d", i + 1); | |
106 | sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]), | |
107 | TYPE_IMX_SPI); | |
108 | } | |
109 | ||
110 | /* | |
111 | * I2C | |
112 | */ | |
113 | for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) { | |
114 | snprintf(name, NAME_SIZE, "i2c%d", i + 1); | |
115 | sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]), | |
116 | TYPE_IMX_I2C); | |
117 | } | |
118 | ||
119 | /* | |
120 | * UART | |
121 | */ | |
122 | for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) { | |
123 | snprintf(name, NAME_SIZE, "uart%d", i); | |
124 | sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]), | |
125 | TYPE_IMX_SERIAL); | |
126 | } | |
127 | ||
128 | /* | |
129 | * Ethernet | |
130 | */ | |
131 | for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) { | |
132 | snprintf(name, NAME_SIZE, "eth%d", i); | |
133 | sysbus_init_child_obj(obj, name, &s->eth[i], sizeof(s->eth[i]), | |
134 | TYPE_IMX_ENET); | |
135 | } | |
136 | ||
17372bd8 GR |
137 | /* USB */ |
138 | for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) { | |
139 | snprintf(name, NAME_SIZE, "usbphy%d", i); | |
140 | sysbus_init_child_obj(obj, name, &s->usbphy[i], sizeof(s->usbphy[i]), | |
141 | TYPE_IMX_USBPHY); | |
142 | } | |
143 | for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) { | |
144 | snprintf(name, NAME_SIZE, "usb%d", i); | |
145 | sysbus_init_child_obj(obj, name, &s->usb[i], sizeof(s->usb[i]), | |
146 | TYPE_CHIPIDEA); | |
147 | } | |
148 | ||
31cbf933 JCD |
149 | /* |
150 | * SDHCI | |
151 | */ | |
152 | for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) { | |
153 | snprintf(name, NAME_SIZE, "usdhc%d", i); | |
154 | sysbus_init_child_obj(obj, name, &s->usdhc[i], sizeof(s->usdhc[i]), | |
155 | TYPE_IMX_USDHC); | |
156 | } | |
157 | ||
158 | /* | |
159 | * Watchdog | |
160 | */ | |
161 | for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) { | |
162 | snprintf(name, NAME_SIZE, "wdt%d", i); | |
163 | sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]), | |
164 | TYPE_IMX2_WDT); | |
165 | } | |
166 | } | |
167 | ||
168 | static void fsl_imx6ul_realize(DeviceState *dev, Error **errp) | |
169 | { | |
cc7d44c2 | 170 | MachineState *ms = MACHINE(qdev_get_machine()); |
31cbf933 JCD |
171 | FslIMX6ULState *s = FSL_IMX6UL(dev); |
172 | int i; | |
31cbf933 | 173 | char name[NAME_SIZE]; |
bc8c2ecf PM |
174 | SysBusDevice *sbd; |
175 | DeviceState *d; | |
31cbf933 | 176 | |
bc8c2ecf PM |
177 | if (ms->smp.cpus > 1) { |
178 | error_setg(errp, "%s: Only a single CPU is supported (%d requested)", | |
179 | TYPE_FSL_IMX6UL, ms->smp.cpus); | |
31cbf933 JCD |
180 | return; |
181 | } | |
182 | ||
bc8c2ecf PM |
183 | object_property_set_int(OBJECT(&s->cpu), QEMU_PSCI_CONDUIT_SMC, |
184 | "psci-conduit", &error_abort); | |
185 | object_property_set_bool(OBJECT(&s->cpu), true, | |
186 | "realized", &error_abort); | |
31cbf933 JCD |
187 | |
188 | /* | |
189 | * A7MPCORE | |
190 | */ | |
bc8c2ecf | 191 | object_property_set_int(OBJECT(&s->a7mpcore), 1, "num-cpu", &error_abort); |
31cbf933 JCD |
192 | object_property_set_int(OBJECT(&s->a7mpcore), |
193 | FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL, | |
194 | "num-irq", &error_abort); | |
195 | object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", | |
196 | &error_abort); | |
197 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR); | |
198 | ||
bc8c2ecf PM |
199 | sbd = SYS_BUS_DEVICE(&s->a7mpcore); |
200 | d = DEVICE(&s->cpu); | |
201 | ||
202 | sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(d, ARM_CPU_IRQ)); | |
203 | sysbus_connect_irq(sbd, 1, qdev_get_gpio_in(d, ARM_CPU_FIQ)); | |
204 | sysbus_connect_irq(sbd, 2, qdev_get_gpio_in(d, ARM_CPU_VIRQ)); | |
205 | sysbus_connect_irq(sbd, 3, qdev_get_gpio_in(d, ARM_CPU_VFIQ)); | |
31cbf933 JCD |
206 | |
207 | /* | |
208 | * A7MPCORE DAP | |
209 | */ | |
210 | create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR, | |
211 | 0x100000); | |
212 | ||
213 | /* | |
214 | * GPT 1, 2 | |
215 | */ | |
216 | for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) { | |
217 | static const hwaddr FSL_IMX6UL_GPTn_ADDR[FSL_IMX6UL_NUM_GPTS] = { | |
218 | FSL_IMX6UL_GPT1_ADDR, | |
219 | FSL_IMX6UL_GPT2_ADDR, | |
220 | }; | |
221 | ||
222 | static const int FSL_IMX6UL_GPTn_IRQ[FSL_IMX6UL_NUM_GPTS] = { | |
223 | FSL_IMX6UL_GPT1_IRQ, | |
224 | FSL_IMX6UL_GPT2_IRQ, | |
225 | }; | |
226 | ||
227 | s->gpt[i].ccm = IMX_CCM(&s->ccm); | |
228 | object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", | |
229 | &error_abort); | |
230 | ||
231 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, | |
232 | FSL_IMX6UL_GPTn_ADDR[i]); | |
233 | ||
234 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0, | |
235 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
236 | FSL_IMX6UL_GPTn_IRQ[i])); | |
237 | } | |
238 | ||
239 | /* | |
240 | * EPIT 1, 2 | |
241 | */ | |
242 | for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) { | |
243 | static const hwaddr FSL_IMX6UL_EPITn_ADDR[FSL_IMX6UL_NUM_EPITS] = { | |
244 | FSL_IMX6UL_EPIT1_ADDR, | |
245 | FSL_IMX6UL_EPIT2_ADDR, | |
246 | }; | |
247 | ||
248 | static const int FSL_IMX6UL_EPITn_IRQ[FSL_IMX6UL_NUM_EPITS] = { | |
249 | FSL_IMX6UL_EPIT1_IRQ, | |
250 | FSL_IMX6UL_EPIT2_IRQ, | |
251 | }; | |
252 | ||
253 | s->epit[i].ccm = IMX_CCM(&s->ccm); | |
254 | object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", | |
255 | &error_abort); | |
256 | ||
257 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, | |
258 | FSL_IMX6UL_EPITn_ADDR[i]); | |
259 | ||
260 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0, | |
261 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
262 | FSL_IMX6UL_EPITn_IRQ[i])); | |
263 | } | |
264 | ||
265 | /* | |
266 | * GPIO | |
267 | */ | |
268 | for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) { | |
269 | static const hwaddr FSL_IMX6UL_GPIOn_ADDR[FSL_IMX6UL_NUM_GPIOS] = { | |
270 | FSL_IMX6UL_GPIO1_ADDR, | |
271 | FSL_IMX6UL_GPIO2_ADDR, | |
272 | FSL_IMX6UL_GPIO3_ADDR, | |
273 | FSL_IMX6UL_GPIO4_ADDR, | |
274 | FSL_IMX6UL_GPIO5_ADDR, | |
275 | }; | |
276 | ||
277 | static const int FSL_IMX6UL_GPIOn_LOW_IRQ[FSL_IMX6UL_NUM_GPIOS] = { | |
278 | FSL_IMX6UL_GPIO1_LOW_IRQ, | |
279 | FSL_IMX6UL_GPIO2_LOW_IRQ, | |
280 | FSL_IMX6UL_GPIO3_LOW_IRQ, | |
281 | FSL_IMX6UL_GPIO4_LOW_IRQ, | |
282 | FSL_IMX6UL_GPIO5_LOW_IRQ, | |
283 | }; | |
284 | ||
285 | static const int FSL_IMX6UL_GPIOn_HIGH_IRQ[FSL_IMX6UL_NUM_GPIOS] = { | |
286 | FSL_IMX6UL_GPIO1_HIGH_IRQ, | |
287 | FSL_IMX6UL_GPIO2_HIGH_IRQ, | |
288 | FSL_IMX6UL_GPIO3_HIGH_IRQ, | |
289 | FSL_IMX6UL_GPIO4_HIGH_IRQ, | |
290 | FSL_IMX6UL_GPIO5_HIGH_IRQ, | |
291 | }; | |
292 | ||
293 | object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", | |
294 | &error_abort); | |
295 | ||
296 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, | |
297 | FSL_IMX6UL_GPIOn_ADDR[i]); | |
298 | ||
299 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0, | |
300 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
301 | FSL_IMX6UL_GPIOn_LOW_IRQ[i])); | |
302 | ||
303 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1, | |
304 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
305 | FSL_IMX6UL_GPIOn_HIGH_IRQ[i])); | |
306 | } | |
307 | ||
308 | /* | |
309 | * IOMUXC and IOMUXC_GPR | |
310 | */ | |
311 | for (i = 0; i < 1; i++) { | |
312 | static const hwaddr FSL_IMX6UL_IOMUXCn_ADDR[FSL_IMX6UL_NUM_IOMUXCS] = { | |
313 | FSL_IMX6UL_IOMUXC_ADDR, | |
314 | FSL_IMX6UL_IOMUXC_GPR_ADDR, | |
315 | }; | |
316 | ||
317 | snprintf(name, NAME_SIZE, "iomuxc%d", i); | |
318 | create_unimplemented_device(name, FSL_IMX6UL_IOMUXCn_ADDR[i], 0x4000); | |
319 | } | |
320 | ||
321 | /* | |
322 | * CCM | |
323 | */ | |
324 | object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort); | |
325 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6UL_CCM_ADDR); | |
326 | ||
327 | /* | |
328 | * SRC | |
329 | */ | |
330 | object_property_set_bool(OBJECT(&s->src), true, "realized", &error_abort); | |
331 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6UL_SRC_ADDR); | |
332 | ||
333 | /* | |
334 | * GPCv2 | |
335 | */ | |
336 | object_property_set_bool(OBJECT(&s->gpcv2), true, | |
337 | "realized", &error_abort); | |
338 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR); | |
339 | ||
340 | /* Initialize all ECSPI */ | |
341 | for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) { | |
342 | static const hwaddr FSL_IMX6UL_SPIn_ADDR[FSL_IMX6UL_NUM_ECSPIS] = { | |
343 | FSL_IMX6UL_ECSPI1_ADDR, | |
344 | FSL_IMX6UL_ECSPI2_ADDR, | |
345 | FSL_IMX6UL_ECSPI3_ADDR, | |
346 | FSL_IMX6UL_ECSPI4_ADDR, | |
347 | }; | |
348 | ||
349 | static const int FSL_IMX6UL_SPIn_IRQ[FSL_IMX6UL_NUM_ECSPIS] = { | |
350 | FSL_IMX6UL_ECSPI1_IRQ, | |
351 | FSL_IMX6UL_ECSPI2_IRQ, | |
352 | FSL_IMX6UL_ECSPI3_IRQ, | |
353 | FSL_IMX6UL_ECSPI4_IRQ, | |
354 | }; | |
355 | ||
356 | /* Initialize the SPI */ | |
357 | object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", | |
358 | &error_abort); | |
359 | ||
360 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, | |
361 | FSL_IMX6UL_SPIn_ADDR[i]); | |
362 | ||
363 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, | |
364 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
365 | FSL_IMX6UL_SPIn_IRQ[i])); | |
366 | } | |
367 | ||
368 | /* | |
369 | * I2C | |
370 | */ | |
371 | for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) { | |
372 | static const hwaddr FSL_IMX6UL_I2Cn_ADDR[FSL_IMX6UL_NUM_I2CS] = { | |
373 | FSL_IMX6UL_I2C1_ADDR, | |
374 | FSL_IMX6UL_I2C2_ADDR, | |
375 | FSL_IMX6UL_I2C3_ADDR, | |
376 | FSL_IMX6UL_I2C4_ADDR, | |
377 | }; | |
378 | ||
379 | static const int FSL_IMX6UL_I2Cn_IRQ[FSL_IMX6UL_NUM_I2CS] = { | |
380 | FSL_IMX6UL_I2C1_IRQ, | |
381 | FSL_IMX6UL_I2C2_IRQ, | |
382 | FSL_IMX6UL_I2C3_IRQ, | |
383 | FSL_IMX6UL_I2C4_IRQ, | |
384 | }; | |
385 | ||
386 | object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", | |
387 | &error_abort); | |
388 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX6UL_I2Cn_ADDR[i]); | |
389 | ||
390 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, | |
391 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
392 | FSL_IMX6UL_I2Cn_IRQ[i])); | |
393 | } | |
394 | ||
395 | /* | |
396 | * UART | |
397 | */ | |
398 | for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) { | |
399 | static const hwaddr FSL_IMX6UL_UARTn_ADDR[FSL_IMX6UL_NUM_UARTS] = { | |
400 | FSL_IMX6UL_UART1_ADDR, | |
401 | FSL_IMX6UL_UART2_ADDR, | |
402 | FSL_IMX6UL_UART3_ADDR, | |
403 | FSL_IMX6UL_UART4_ADDR, | |
404 | FSL_IMX6UL_UART5_ADDR, | |
405 | FSL_IMX6UL_UART6_ADDR, | |
406 | FSL_IMX6UL_UART7_ADDR, | |
407 | FSL_IMX6UL_UART8_ADDR, | |
408 | }; | |
409 | ||
410 | static const int FSL_IMX6UL_UARTn_IRQ[FSL_IMX6UL_NUM_UARTS] = { | |
411 | FSL_IMX6UL_UART1_IRQ, | |
412 | FSL_IMX6UL_UART2_IRQ, | |
413 | FSL_IMX6UL_UART3_IRQ, | |
414 | FSL_IMX6UL_UART4_IRQ, | |
415 | FSL_IMX6UL_UART5_IRQ, | |
416 | FSL_IMX6UL_UART6_IRQ, | |
417 | FSL_IMX6UL_UART7_IRQ, | |
418 | FSL_IMX6UL_UART8_IRQ, | |
419 | }; | |
420 | ||
421 | qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i)); | |
422 | ||
423 | object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", | |
424 | &error_abort); | |
425 | ||
426 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, | |
427 | FSL_IMX6UL_UARTn_ADDR[i]); | |
428 | ||
429 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, | |
430 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
431 | FSL_IMX6UL_UARTn_IRQ[i])); | |
432 | } | |
433 | ||
434 | /* | |
435 | * Ethernet | |
436 | */ | |
437 | for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) { | |
438 | static const hwaddr FSL_IMX6UL_ENETn_ADDR[FSL_IMX6UL_NUM_ETHS] = { | |
439 | FSL_IMX6UL_ENET1_ADDR, | |
440 | FSL_IMX6UL_ENET2_ADDR, | |
441 | }; | |
442 | ||
443 | static const int FSL_IMX6UL_ENETn_IRQ[FSL_IMX6UL_NUM_ETHS] = { | |
444 | FSL_IMX6UL_ENET1_IRQ, | |
445 | FSL_IMX6UL_ENET2_IRQ, | |
446 | }; | |
447 | ||
448 | static const int FSL_IMX6UL_ENETn_TIMER_IRQ[FSL_IMX6UL_NUM_ETHS] = { | |
449 | FSL_IMX6UL_ENET1_TIMER_IRQ, | |
450 | FSL_IMX6UL_ENET2_TIMER_IRQ, | |
451 | }; | |
452 | ||
453 | object_property_set_uint(OBJECT(&s->eth[i]), | |
454 | FSL_IMX6UL_ETH_NUM_TX_RINGS, | |
455 | "tx-ring-num", &error_abort); | |
456 | qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]); | |
457 | object_property_set_bool(OBJECT(&s->eth[i]), true, "realized", | |
458 | &error_abort); | |
459 | ||
460 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, | |
461 | FSL_IMX6UL_ENETn_ADDR[i]); | |
462 | ||
463 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0, | |
464 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
465 | FSL_IMX6UL_ENETn_IRQ[i])); | |
466 | ||
467 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1, | |
468 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
469 | FSL_IMX6UL_ENETn_TIMER_IRQ[i])); | |
470 | } | |
471 | ||
17372bd8 GR |
472 | /* USB */ |
473 | for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) { | |
474 | object_property_set_bool(OBJECT(&s->usbphy[i]), true, "realized", | |
475 | &error_abort); | |
476 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0, | |
477 | FSL_IMX6UL_USBPHY1_ADDR + i * 0x1000); | |
478 | } | |
479 | ||
480 | for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) { | |
481 | static const int FSL_IMX6UL_USBn_IRQ[] = { | |
482 | FSL_IMX6UL_USB1_IRQ, | |
483 | FSL_IMX6UL_USB2_IRQ, | |
484 | }; | |
485 | object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", | |
486 | &error_abort); | |
487 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, | |
488 | FSL_IMX6UL_USBO2_USB_ADDR + i * 0x200); | |
489 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, | |
490 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
491 | FSL_IMX6UL_USBn_IRQ[i])); | |
492 | } | |
493 | ||
31cbf933 JCD |
494 | /* |
495 | * USDHC | |
496 | */ | |
497 | for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) { | |
498 | static const hwaddr FSL_IMX6UL_USDHCn_ADDR[FSL_IMX6UL_NUM_USDHCS] = { | |
499 | FSL_IMX6UL_USDHC1_ADDR, | |
500 | FSL_IMX6UL_USDHC2_ADDR, | |
501 | }; | |
502 | ||
503 | static const int FSL_IMX6UL_USDHCn_IRQ[FSL_IMX6UL_NUM_USDHCS] = { | |
504 | FSL_IMX6UL_USDHC1_IRQ, | |
505 | FSL_IMX6UL_USDHC2_IRQ, | |
506 | }; | |
507 | ||
508 | object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized", | |
509 | &error_abort); | |
510 | ||
511 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, | |
512 | FSL_IMX6UL_USDHCn_ADDR[i]); | |
513 | ||
514 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, | |
515 | qdev_get_gpio_in(DEVICE(&s->a7mpcore), | |
516 | FSL_IMX6UL_USDHCn_IRQ[i])); | |
517 | } | |
518 | ||
519 | /* | |
520 | * SNVS | |
521 | */ | |
522 | object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort); | |
523 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR); | |
524 | ||
525 | /* | |
526 | * Watchdog | |
527 | */ | |
528 | for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) { | |
529 | static const hwaddr FSL_IMX6UL_WDOGn_ADDR[FSL_IMX6UL_NUM_WDTS] = { | |
530 | FSL_IMX6UL_WDOG1_ADDR, | |
531 | FSL_IMX6UL_WDOG2_ADDR, | |
532 | FSL_IMX6UL_WDOG3_ADDR, | |
533 | }; | |
534 | ||
535 | object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", | |
536 | &error_abort); | |
537 | ||
538 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, | |
539 | FSL_IMX6UL_WDOGn_ADDR[i]); | |
540 | } | |
541 | ||
542 | /* | |
543 | * GPR | |
544 | */ | |
545 | object_property_set_bool(OBJECT(&s->gpr), true, "realized", | |
546 | &error_abort); | |
547 | sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR); | |
548 | ||
549 | /* | |
550 | * SDMA | |
551 | */ | |
552 | create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000); | |
553 | ||
8e0c1585 GR |
554 | /* |
555 | * PWM | |
556 | */ | |
557 | create_unimplemented_device("pwm1", FSL_IMX6UL_PWM1_ADDR, 0x4000); | |
558 | create_unimplemented_device("pwm2", FSL_IMX6UL_PWM2_ADDR, 0x4000); | |
559 | create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000); | |
560 | create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000); | |
561 | ||
562 | /* | |
563 | * CAN | |
564 | */ | |
565 | create_unimplemented_device("can1", FSL_IMX6UL_CAN1_ADDR, 0x4000); | |
566 | create_unimplemented_device("can2", FSL_IMX6UL_CAN2_ADDR, 0x4000); | |
567 | ||
31cbf933 JCD |
568 | /* |
569 | * APHB_DMA | |
570 | */ | |
571 | create_unimplemented_device("aphb_dma", FSL_IMX6UL_APBH_DMA_ADDR, | |
572 | FSL_IMX6UL_APBH_DMA_SIZE); | |
573 | ||
574 | /* | |
575 | * ADCs | |
576 | */ | |
577 | for (i = 0; i < FSL_IMX6UL_NUM_ADCS; i++) { | |
578 | static const hwaddr FSL_IMX6UL_ADCn_ADDR[FSL_IMX6UL_NUM_ADCS] = { | |
579 | FSL_IMX6UL_ADC1_ADDR, | |
580 | FSL_IMX6UL_ADC2_ADDR, | |
581 | }; | |
582 | ||
583 | snprintf(name, NAME_SIZE, "adc%d", i); | |
584 | create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i], 0x4000); | |
585 | } | |
586 | ||
587 | /* | |
588 | * LCD | |
589 | */ | |
590 | create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR, 0x4000); | |
591 | ||
592 | /* | |
593 | * ROM memory | |
594 | */ | |
32b9523a | 595 | memory_region_init_rom(&s->rom, OBJECT(dev), "imx6ul.rom", |
31cbf933 JCD |
596 | FSL_IMX6UL_ROM_SIZE, &error_abort); |
597 | memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_ROM_ADDR, | |
598 | &s->rom); | |
599 | ||
600 | /* | |
601 | * CAAM memory | |
602 | */ | |
32b9523a | 603 | memory_region_init_rom(&s->caam, OBJECT(dev), "imx6ul.caam", |
31cbf933 JCD |
604 | FSL_IMX6UL_CAAM_MEM_SIZE, &error_abort); |
605 | memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_CAAM_MEM_ADDR, | |
606 | &s->caam); | |
607 | ||
608 | /* | |
609 | * OCRAM memory | |
610 | */ | |
611 | memory_region_init_ram(&s->ocram, NULL, "imx6ul.ocram", | |
612 | FSL_IMX6UL_OCRAM_MEM_SIZE, | |
613 | &error_abort); | |
614 | memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_OCRAM_MEM_ADDR, | |
615 | &s->ocram); | |
616 | ||
617 | /* | |
618 | * internal OCRAM (128 KB) is aliased over 512 KB | |
619 | */ | |
32b9523a PMD |
620 | memory_region_init_alias(&s->ocram_alias, OBJECT(dev), |
621 | "imx6ul.ocram_alias", &s->ocram, 0, | |
622 | FSL_IMX6UL_OCRAM_ALIAS_SIZE); | |
31cbf933 JCD |
623 | memory_region_add_subregion(get_system_memory(), |
624 | FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias); | |
625 | } | |
626 | ||
627 | static void fsl_imx6ul_class_init(ObjectClass *oc, void *data) | |
628 | { | |
629 | DeviceClass *dc = DEVICE_CLASS(oc); | |
630 | ||
631 | dc->realize = fsl_imx6ul_realize; | |
632 | dc->desc = "i.MX6UL SOC"; | |
633 | /* Reason: Uses serial_hds and nd_table in realize() directly */ | |
634 | dc->user_creatable = false; | |
635 | } | |
636 | ||
637 | static const TypeInfo fsl_imx6ul_type_info = { | |
638 | .name = TYPE_FSL_IMX6UL, | |
639 | .parent = TYPE_DEVICE, | |
640 | .instance_size = sizeof(FslIMX6ULState), | |
641 | .instance_init = fsl_imx6ul_init, | |
642 | .class_init = fsl_imx6ul_class_init, | |
643 | }; | |
644 | ||
645 | static void fsl_imx6ul_register_types(void) | |
646 | { | |
647 | type_register_static(&fsl_imx6ul_type_info); | |
648 | } | |
649 | type_init(fsl_imx6ul_register_types) |