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