master
c 705 lines 28.3 KB
Raw
1 /*
2 * i.MX 8MM SoC Implementation
3 *
4 * Based on hw/arm/fsl-imx6.c
5 *
6 * Copyright (c) 2025, NXP Semiconductors
7 * Author: Gaurav Sharma <gaurav.sharma_7@nxp.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 *
11 * iMX8MM Reference Manual - https://www.nxp.com/products/i.MX8MMINI -> Documentation
12 */
13
14 #include "qemu/osdep.h"
15 #include "system/address-spaces.h"
16 #include "hw/arm/bsa.h"
17 #include "hw/arm/fsl-imx8mm.h"
18 #include "hw/misc/unimp.h"
19 #include "hw/core/boards.h"
20 #include "system/kvm.h"
21 #include "system/system.h"
22 #include "target/arm/cpu.h"
23 #include "target/arm/cpu-qom.h"
24 #include "target/arm/kvm_arm.h"
25 #include "qapi/error.h"
26 #include "qobject/qlist.h"
27
28 static const struct {
29 hwaddr addr;
30 size_t size;
31 const char *name;
32 } fsl_imx8mm_memmap[] = {
33 [FSL_IMX8MM_RAM] = { FSL_IMX8MM_RAM_START, FSL_IMX8MM_RAM_SIZE_MAX, "ram" },
34 [FSL_IMX8MM_DDR_PHY_BROADCAST] = { 0x3dc00000, 4 * MiB, "ddr_phy_broadcast" },
35 [FSL_IMX8MM_DDR_PERF_MON] = { 0x3d800000, 4 * MiB, "ddr_perf_mon" },
36 [FSL_IMX8MM_DDR_CTL] = { 0x3d400000, 4 * MiB, "ddr_ctl" },
37 [FSL_IMX8MM_DDR_PHY] = { 0x3c000000, 16 * MiB, "ddr_phy" },
38 [FSL_IMX8MM_GIC_DIST] = { 0x38800000, 512 * KiB, "gic_dist" },
39 [FSL_IMX8MM_GIC_REDIST] = { 0x38880000, 512 * KiB, "gic_redist" },
40 [FSL_IMX8MM_VPU] = { 0x38340000, 2 * MiB, "vpu" },
41 [FSL_IMX8MM_VPU_BLK_CTRL] = { 0x38330000, 2 * MiB, "vpu_blk_ctrl" },
42 [FSL_IMX8MM_VPU_G2_DECODER] = { 0x38310000, 1 * MiB, "vpu_g2_decoder" },
43 [FSL_IMX8MM_VPU_G1_DECODER] = { 0x38300000, 1 * MiB, "vpu_g1_decoder" },
44 [FSL_IMX8MM_USB2_OTG] = { 0x32e50200, 0x200, "usb2_otg" },
45 [FSL_IMX8MM_USB2] = { 0x32e50000, 0x200, "usb2" },
46 [FSL_IMX8MM_USB1_OTG] = { 0x32e40200, 0x200, "usb1_otg" },
47 [FSL_IMX8MM_USB1] = { 0x32e40000, 0x200, "usb1" },
48 [FSL_IMX8MM_GPU2D] = { 0x38000000, 64 * KiB, "gpu2d" },
49 [FSL_IMX8MM_QSPI1_RX_BUFFER] = { 0x34000000, 32 * MiB, "qspi1_rx_buffer" },
50 [FSL_IMX8MM_PCIE1] = { 0x33800000, 4 * MiB, "pcie1" },
51 [FSL_IMX8MM_QSPI1_TX_BUFFER] = { 0x33008000, 32 * KiB, "qspi1_tx_buffer" },
52 [FSL_IMX8MM_APBH_DMA] = { 0x33000000, 32 * KiB, "apbh_dma" },
53
54 /* AIPS-4 Begin */
55 [FSL_IMX8MM_TZASC] = { 0x32f80000, 64 * KiB, "tzasc" },
56 [FSL_IMX8MM_PCIE_PHY1] = { 0x32f00000, 64 * KiB, "pcie_phy1" },
57 [FSL_IMX8MM_MEDIA_BLK_CTL] = { 0x32e28000, 256, "media_blk_ctl" },
58 [FSL_IMX8MM_LCDIF] = { 0x32e00000, 64 * KiB, "lcdif" },
59 [FSL_IMX8MM_MIPI_DSI] = { 0x32e10000, 64 * KiB, "mipi_dsi" },
60 [FSL_IMX8MM_MIPI_CSI] = { 0x32e30000, 64 * KiB, "mipi_csi" },
61 [FSL_IMX8MM_AIPS4_CONFIGURATION] = { 0x32df0000, 64 * KiB, "aips4_configuration" },
62 /* AIPS-4 End */
63
64 [FSL_IMX8MM_INTERCONNECT] = { 0x32700000, 1 * MiB, "interconnect" },
65
66 /* AIPS-3 Begin */
67 [FSL_IMX8MM_ENET1] = { 0x30be0000, 64 * KiB, "enet1" },
68 [FSL_IMX8MM_SDMA1] = { 0x30bd0000, 64 * KiB, "sdma1" },
69 [FSL_IMX8MM_QSPI] = { 0x30bb0000, 64 * KiB, "qspi" },
70 [FSL_IMX8MM_USDHC3] = { 0x30b60000, 64 * KiB, "usdhc3" },
71 [FSL_IMX8MM_USDHC2] = { 0x30b50000, 64 * KiB, "usdhc2" },
72 [FSL_IMX8MM_USDHC1] = { 0x30b40000, 64 * KiB, "usdhc1" },
73 [FSL_IMX8MM_SEMAPHORE_HS] = { 0x30ac0000, 64 * KiB, "semaphore_hs" },
74 [FSL_IMX8MM_MU_B] = { 0x30ab0000, 64 * KiB, "mu_b" },
75 [FSL_IMX8MM_MU_A] = { 0x30aa0000, 64 * KiB, "mu_a" },
76 [FSL_IMX8MM_UART4] = { 0x30a60000, 64 * KiB, "uart4" },
77 [FSL_IMX8MM_I2C4] = { 0x30a50000, 64 * KiB, "i2c4" },
78 [FSL_IMX8MM_I2C3] = { 0x30a40000, 64 * KiB, "i2c3" },
79 [FSL_IMX8MM_I2C2] = { 0x30a30000, 64 * KiB, "i2c2" },
80 [FSL_IMX8MM_I2C1] = { 0x30a20000, 64 * KiB, "i2c1" },
81 [FSL_IMX8MM_AIPS3_CONFIGURATION] = { 0x309f0000, 64 * KiB, "aips3_configuration" },
82 [FSL_IMX8MM_CAAM] = { 0x30900000, 256 * KiB, "caam" },
83 [FSL_IMX8MM_SPBA1] = { 0x308f0000, 64 * KiB, "spba1" },
84 [FSL_IMX8MM_UART2] = { 0x30890000, 64 * KiB, "uart2" },
85 [FSL_IMX8MM_UART3] = { 0x30880000, 64 * KiB, "uart3" },
86 [FSL_IMX8MM_UART1] = { 0x30860000, 64 * KiB, "uart1" },
87 [FSL_IMX8MM_ECSPI3] = { 0x30840000, 64 * KiB, "ecspi3" },
88 [FSL_IMX8MM_ECSPI2] = { 0x30830000, 64 * KiB, "ecspi2" },
89 [FSL_IMX8MM_ECSPI1] = { 0x30820000, 64 * KiB, "ecspi1" },
90 /* AIPS-3 End */
91
92 /* AIPS-2 Begin */
93 [FSL_IMX8MM_QOSC] = { 0x307f0000, 64 * KiB, "qosc" },
94 [FSL_IMX8MM_PERFMON2] = { 0x307d0000, 64 * KiB, "perfmon2" },
95 [FSL_IMX8MM_PERFMON1] = { 0x307c0000, 64 * KiB, "perfmon1" },
96 [FSL_IMX8MM_GPT4] = { 0x30700000, 64 * KiB, "gpt4" },
97 [FSL_IMX8MM_GPT5] = { 0x306f0000, 64 * KiB, "gpt5" },
98 [FSL_IMX8MM_GPT6] = { 0x306e0000, 64 * KiB, "gpt6" },
99 [FSL_IMX8MM_SYSCNT_CTRL] = { 0x306c0000, 64 * KiB, "syscnt_ctrl" },
100 [FSL_IMX8MM_SYSCNT_CMP] = { 0x306b0000, 64 * KiB, "syscnt_cmp" },
101 [FSL_IMX8MM_SYSCNT_RD] = { 0x306a0000, 64 * KiB, "syscnt_rd" },
102 [FSL_IMX8MM_PWM4] = { 0x30690000, 64 * KiB, "pwm4" },
103 [FSL_IMX8MM_PWM3] = { 0x30680000, 64 * KiB, "pwm3" },
104 [FSL_IMX8MM_PWM2] = { 0x30670000, 64 * KiB, "pwm2" },
105 [FSL_IMX8MM_PWM1] = { 0x30660000, 64 * KiB, "pwm1" },
106 [FSL_IMX8MM_AIPS2_CONFIGURATION] = { 0x305f0000, 64 * KiB, "aips2_configuration" },
107 /* AIPS-2 End */
108
109 /* AIPS-1 Begin */
110 [FSL_IMX8MM_CSU] = { 0x303e0000, 64 * KiB, "csu" },
111 [FSL_IMX8MM_RDC] = { 0x303d0000, 64 * KiB, "rdc" },
112 [FSL_IMX8MM_SEMAPHORE2] = { 0x303c0000, 64 * KiB, "semaphore2" },
113 [FSL_IMX8MM_SEMAPHORE1] = { 0x303b0000, 64 * KiB, "semaphore1" },
114 [FSL_IMX8MM_GPC] = { 0x303a0000, 64 * KiB, "gpc" },
115 [FSL_IMX8MM_SRC] = { 0x30390000, 64 * KiB, "src" },
116 [FSL_IMX8MM_CCM] = { 0x30380000, 64 * KiB, "ccm" },
117 [FSL_IMX8MM_SNVS_HP] = { 0x30370000, 64 * KiB, "snvs_hp" },
118 [FSL_IMX8MM_ANA_PLL] = { 0x30360000, 64 * KiB, "ana_pll" },
119 [FSL_IMX8MM_OCOTP_CTRL] = { 0x30350000, 64 * KiB, "ocotp_ctrl" },
120 [FSL_IMX8MM_IOMUXC_GPR] = { 0x30340000, 64 * KiB, "iomuxc_gpr" },
121 [FSL_IMX8MM_IOMUXC] = { 0x30330000, 64 * KiB, "iomuxc" },
122 [FSL_IMX8MM_GPT3] = { 0x302f0000, 64 * KiB, "gpt3" },
123 [FSL_IMX8MM_GPT2] = { 0x302e0000, 64 * KiB, "gpt2" },
124 [FSL_IMX8MM_GPT1] = { 0x302d0000, 64 * KiB, "gpt1" },
125 [FSL_IMX8MM_SDMA2] = { 0x302c0000, 64 * KiB, "sdma2" },
126 [FSL_IMX8MM_SDMA3] = { 0x302b0000, 64 * KiB, "sdma3" },
127 [FSL_IMX8MM_WDOG3] = { 0x302a0000, 64 * KiB, "wdog3" },
128 [FSL_IMX8MM_WDOG2] = { 0x30290000, 64 * KiB, "wdog2" },
129 [FSL_IMX8MM_WDOG1] = { 0x30280000, 64 * KiB, "wdog1" },
130 [FSL_IMX8MM_ANA_OSC] = { 0x30270000, 64 * KiB, "ana_osc" },
131 [FSL_IMX8MM_ANA_TSENSOR] = { 0x30260000, 64 * KiB, "ana_tsensor" },
132 [FSL_IMX8MM_GPIO5] = { 0x30240000, 64 * KiB, "gpio5" },
133 [FSL_IMX8MM_GPIO4] = { 0x30230000, 64 * KiB, "gpio4" },
134 [FSL_IMX8MM_GPIO3] = { 0x30220000, 64 * KiB, "gpio3" },
135 [FSL_IMX8MM_GPIO2] = { 0x30210000, 64 * KiB, "gpio2" },
136 [FSL_IMX8MM_GPIO1] = { 0x30200000, 64 * KiB, "gpio1" },
137 [FSL_IMX8MM_AIPS1_CONFIGURATION] = { 0x301f0000, 64 * KiB, "aips1_configuration" },
138 [FSL_IMX8MM_SAI6] = { 0x30060000, 64 * KiB, "sai6" },
139 [FSL_IMX8MM_SAI5] = { 0x30050000, 64 * KiB, "sai5" },
140 [FSL_IMX8MM_SAI3] = { 0x30030000, 64 * KiB, "sai3" },
141 [FSL_IMX8MM_SAI2] = { 0x30020000, 64 * KiB, "sai2" },
142 [FSL_IMX8MM_SAI1] = { 0x30010000, 64 * KiB, "sai1" },
143
144 /* AIPS-1 End */
145
146 [FSL_IMX8MM_A53_DAP] = { 0x28000000, 16 * MiB, "a53_dap" },
147 [FSL_IMX8MM_PCIE1_MEM] = { 0x18000000, 128 * MiB, "pcie1_mem" },
148 [FSL_IMX8MM_QSPI_MEM] = { 0x08000000, 256 * MiB, "qspi_mem" },
149 [FSL_IMX8MM_OCRAM] = { 0x00900000, 256 * KiB, "ocram" },
150 [FSL_IMX8MM_TCM_DTCM] = { 0x00800000, 128 * KiB, "tcm_dtcm" },
151 [FSL_IMX8MM_TCM_ITCM] = { 0x007e0000, 128 * KiB, "tcm_itcm" },
152 [FSL_IMX8MM_OCRAM_S] = { 0x00180000, 32 * KiB, "ocram_s" },
153 [FSL_IMX8MM_CAAM_MEM] = { 0x00100000, 32 * KiB, "caam_mem" },
154 [FSL_IMX8MM_BOOT_ROM_PROTECTED] = { 0x0003f000, 4 * KiB, "boot_rom_protected" },
155 [FSL_IMX8MM_BOOT_ROM] = { 0x00000000, 252 * KiB, "boot_rom" },
156 };
157
158 static void fsl_imx8mm_init(Object *obj)
159 {
160 FslImx8mmState *s = FSL_IMX8MM(obj);
161 int i;
162
163 object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
164
165 object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
166
167 object_initialize_child(obj, "analog", &s->analog, TYPE_IMX8MP_ANALOG);
168
169 object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
170
171 for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
172 g_autofree char *name = g_strdup_printf("uart%d", i + 1);
173 object_initialize_child(obj, name, &s->uart[i], TYPE_IMX_SERIAL);
174 }
175
176 for (i = 0; i < FSL_IMX8MM_NUM_GPTS; i++) {
177 g_autofree char *name = g_strdup_printf("gpt%d", i + 1);
178 object_initialize_child(obj, name, &s->gpt[i], TYPE_IMX8MM_GPT);
179 }
180 object_initialize_child(obj, "gpt5-gpt6-irq", &s->gpt5_gpt6_irq,
181 TYPE_OR_IRQ);
182
183 for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
184 g_autofree char *name = g_strdup_printf("i2c%d", i + 1);
185 object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
186 }
187
188 for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
189 g_autofree char *name = g_strdup_printf("gpio%d", i + 1);
190 object_initialize_child(obj, name, &s->gpio[i], TYPE_IMX_GPIO);
191 }
192
193 for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
194 g_autofree char *name = g_strdup_printf("usdhc%d", i + 1);
195 object_initialize_child(obj, name, &s->usdhc[i], TYPE_IMX_USDHC);
196 }
197
198 for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
199 g_autofree char *name = g_strdup_printf("usb%d", i);
200 object_initialize_child(obj, name, &s->usb[i], TYPE_USB_DWC3);
201 }
202
203 for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
204 g_autofree char *name = g_strdup_printf("spi%d", i + 1);
205 object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
206 }
207
208 for (i = 0; i < FSL_IMX8MM_NUM_WDTS; i++) {
209 g_autofree char *name = g_strdup_printf("wdt%d", i);
210 object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
211 }
212
213 object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
214
215 object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
216 object_initialize_child(obj, "pcie_phy", &s->pcie_phy,
217 TYPE_FSL_IMX8M_PCIE_PHY);
218 }
219
220 static void fsl_imx8mm_realize(DeviceState *dev, Error **errp)
221 {
222 MachineState *ms = MACHINE(qdev_get_machine());
223 FslImx8mmState *s = FSL_IMX8MM(dev);
224 DeviceState *gicdev = DEVICE(&s->gic);
225 const char *cpu_type =
226 ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
227 int i;
228
229 if (ms->smp.cpus > FSL_IMX8MM_NUM_CPUS) {
230 error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
231 TYPE_FSL_IMX8MM, FSL_IMX8MM_NUM_CPUS, ms->smp.cpus);
232 return;
233 }
234
235 for (i = 0; i < ms->smp.cpus; i++) {
236 g_autofree char *name = g_strdup_printf("cpu%d", i);
237 object_initialize_child(OBJECT(dev), name,
238 &s->cpu[i], cpu_type);
239 }
240
241 /* CPUs */
242 for (i = 0; i < ms->smp.cpus; i++) {
243 /* On uniprocessor, the CBAR is set to 0 */
244 if (ms->smp.cpus > 1 &&
245 object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
246 object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
247 fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr,
248 &error_abort);
249 }
250
251 /*
252 * CNTFID0 base frequency in Hz of system counter
253 */
254 object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
255 &error_abort);
256
257 if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
258 object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
259 !kvm_enabled(), &error_abort);
260 }
261
262 if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
263 object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
264 !kvm_enabled(), &error_abort);
265 }
266
267 if (i) {
268 /*
269 * Secondary CPUs start in powered-down state (and can be
270 * powered up via the SRC system reset controller)
271 */
272 object_property_set_bool(OBJECT(&s->cpu[i]), "start-powered-off",
273 true, &error_abort);
274 }
275
276 if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
277 return;
278 }
279 }
280
281 /* GIC */
282 {
283 SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
284 QList *redist_region_count;
285 bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
286
287 qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
288 qdev_prop_set_uint32(gicdev, "num-irq",
289 FSL_IMX8MM_NUM_IRQS + GIC_INTERNAL);
290 redist_region_count = qlist_new();
291 qlist_append_int(redist_region_count, ms->smp.cpus);
292 qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count);
293 object_property_set_link(OBJECT(&s->gic), "sysmem",
294 OBJECT(get_system_memory()), &error_fatal);
295 if (!sysbus_realize(gicsbd, errp)) {
296 return;
297 }
298 sysbus_mmio_map(gicsbd, 0, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_DIST].addr);
299 sysbus_mmio_map(gicsbd, 1, fsl_imx8mm_memmap[FSL_IMX8MM_GIC_REDIST].addr);
300
301 /*
302 * Wire the outputs from each CPU's generic timer and the GICv3
303 * maintenance interrupt signal to the appropriate GIC PPI inputs, and
304 * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
305 */
306 for (i = 0; i < ms->smp.cpus; i++) {
307 DeviceState *cpudev = DEVICE(&s->cpu[i]);
308 int intidbase = FSL_IMX8MM_NUM_IRQS + i * GIC_INTERNAL;
309 qemu_irq irq;
310
311 /*
312 * Mapping from the output timer irq lines from the CPU to the
313 * GIC PPI inputs.
314 */
315 static const int timer_irqs[] = {
316 [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
317 [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
318 [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
319 [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
320 };
321
322 for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
323 irq = qdev_get_gpio_in(gicdev, intidbase + timer_irqs[j]);
324 qdev_connect_gpio_out(cpudev, j, irq);
325 }
326
327 irq = qdev_get_gpio_in(gicdev, intidbase + ARCH_GIC_MAINT_IRQ);
328 qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
329 0, irq);
330
331 irq = qdev_get_gpio_in(gicdev, intidbase + VIRTUAL_PMU_IRQ);
332 qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, irq);
333
334 sysbus_connect_irq(gicsbd, i,
335 qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
336 sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
337 qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
338 sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
339 qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
340 sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
341 qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
342
343 if (kvm_enabled()) {
344 if (pmu) {
345 assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
346 if (kvm_irqchip_in_kernel()) {
347 kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
348 }
349 kvm_arm_pmu_init(&s->cpu[i]);
350 }
351 }
352 }
353 }
354
355 /* CCM */
356 if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
357 return;
358 }
359 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0,
360 fsl_imx8mm_memmap[FSL_IMX8MM_CCM].addr);
361
362 /* Analog */
363 object_property_set_uint(OBJECT(&s->analog), "arm-pll-fdiv-ctl0-reset",
364 0x000fa030, &error_abort);
365 if (!sysbus_realize(SYS_BUS_DEVICE(&s->analog), errp)) {
366 return;
367 }
368 sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0,
369 fsl_imx8mm_memmap[FSL_IMX8MM_ANA_PLL].addr);
370
371 /* UARTs */
372 for (i = 0; i < FSL_IMX8MM_NUM_UARTS; i++) {
373 static const struct {
374 hwaddr addr;
375 unsigned int irq;
376 } serial_table[FSL_IMX8MM_NUM_UARTS] = {
377 { fsl_imx8mm_memmap[FSL_IMX8MM_UART1].addr, FSL_IMX8MM_UART1_IRQ },
378 { fsl_imx8mm_memmap[FSL_IMX8MM_UART2].addr, FSL_IMX8MM_UART2_IRQ },
379 { fsl_imx8mm_memmap[FSL_IMX8MM_UART3].addr, FSL_IMX8MM_UART3_IRQ },
380 { fsl_imx8mm_memmap[FSL_IMX8MM_UART4].addr, FSL_IMX8MM_UART4_IRQ },
381 };
382
383 qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
384 if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
385 return;
386 }
387
388 sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
389 sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
390 qdev_get_gpio_in(gicdev, serial_table[i].irq));
391 }
392
393 /* On-Chip RAM */
394 if (!memory_region_init_ram(&s->ocram, OBJECT(dev), "imx8mm.ocram",
395 fsl_imx8mm_memmap[FSL_IMX8MM_OCRAM].size,
396 errp)) {
397 return;
398 }
399 memory_region_add_subregion(get_system_memory(),
400 fsl_imx8mm_memmap[FSL_IMX8MM_OCRAM].addr,
401 &s->ocram);
402
403 /* GPTs */
404 object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
405 &error_abort);
406 if (!qdev_realize(DEVICE(&s->gpt5_gpt6_irq), NULL, errp)) {
407 return;
408 }
409
410 qdev_connect_gpio_out(DEVICE(&s->gpt5_gpt6_irq), 0,
411 qdev_get_gpio_in(gicdev, FSL_IMX8MM_GPT5_GPT6_IRQ));
412
413 for (i = 0; i < FSL_IMX8MM_NUM_GPTS; i++) {
414 hwaddr gpt_addrs[FSL_IMX8MM_NUM_GPTS] = {
415 fsl_imx8mm_memmap[FSL_IMX8MM_GPT1].addr,
416 fsl_imx8mm_memmap[FSL_IMX8MM_GPT2].addr,
417 fsl_imx8mm_memmap[FSL_IMX8MM_GPT3].addr,
418 fsl_imx8mm_memmap[FSL_IMX8MM_GPT4].addr,
419 fsl_imx8mm_memmap[FSL_IMX8MM_GPT5].addr,
420 fsl_imx8mm_memmap[FSL_IMX8MM_GPT6].addr,
421 };
422
423 s->gpt[i].ccm = IMX_CCM(&s->ccm);
424
425 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
426 return;
427 }
428
429 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_addrs[i]);
430
431 if (i < FSL_IMX8MM_NUM_GPTS - 2) {
432 static const unsigned int gpt_irqs[FSL_IMX8MM_NUM_GPTS - 2] = {
433 FSL_IMX8MM_GPT1_IRQ,
434 FSL_IMX8MM_GPT2_IRQ,
435 FSL_IMX8MM_GPT3_IRQ,
436 FSL_IMX8MM_GPT4_IRQ,
437 };
438
439 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
440 qdev_get_gpio_in(gicdev, gpt_irqs[i]));
441 } else {
442 int irq = i - FSL_IMX8MM_NUM_GPTS + 2;
443
444 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
445 qdev_get_gpio_in(DEVICE(&s->gpt5_gpt6_irq), irq));
446 }
447 }
448
449 /* I2Cs */
450 for (i = 0; i < FSL_IMX8MM_NUM_I2CS; i++) {
451 static const struct {
452 hwaddr addr;
453 unsigned int irq;
454 } i2c_table[FSL_IMX8MM_NUM_I2CS] = {
455 { fsl_imx8mm_memmap[FSL_IMX8MM_I2C1].addr, FSL_IMX8MM_I2C1_IRQ },
456 { fsl_imx8mm_memmap[FSL_IMX8MM_I2C2].addr, FSL_IMX8MM_I2C2_IRQ },
457 { fsl_imx8mm_memmap[FSL_IMX8MM_I2C3].addr, FSL_IMX8MM_I2C3_IRQ },
458 { fsl_imx8mm_memmap[FSL_IMX8MM_I2C4].addr, FSL_IMX8MM_I2C4_IRQ },
459 };
460
461 if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
462 return;
463 }
464
465 sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
466 sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
467 qdev_get_gpio_in(gicdev, i2c_table[i].irq));
468 }
469
470 /* GPIOs */
471 for (i = 0; i < FSL_IMX8MM_NUM_GPIOS; i++) {
472 static const struct {
473 hwaddr addr;
474 unsigned int irq_low;
475 unsigned int irq_high;
476 } gpio_table[FSL_IMX8MM_NUM_GPIOS] = {
477 {
478 fsl_imx8mm_memmap[FSL_IMX8MM_GPIO1].addr,
479 FSL_IMX8MM_GPIO1_LOW_IRQ,
480 FSL_IMX8MM_GPIO1_HIGH_IRQ
481 },
482 {
483 fsl_imx8mm_memmap[FSL_IMX8MM_GPIO2].addr,
484 FSL_IMX8MM_GPIO2_LOW_IRQ,
485 FSL_IMX8MM_GPIO2_HIGH_IRQ
486 },
487 {
488 fsl_imx8mm_memmap[FSL_IMX8MM_GPIO3].addr,
489 FSL_IMX8MM_GPIO3_LOW_IRQ,
490 FSL_IMX8MM_GPIO3_HIGH_IRQ
491 },
492 {
493 fsl_imx8mm_memmap[FSL_IMX8MM_GPIO4].addr,
494 FSL_IMX8MM_GPIO4_LOW_IRQ,
495 FSL_IMX8MM_GPIO4_HIGH_IRQ
496 },
497 {
498 fsl_imx8mm_memmap[FSL_IMX8MM_GPIO5].addr,
499 FSL_IMX8MM_GPIO5_LOW_IRQ,
500 FSL_IMX8MM_GPIO5_HIGH_IRQ
501 },
502 };
503 object_property_set_bool(OBJECT(&s->gpio[i]), "has-edge-sel", true,
504 &error_abort);
505 object_property_set_bool(OBJECT(&s->gpio[i]), "has-upper-pin-irq",
506 true, &error_abort);
507 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
508 return;
509 }
510
511 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
512 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
513 qdev_get_gpio_in(gicdev, gpio_table[i].irq_low));
514 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
515 qdev_get_gpio_in(gicdev, gpio_table[i].irq_high));
516 }
517
518 /* USDHCs */
519 for (i = 0; i < FSL_IMX8MM_NUM_USDHCS; i++) {
520 static const struct {
521 hwaddr addr;
522 unsigned int irq;
523 } usdhc_table[FSL_IMX8MM_NUM_USDHCS] = {
524 { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC1].addr, FSL_IMX8MM_USDHC1_IRQ },
525 { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC2].addr, FSL_IMX8MM_USDHC2_IRQ },
526 { fsl_imx8mm_memmap[FSL_IMX8MM_USDHC3].addr, FSL_IMX8MM_USDHC3_IRQ },
527 };
528
529 if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
530 return;
531 }
532
533 sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, usdhc_table[i].addr);
534 sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
535 qdev_get_gpio_in(gicdev, usdhc_table[i].irq));
536 }
537
538 /* USBs */
539 for (i = 0; i < FSL_IMX8MM_NUM_USBS; i++) {
540 static const struct {
541 hwaddr addr;
542 unsigned int irq;
543 } usb_table[FSL_IMX8MM_NUM_USBS] = {
544 { fsl_imx8mm_memmap[FSL_IMX8MM_USB1].addr, FSL_IMX8MM_USB1_IRQ },
545 { fsl_imx8mm_memmap[FSL_IMX8MM_USB2].addr, FSL_IMX8MM_USB2_IRQ },
546 };
547
548 qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p2", 1);
549 qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "p3", 1);
550 qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2);
551 if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) {
552 return;
553 }
554 sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
555 sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0,
556 qdev_get_gpio_in(gicdev, usb_table[i].irq));
557 }
558
559 /* ECSPIs */
560 for (i = 0; i < FSL_IMX8MM_NUM_ECSPIS; i++) {
561 static const struct {
562 hwaddr addr;
563 unsigned int irq;
564 } spi_table[FSL_IMX8MM_NUM_ECSPIS] = {
565 { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI1].addr, FSL_IMX8MM_ECSPI1_IRQ },
566 { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI2].addr, FSL_IMX8MM_ECSPI2_IRQ },
567 { fsl_imx8mm_memmap[FSL_IMX8MM_ECSPI3].addr, FSL_IMX8MM_ECSPI3_IRQ },
568 };
569
570 if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
571 return;
572 }
573
574 sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr);
575 sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
576 qdev_get_gpio_in(gicdev, spi_table[i].irq));
577 }
578
579 /* ENET1 */
580 object_property_set_uint(OBJECT(&s->enet), "phy-num", s->phy_num,
581 &error_abort);
582 object_property_set_uint(OBJECT(&s->enet), "tx-ring-num", 3, &error_abort);
583 qemu_configure_nic_device(DEVICE(&s->enet), true, NULL);
584 if (!sysbus_realize(SYS_BUS_DEVICE(&s->enet), errp)) {
585 return;
586 }
587 sysbus_mmio_map(SYS_BUS_DEVICE(&s->enet), 0,
588 fsl_imx8mm_memmap[FSL_IMX8MM_ENET1].addr);
589 sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 0,
590 qdev_get_gpio_in(gicdev, FSL_IMX8MM_ENET1_MAC_IRQ));
591 sysbus_connect_irq(SYS_BUS_DEVICE(&s->enet), 1,
592 qdev_get_gpio_in(gicdev, FSL_IMX6_ENET1_MAC_1588_IRQ));
593
594 /* SNVS */
595 if (!sysbus_realize(SYS_BUS_DEVICE(&s->snvs), errp)) {
596 return;
597 }
598 sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0,
599 fsl_imx8mm_memmap[FSL_IMX8MM_SNVS_HP].addr);
600
601 /* Watchdogs */
602 for (i = 0; i < FSL_IMX8MM_NUM_WDTS; i++) {
603 static const struct {
604 hwaddr addr;
605 unsigned int irq;
606 } wdog_table[FSL_IMX8MM_NUM_WDTS] = {
607 { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG1].addr, FSL_IMX8MM_WDOG1_IRQ },
608 { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG2].addr, FSL_IMX8MM_WDOG2_IRQ },
609 { fsl_imx8mm_memmap[FSL_IMX8MM_WDOG3].addr, FSL_IMX8MM_WDOG3_IRQ },
610 };
611
612 object_property_set_bool(OBJECT(&s->wdt[i]), "pretimeout-support",
613 true, &error_abort);
614 if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
615 return;
616 }
617
618 sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, wdog_table[i].addr);
619 sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
620 qdev_get_gpio_in(gicdev, wdog_table[i].irq));
621 }
622
623 /* PCIe */
624 if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie), errp)) {
625 return;
626 }
627 sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0,
628 fsl_imx8mm_memmap[FSL_IMX8MM_PCIE1].addr);
629
630 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0,
631 qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTA_IRQ));
632 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1,
633 qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTB_IRQ));
634 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2,
635 qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTC_IRQ));
636 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3,
637 qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_INTD_IRQ));
638 sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4,
639 qdev_get_gpio_in(gicdev, FSL_IMX8MM_PCI_MSI_IRQ));
640
641 if (!sysbus_realize(SYS_BUS_DEVICE(&s->pcie_phy), errp)) {
642 return;
643 }
644 sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
645 fsl_imx8mm_memmap[FSL_IMX8MM_PCIE_PHY1].addr);
646
647 /* Unimplemented devices */
648 for (i = 0; i < ARRAY_SIZE(fsl_imx8mm_memmap); i++) {
649 switch (i) {
650 case FSL_IMX8MM_ANA_PLL:
651 case FSL_IMX8MM_CCM:
652 case FSL_IMX8MM_GIC_DIST:
653 case FSL_IMX8MM_GIC_REDIST:
654 case FSL_IMX8MM_GPIO1 ... FSL_IMX8MM_GPIO5:
655 case FSL_IMX8MM_GPT1 ... FSL_IMX8MM_GPT6:
656 case FSL_IMX8MM_ECSPI1 ... FSL_IMX8MM_ECSPI3:
657 case FSL_IMX8MM_ENET1:
658 case FSL_IMX8MM_I2C1 ... FSL_IMX8MM_I2C4:
659 case FSL_IMX8MM_PCIE1:
660 case FSL_IMX8MM_PCIE_PHY1:
661 case FSL_IMX8MM_RAM:
662 case FSL_IMX8MM_OCRAM:
663 case FSL_IMX8MM_SNVS_HP:
664 case FSL_IMX8MM_UART1 ... FSL_IMX8MM_UART4:
665 case FSL_IMX8MM_USB1 ... FSL_IMX8MM_USB2:
666 case FSL_IMX8MM_USDHC1 ... FSL_IMX8MM_USDHC3:
667 case FSL_IMX8MM_WDOG1 ... FSL_IMX8MM_WDOG3:
668 /* device implemented and treated above */
669 break;
670
671 default:
672 create_unimplemented_device(fsl_imx8mm_memmap[i].name,
673 fsl_imx8mm_memmap[i].addr,
674 fsl_imx8mm_memmap[i].size);
675 break;
676 }
677 }
678 }
679
680 static const Property fsl_imx8mm_properties[] = {
681 DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mmState, phy_num, 0),
682 DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mmState, phy_connected, true),
683 };
684
685 static void fsl_imx8mm_class_init(ObjectClass *oc, const void *data)
686 {
687 DeviceClass *dc = DEVICE_CLASS(oc);
688
689 device_class_set_props(dc, fsl_imx8mm_properties);
690 dc->realize = fsl_imx8mm_realize;
691
692 dc->desc = "i.MX 8MM SoC";
693 }
694
695 static const TypeInfo fsl_imx8mm_types[] = {
696 {
697 .name = TYPE_FSL_IMX8MM,
698 .parent = TYPE_SYS_BUS_DEVICE,
699 .instance_size = sizeof(FslImx8mmState),
700 .instance_init = fsl_imx8mm_init,
701 .class_init = fsl_imx8mm_class_init,
702 },
703 };
704
705 DEFINE_TYPES(fsl_imx8mm_types)