2 * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
6 * Based on hw/arm/fsl-imx31.c
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "qemu/osdep.h"
23 #include "qapi/error.h"
24 #include "hw/arm/fsl-imx6.h"
25 #include "hw/misc/unimp.h"
26 #include "hw/usb/imx-usb-phy.h"
27 #include "hw/boards.h"
28 #include "hw/qdev-properties.h"
29 #include "sysemu/sysemu.h"
30 #include "chardev/char.h"
31 #include "qemu/error-report.h"
32 #include "qemu/module.h"
33 #include "target/arm/cpu-qom.h"
35 #define IMX6_ESDHC_CAPABILITIES 0x057834b4
39 static void fsl_imx6_init(Object
*obj
)
41 MachineState
*ms
= MACHINE(qdev_get_machine());
42 FslIMX6State
*s
= FSL_IMX6(obj
);
46 for (i
= 0; i
< MIN(ms
->smp
.cpus
, FSL_IMX6_NUM_CPUS
); i
++) {
47 snprintf(name
, NAME_SIZE
, "cpu%d", i
);
48 object_initialize_child(obj
, name
, &s
->cpu
[i
],
49 ARM_CPU_TYPE_NAME("cortex-a9"));
52 object_initialize_child(obj
, "a9mpcore", &s
->a9mpcore
, TYPE_A9MPCORE_PRIV
);
54 object_initialize_child(obj
, "ccm", &s
->ccm
, TYPE_IMX6_CCM
);
56 object_initialize_child(obj
, "src", &s
->src
, TYPE_IMX6_SRC
);
58 object_initialize_child(obj
, "snvs", &s
->snvs
, TYPE_IMX7_SNVS
);
60 for (i
= 0; i
< FSL_IMX6_NUM_UARTS
; i
++) {
61 snprintf(name
, NAME_SIZE
, "uart%d", i
+ 1);
62 object_initialize_child(obj
, name
, &s
->uart
[i
], TYPE_IMX_SERIAL
);
65 object_initialize_child(obj
, "gpt", &s
->gpt
, TYPE_IMX6_GPT
);
67 for (i
= 0; i
< FSL_IMX6_NUM_EPITS
; i
++) {
68 snprintf(name
, NAME_SIZE
, "epit%d", i
+ 1);
69 object_initialize_child(obj
, name
, &s
->epit
[i
], TYPE_IMX_EPIT
);
72 for (i
= 0; i
< FSL_IMX6_NUM_I2CS
; i
++) {
73 snprintf(name
, NAME_SIZE
, "i2c%d", i
+ 1);
74 object_initialize_child(obj
, name
, &s
->i2c
[i
], TYPE_IMX_I2C
);
77 for (i
= 0; i
< FSL_IMX6_NUM_GPIOS
; i
++) {
78 snprintf(name
, NAME_SIZE
, "gpio%d", i
+ 1);
79 object_initialize_child(obj
, name
, &s
->gpio
[i
], TYPE_IMX_GPIO
);
82 for (i
= 0; i
< FSL_IMX6_NUM_ESDHCS
; i
++) {
83 snprintf(name
, NAME_SIZE
, "sdhc%d", i
+ 1);
84 object_initialize_child(obj
, name
, &s
->esdhc
[i
], TYPE_IMX_USDHC
);
87 for (i
= 0; i
< FSL_IMX6_NUM_USB_PHYS
; i
++) {
88 snprintf(name
, NAME_SIZE
, "usbphy%d", i
);
89 object_initialize_child(obj
, name
, &s
->usbphy
[i
], TYPE_IMX_USBPHY
);
91 for (i
= 0; i
< FSL_IMX6_NUM_USBS
; i
++) {
92 snprintf(name
, NAME_SIZE
, "usb%d", i
);
93 object_initialize_child(obj
, name
, &s
->usb
[i
], TYPE_CHIPIDEA
);
96 for (i
= 0; i
< FSL_IMX6_NUM_ECSPIS
; i
++) {
97 snprintf(name
, NAME_SIZE
, "spi%d", i
+ 1);
98 object_initialize_child(obj
, name
, &s
->spi
[i
], TYPE_IMX_SPI
);
100 for (i
= 0; i
< FSL_IMX6_NUM_WDTS
; i
++) {
101 snprintf(name
, NAME_SIZE
, "wdt%d", i
);
102 object_initialize_child(obj
, name
, &s
->wdt
[i
], TYPE_IMX2_WDT
);
106 object_initialize_child(obj
, "eth", &s
->eth
, TYPE_IMX_ENET
);
108 object_initialize_child(obj
, "pcie", &s
->pcie
, TYPE_DESIGNWARE_PCIE_HOST
);
111 static void fsl_imx6_realize(DeviceState
*dev
, Error
**errp
)
113 MachineState
*ms
= MACHINE(qdev_get_machine());
114 FslIMX6State
*s
= FSL_IMX6(dev
);
117 unsigned int smp_cpus
= ms
->smp
.cpus
;
119 if (smp_cpus
> FSL_IMX6_NUM_CPUS
) {
120 error_setg(errp
, "%s: Only %d CPUs are supported (%d requested)",
121 TYPE_FSL_IMX6
, FSL_IMX6_NUM_CPUS
, smp_cpus
);
125 for (i
= 0; i
< smp_cpus
; i
++) {
127 /* On uniprocessor, the CBAR is set to 0 */
129 object_property_set_int(OBJECT(&s
->cpu
[i
]), "reset-cbar",
130 FSL_IMX6_A9MPCORE_ADDR
, &error_abort
);
133 /* All CPU but CPU 0 start in power off mode */
135 object_property_set_bool(OBJECT(&s
->cpu
[i
]), "start-powered-off",
139 if (!qdev_realize(DEVICE(&s
->cpu
[i
]), NULL
, errp
)) {
144 object_property_set_int(OBJECT(&s
->a9mpcore
), "num-cpu", smp_cpus
,
147 object_property_set_int(OBJECT(&s
->a9mpcore
), "num-irq",
148 FSL_IMX6_MAX_IRQ
+ GIC_INTERNAL
, &error_abort
);
150 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->a9mpcore
), errp
)) {
153 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->a9mpcore
), 0, FSL_IMX6_A9MPCORE_ADDR
);
155 for (i
= 0; i
< smp_cpus
; i
++) {
156 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->a9mpcore
), i
,
157 qdev_get_gpio_in(DEVICE(&s
->cpu
[i
]), ARM_CPU_IRQ
));
158 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->a9mpcore
), i
+ smp_cpus
,
159 qdev_get_gpio_in(DEVICE(&s
->cpu
[i
]), ARM_CPU_FIQ
));
162 /* L2 cache controller */
163 sysbus_create_simple("l2x0", FSL_IMX6_PL310_ADDR
, NULL
);
165 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->ccm
), errp
)) {
168 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->ccm
), 0, FSL_IMX6_CCM_ADDR
);
170 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->src
), errp
)) {
173 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->src
), 0, FSL_IMX6_SRC_ADDR
);
175 /* Initialize all UARTs */
176 for (i
= 0; i
< FSL_IMX6_NUM_UARTS
; i
++) {
177 static const struct {
180 } serial_table
[FSL_IMX6_NUM_UARTS
] = {
181 { FSL_IMX6_UART1_ADDR
, FSL_IMX6_UART1_IRQ
},
182 { FSL_IMX6_UART2_ADDR
, FSL_IMX6_UART2_IRQ
},
183 { FSL_IMX6_UART3_ADDR
, FSL_IMX6_UART3_IRQ
},
184 { FSL_IMX6_UART4_ADDR
, FSL_IMX6_UART4_IRQ
},
185 { FSL_IMX6_UART5_ADDR
, FSL_IMX6_UART5_IRQ
},
188 qdev_prop_set_chr(DEVICE(&s
->uart
[i
]), "chardev", serial_hd(i
));
190 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->uart
[i
]), errp
)) {
194 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->uart
[i
]), 0, serial_table
[i
].addr
);
195 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->uart
[i
]), 0,
196 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
197 serial_table
[i
].irq
));
200 s
->gpt
.ccm
= IMX_CCM(&s
->ccm
);
202 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->gpt
), errp
)) {
206 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->gpt
), 0, FSL_IMX6_GPT_ADDR
);
207 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->gpt
), 0,
208 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
211 /* Initialize all EPIT timers */
212 for (i
= 0; i
< FSL_IMX6_NUM_EPITS
; i
++) {
213 static const struct {
216 } epit_table
[FSL_IMX6_NUM_EPITS
] = {
217 { FSL_IMX6_EPIT1_ADDR
, FSL_IMX6_EPIT1_IRQ
},
218 { FSL_IMX6_EPIT2_ADDR
, FSL_IMX6_EPIT2_IRQ
},
221 s
->epit
[i
].ccm
= IMX_CCM(&s
->ccm
);
223 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->epit
[i
]), errp
)) {
227 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->epit
[i
]), 0, epit_table
[i
].addr
);
228 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->epit
[i
]), 0,
229 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
233 /* Initialize all I2C */
234 for (i
= 0; i
< FSL_IMX6_NUM_I2CS
; i
++) {
235 static const struct {
238 } i2c_table
[FSL_IMX6_NUM_I2CS
] = {
239 { FSL_IMX6_I2C1_ADDR
, FSL_IMX6_I2C1_IRQ
},
240 { FSL_IMX6_I2C2_ADDR
, FSL_IMX6_I2C2_IRQ
},
241 { FSL_IMX6_I2C3_ADDR
, FSL_IMX6_I2C3_IRQ
}
244 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->i2c
[i
]), errp
)) {
248 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->i2c
[i
]), 0, i2c_table
[i
].addr
);
249 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->i2c
[i
]), 0,
250 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
254 /* Initialize all GPIOs */
255 for (i
= 0; i
< FSL_IMX6_NUM_GPIOS
; i
++) {
256 static const struct {
258 unsigned int irq_low
;
259 unsigned int irq_high
;
260 } gpio_table
[FSL_IMX6_NUM_GPIOS
] = {
263 FSL_IMX6_GPIO1_LOW_IRQ
,
264 FSL_IMX6_GPIO1_HIGH_IRQ
268 FSL_IMX6_GPIO2_LOW_IRQ
,
269 FSL_IMX6_GPIO2_HIGH_IRQ
273 FSL_IMX6_GPIO3_LOW_IRQ
,
274 FSL_IMX6_GPIO3_HIGH_IRQ
278 FSL_IMX6_GPIO4_LOW_IRQ
,
279 FSL_IMX6_GPIO4_HIGH_IRQ
283 FSL_IMX6_GPIO5_LOW_IRQ
,
284 FSL_IMX6_GPIO5_HIGH_IRQ
288 FSL_IMX6_GPIO6_LOW_IRQ
,
289 FSL_IMX6_GPIO6_HIGH_IRQ
293 FSL_IMX6_GPIO7_LOW_IRQ
,
294 FSL_IMX6_GPIO7_HIGH_IRQ
298 object_property_set_bool(OBJECT(&s
->gpio
[i
]), "has-edge-sel", true,
300 object_property_set_bool(OBJECT(&s
->gpio
[i
]), "has-upper-pin-irq",
302 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->gpio
[i
]), errp
)) {
306 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->gpio
[i
]), 0, gpio_table
[i
].addr
);
307 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->gpio
[i
]), 0,
308 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
309 gpio_table
[i
].irq_low
));
310 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->gpio
[i
]), 1,
311 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
312 gpio_table
[i
].irq_high
));
315 /* Initialize all SDHC */
316 for (i
= 0; i
< FSL_IMX6_NUM_ESDHCS
; i
++) {
317 static const struct {
320 } esdhc_table
[FSL_IMX6_NUM_ESDHCS
] = {
321 { FSL_IMX6_uSDHC1_ADDR
, FSL_IMX6_uSDHC1_IRQ
},
322 { FSL_IMX6_uSDHC2_ADDR
, FSL_IMX6_uSDHC2_IRQ
},
323 { FSL_IMX6_uSDHC3_ADDR
, FSL_IMX6_uSDHC3_IRQ
},
324 { FSL_IMX6_uSDHC4_ADDR
, FSL_IMX6_uSDHC4_IRQ
},
327 /* UHS-I SDIO3.0 SDR104 1.8V ADMA */
328 object_property_set_uint(OBJECT(&s
->esdhc
[i
]), "sd-spec-version", 3,
330 object_property_set_uint(OBJECT(&s
->esdhc
[i
]), "capareg",
331 IMX6_ESDHC_CAPABILITIES
, &error_abort
);
332 object_property_set_uint(OBJECT(&s
->esdhc
[i
]), "vendor",
333 SDHCI_VENDOR_IMX
, &error_abort
);
334 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->esdhc
[i
]), errp
)) {
337 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->esdhc
[i
]), 0, esdhc_table
[i
].addr
);
338 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->esdhc
[i
]), 0,
339 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
340 esdhc_table
[i
].irq
));
344 for (i
= 0; i
< FSL_IMX6_NUM_USB_PHYS
; i
++) {
345 sysbus_realize(SYS_BUS_DEVICE(&s
->usbphy
[i
]), &error_abort
);
346 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->usbphy
[i
]), 0,
347 FSL_IMX6_USBPHY1_ADDR
+ i
* 0x1000);
349 for (i
= 0; i
< FSL_IMX6_NUM_USBS
; i
++) {
350 static const int FSL_IMX6_USBn_IRQ
[] = {
351 FSL_IMX6_USB_OTG_IRQ
,
352 FSL_IMX6_USB_HOST1_IRQ
,
353 FSL_IMX6_USB_HOST2_IRQ
,
354 FSL_IMX6_USB_HOST3_IRQ
,
357 sysbus_realize(SYS_BUS_DEVICE(&s
->usb
[i
]), &error_abort
);
358 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->usb
[i
]), 0,
359 FSL_IMX6_USBOH3_USB_ADDR
+ i
* 0x200);
360 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->usb
[i
]), 0,
361 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
362 FSL_IMX6_USBn_IRQ
[i
]));
365 /* Initialize all ECSPI */
366 for (i
= 0; i
< FSL_IMX6_NUM_ECSPIS
; i
++) {
367 static const struct {
370 } spi_table
[FSL_IMX6_NUM_ECSPIS
] = {
371 { FSL_IMX6_eCSPI1_ADDR
, FSL_IMX6_ECSPI1_IRQ
},
372 { FSL_IMX6_eCSPI2_ADDR
, FSL_IMX6_ECSPI2_IRQ
},
373 { FSL_IMX6_eCSPI3_ADDR
, FSL_IMX6_ECSPI3_IRQ
},
374 { FSL_IMX6_eCSPI4_ADDR
, FSL_IMX6_ECSPI4_IRQ
},
375 { FSL_IMX6_eCSPI5_ADDR
, FSL_IMX6_ECSPI5_IRQ
},
378 /* Initialize the SPI */
379 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->spi
[i
]), errp
)) {
383 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->spi
[i
]), 0, spi_table
[i
].addr
);
384 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->spi
[i
]), 0,
385 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
389 object_property_set_uint(OBJECT(&s
->eth
), "phy-num", s
->phy_num
,
391 qemu_configure_nic_device(DEVICE(&s
->eth
), true, NULL
);
392 if (!sysbus_realize(SYS_BUS_DEVICE(&s
->eth
), errp
)) {
395 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->eth
), 0, FSL_IMX6_ENET_ADDR
);
396 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->eth
), 0,
397 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
398 FSL_IMX6_ENET_MAC_IRQ
));
399 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->eth
), 1,
400 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
401 FSL_IMX6_ENET_MAC_1588_IRQ
));
406 sysbus_realize(SYS_BUS_DEVICE(&s
->snvs
), &error_abort
);
407 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->snvs
), 0, FSL_IMX6_SNVSHP_ADDR
);
412 for (i
= 0; i
< FSL_IMX6_NUM_WDTS
; i
++) {
413 static const hwaddr FSL_IMX6_WDOGn_ADDR
[FSL_IMX6_NUM_WDTS
] = {
417 static const int FSL_IMX6_WDOGn_IRQ
[FSL_IMX6_NUM_WDTS
] = {
422 object_property_set_bool(OBJECT(&s
->wdt
[i
]), "pretimeout-support",
424 sysbus_realize(SYS_BUS_DEVICE(&s
->wdt
[i
]), &error_abort
);
426 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->wdt
[i
]), 0, FSL_IMX6_WDOGn_ADDR
[i
]);
427 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->wdt
[i
]), 0,
428 qdev_get_gpio_in(DEVICE(&s
->a9mpcore
),
429 FSL_IMX6_WDOGn_IRQ
[i
]));
435 sysbus_realize(SYS_BUS_DEVICE(&s
->pcie
), &error_abort
);
436 sysbus_mmio_map(SYS_BUS_DEVICE(&s
->pcie
), 0, FSL_IMX6_PCIe_REG_ADDR
);
438 irq
= qdev_get_gpio_in(DEVICE(&s
->a9mpcore
), FSL_IMX6_PCIE1_IRQ
);
439 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->pcie
), 0, irq
);
440 irq
= qdev_get_gpio_in(DEVICE(&s
->a9mpcore
), FSL_IMX6_PCIE2_IRQ
);
441 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->pcie
), 1, irq
);
442 irq
= qdev_get_gpio_in(DEVICE(&s
->a9mpcore
), FSL_IMX6_PCIE3_IRQ
);
443 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->pcie
), 2, irq
);
444 irq
= qdev_get_gpio_in(DEVICE(&s
->a9mpcore
), FSL_IMX6_PCIE4_IRQ
);
445 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->pcie
), 3, irq
);
450 create_unimplemented_device("pcie-phy", FSL_IMX6_PCIe_ADDR
,
454 if (!memory_region_init_rom(&s
->rom
, OBJECT(dev
), "imx6.rom",
455 FSL_IMX6_ROM_SIZE
, errp
)) {
458 memory_region_add_subregion(get_system_memory(), FSL_IMX6_ROM_ADDR
,
462 if (!memory_region_init_rom(&s
->caam
, OBJECT(dev
), "imx6.caam",
463 FSL_IMX6_CAAM_MEM_SIZE
, errp
)) {
466 memory_region_add_subregion(get_system_memory(), FSL_IMX6_CAAM_MEM_ADDR
,
470 if (!memory_region_init_ram(&s
->ocram
, NULL
, "imx6.ocram",
471 FSL_IMX6_OCRAM_SIZE
, errp
)) {
474 memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ADDR
,
477 /* internal OCRAM (256 KB) is aliased over 1 MB */
478 memory_region_init_alias(&s
->ocram_alias
, OBJECT(dev
), "imx6.ocram_alias",
479 &s
->ocram
, 0, FSL_IMX6_OCRAM_ALIAS_SIZE
);
480 memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ALIAS_ADDR
,
484 static Property fsl_imx6_properties
[] = {
485 DEFINE_PROP_UINT32("fec-phy-num", FslIMX6State
, phy_num
, 0),
486 DEFINE_PROP_END_OF_LIST(),
489 static void fsl_imx6_class_init(ObjectClass
*oc
, void *data
)
491 DeviceClass
*dc
= DEVICE_CLASS(oc
);
493 device_class_set_props(dc
, fsl_imx6_properties
);
494 dc
->realize
= fsl_imx6_realize
;
495 dc
->desc
= "i.MX6 SOC";
496 /* Reason: Uses serial_hd() in the realize() function */
497 dc
->user_creatable
= false;
500 static const TypeInfo fsl_imx6_type_info
= {
501 .name
= TYPE_FSL_IMX6
,
502 .parent
= TYPE_DEVICE
,
503 .instance_size
= sizeof(FslIMX6State
),
504 .instance_init
= fsl_imx6_init
,
505 .class_init
= fsl_imx6_class_init
,
508 static void fsl_imx6_register_types(void)
510 type_register_static(&fsl_imx6_type_info
);
513 type_init(fsl_imx6_register_types
)