blob: cc68b5d8f125beb9c08a01903831d76578ef9bd1 [file] [log] [blame]
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -07001/*
2 * Nuvoton NPCM7xx SoC family.
3 *
4 * Copyright 2020 Google LLC
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17#include "qemu/osdep.h"
18
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070019#include "hw/arm/boot.h"
20#include "hw/arm/npcm7xx.h"
21#include "hw/char/serial.h"
22#include "hw/loader.h"
23#include "hw/misc/unimp.h"
Hao Wu0be12dc2021-01-08 11:09:41 -080024#include "hw/qdev-clock.h"
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070025#include "hw/qdev-properties.h"
26#include "qapi/error.h"
27#include "qemu/units.h"
28#include "sysemu/sysemu.h"
Philippe Mathieu-Daudéd780d052024-01-18 21:06:38 +010029#include "target/arm/cpu-qom.h"
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070030
31/*
32 * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
33 * that aren't handled by any device.
34 */
35#define NPCM7XX_MMIO_BA (0x80000000)
36#define NPCM7XX_MMIO_SZ (0x7ffd0000)
37
Havard Skinnemoenc752bb02020-09-10 22:20:55 -070038/* OTP key storage and fuse strap array */
39#define NPCM7XX_OTP1_BA (0xf0189000)
40#define NPCM7XX_OTP2_BA (0xf018a000)
41
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070042/* Core system modules. */
43#define NPCM7XX_L2C_BA (0xf03fc000)
44#define NPCM7XX_CPUP_BA (0xf03fe000)
45#define NPCM7XX_GCR_BA (0xf0800000)
46#define NPCM7XX_CLK_BA (0xf0801000)
Havard Skinnemoen1351f892020-09-10 22:20:56 -070047#define NPCM7XX_MC_BA (0xf0824000)
Havard Skinnemoen326ccfe2020-10-23 14:06:35 -070048#define NPCM7XX_RNG_BA (0xf000b000)
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070049
Havard Skinnemoene23e7b12020-10-23 14:06:36 -070050/* USB Host modules */
51#define NPCM7XX_EHCI_BA (0xf0806000)
52#define NPCM7XX_OHCI_BA (0xf0807000)
53
Hao Wu77c05b02021-01-08 11:09:42 -080054/* ADC Module */
55#define NPCM7XX_ADC_BA (0xf000c000)
56
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070057/* Internal AHB SRAM */
58#define NPCM7XX_RAM3_BA (0xc0008000)
59#define NPCM7XX_RAM3_SZ (4 * KiB)
60
61/* Memory blocks at the end of the address space */
62#define NPCM7XX_RAM2_BA (0xfffd0000)
63#define NPCM7XX_RAM2_SZ (128 * KiB)
64#define NPCM7XX_ROM_BA (0xffff0000)
65#define NPCM7XX_ROM_SZ (64 * KiB)
66
Shengtan Mao0a9df6c2021-10-07 17:26:25 -070067/* SDHCI Modules */
68#define NPCM7XX_MMC_BA (0xf0842000)
Hao Wu77c05b02021-01-08 11:09:42 -080069
Havard Skinnemoen2ddae9c2020-09-10 22:20:59 -070070/* Clock configuration values to be fixed up when bypassing bootloader */
71
72/* Run PLL1 at 1600 MHz */
73#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
74/* Run the CPU from PLL1 and UART from PLL2 */
75#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
76
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070077/*
78 * Interrupt lines going into the GIC. This does not include internal Cortex-A9
79 * interrupts.
80 */
81enum NPCM7xxInterrupt {
Hao Wu77c05b02021-01-08 11:09:42 -080082 NPCM7XX_ADC_IRQ = 0,
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070083 NPCM7XX_UART0_IRQ = 2,
84 NPCM7XX_UART1_IRQ,
85 NPCM7XX_UART2_IRQ,
86 NPCM7XX_UART3_IRQ,
Hao Wu21e53262024-01-31 00:27:55 +000087 NPCM7XX_GMAC1_IRQ = 14,
Doug Evans77586432021-02-18 13:24:52 -080088 NPCM7XX_EMC1RX_IRQ = 15,
89 NPCM7XX_EMC1TX_IRQ,
Hao Wu21e53262024-01-31 00:27:55 +000090 NPCM7XX_GMAC2_IRQ,
Shengtan Mao0a9df6c2021-10-07 17:26:25 -070091 NPCM7XX_MMC_IRQ = 26,
Hao Wu4d120d72023-02-08 15:54:33 -080092 NPCM7XX_PSPI2_IRQ = 28,
93 NPCM7XX_PSPI1_IRQ = 31,
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -070094 NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
95 NPCM7XX_TIMER1_IRQ,
96 NPCM7XX_TIMER2_IRQ,
97 NPCM7XX_TIMER3_IRQ,
98 NPCM7XX_TIMER4_IRQ,
99 NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
100 NPCM7XX_TIMER6_IRQ,
101 NPCM7XX_TIMER7_IRQ,
102 NPCM7XX_TIMER8_IRQ,
103 NPCM7XX_TIMER9_IRQ,
104 NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
105 NPCM7XX_TIMER11_IRQ,
106 NPCM7XX_TIMER12_IRQ,
107 NPCM7XX_TIMER13_IRQ,
108 NPCM7XX_TIMER14_IRQ,
Hao Wu7d378ed2020-10-23 14:06:34 -0700109 NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
110 NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
111 NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
Havard Skinnemoene23e7b12020-10-23 14:06:36 -0700112 NPCM7XX_EHCI_IRQ = 61,
113 NPCM7XX_OHCI_IRQ = 62,
Hao Wu94e77872021-02-10 14:04:22 -0800114 NPCM7XX_SMBUS0_IRQ = 64,
115 NPCM7XX_SMBUS1_IRQ,
116 NPCM7XX_SMBUS2_IRQ,
117 NPCM7XX_SMBUS3_IRQ,
118 NPCM7XX_SMBUS4_IRQ,
119 NPCM7XX_SMBUS5_IRQ,
120 NPCM7XX_SMBUS6_IRQ,
121 NPCM7XX_SMBUS7_IRQ,
122 NPCM7XX_SMBUS8_IRQ,
123 NPCM7XX_SMBUS9_IRQ,
124 NPCM7XX_SMBUS10_IRQ,
125 NPCM7XX_SMBUS11_IRQ,
126 NPCM7XX_SMBUS12_IRQ,
127 NPCM7XX_SMBUS13_IRQ,
128 NPCM7XX_SMBUS14_IRQ,
129 NPCM7XX_SMBUS15_IRQ,
Hao Wu1e943c52021-01-08 11:09:43 -0800130 NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
131 NPCM7XX_PWM1_IRQ, /* PWM module 1 */
Hao Wufc111152021-03-11 10:08:53 -0800132 NPCM7XX_MFT0_IRQ = 96, /* MFT module 0 */
133 NPCM7XX_MFT1_IRQ, /* MFT module 1 */
134 NPCM7XX_MFT2_IRQ, /* MFT module 2 */
135 NPCM7XX_MFT3_IRQ, /* MFT module 3 */
136 NPCM7XX_MFT4_IRQ, /* MFT module 4 */
137 NPCM7XX_MFT5_IRQ, /* MFT module 5 */
138 NPCM7XX_MFT6_IRQ, /* MFT module 6 */
139 NPCM7XX_MFT7_IRQ, /* MFT module 7 */
Doug Evans77586432021-02-18 13:24:52 -0800140 NPCM7XX_EMC2RX_IRQ = 114,
141 NPCM7XX_EMC2TX_IRQ,
Havard Skinnemoen526dbbe2020-10-23 14:06:37 -0700142 NPCM7XX_GPIO0_IRQ = 116,
143 NPCM7XX_GPIO1_IRQ,
144 NPCM7XX_GPIO2_IRQ,
145 NPCM7XX_GPIO3_IRQ,
146 NPCM7XX_GPIO4_IRQ,
147 NPCM7XX_GPIO5_IRQ,
148 NPCM7XX_GPIO6_IRQ,
149 NPCM7XX_GPIO7_IRQ,
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700150};
151
152/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
153#define NPCM7XX_NUM_IRQ (160)
154
155/* Register base address for each Timer Module */
156static const hwaddr npcm7xx_tim_addr[] = {
157 0xf0008000,
158 0xf0009000,
159 0xf000a000,
160};
161
162/* Register base address for each 16550 UART */
163static const hwaddr npcm7xx_uart_addr[] = {
164 0xf0001000,
165 0xf0002000,
166 0xf0003000,
167 0xf0004000,
168};
169
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700170/* Direct memory-mapped access to SPI0 CS0-1. */
171static const hwaddr npcm7xx_fiu0_flash_addr[] = {
172 0x80000000, /* CS0 */
173 0x88000000, /* CS1 */
174};
175
176/* Direct memory-mapped access to SPI3 CS0-3. */
177static const hwaddr npcm7xx_fiu3_flash_addr[] = {
178 0xa0000000, /* CS0 */
179 0xa8000000, /* CS1 */
180 0xb0000000, /* CS2 */
181 0xb8000000, /* CS3 */
182};
183
Hao Wu1e943c52021-01-08 11:09:43 -0800184/* Register base address for each PWM Module */
185static const hwaddr npcm7xx_pwm_addr[] = {
186 0xf0103000,
187 0xf0104000,
188};
189
Hao Wufc111152021-03-11 10:08:53 -0800190/* Register base address for each MFT Module */
191static const hwaddr npcm7xx_mft_addr[] = {
192 0xf0180000,
193 0xf0181000,
194 0xf0182000,
195 0xf0183000,
196 0xf0184000,
197 0xf0185000,
198 0xf0186000,
199 0xf0187000,
200};
201
Hao Wu94e77872021-02-10 14:04:22 -0800202/* Direct memory-mapped access to each SMBus Module. */
203static const hwaddr npcm7xx_smbus_addr[] = {
204 0xf0080000,
205 0xf0081000,
206 0xf0082000,
207 0xf0083000,
208 0xf0084000,
209 0xf0085000,
210 0xf0086000,
211 0xf0087000,
212 0xf0088000,
213 0xf0089000,
214 0xf008a000,
215 0xf008b000,
216 0xf008c000,
217 0xf008d000,
218 0xf008e000,
219 0xf008f000,
220};
221
Doug Evans77586432021-02-18 13:24:52 -0800222/* Register base address for each EMC Module */
223static const hwaddr npcm7xx_emc_addr[] = {
224 0xf0825000,
225 0xf0826000,
226};
227
Hao Wu4d120d72023-02-08 15:54:33 -0800228/* Register base address for each PSPI Module */
229static const hwaddr npcm7xx_pspi_addr[] = {
230 0xf0200000,
231 0xf0201000,
232};
233
Hao Wu21e53262024-01-31 00:27:55 +0000234/* Register base address for each GMAC Module */
235static const hwaddr npcm7xx_gmac_addr[] = {
236 0xf0802000,
237 0xf0804000,
238};
239
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700240static const struct {
Havard Skinnemoen526dbbe2020-10-23 14:06:37 -0700241 hwaddr regs_addr;
242 uint32_t unconnected_pins;
243 uint32_t reset_pu;
244 uint32_t reset_pd;
245 uint32_t reset_osrc;
246 uint32_t reset_odsc;
247} npcm7xx_gpio[] = {
248 {
249 .regs_addr = 0xf0010000,
250 .reset_pu = 0xff03ffff,
251 .reset_pd = 0x00fc0000,
252 }, {
253 .regs_addr = 0xf0011000,
254 .unconnected_pins = 0x0000001e,
255 .reset_pu = 0xfefffe07,
256 .reset_pd = 0x010001e0,
257 }, {
258 .regs_addr = 0xf0012000,
259 .reset_pu = 0x780fffff,
260 .reset_pd = 0x07f00000,
261 .reset_odsc = 0x00700000,
262 }, {
263 .regs_addr = 0xf0013000,
264 .reset_pu = 0x00fc0000,
265 .reset_pd = 0xff000000,
266 }, {
267 .regs_addr = 0xf0014000,
268 .reset_pu = 0xffffffff,
269 }, {
270 .regs_addr = 0xf0015000,
271 .reset_pu = 0xbf83f801,
272 .reset_pd = 0x007c0000,
273 .reset_osrc = 0x000000f1,
274 .reset_odsc = 0x3f9f80f1,
275 }, {
276 .regs_addr = 0xf0016000,
277 .reset_pu = 0xfc00f801,
278 .reset_pd = 0x000007fe,
279 .reset_odsc = 0x00000800,
280 }, {
281 .regs_addr = 0xf0017000,
282 .unconnected_pins = 0xffffff00,
283 .reset_pu = 0x0000007f,
284 .reset_osrc = 0x0000007f,
285 .reset_odsc = 0x0000007f,
286 },
287};
288
289static const struct {
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700290 const char *name;
291 hwaddr regs_addr;
292 int cs_count;
293 const hwaddr *flash_addr;
294} npcm7xx_fiu[] = {
295 {
296 .name = "fiu0",
297 .regs_addr = 0xfb000000,
298 .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
299 .flash_addr = npcm7xx_fiu0_flash_addr,
300 }, {
301 .name = "fiu3",
302 .regs_addr = 0xc0000000,
303 .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
304 .flash_addr = npcm7xx_fiu3_flash_addr,
305 },
306};
307
Havard Skinnemoen2ddae9c2020-09-10 22:20:59 -0700308static void npcm7xx_write_board_setup(ARMCPU *cpu,
309 const struct arm_boot_info *info)
310{
311 uint32_t board_setup[] = {
312 0xe59f0010, /* ldr r0, clk_base_addr */
313 0xe59f1010, /* ldr r1, pllcon1_value */
314 0xe5801010, /* str r1, [r0, #16] */
315 0xe59f100c, /* ldr r1, clksel_value */
316 0xe5801004, /* str r1, [r0, #4] */
317 0xe12fff1e, /* bx lr */
318 NPCM7XX_CLK_BA,
319 NPCM7XX_PLLCON1_FIXUP_VAL,
320 NPCM7XX_CLKSEL_FIXUP_VAL,
321 };
322 int i;
323
324 for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
325 board_setup[i] = tswap32(board_setup[i]);
326 }
327 rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
328 info->board_setup_addr);
329}
330
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700331static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
332 const struct arm_boot_info *info)
333{
334 /*
335 * The default smpboot stub halts the secondary CPU with a 'wfi'
336 * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
337 * does not send an IPI to wake it up, so the second CPU fails to boot. So
338 * we need to provide our own smpboot stub that can not use 'wfi', it has
339 * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
340 */
341 uint32_t smpboot[] = {
342 0xe59f2018, /* ldr r2, bootreg_addr */
343 0xe3a00000, /* mov r0, #0 */
344 0xe5820000, /* str r0, [r2] */
345 0xe320f002, /* wfe */
346 0xe5921000, /* ldr r1, [r2] */
347 0xe1110001, /* tst r1, r1 */
348 0x0afffffb, /* beq <wfe> */
349 0xe12fff11, /* bx r1 */
350 NPCM7XX_SMP_BOOTREG_ADDR,
351 };
352 int i;
353
354 for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
355 smpboot[i] = tswap32(smpboot[i]);
356 }
357
358 rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
359 NPCM7XX_SMP_LOADER_START);
360}
361
362static struct arm_boot_info npcm7xx_binfo = {
363 .loader_start = NPCM7XX_LOADER_START,
364 .smp_loader_start = NPCM7XX_SMP_LOADER_START,
365 .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
366 .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
367 .write_secondary_boot = npcm7xx_write_secondary_boot,
368 .board_id = -1,
Havard Skinnemoen2ddae9c2020-09-10 22:20:59 -0700369 .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
370 .write_board_setup = npcm7xx_write_board_setup,
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700371};
372
373void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
374{
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700375 npcm7xx_binfo.ram_size = machine->ram_size;
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700376
377 arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
378}
379
Havard Skinnemoenc752bb02020-09-10 22:20:55 -0700380static void npcm7xx_init_fuses(NPCM7xxState *s)
381{
382 NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
383 uint32_t value;
384
385 /*
386 * The initial mask of disabled modules indicates the chip derivative (e.g.
387 * NPCM750 or NPCM730).
388 */
389 value = tswap32(nc->disabled_modules);
390 npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
391 sizeof(value));
392}
393
Hao Wu77c05b02021-01-08 11:09:42 -0800394static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
395{
396 /* Both ADC and the fuse array must have realized. */
397 QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
398 npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
399 NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
400}
401
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700402static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
403{
404 return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
405}
406
407static void npcm7xx_init(Object *obj)
408{
409 NPCM7xxState *s = NPCM7XX(obj);
410 int i;
411
412 for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
413 object_initialize_child(obj, "cpu[*]", &s->cpu[i],
414 ARM_CPU_TYPE_NAME("cortex-a9"));
415 }
416
417 object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
418 object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
419 object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
420 "power-on-straps");
421 object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
Havard Skinnemoenc752bb02020-09-10 22:20:55 -0700422 object_initialize_child(obj, "otp1", &s->key_storage,
423 TYPE_NPCM7XX_KEY_STORAGE);
424 object_initialize_child(obj, "otp2", &s->fuse_array,
425 TYPE_NPCM7XX_FUSE_ARRAY);
Havard Skinnemoen1351f892020-09-10 22:20:56 -0700426 object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
Havard Skinnemoen326ccfe2020-10-23 14:06:35 -0700427 object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
Hao Wu77c05b02021-01-08 11:09:42 -0800428 object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700429
430 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
431 object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
432 }
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700433
Havard Skinnemoen526dbbe2020-10-23 14:06:37 -0700434 for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
435 object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
436 }
437
Hao Wu94e77872021-02-10 14:04:22 -0800438 for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
439 object_initialize_child(obj, "smbus[*]", &s->smbus[i],
440 TYPE_NPCM7XX_SMBUS);
441 }
442
Havard Skinnemoene23e7b12020-10-23 14:06:36 -0700443 object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
444 object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
445
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700446 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
447 for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
448 object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
449 TYPE_NPCM7XX_FIU);
450 }
Hao Wu1e943c52021-01-08 11:09:43 -0800451
452 for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
453 object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
454 }
Doug Evans77586432021-02-18 13:24:52 -0800455
Hao Wufc111152021-03-11 10:08:53 -0800456 for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
457 object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
458 }
459
Doug Evans77586432021-02-18 13:24:52 -0800460 for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
461 object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
462 }
Shengtan Mao0a9df6c2021-10-07 17:26:25 -0700463
Hao Wu4d120d72023-02-08 15:54:33 -0800464 for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
465 object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
466 }
467
Hao Wu21e53262024-01-31 00:27:55 +0000468 for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
469 object_initialize_child(obj, "gmac[*]", &s->gmac[i], TYPE_NPCM_GMAC);
470 }
471
Shengtan Mao0a9df6c2021-10-07 17:26:25 -0700472 object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700473}
474
475static void npcm7xx_realize(DeviceState *dev, Error **errp)
476{
477 NPCM7xxState *s = NPCM7XX(dev);
478 NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
479 int i;
480
481 if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
482 error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
483 " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
484 return;
485 }
486
487 /* CPUs */
488 for (i = 0; i < nc->num_cpus; i++) {
489 object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
Richard Henderson750245e2024-01-18 21:06:29 +0100490 arm_build_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700491 &error_abort);
492 object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
493 NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
494 object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
495 &error_abort);
496
497 /* Disable security extensions. */
498 object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
499 &error_abort);
500
501 if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
502 return;
503 }
504 }
505
506 /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
507 object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
508 &error_abort);
509 object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
510 &error_abort);
511 sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
512 sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
513
514 for (i = 0; i < nc->num_cpus; i++) {
515 sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
516 qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
517 sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
518 qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
519 }
520
521 /* L2 cache controller */
522 sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
523
524 /* System Global Control Registers (GCR). Can fail due to user input. */
525 object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
526 nc->disabled_modules, &error_abort);
527 object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
528 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
529 return;
530 }
531 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
532
533 /* Clock Control Registers (CLK). Cannot fail. */
534 sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
535 sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
536
Havard Skinnemoenc752bb02020-09-10 22:20:55 -0700537 /* OTP key storage and fuse strap array. Cannot fail. */
538 sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
539 sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
540 sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
541 sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
542 npcm7xx_init_fuses(s);
543
Havard Skinnemoen1351f892020-09-10 22:20:56 -0700544 /* Fake Memory Controller (MC). Cannot fail. */
545 sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
546 sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
547
Hao Wu77c05b02021-01-08 11:09:42 -0800548 /* ADC Modules. Cannot fail. */
549 qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
550 DEVICE(&s->clk), "adc-clock"));
551 sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
552 sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
553 sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
554 npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
555 npcm7xx_write_adc_calibration(s);
556
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700557 /* Timer Modules (TIM). Cannot fail. */
558 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
559 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
560 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
561 int first_irq;
562 int j;
563
Hao Wu0be12dc2021-01-08 11:09:41 -0800564 /* Connect the timer clock. */
565 qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
566 DEVICE(&s->clk), "timer-clock"));
567
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700568 sysbus_realize(sbd, &error_abort);
569 sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
570
571 first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
572 for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
573 qemu_irq irq = npcm7xx_irq(s, first_irq + j);
574 sysbus_connect_irq(sbd, j, irq);
575 }
Hao Wu7d378ed2020-10-23 14:06:34 -0700576
577 /* IRQ for watchdogs */
578 sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL,
579 npcm7xx_irq(s, NPCM7XX_WDG0_IRQ + i));
580 /* GPIO that connects clk module with watchdog */
581 qdev_connect_gpio_out_named(DEVICE(&s->tim[i]),
582 NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0,
583 qdev_get_gpio_in_named(DEVICE(&s->clk),
584 NPCM7XX_WATCHDOG_RESET_GPIO_IN, i));
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700585 }
586
587 /* UART0..3 (16550 compatible) */
588 for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
589 serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
590 npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
591 serial_hd(i), DEVICE_LITTLE_ENDIAN);
592 }
593
Havard Skinnemoen326ccfe2020-10-23 14:06:35 -0700594 /* Random Number Generator. Cannot fail. */
595 sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
596 sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
597
Havard Skinnemoen526dbbe2020-10-23 14:06:37 -0700598 /* GPIO modules. Cannot fail. */
599 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio));
600 for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
601 Object *obj = OBJECT(&s->gpio[i]);
602
603 object_property_set_uint(obj, "reset-pullup",
604 npcm7xx_gpio[i].reset_pu, &error_abort);
605 object_property_set_uint(obj, "reset-pulldown",
606 npcm7xx_gpio[i].reset_pd, &error_abort);
607 object_property_set_uint(obj, "reset-osrc",
608 npcm7xx_gpio[i].reset_osrc, &error_abort);
609 object_property_set_uint(obj, "reset-odsc",
610 npcm7xx_gpio[i].reset_odsc, &error_abort);
611 sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
612 sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_gpio[i].regs_addr);
613 sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
614 npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
615 }
616
Hao Wu94e77872021-02-10 14:04:22 -0800617 /* SMBus modules. Cannot fail. */
618 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) != ARRAY_SIZE(s->smbus));
619 for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
620 Object *obj = OBJECT(&s->smbus[i]);
621
622 sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
623 sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]);
624 sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
625 npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i));
626 }
627
Havard Skinnemoene23e7b12020-10-23 14:06:36 -0700628 /* USB Host */
629 object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
630 &error_abort);
631 sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort);
632 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA);
633 sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0,
634 npcm7xx_irq(s, NPCM7XX_EHCI_IRQ));
635
636 object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0",
637 &error_abort);
638 object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort);
639 sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort);
640 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA);
641 sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
642 npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
643
Hao Wu1e943c52021-01-08 11:09:43 -0800644 /* PWM Modules. Cannot fail. */
645 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
646 for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
647 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
648
649 qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
650 DEVICE(&s->clk), "apb3-clock"));
651 sysbus_realize(sbd, &error_abort);
652 sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
653 sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
654 }
655
Hao Wufc111152021-03-11 10:08:53 -0800656 /* MFT Modules. Cannot fail. */
657 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
658 for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
659 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
660
661 qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
662 qdev_get_clock_out(DEVICE(&s->clk),
663 "apb4-clock"));
664 sysbus_realize(sbd, &error_abort);
665 sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
666 sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
667 }
668
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700669 /*
Doug Evans77586432021-02-18 13:24:52 -0800670 * EMC Modules. Cannot fail.
David Woodhouse707a42e2023-10-23 09:37:39 +0100671 * Use the available NIC configurations in order, allowing 'emc0' and
672 * 'emc1' to by used as aliases for the model= parameter to override.
673 *
Doug Evans77586432021-02-18 13:24:52 -0800674 * This works around the inability to specify the netdev property for the
675 * emc device: it's not pluggable and thus the -device option can't be
676 * used.
677 */
678 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
679 QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
680 for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
Doug Evans77586432021-02-18 13:24:52 -0800681 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
David Woodhouse707a42e2023-10-23 09:37:39 +0100682 char alias[6];
683
684 s->emc[i].emc_num = i;
685 snprintf(alias, sizeof(alias), "emc%u", i);
686 qemu_configure_nic_device(DEVICE(sbd), true, alias);
687
Doug Evans77586432021-02-18 13:24:52 -0800688 /*
689 * The device exists regardless of whether it's connected to a QEMU
690 * netdev backend. So always instantiate it even if there is no
691 * backend.
692 */
693 sysbus_realize(sbd, &error_abort);
694 sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
695 int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
696 int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
697 /*
698 * N.B. The values for the second argument sysbus_connect_irq are
699 * chosen to match the registration order in npcm7xx_emc_realize.
700 */
701 sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
702 sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
703 }
704
705 /*
Hao Wu21e53262024-01-31 00:27:55 +0000706 * GMAC Modules. Cannot fail.
707 */
708 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gmac_addr) != ARRAY_SIZE(s->gmac));
709 QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->gmac) != 2);
710 for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
711 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
712
Peter Maydell243f8652024-02-06 17:12:30 +0000713 qemu_configure_nic_device(DEVICE(sbd), false, NULL);
Hao Wu21e53262024-01-31 00:27:55 +0000714 /*
715 * The device exists regardless of whether it's connected to a QEMU
716 * netdev backend. So always instantiate it even if there is no
717 * backend.
718 */
719 sysbus_realize(sbd, &error_abort);
720 sysbus_mmio_map(sbd, 0, npcm7xx_gmac_addr[i]);
721 int irq = i == 0 ? NPCM7XX_GMAC1_IRQ : NPCM7XX_GMAC2_IRQ;
722 /*
723 * N.B. The values for the second argument sysbus_connect_irq are
724 * chosen to match the registration order in npcm7xx_emc_realize.
725 */
726 sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
727 }
728
729 /*
Havard Skinnemoenb8212422020-09-10 22:20:57 -0700730 * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
731 * specified, but this is a programming error.
732 */
733 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
734 for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
735 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
736 int j;
737
738 object_property_set_int(OBJECT(sbd), "cs-count",
739 npcm7xx_fiu[i].cs_count, &error_abort);
740 sysbus_realize(sbd, &error_abort);
741
742 sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
743 for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
744 sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
745 }
746 }
747
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700748 /* RAM2 (SRAM) */
749 memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
750 NPCM7XX_RAM2_SZ, &error_abort);
751 memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
752
753 /* RAM3 (SRAM) */
754 memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
755 NPCM7XX_RAM3_SZ, &error_abort);
756 memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
757
758 /* Internal ROM */
759 memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
760 &error_abort);
761 memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
762
Shengtan Mao0a9df6c2021-10-07 17:26:25 -0700763 /* SDHCI */
764 sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort);
765 sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA);
766 sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
767 npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
768
Hao Wu4d120d72023-02-08 15:54:33 -0800769 /* PSPI */
770 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pspi_addr) != ARRAY_SIZE(s->pspi));
771 for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
772 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pspi[i]);
773 int irq = (i == 0) ? NPCM7XX_PSPI1_IRQ : NPCM7XX_PSPI2_IRQ;
774
775 sysbus_realize(sbd, &error_abort);
776 sysbus_mmio_map(sbd, 0, npcm7xx_pspi_addr[i]);
777 sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
778 }
779
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700780 create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
781 create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
782 create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
783 create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700784 create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700785 create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
786 create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
787 create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
788 create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700789 create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
790 create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700791 create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
792 create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
793 create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700794 create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
795 create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
796 create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
797 create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
798 create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
799 create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
800 create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
801 create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
802 create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
803 create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
804 create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
Havard Skinnemoen2d8f0482020-09-10 22:20:51 -0700805 create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
806 create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
807 create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
808 create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
809 create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
810 create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
811 create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
812 create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
813}
814
815static Property npcm7xx_properties[] = {
816 DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
817 MemoryRegion *),
818 DEFINE_PROP_END_OF_LIST(),
819};
820
821static void npcm7xx_class_init(ObjectClass *oc, void *data)
822{
823 DeviceClass *dc = DEVICE_CLASS(oc);
824
825 dc->realize = npcm7xx_realize;
826 dc->user_creatable = false;
827 device_class_set_props(dc, npcm7xx_properties);
828}
829
830static void npcm730_class_init(ObjectClass *oc, void *data)
831{
832 NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
833
834 /* NPCM730 is optimized for data center use, so no graphics, etc. */
835 nc->disabled_modules = 0x00300395;
836 nc->num_cpus = 2;
837}
838
839static void npcm750_class_init(ObjectClass *oc, void *data)
840{
841 NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
842
843 /* NPCM750 has 2 cores and a full set of peripherals */
844 nc->disabled_modules = 0x00000000;
845 nc->num_cpus = 2;
846}
847
848static const TypeInfo npcm7xx_soc_types[] = {
849 {
850 .name = TYPE_NPCM7XX,
851 .parent = TYPE_DEVICE,
852 .instance_size = sizeof(NPCM7xxState),
853 .instance_init = npcm7xx_init,
854 .class_size = sizeof(NPCM7xxClass),
855 .class_init = npcm7xx_class_init,
856 .abstract = true,
857 }, {
858 .name = TYPE_NPCM730,
859 .parent = TYPE_NPCM7XX,
860 .class_init = npcm730_class_init,
861 }, {
862 .name = TYPE_NPCM750,
863 .parent = TYPE_NPCM7XX,
864 .class_init = npcm750_class_init,
865 },
866};
867
868DEFINE_TYPES(npcm7xx_soc_types);