xref: /qemu/hw/arm/fsl-imx7.c (revision 757282ada8c64e233825d7e2ef1d8841fdf590fc)
1*757282adSAndrey Smirnov /*
2*757282adSAndrey Smirnov  * Copyright (c) 2018, Impinj, Inc.
3*757282adSAndrey Smirnov  *
4*757282adSAndrey Smirnov  * i.MX7 SoC definitions
5*757282adSAndrey Smirnov  *
6*757282adSAndrey Smirnov  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
7*757282adSAndrey Smirnov  *
8*757282adSAndrey Smirnov  * Based on hw/arm/fsl-imx6.c
9*757282adSAndrey Smirnov  *
10*757282adSAndrey Smirnov  * This program is free software; you can redistribute it and/or modify
11*757282adSAndrey Smirnov  * it under the terms of the GNU General Public License as published by
12*757282adSAndrey Smirnov  * the Free Software Foundation; either version 2 of the License, or
13*757282adSAndrey Smirnov  * (at your option) any later version.
14*757282adSAndrey Smirnov  *
15*757282adSAndrey Smirnov  * This program is distributed in the hope that it will be useful,
16*757282adSAndrey Smirnov  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*757282adSAndrey Smirnov  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18*757282adSAndrey Smirnov  * GNU General Public License for more details.
19*757282adSAndrey Smirnov  */
20*757282adSAndrey Smirnov 
21*757282adSAndrey Smirnov #include "qemu/osdep.h"
22*757282adSAndrey Smirnov #include "qapi/error.h"
23*757282adSAndrey Smirnov #include "qemu-common.h"
24*757282adSAndrey Smirnov #include "hw/arm/fsl-imx7.h"
25*757282adSAndrey Smirnov #include "hw/misc/unimp.h"
26*757282adSAndrey Smirnov #include "sysemu/sysemu.h"
27*757282adSAndrey Smirnov #include "qemu/error-report.h"
28*757282adSAndrey Smirnov 
29*757282adSAndrey Smirnov #define NAME_SIZE 20
30*757282adSAndrey Smirnov 
31*757282adSAndrey Smirnov static void fsl_imx7_init(Object *obj)
32*757282adSAndrey Smirnov {
33*757282adSAndrey Smirnov     BusState *sysbus = sysbus_get_default();
34*757282adSAndrey Smirnov     FslIMX7State *s = FSL_IMX7(obj);
35*757282adSAndrey Smirnov     char name[NAME_SIZE];
36*757282adSAndrey Smirnov     int i;
37*757282adSAndrey Smirnov 
38*757282adSAndrey Smirnov     if (smp_cpus > FSL_IMX7_NUM_CPUS) {
39*757282adSAndrey Smirnov         error_report("%s: Only %d CPUs are supported (%d requested)",
40*757282adSAndrey Smirnov                      TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
41*757282adSAndrey Smirnov         exit(1);
42*757282adSAndrey Smirnov     }
43*757282adSAndrey Smirnov 
44*757282adSAndrey Smirnov     for (i = 0; i < smp_cpus; i++) {
45*757282adSAndrey Smirnov         object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
46*757282adSAndrey Smirnov                           ARM_CPU_TYPE_NAME("cortex-a7"));
47*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "cpu%d", i);
48*757282adSAndrey Smirnov         object_property_add_child(obj, name, OBJECT(&s->cpu[i]),
49*757282adSAndrey Smirnov                                   &error_fatal);
50*757282adSAndrey Smirnov     }
51*757282adSAndrey Smirnov 
52*757282adSAndrey Smirnov     /*
53*757282adSAndrey Smirnov      * A7MPCORE
54*757282adSAndrey Smirnov      */
55*757282adSAndrey Smirnov     object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
56*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->a7mpcore), sysbus);
57*757282adSAndrey Smirnov     object_property_add_child(obj, "a7mpcore",
58*757282adSAndrey Smirnov                               OBJECT(&s->a7mpcore), &error_fatal);
59*757282adSAndrey Smirnov 
60*757282adSAndrey Smirnov     /*
61*757282adSAndrey Smirnov      * GPIOs 1 to 7
62*757282adSAndrey Smirnov      */
63*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
64*757282adSAndrey Smirnov         object_initialize(&s->gpio[i], sizeof(s->gpio[i]),
65*757282adSAndrey Smirnov                           TYPE_IMX_GPIO);
66*757282adSAndrey Smirnov         qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus);
67*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "gpio%d", i);
68*757282adSAndrey Smirnov         object_property_add_child(obj, name,
69*757282adSAndrey Smirnov                                   OBJECT(&s->gpio[i]), &error_fatal);
70*757282adSAndrey Smirnov     }
71*757282adSAndrey Smirnov 
72*757282adSAndrey Smirnov     /*
73*757282adSAndrey Smirnov      * GPT1, 2, 3, 4
74*757282adSAndrey Smirnov      */
75*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
76*757282adSAndrey Smirnov         object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX7_GPT);
77*757282adSAndrey Smirnov         qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus);
78*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "gpt%d", i);
79*757282adSAndrey Smirnov         object_property_add_child(obj, name, OBJECT(&s->gpt[i]),
80*757282adSAndrey Smirnov                                   &error_fatal);
81*757282adSAndrey Smirnov     }
82*757282adSAndrey Smirnov 
83*757282adSAndrey Smirnov     /*
84*757282adSAndrey Smirnov      * CCM
85*757282adSAndrey Smirnov      */
86*757282adSAndrey Smirnov     object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX7_CCM);
87*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->ccm), sysbus);
88*757282adSAndrey Smirnov     object_property_add_child(obj, "ccm", OBJECT(&s->ccm), &error_fatal);
89*757282adSAndrey Smirnov 
90*757282adSAndrey Smirnov     /*
91*757282adSAndrey Smirnov      * Analog
92*757282adSAndrey Smirnov      */
93*757282adSAndrey Smirnov     object_initialize(&s->analog, sizeof(s->analog), TYPE_IMX7_ANALOG);
94*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->analog), sysbus);
95*757282adSAndrey Smirnov     object_property_add_child(obj, "analog", OBJECT(&s->analog), &error_fatal);
96*757282adSAndrey Smirnov 
97*757282adSAndrey Smirnov     /*
98*757282adSAndrey Smirnov      * GPCv2
99*757282adSAndrey Smirnov      */
100*757282adSAndrey Smirnov     object_initialize(&s->gpcv2, sizeof(s->gpcv2), TYPE_IMX_GPCV2);
101*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->gpcv2), sysbus);
102*757282adSAndrey Smirnov     object_property_add_child(obj, "gpcv2", OBJECT(&s->gpcv2), &error_fatal);
103*757282adSAndrey Smirnov 
104*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
105*757282adSAndrey Smirnov         object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI);
106*757282adSAndrey Smirnov         qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
107*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "spi%d", i + 1);
108*757282adSAndrey Smirnov         object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL);
109*757282adSAndrey Smirnov     }
110*757282adSAndrey Smirnov 
111*757282adSAndrey Smirnov 
112*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
113*757282adSAndrey Smirnov         object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
114*757282adSAndrey Smirnov         qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
115*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "i2c%d", i + 1);
116*757282adSAndrey Smirnov         object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL);
117*757282adSAndrey Smirnov     }
118*757282adSAndrey Smirnov 
119*757282adSAndrey Smirnov     /*
120*757282adSAndrey Smirnov      * UART
121*757282adSAndrey Smirnov      */
122*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
123*757282adSAndrey Smirnov             object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
124*757282adSAndrey Smirnov             qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus);
125*757282adSAndrey Smirnov             snprintf(name, NAME_SIZE, "uart%d", i);
126*757282adSAndrey Smirnov             object_property_add_child(obj, name, OBJECT(&s->uart[i]),
127*757282adSAndrey Smirnov                                       &error_fatal);
128*757282adSAndrey Smirnov     }
129*757282adSAndrey Smirnov 
130*757282adSAndrey Smirnov     /*
131*757282adSAndrey Smirnov      * Ethernet
132*757282adSAndrey Smirnov      */
133*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
134*757282adSAndrey Smirnov             object_initialize(&s->eth[i], sizeof(s->eth[i]), TYPE_IMX_ENET);
135*757282adSAndrey Smirnov             qdev_set_parent_bus(DEVICE(&s->eth[i]), sysbus);
136*757282adSAndrey Smirnov             snprintf(name, NAME_SIZE, "eth%d", i);
137*757282adSAndrey Smirnov             object_property_add_child(obj, name, OBJECT(&s->eth[i]),
138*757282adSAndrey Smirnov                                       &error_fatal);
139*757282adSAndrey Smirnov     }
140*757282adSAndrey Smirnov 
141*757282adSAndrey Smirnov     /*
142*757282adSAndrey Smirnov      * SDHCI
143*757282adSAndrey Smirnov      */
144*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
145*757282adSAndrey Smirnov             object_initialize(&s->usdhc[i], sizeof(s->usdhc[i]),
146*757282adSAndrey Smirnov                               TYPE_IMX_USDHC);
147*757282adSAndrey Smirnov             qdev_set_parent_bus(DEVICE(&s->usdhc[i]), sysbus);
148*757282adSAndrey Smirnov             snprintf(name, NAME_SIZE, "usdhc%d", i);
149*757282adSAndrey Smirnov             object_property_add_child(obj, name, OBJECT(&s->usdhc[i]),
150*757282adSAndrey Smirnov                                       &error_fatal);
151*757282adSAndrey Smirnov     }
152*757282adSAndrey Smirnov 
153*757282adSAndrey Smirnov     /*
154*757282adSAndrey Smirnov      * SNVS
155*757282adSAndrey Smirnov      */
156*757282adSAndrey Smirnov     object_initialize(&s->snvs, sizeof(s->snvs), TYPE_IMX7_SNVS);
157*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->snvs), sysbus);
158*757282adSAndrey Smirnov     object_property_add_child(obj, "snvs", OBJECT(&s->snvs), &error_fatal);
159*757282adSAndrey Smirnov 
160*757282adSAndrey Smirnov     /*
161*757282adSAndrey Smirnov      * Watchdog
162*757282adSAndrey Smirnov      */
163*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
164*757282adSAndrey Smirnov             object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_IMX2_WDT);
165*757282adSAndrey Smirnov             qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus);
166*757282adSAndrey Smirnov             snprintf(name, NAME_SIZE, "wdt%d", i);
167*757282adSAndrey Smirnov             object_property_add_child(obj, name, OBJECT(&s->wdt[i]),
168*757282adSAndrey Smirnov                                       &error_fatal);
169*757282adSAndrey Smirnov     }
170*757282adSAndrey Smirnov 
171*757282adSAndrey Smirnov     /*
172*757282adSAndrey Smirnov      * GPR
173*757282adSAndrey Smirnov      */
174*757282adSAndrey Smirnov     object_initialize(&s->gpr, sizeof(s->gpr), TYPE_IMX7_GPR);
175*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->gpr), sysbus);
176*757282adSAndrey Smirnov     object_property_add_child(obj, "gpr", OBJECT(&s->gpr), &error_fatal);
177*757282adSAndrey Smirnov 
178*757282adSAndrey Smirnov     object_initialize(&s->pcie, sizeof(s->pcie), TYPE_DESIGNWARE_PCIE_HOST);
179*757282adSAndrey Smirnov     qdev_set_parent_bus(DEVICE(&s->pcie), sysbus);
180*757282adSAndrey Smirnov     object_property_add_child(obj, "pcie", OBJECT(&s->pcie), &error_fatal);
181*757282adSAndrey Smirnov 
182*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
183*757282adSAndrey Smirnov         object_initialize(&s->usb[i],
184*757282adSAndrey Smirnov                           sizeof(s->usb[i]), TYPE_CHIPIDEA);
185*757282adSAndrey Smirnov         qdev_set_parent_bus(DEVICE(&s->usb[i]), sysbus);
186*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "usb%d", i);
187*757282adSAndrey Smirnov         object_property_add_child(obj, name,
188*757282adSAndrey Smirnov                                   OBJECT(&s->usb[i]), &error_fatal);
189*757282adSAndrey Smirnov     }
190*757282adSAndrey Smirnov }
191*757282adSAndrey Smirnov 
192*757282adSAndrey Smirnov static void fsl_imx7_realize(DeviceState *dev, Error **errp)
193*757282adSAndrey Smirnov {
194*757282adSAndrey Smirnov     FslIMX7State *s = FSL_IMX7(dev);
195*757282adSAndrey Smirnov     Object *o;
196*757282adSAndrey Smirnov     int i;
197*757282adSAndrey Smirnov     qemu_irq irq;
198*757282adSAndrey Smirnov     char name[NAME_SIZE];
199*757282adSAndrey Smirnov 
200*757282adSAndrey Smirnov     for (i = 0; i < smp_cpus; i++) {
201*757282adSAndrey Smirnov         o = OBJECT(&s->cpu[i]);
202*757282adSAndrey Smirnov 
203*757282adSAndrey Smirnov         object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC,
204*757282adSAndrey Smirnov                                 "psci-conduit", &error_abort);
205*757282adSAndrey Smirnov 
206*757282adSAndrey Smirnov         /* On uniprocessor, the CBAR is set to 0 */
207*757282adSAndrey Smirnov         if (smp_cpus > 1) {
208*757282adSAndrey Smirnov             object_property_set_int(o, FSL_IMX7_A7MPCORE_ADDR,
209*757282adSAndrey Smirnov                                     "reset-cbar", &error_abort);
210*757282adSAndrey Smirnov         }
211*757282adSAndrey Smirnov 
212*757282adSAndrey Smirnov         if (i) {
213*757282adSAndrey Smirnov             /* Secondary CPUs start in PSCI powered-down state */
214*757282adSAndrey Smirnov             object_property_set_bool(o, true,
215*757282adSAndrey Smirnov                                      "start-powered-off", &error_abort);
216*757282adSAndrey Smirnov         }
217*757282adSAndrey Smirnov 
218*757282adSAndrey Smirnov         object_property_set_bool(o, true, "realized", &error_abort);
219*757282adSAndrey Smirnov     }
220*757282adSAndrey Smirnov 
221*757282adSAndrey Smirnov     /*
222*757282adSAndrey Smirnov      * A7MPCORE
223*757282adSAndrey Smirnov      */
224*757282adSAndrey Smirnov     object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu",
225*757282adSAndrey Smirnov                             &error_abort);
226*757282adSAndrey Smirnov     object_property_set_int(OBJECT(&s->a7mpcore),
227*757282adSAndrey Smirnov                             FSL_IMX7_MAX_IRQ + GIC_INTERNAL,
228*757282adSAndrey Smirnov                             "num-irq", &error_abort);
229*757282adSAndrey Smirnov 
230*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized",
231*757282adSAndrey Smirnov                              &error_abort);
232*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR);
233*757282adSAndrey Smirnov 
234*757282adSAndrey Smirnov     for (i = 0; i < smp_cpus; i++) {
235*757282adSAndrey Smirnov         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
236*757282adSAndrey Smirnov         DeviceState  *d   = DEVICE(qemu_get_cpu(i));
237*757282adSAndrey Smirnov 
238*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
239*757282adSAndrey Smirnov         sysbus_connect_irq(sbd, i, irq);
240*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
241*757282adSAndrey Smirnov         sysbus_connect_irq(sbd, i + smp_cpus, irq);
242*757282adSAndrey Smirnov     }
243*757282adSAndrey Smirnov 
244*757282adSAndrey Smirnov     /*
245*757282adSAndrey Smirnov      * A7MPCORE DAP
246*757282adSAndrey Smirnov      */
247*757282adSAndrey Smirnov     create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR,
248*757282adSAndrey Smirnov                                 0x100000);
249*757282adSAndrey Smirnov 
250*757282adSAndrey Smirnov     /*
251*757282adSAndrey Smirnov      * GPT1, 2, 3, 4
252*757282adSAndrey Smirnov      */
253*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
254*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = {
255*757282adSAndrey Smirnov             FSL_IMX7_GPT1_ADDR,
256*757282adSAndrey Smirnov             FSL_IMX7_GPT2_ADDR,
257*757282adSAndrey Smirnov             FSL_IMX7_GPT3_ADDR,
258*757282adSAndrey Smirnov             FSL_IMX7_GPT4_ADDR,
259*757282adSAndrey Smirnov         };
260*757282adSAndrey Smirnov 
261*757282adSAndrey Smirnov         s->gpt[i].ccm = IMX_CCM(&s->ccm);
262*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized",
263*757282adSAndrey Smirnov                                  &error_abort);
264*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]);
265*757282adSAndrey Smirnov     }
266*757282adSAndrey Smirnov 
267*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
268*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = {
269*757282adSAndrey Smirnov             FSL_IMX7_GPIO1_ADDR,
270*757282adSAndrey Smirnov             FSL_IMX7_GPIO2_ADDR,
271*757282adSAndrey Smirnov             FSL_IMX7_GPIO3_ADDR,
272*757282adSAndrey Smirnov             FSL_IMX7_GPIO4_ADDR,
273*757282adSAndrey Smirnov             FSL_IMX7_GPIO5_ADDR,
274*757282adSAndrey Smirnov             FSL_IMX7_GPIO6_ADDR,
275*757282adSAndrey Smirnov             FSL_IMX7_GPIO7_ADDR,
276*757282adSAndrey Smirnov         };
277*757282adSAndrey Smirnov 
278*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized",
279*757282adSAndrey Smirnov                                  &error_abort);
280*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, FSL_IMX7_GPIOn_ADDR[i]);
281*757282adSAndrey Smirnov     }
282*757282adSAndrey Smirnov 
283*757282adSAndrey Smirnov     /*
284*757282adSAndrey Smirnov      * IOMUXC and IOMUXC_LPSR
285*757282adSAndrey Smirnov      */
286*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) {
287*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_IOMUXCn_ADDR[FSL_IMX7_NUM_IOMUXCS] = {
288*757282adSAndrey Smirnov             FSL_IMX7_IOMUXC_ADDR,
289*757282adSAndrey Smirnov             FSL_IMX7_IOMUXC_LPSR_ADDR,
290*757282adSAndrey Smirnov         };
291*757282adSAndrey Smirnov 
292*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "iomuxc%d", i);
293*757282adSAndrey Smirnov         create_unimplemented_device(name, FSL_IMX7_IOMUXCn_ADDR[i],
294*757282adSAndrey Smirnov                                     FSL_IMX7_IOMUXCn_SIZE);
295*757282adSAndrey Smirnov     }
296*757282adSAndrey Smirnov 
297*757282adSAndrey Smirnov     /*
298*757282adSAndrey Smirnov      * CCM
299*757282adSAndrey Smirnov      */
300*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort);
301*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX7_CCM_ADDR);
302*757282adSAndrey Smirnov 
303*757282adSAndrey Smirnov     /*
304*757282adSAndrey Smirnov      * Analog
305*757282adSAndrey Smirnov      */
306*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->analog), true, "realized",
307*757282adSAndrey Smirnov                              &error_abort);
308*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0, FSL_IMX7_ANALOG_ADDR);
309*757282adSAndrey Smirnov 
310*757282adSAndrey Smirnov     /*
311*757282adSAndrey Smirnov      * GPCv2
312*757282adSAndrey Smirnov      */
313*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->gpcv2), true,
314*757282adSAndrey Smirnov                              "realized", &error_abort);
315*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR);
316*757282adSAndrey Smirnov 
317*757282adSAndrey Smirnov     /* Initialize all ECSPI */
318*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
319*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = {
320*757282adSAndrey Smirnov             FSL_IMX7_ECSPI1_ADDR,
321*757282adSAndrey Smirnov             FSL_IMX7_ECSPI2_ADDR,
322*757282adSAndrey Smirnov             FSL_IMX7_ECSPI3_ADDR,
323*757282adSAndrey Smirnov             FSL_IMX7_ECSPI4_ADDR,
324*757282adSAndrey Smirnov         };
325*757282adSAndrey Smirnov 
326*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = {
327*757282adSAndrey Smirnov             FSL_IMX7_ECSPI1_IRQ,
328*757282adSAndrey Smirnov             FSL_IMX7_ECSPI2_IRQ,
329*757282adSAndrey Smirnov             FSL_IMX7_ECSPI3_IRQ,
330*757282adSAndrey Smirnov             FSL_IMX7_ECSPI4_IRQ,
331*757282adSAndrey Smirnov         };
332*757282adSAndrey Smirnov 
333*757282adSAndrey Smirnov         /* Initialize the SPI */
334*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
335*757282adSAndrey Smirnov                                  &error_abort);
336*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
337*757282adSAndrey Smirnov                         FSL_IMX7_SPIn_ADDR[i]);
338*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
339*757282adSAndrey Smirnov                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
340*757282adSAndrey Smirnov                                             FSL_IMX7_SPIn_IRQ[i]));
341*757282adSAndrey Smirnov     }
342*757282adSAndrey Smirnov 
343*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
344*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = {
345*757282adSAndrey Smirnov             FSL_IMX7_I2C1_ADDR,
346*757282adSAndrey Smirnov             FSL_IMX7_I2C2_ADDR,
347*757282adSAndrey Smirnov             FSL_IMX7_I2C3_ADDR,
348*757282adSAndrey Smirnov             FSL_IMX7_I2C4_ADDR,
349*757282adSAndrey Smirnov         };
350*757282adSAndrey Smirnov 
351*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = {
352*757282adSAndrey Smirnov             FSL_IMX7_I2C1_IRQ,
353*757282adSAndrey Smirnov             FSL_IMX7_I2C2_IRQ,
354*757282adSAndrey Smirnov             FSL_IMX7_I2C3_IRQ,
355*757282adSAndrey Smirnov             FSL_IMX7_I2C4_IRQ,
356*757282adSAndrey Smirnov         };
357*757282adSAndrey Smirnov 
358*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized",
359*757282adSAndrey Smirnov                                  &error_abort);
360*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]);
361*757282adSAndrey Smirnov 
362*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
363*757282adSAndrey Smirnov                            qdev_get_gpio_in(DEVICE(&s->a7mpcore),
364*757282adSAndrey Smirnov                                             FSL_IMX7_I2Cn_IRQ[i]));
365*757282adSAndrey Smirnov     }
366*757282adSAndrey Smirnov 
367*757282adSAndrey Smirnov     /*
368*757282adSAndrey Smirnov      * UART
369*757282adSAndrey Smirnov      */
370*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
371*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = {
372*757282adSAndrey Smirnov             FSL_IMX7_UART1_ADDR,
373*757282adSAndrey Smirnov             FSL_IMX7_UART2_ADDR,
374*757282adSAndrey Smirnov             FSL_IMX7_UART3_ADDR,
375*757282adSAndrey Smirnov             FSL_IMX7_UART4_ADDR,
376*757282adSAndrey Smirnov             FSL_IMX7_UART5_ADDR,
377*757282adSAndrey Smirnov             FSL_IMX7_UART6_ADDR,
378*757282adSAndrey Smirnov             FSL_IMX7_UART7_ADDR,
379*757282adSAndrey Smirnov         };
380*757282adSAndrey Smirnov 
381*757282adSAndrey Smirnov         static const int FSL_IMX7_UARTn_IRQ[FSL_IMX7_NUM_UARTS] = {
382*757282adSAndrey Smirnov             FSL_IMX7_UART1_IRQ,
383*757282adSAndrey Smirnov             FSL_IMX7_UART2_IRQ,
384*757282adSAndrey Smirnov             FSL_IMX7_UART3_IRQ,
385*757282adSAndrey Smirnov             FSL_IMX7_UART4_IRQ,
386*757282adSAndrey Smirnov             FSL_IMX7_UART5_IRQ,
387*757282adSAndrey Smirnov             FSL_IMX7_UART6_IRQ,
388*757282adSAndrey Smirnov             FSL_IMX7_UART7_IRQ,
389*757282adSAndrey Smirnov         };
390*757282adSAndrey Smirnov 
391*757282adSAndrey Smirnov 
392*757282adSAndrey Smirnov         if (i < MAX_SERIAL_PORTS) {
393*757282adSAndrey Smirnov             qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hds[i]);
394*757282adSAndrey Smirnov         }
395*757282adSAndrey Smirnov 
396*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->uart[i]), true, "realized",
397*757282adSAndrey Smirnov                                  &error_abort);
398*757282adSAndrey Smirnov 
399*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX7_UARTn_ADDR[i]);
400*757282adSAndrey Smirnov 
401*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_UARTn_IRQ[i]);
402*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, irq);
403*757282adSAndrey Smirnov     }
404*757282adSAndrey Smirnov 
405*757282adSAndrey Smirnov     /*
406*757282adSAndrey Smirnov      * Ethernet
407*757282adSAndrey Smirnov      */
408*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
409*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = {
410*757282adSAndrey Smirnov             FSL_IMX7_ENET1_ADDR,
411*757282adSAndrey Smirnov             FSL_IMX7_ENET2_ADDR,
412*757282adSAndrey Smirnov         };
413*757282adSAndrey Smirnov 
414*757282adSAndrey Smirnov         object_property_set_uint(OBJECT(&s->eth[i]), FSL_IMX7_ETH_NUM_TX_RINGS,
415*757282adSAndrey Smirnov                                  "tx-ring-num", &error_abort);
416*757282adSAndrey Smirnov         qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]);
417*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->eth[i]), true, "realized",
418*757282adSAndrey Smirnov                                  &error_abort);
419*757282adSAndrey Smirnov 
420*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
421*757282adSAndrey Smirnov 
422*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 0));
423*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0, irq);
424*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 3));
425*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1, irq);
426*757282adSAndrey Smirnov     }
427*757282adSAndrey Smirnov 
428*757282adSAndrey Smirnov     /*
429*757282adSAndrey Smirnov      * USDHC
430*757282adSAndrey Smirnov      */
431*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
432*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = {
433*757282adSAndrey Smirnov             FSL_IMX7_USDHC1_ADDR,
434*757282adSAndrey Smirnov             FSL_IMX7_USDHC2_ADDR,
435*757282adSAndrey Smirnov             FSL_IMX7_USDHC3_ADDR,
436*757282adSAndrey Smirnov         };
437*757282adSAndrey Smirnov 
438*757282adSAndrey Smirnov         static const int FSL_IMX7_USDHCn_IRQ[FSL_IMX7_NUM_USDHCS] = {
439*757282adSAndrey Smirnov             FSL_IMX7_USDHC1_IRQ,
440*757282adSAndrey Smirnov             FSL_IMX7_USDHC2_IRQ,
441*757282adSAndrey Smirnov             FSL_IMX7_USDHC3_IRQ,
442*757282adSAndrey Smirnov         };
443*757282adSAndrey Smirnov 
444*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
445*757282adSAndrey Smirnov                                  &error_abort);
446*757282adSAndrey Smirnov 
447*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
448*757282adSAndrey Smirnov                         FSL_IMX7_USDHCn_ADDR[i]);
449*757282adSAndrey Smirnov 
450*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USDHCn_IRQ[i]);
451*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, irq);
452*757282adSAndrey Smirnov     }
453*757282adSAndrey Smirnov 
454*757282adSAndrey Smirnov     /*
455*757282adSAndrey Smirnov      * SNVS
456*757282adSAndrey Smirnov      */
457*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort);
458*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR);
459*757282adSAndrey Smirnov 
460*757282adSAndrey Smirnov     /*
461*757282adSAndrey Smirnov      * SRC
462*757282adSAndrey Smirnov      */
463*757282adSAndrey Smirnov     create_unimplemented_device("sdma", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
464*757282adSAndrey Smirnov 
465*757282adSAndrey Smirnov     /*
466*757282adSAndrey Smirnov      * Watchdog
467*757282adSAndrey Smirnov      */
468*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
469*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = {
470*757282adSAndrey Smirnov             FSL_IMX7_WDOG1_ADDR,
471*757282adSAndrey Smirnov             FSL_IMX7_WDOG2_ADDR,
472*757282adSAndrey Smirnov             FSL_IMX7_WDOG3_ADDR,
473*757282adSAndrey Smirnov             FSL_IMX7_WDOG4_ADDR,
474*757282adSAndrey Smirnov         };
475*757282adSAndrey Smirnov 
476*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
477*757282adSAndrey Smirnov                                  &error_abort);
478*757282adSAndrey Smirnov 
479*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
480*757282adSAndrey Smirnov     }
481*757282adSAndrey Smirnov 
482*757282adSAndrey Smirnov     /*
483*757282adSAndrey Smirnov      * SDMA
484*757282adSAndrey Smirnov      */
485*757282adSAndrey Smirnov     create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE);
486*757282adSAndrey Smirnov 
487*757282adSAndrey Smirnov 
488*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->gpr), true, "realized",
489*757282adSAndrey Smirnov                              &error_abort);
490*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR);
491*757282adSAndrey Smirnov 
492*757282adSAndrey Smirnov     object_property_set_bool(OBJECT(&s->pcie), true,
493*757282adSAndrey Smirnov                              "realized", &error_abort);
494*757282adSAndrey Smirnov     sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
495*757282adSAndrey Smirnov 
496*757282adSAndrey Smirnov     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ);
497*757282adSAndrey Smirnov     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq);
498*757282adSAndrey Smirnov     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ);
499*757282adSAndrey Smirnov     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq);
500*757282adSAndrey Smirnov     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ);
501*757282adSAndrey Smirnov     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq);
502*757282adSAndrey Smirnov     irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
503*757282adSAndrey Smirnov     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
504*757282adSAndrey Smirnov 
505*757282adSAndrey Smirnov 
506*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
507*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = {
508*757282adSAndrey Smirnov             FSL_IMX7_USBMISC1_ADDR,
509*757282adSAndrey Smirnov             FSL_IMX7_USBMISC2_ADDR,
510*757282adSAndrey Smirnov             FSL_IMX7_USBMISC3_ADDR,
511*757282adSAndrey Smirnov         };
512*757282adSAndrey Smirnov 
513*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_USBn_ADDR[FSL_IMX7_NUM_USBS] = {
514*757282adSAndrey Smirnov             FSL_IMX7_USB1_ADDR,
515*757282adSAndrey Smirnov             FSL_IMX7_USB2_ADDR,
516*757282adSAndrey Smirnov             FSL_IMX7_USB3_ADDR,
517*757282adSAndrey Smirnov         };
518*757282adSAndrey Smirnov 
519*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = {
520*757282adSAndrey Smirnov             FSL_IMX7_USB1_IRQ,
521*757282adSAndrey Smirnov             FSL_IMX7_USB2_IRQ,
522*757282adSAndrey Smirnov             FSL_IMX7_USB3_IRQ,
523*757282adSAndrey Smirnov         };
524*757282adSAndrey Smirnov 
525*757282adSAndrey Smirnov         object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
526*757282adSAndrey Smirnov                                  &error_abort);
527*757282adSAndrey Smirnov         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
528*757282adSAndrey Smirnov                         FSL_IMX7_USBn_ADDR[i]);
529*757282adSAndrey Smirnov 
530*757282adSAndrey Smirnov         irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USBn_IRQ[i]);
531*757282adSAndrey Smirnov         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, irq);
532*757282adSAndrey Smirnov 
533*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "usbmisc%d", i);
534*757282adSAndrey Smirnov         create_unimplemented_device(name, FSL_IMX7_USBMISCn_ADDR[i],
535*757282adSAndrey Smirnov                                     FSL_IMX7_USBMISCn_SIZE);
536*757282adSAndrey Smirnov     }
537*757282adSAndrey Smirnov 
538*757282adSAndrey Smirnov     /*
539*757282adSAndrey Smirnov      * ADCs
540*757282adSAndrey Smirnov      */
541*757282adSAndrey Smirnov     for (i = 0; i < FSL_IMX7_NUM_ADCS; i++) {
542*757282adSAndrey Smirnov         static const hwaddr FSL_IMX7_ADCn_ADDR[FSL_IMX7_NUM_ADCS] = {
543*757282adSAndrey Smirnov             FSL_IMX7_ADC1_ADDR,
544*757282adSAndrey Smirnov             FSL_IMX7_ADC2_ADDR,
545*757282adSAndrey Smirnov         };
546*757282adSAndrey Smirnov 
547*757282adSAndrey Smirnov         snprintf(name, NAME_SIZE, "adc%d", i);
548*757282adSAndrey Smirnov         create_unimplemented_device(name, FSL_IMX7_ADCn_ADDR[i],
549*757282adSAndrey Smirnov                                     FSL_IMX7_ADCn_SIZE);
550*757282adSAndrey Smirnov     }
551*757282adSAndrey Smirnov 
552*757282adSAndrey Smirnov     /*
553*757282adSAndrey Smirnov      * LCD
554*757282adSAndrey Smirnov      */
555*757282adSAndrey Smirnov     create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR,
556*757282adSAndrey Smirnov                                 FSL_IMX7_LCDIF_SIZE);
557*757282adSAndrey Smirnov }
558*757282adSAndrey Smirnov 
559*757282adSAndrey Smirnov static void fsl_imx7_class_init(ObjectClass *oc, void *data)
560*757282adSAndrey Smirnov {
561*757282adSAndrey Smirnov     DeviceClass *dc = DEVICE_CLASS(oc);
562*757282adSAndrey Smirnov 
563*757282adSAndrey Smirnov     dc->realize = fsl_imx7_realize;
564*757282adSAndrey Smirnov 
565*757282adSAndrey Smirnov     /* Reason: Uses serial_hds and nd_table in realize() directly */
566*757282adSAndrey Smirnov     dc->user_creatable = false;
567*757282adSAndrey Smirnov     dc->desc = "i.MX7 SOC";
568*757282adSAndrey Smirnov }
569*757282adSAndrey Smirnov 
570*757282adSAndrey Smirnov static const TypeInfo fsl_imx7_type_info = {
571*757282adSAndrey Smirnov     .name = TYPE_FSL_IMX7,
572*757282adSAndrey Smirnov     .parent = TYPE_DEVICE,
573*757282adSAndrey Smirnov     .instance_size = sizeof(FslIMX7State),
574*757282adSAndrey Smirnov     .instance_init = fsl_imx7_init,
575*757282adSAndrey Smirnov     .class_init = fsl_imx7_class_init,
576*757282adSAndrey Smirnov };
577*757282adSAndrey Smirnov 
578*757282adSAndrey Smirnov static void fsl_imx7_register_types(void)
579*757282adSAndrey Smirnov {
580*757282adSAndrey Smirnov     type_register_static(&fsl_imx7_type_info);
581*757282adSAndrey Smirnov }
582*757282adSAndrey Smirnov type_init(fsl_imx7_register_types)
583