xref: /qemu/hw/arm/fsl-imx7.c (revision 45b8b34dfacb14503d6f8692fa450f81175328e6)
1 /*
2  * Copyright (c) 2018, Impinj, Inc.
3  *
4  * i.MX7 SoC definitions
5  *
6  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
7  *
8  * Based on hw/arm/fsl-imx6.c
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "hw/arm/fsl-imx7.h"
24 #include "hw/misc/unimp.h"
25 #include "hw/boards.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/error-report.h"
28 #include "qemu/module.h"
29 
30 #define NAME_SIZE 20
31 
32 static void fsl_imx7_init(Object *obj)
33 {
34     MachineState *ms = MACHINE(qdev_get_machine());
35     FslIMX7State *s = FSL_IMX7(obj);
36     char name[NAME_SIZE];
37     int i;
38 
39     /*
40      * CPUs
41      */
42     for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) {
43         snprintf(name, NAME_SIZE, "cpu%d", i);
44         object_initialize_child(obj, name, &s->cpu[i],
45                                 ARM_CPU_TYPE_NAME("cortex-a7"));
46     }
47 
48     /*
49      * A7MPCORE
50      */
51     object_initialize_child(obj, "a7mpcore", &s->a7mpcore,
52                             TYPE_A15MPCORE_PRIV);
53 
54     /*
55      * GPIOs
56      */
57     for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
58         snprintf(name, NAME_SIZE, "gpio%d", i);
59         object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
60     }
61 
62     /*
63      * GPTs
64      */
65     for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
66         snprintf(name, NAME_SIZE, "gpt%d", i);
67         object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX7_GPT);
68     }
69 
70     /*
71      * CCM
72      */
73     object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX7_CCM);
74 
75     /*
76      * Analog
77      */
78     object_initialize_child(obj, "analog", &s->analog, TYPE_IMX7_ANALOG);
79 
80     /*
81      * GPCv2
82      */
83     object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2);
84 
85     /*
86      * ECSPIs
87      */
88     for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
89         snprintf(name, NAME_SIZE, "spi%d", i + 1);
90         object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
91     }
92 
93     /*
94      * I2Cs
95      */
96     for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
97         snprintf(name, NAME_SIZE, "i2c%d", i + 1);
98         object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
99     }
100 
101     /*
102      * UARTs
103      */
104     for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
105             snprintf(name, NAME_SIZE, "uart%d", i);
106             object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
107     }
108 
109     /*
110      * Ethernets
111      */
112     for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
113             snprintf(name, NAME_SIZE, "eth%d", i);
114             object_initialize_child(obj, name, &s->eth[i], TYPE_IMX_ENET);
115     }
116 
117     /*
118      * SDHCIs
119      */
120     for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
121             snprintf(name, NAME_SIZE, "usdhc%d", i);
122             object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
123     }
124 
125     /*
126      * SNVS
127      */
128     object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
129 
130     /*
131      * Watchdogs
132      */
133     for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
134             snprintf(name, NAME_SIZE, "wdt%d", i);
135             object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
136     }
137 
138     /*
139      * GPR
140      */
141     object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR);
142 
143     /*
144      * PCIE
145      */
146     object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
147 
148     /*
149      * USBs
150      */
151     for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
152         snprintf(name, NAME_SIZE, "usb%d", i);
153         object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA);
154     }
155 }
156 
157 static void fsl_imx7_realize(DeviceState *dev, Error **errp)
158 {
159     MachineState *ms = MACHINE(qdev_get_machine());
160     FslIMX7State *s = FSL_IMX7(dev);
161     Object *o;
162     int i;
163     qemu_irq irq;
164     char name[NAME_SIZE];
165     unsigned int smp_cpus = ms->smp.cpus;
166 
167     if (smp_cpus > FSL_IMX7_NUM_CPUS) {
168         error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
169                    TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
170         return;
171     }
172 
173     /*
174      * CPUs
175      */
176     for (i = 0; i < smp_cpus; i++) {
177         o = OBJECT(&s->cpu[i]);
178 
179         /* On uniprocessor, the CBAR is set to 0 */
180         if (smp_cpus > 1) {
181             object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR,
182                                     &error_abort);
183         }
184 
185         if (i) {
186             /*
187              * Secondary CPUs start in powered-down state (and can be
188              * powered up via the SRC system reset controller)
189              */
190             object_property_set_bool(o, "start-powered-off", true,
191                                      &error_abort);
192         }
193 
194         qdev_realize(DEVICE(o), NULL, &error_abort);
195     }
196 
197     /*
198      * A7MPCORE
199      */
200     object_property_set_int(OBJECT(&s->a7mpcore), "num-cpu", smp_cpus,
201                             &error_abort);
202     object_property_set_int(OBJECT(&s->a7mpcore), "num-irq",
203                             FSL_IMX7_MAX_IRQ + GIC_INTERNAL, &error_abort);
204 
205     sysbus_realize(SYS_BUS_DEVICE(&s->a7mpcore), &error_abort);
206     sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR);
207 
208     for (i = 0; i < smp_cpus; i++) {
209         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
210         DeviceState  *d   = DEVICE(qemu_get_cpu(i));
211 
212         irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
213         sysbus_connect_irq(sbd, i, irq);
214         irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
215         sysbus_connect_irq(sbd, i + smp_cpus, irq);
216         irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ);
217         sysbus_connect_irq(sbd, i + 2 * smp_cpus, irq);
218         irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ);
219         sysbus_connect_irq(sbd, i + 3 * smp_cpus, irq);
220     }
221 
222     /*
223      * A7MPCORE DAP
224      */
225     create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR,
226                                 FSL_IMX7_A7MPCORE_DAP_SIZE);
227 
228     /*
229      * GPTs
230      */
231     for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
232         static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = {
233             FSL_IMX7_GPT1_ADDR,
234             FSL_IMX7_GPT2_ADDR,
235             FSL_IMX7_GPT3_ADDR,
236             FSL_IMX7_GPT4_ADDR,
237         };
238 
239         static const int FSL_IMX7_GPTn_IRQ[FSL_IMX7_NUM_GPTS] = {
240             FSL_IMX7_GPT1_IRQ,
241             FSL_IMX7_GPT2_IRQ,
242             FSL_IMX7_GPT3_IRQ,
243             FSL_IMX7_GPT4_IRQ,
244         };
245 
246         s->gpt[i].ccm = IMX_CCM(&s->ccm);
247         sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), &error_abort);
248         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]);
249         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
250                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
251                                             FSL_IMX7_GPTn_IRQ[i]));
252     }
253 
254     /*
255      * GPIOs
256      */
257     for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
258         static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = {
259             FSL_IMX7_GPIO1_ADDR,
260             FSL_IMX7_GPIO2_ADDR,
261             FSL_IMX7_GPIO3_ADDR,
262             FSL_IMX7_GPIO4_ADDR,
263             FSL_IMX7_GPIO5_ADDR,
264             FSL_IMX7_GPIO6_ADDR,
265             FSL_IMX7_GPIO7_ADDR,
266         };
267 
268         static const int FSL_IMX7_GPIOn_LOW_IRQ[FSL_IMX7_NUM_GPIOS] = {
269             FSL_IMX7_GPIO1_LOW_IRQ,
270             FSL_IMX7_GPIO2_LOW_IRQ,
271             FSL_IMX7_GPIO3_LOW_IRQ,
272             FSL_IMX7_GPIO4_LOW_IRQ,
273             FSL_IMX7_GPIO5_LOW_IRQ,
274             FSL_IMX7_GPIO6_LOW_IRQ,
275             FSL_IMX7_GPIO7_LOW_IRQ,
276         };
277 
278         static const int FSL_IMX7_GPIOn_HIGH_IRQ[FSL_IMX7_NUM_GPIOS] = {
279             FSL_IMX7_GPIO1_HIGH_IRQ,
280             FSL_IMX7_GPIO2_HIGH_IRQ,
281             FSL_IMX7_GPIO3_HIGH_IRQ,
282             FSL_IMX7_GPIO4_HIGH_IRQ,
283             FSL_IMX7_GPIO5_HIGH_IRQ,
284             FSL_IMX7_GPIO6_HIGH_IRQ,
285             FSL_IMX7_GPIO7_HIGH_IRQ,
286         };
287 
288         sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), &error_abort);
289         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0,
290                         FSL_IMX7_GPIOn_ADDR[i]);
291 
292         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
293                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
294                                             FSL_IMX7_GPIOn_LOW_IRQ[i]));
295 
296         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
297                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
298                                             FSL_IMX7_GPIOn_HIGH_IRQ[i]));
299     }
300 
301     /*
302      * IOMUXC and IOMUXC_LPSR
303      */
304     create_unimplemented_device("iomuxc", FSL_IMX7_IOMUXC_ADDR,
305                                 FSL_IMX7_IOMUXC_SIZE);
306     create_unimplemented_device("iomuxc_lspr", FSL_IMX7_IOMUXC_LPSR_ADDR,
307                                 FSL_IMX7_IOMUXC_LPSR_SIZE);
308 
309     /*
310      * CCM
311      */
312     sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_abort);
313     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX7_CCM_ADDR);
314 
315     /*
316      * Analog
317      */
318     sysbus_realize(SYS_BUS_DEVICE(&s->analog), &error_abort);
319     sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0, FSL_IMX7_ANALOG_ADDR);
320 
321     /*
322      * GPCv2
323      */
324     sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort);
325     sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR);
326 
327     /*
328      * ECSPIs
329      */
330     for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
331         static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = {
332             FSL_IMX7_ECSPI1_ADDR,
333             FSL_IMX7_ECSPI2_ADDR,
334             FSL_IMX7_ECSPI3_ADDR,
335             FSL_IMX7_ECSPI4_ADDR,
336         };
337 
338         static const int FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = {
339             FSL_IMX7_ECSPI1_IRQ,
340             FSL_IMX7_ECSPI2_IRQ,
341             FSL_IMX7_ECSPI3_IRQ,
342             FSL_IMX7_ECSPI4_IRQ,
343         };
344 
345         /* Initialize the SPI */
346         sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), &error_abort);
347         sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
348                         FSL_IMX7_SPIn_ADDR[i]);
349         sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
350                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
351                                             FSL_IMX7_SPIn_IRQ[i]));
352     }
353 
354     /*
355      * I2Cs
356      */
357     for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
358         static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = {
359             FSL_IMX7_I2C1_ADDR,
360             FSL_IMX7_I2C2_ADDR,
361             FSL_IMX7_I2C3_ADDR,
362             FSL_IMX7_I2C4_ADDR,
363         };
364 
365         static const int FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = {
366             FSL_IMX7_I2C1_IRQ,
367             FSL_IMX7_I2C2_IRQ,
368             FSL_IMX7_I2C3_IRQ,
369             FSL_IMX7_I2C4_IRQ,
370         };
371 
372         sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), &error_abort);
373         sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]);
374 
375         sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
376                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
377                                             FSL_IMX7_I2Cn_IRQ[i]));
378     }
379 
380     /*
381      * UARTs
382      */
383     for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
384         static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = {
385             FSL_IMX7_UART1_ADDR,
386             FSL_IMX7_UART2_ADDR,
387             FSL_IMX7_UART3_ADDR,
388             FSL_IMX7_UART4_ADDR,
389             FSL_IMX7_UART5_ADDR,
390             FSL_IMX7_UART6_ADDR,
391             FSL_IMX7_UART7_ADDR,
392         };
393 
394         static const int FSL_IMX7_UARTn_IRQ[FSL_IMX7_NUM_UARTS] = {
395             FSL_IMX7_UART1_IRQ,
396             FSL_IMX7_UART2_IRQ,
397             FSL_IMX7_UART3_IRQ,
398             FSL_IMX7_UART4_IRQ,
399             FSL_IMX7_UART5_IRQ,
400             FSL_IMX7_UART6_IRQ,
401             FSL_IMX7_UART7_IRQ,
402         };
403 
404 
405         qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
406 
407         sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), &error_abort);
408 
409         sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX7_UARTn_ADDR[i]);
410 
411         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_UARTn_IRQ[i]);
412         sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, irq);
413     }
414 
415     /*
416      * Ethernets
417      *
418      * We must use two loops since phy_connected affects the other interface
419      * and we have to set all properties before calling sysbus_realize().
420      */
421     for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
422         object_property_set_bool(OBJECT(&s->eth[i]), "phy-connected",
423                                  s->phy_connected[i], &error_abort);
424         /*
425          * If the MDIO bus on this controller is not connected, assume the
426          * other controller provides support for it.
427          */
428         if (!s->phy_connected[i]) {
429             object_property_set_link(OBJECT(&s->eth[1 - i]), "phy-consumer",
430                                      OBJECT(&s->eth[i]), &error_abort);
431         }
432     }
433 
434     for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
435         static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = {
436             FSL_IMX7_ENET1_ADDR,
437             FSL_IMX7_ENET2_ADDR,
438         };
439 
440         object_property_set_uint(OBJECT(&s->eth[i]), "phy-num",
441                                  s->phy_num[i], &error_abort);
442         object_property_set_uint(OBJECT(&s->eth[i]), "tx-ring-num",
443                                  FSL_IMX7_ETH_NUM_TX_RINGS, &error_abort);
444         qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]);
445         sysbus_realize(SYS_BUS_DEVICE(&s->eth[i]), &error_abort);
446 
447         sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
448 
449         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 0));
450         sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0, irq);
451         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 3));
452         sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1, irq);
453     }
454 
455     /*
456      * USDHCs
457      */
458     for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
459         static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = {
460             FSL_IMX7_USDHC1_ADDR,
461             FSL_IMX7_USDHC2_ADDR,
462             FSL_IMX7_USDHC3_ADDR,
463         };
464 
465         static const int FSL_IMX7_USDHCn_IRQ[FSL_IMX7_NUM_USDHCS] = {
466             FSL_IMX7_USDHC1_IRQ,
467             FSL_IMX7_USDHC2_IRQ,
468             FSL_IMX7_USDHC3_IRQ,
469         };
470 
471         object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
472                                  SDHCI_VENDOR_IMX, &error_abort);
473         sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort);
474 
475         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
476                         FSL_IMX7_USDHCn_ADDR[i]);
477 
478         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USDHCn_IRQ[i]);
479         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, irq);
480     }
481 
482     /*
483      * SNVS
484      */
485     sysbus_realize(SYS_BUS_DEVICE(&s->snvs), &error_abort);
486     sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_HP_ADDR);
487 
488     /*
489      * SRC
490      */
491     create_unimplemented_device("src", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
492 
493     /*
494      * Watchdogs
495      */
496     for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
497         static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = {
498             FSL_IMX7_WDOG1_ADDR,
499             FSL_IMX7_WDOG2_ADDR,
500             FSL_IMX7_WDOG3_ADDR,
501             FSL_IMX7_WDOG4_ADDR,
502         };
503         static const int FSL_IMX7_WDOGn_IRQ[FSL_IMX7_NUM_WDTS] = {
504             FSL_IMX7_WDOG1_IRQ,
505             FSL_IMX7_WDOG2_IRQ,
506             FSL_IMX7_WDOG3_IRQ,
507             FSL_IMX7_WDOG4_IRQ,
508         };
509 
510         object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
511                                  true, &error_abort);
512         sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), &error_abort);
513 
514         sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
515         sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
516                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
517                                             FSL_IMX7_WDOGn_IRQ[i]));
518     }
519 
520     /*
521      * SDMA
522      */
523     create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE);
524 
525     /*
526      * CAAM
527      */
528     create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE);
529 
530     /*
531      * PWMs
532      */
533     for (i = 0; i < FSL_IMX7_NUM_PWMS; i++) {
534         static const hwaddr FSL_IMX7_PWMn_ADDR[FSL_IMX7_NUM_PWMS] = {
535             FSL_IMX7_PWM1_ADDR,
536             FSL_IMX7_PWM2_ADDR,
537             FSL_IMX7_PWM3_ADDR,
538             FSL_IMX7_PWM4_ADDR,
539         };
540 
541         snprintf(name, NAME_SIZE, "pwm%d", i);
542         create_unimplemented_device(name, FSL_IMX7_PWMn_ADDR[i],
543                                     FSL_IMX7_PWMn_SIZE);
544     }
545 
546     /*
547      * CANs
548      */
549     for (i = 0; i < FSL_IMX7_NUM_CANS; i++) {
550         static const hwaddr FSL_IMX7_CANn_ADDR[FSL_IMX7_NUM_CANS] = {
551             FSL_IMX7_CAN1_ADDR,
552             FSL_IMX7_CAN2_ADDR,
553         };
554 
555         snprintf(name, NAME_SIZE, "can%d", i);
556         create_unimplemented_device(name, FSL_IMX7_CANn_ADDR[i],
557                                     FSL_IMX7_CANn_SIZE);
558     }
559 
560     /*
561      * SAIs (Audio SSI (Synchronous Serial Interface))
562      */
563     for (i = 0; i < FSL_IMX7_NUM_SAIS; i++) {
564         static const hwaddr FSL_IMX7_SAIn_ADDR[FSL_IMX7_NUM_SAIS] = {
565             FSL_IMX7_SAI1_ADDR,
566             FSL_IMX7_SAI2_ADDR,
567             FSL_IMX7_SAI3_ADDR,
568         };
569 
570         snprintf(name, NAME_SIZE, "sai%d", i);
571         create_unimplemented_device(name, FSL_IMX7_SAIn_ADDR[i],
572                                     FSL_IMX7_SAIn_SIZE);
573     }
574 
575     /*
576      * OCOTP
577      */
578     create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR,
579                                 FSL_IMX7_OCOTP_SIZE);
580 
581     /*
582      * GPR
583      */
584     sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort);
585     sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_IOMUXC_GPR_ADDR);
586 
587     /*
588      * PCIE
589      */
590     sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
591     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
592 
593     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ);
594     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
595     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ);
596     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
597     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ);
598     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
599     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
600     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
601 
602     /*
603      * USBs
604      */
605     for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
606         static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = {
607             FSL_IMX7_USBMISC1_ADDR,
608             FSL_IMX7_USBMISC2_ADDR,
609             FSL_IMX7_USBMISC3_ADDR,
610         };
611 
612         static const hwaddr FSL_IMX7_USBn_ADDR[FSL_IMX7_NUM_USBS] = {
613             FSL_IMX7_USB1_ADDR,
614             FSL_IMX7_USB2_ADDR,
615             FSL_IMX7_USB3_ADDR,
616         };
617 
618         static const int FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = {
619             FSL_IMX7_USB1_IRQ,
620             FSL_IMX7_USB2_IRQ,
621             FSL_IMX7_USB3_IRQ,
622         };
623 
624         sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort);
625         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
626                         FSL_IMX7_USBn_ADDR[i]);
627 
628         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USBn_IRQ[i]);
629         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, irq);
630 
631         snprintf(name, NAME_SIZE, "usbmisc%d", i);
632         create_unimplemented_device(name, FSL_IMX7_USBMISCn_ADDR[i],
633                                     FSL_IMX7_USBMISCn_SIZE);
634     }
635 
636     /*
637      * ADCs
638      */
639     for (i = 0; i < FSL_IMX7_NUM_ADCS; i++) {
640         static const hwaddr FSL_IMX7_ADCn_ADDR[FSL_IMX7_NUM_ADCS] = {
641             FSL_IMX7_ADC1_ADDR,
642             FSL_IMX7_ADC2_ADDR,
643         };
644 
645         snprintf(name, NAME_SIZE, "adc%d", i);
646         create_unimplemented_device(name, FSL_IMX7_ADCn_ADDR[i],
647                                     FSL_IMX7_ADCn_SIZE);
648     }
649 
650     /*
651      * LCD
652      */
653     create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR,
654                                 FSL_IMX7_LCDIF_SIZE);
655 
656     /*
657      * DMA APBH
658      */
659     create_unimplemented_device("dma-apbh", FSL_IMX7_DMA_APBH_ADDR,
660                                 FSL_IMX7_DMA_APBH_SIZE);
661     /*
662      * PCIe PHY
663      */
664     create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR,
665                                 FSL_IMX7_PCIE_PHY_SIZE);
666 
667 }
668 
669 static Property fsl_imx7_properties[] = {
670     DEFINE_PROP_UINT32("fec1-phy-num", FslIMX7State, phy_num[0], 0),
671     DEFINE_PROP_UINT32("fec2-phy-num", FslIMX7State, phy_num[1], 1),
672     DEFINE_PROP_BOOL("fec1-phy-connected", FslIMX7State, phy_connected[0],
673                      true),
674     DEFINE_PROP_BOOL("fec2-phy-connected", FslIMX7State, phy_connected[1],
675                      true),
676     DEFINE_PROP_END_OF_LIST(),
677 };
678 
679 static void fsl_imx7_class_init(ObjectClass *oc, void *data)
680 {
681     DeviceClass *dc = DEVICE_CLASS(oc);
682 
683     device_class_set_props(dc, fsl_imx7_properties);
684     dc->realize = fsl_imx7_realize;
685 
686     /* Reason: Uses serial_hds and nd_table in realize() directly */
687     dc->user_creatable = false;
688     dc->desc = "i.MX7 SOC";
689 }
690 
691 static const TypeInfo fsl_imx7_type_info = {
692     .name = TYPE_FSL_IMX7,
693     .parent = TYPE_DEVICE,
694     .instance_size = sizeof(FslIMX7State),
695     .instance_init = fsl_imx7_init,
696     .class_init = fsl_imx7_class_init,
697 };
698 
699 static void fsl_imx7_register_types(void)
700 {
701     type_register_static(&fsl_imx7_type_info);
702 }
703 type_init(fsl_imx7_register_types)
704