xref: /openbmc/qemu/hw/arm/npcm7xx.c (revision eb656a60)
12d8f048cSHavard Skinnemoen /*
22d8f048cSHavard Skinnemoen  * Nuvoton NPCM7xx SoC family.
32d8f048cSHavard Skinnemoen  *
42d8f048cSHavard Skinnemoen  * Copyright 2020 Google LLC
52d8f048cSHavard Skinnemoen  *
62d8f048cSHavard Skinnemoen  * This program is free software; you can redistribute it and/or modify it
72d8f048cSHavard Skinnemoen  * under the terms of the GNU General Public License as published by the
82d8f048cSHavard Skinnemoen  * Free Software Foundation; either version 2 of the License, or
92d8f048cSHavard Skinnemoen  * (at your option) any later version.
102d8f048cSHavard Skinnemoen  *
112d8f048cSHavard Skinnemoen  * This program is distributed in the hope that it will be useful, but WITHOUT
122d8f048cSHavard Skinnemoen  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
132d8f048cSHavard Skinnemoen  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
142d8f048cSHavard Skinnemoen  * for more details.
152d8f048cSHavard Skinnemoen  */
162d8f048cSHavard Skinnemoen 
172d8f048cSHavard Skinnemoen #include "qemu/osdep.h"
182d8f048cSHavard Skinnemoen 
192d8f048cSHavard Skinnemoen #include "hw/arm/boot.h"
202d8f048cSHavard Skinnemoen #include "hw/arm/npcm7xx.h"
212d8f048cSHavard Skinnemoen #include "hw/char/serial.h"
222d8f048cSHavard Skinnemoen #include "hw/loader.h"
232d8f048cSHavard Skinnemoen #include "hw/misc/unimp.h"
240be12dc7SHao Wu #include "hw/qdev-clock.h"
252d8f048cSHavard Skinnemoen #include "hw/qdev-properties.h"
262d8f048cSHavard Skinnemoen #include "qapi/error.h"
27*eb656a60SPhilippe Mathieu-Daudé #include "qemu/bswap.h"
282d8f048cSHavard Skinnemoen #include "qemu/units.h"
292d8f048cSHavard Skinnemoen #include "sysemu/sysemu.h"
30d780d056SPhilippe Mathieu-Daudé #include "target/arm/cpu-qom.h"
312d8f048cSHavard Skinnemoen 
322d8f048cSHavard Skinnemoen /*
332d8f048cSHavard Skinnemoen  * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
342d8f048cSHavard Skinnemoen  * that aren't handled by any device.
352d8f048cSHavard Skinnemoen  */
362d8f048cSHavard Skinnemoen #define NPCM7XX_MMIO_BA         (0x80000000)
372d8f048cSHavard Skinnemoen #define NPCM7XX_MMIO_SZ         (0x7ffd0000)
382d8f048cSHavard Skinnemoen 
39c752bb07SHavard Skinnemoen /* OTP key storage and fuse strap array */
40c752bb07SHavard Skinnemoen #define NPCM7XX_OTP1_BA         (0xf0189000)
41c752bb07SHavard Skinnemoen #define NPCM7XX_OTP2_BA         (0xf018a000)
42c752bb07SHavard Skinnemoen 
432d8f048cSHavard Skinnemoen /* Core system modules. */
442d8f048cSHavard Skinnemoen #define NPCM7XX_L2C_BA          (0xf03fc000)
452d8f048cSHavard Skinnemoen #define NPCM7XX_CPUP_BA         (0xf03fe000)
462d8f048cSHavard Skinnemoen #define NPCM7XX_GCR_BA          (0xf0800000)
472d8f048cSHavard Skinnemoen #define NPCM7XX_CLK_BA          (0xf0801000)
481351f892SHavard Skinnemoen #define NPCM7XX_MC_BA           (0xf0824000)
49326ccfe2SHavard Skinnemoen #define NPCM7XX_RNG_BA          (0xf000b000)
502d8f048cSHavard Skinnemoen 
51e23e7b12SHavard Skinnemoen /* USB Host modules */
52e23e7b12SHavard Skinnemoen #define NPCM7XX_EHCI_BA         (0xf0806000)
53e23e7b12SHavard Skinnemoen #define NPCM7XX_OHCI_BA         (0xf0807000)
54e23e7b12SHavard Skinnemoen 
5577c05b0bSHao Wu /* ADC Module */
5677c05b0bSHao Wu #define NPCM7XX_ADC_BA          (0xf000c000)
5777c05b0bSHao Wu 
582d8f048cSHavard Skinnemoen /* Internal AHB SRAM */
592d8f048cSHavard Skinnemoen #define NPCM7XX_RAM3_BA         (0xc0008000)
602d8f048cSHavard Skinnemoen #define NPCM7XX_RAM3_SZ         (4 * KiB)
612d8f048cSHavard Skinnemoen 
622d8f048cSHavard Skinnemoen /* Memory blocks at the end of the address space */
632d8f048cSHavard Skinnemoen #define NPCM7XX_RAM2_BA         (0xfffd0000)
642d8f048cSHavard Skinnemoen #define NPCM7XX_RAM2_SZ         (128 * KiB)
652d8f048cSHavard Skinnemoen #define NPCM7XX_ROM_BA          (0xffff0000)
662d8f048cSHavard Skinnemoen #define NPCM7XX_ROM_SZ          (64 * KiB)
672d8f048cSHavard Skinnemoen 
680a9df6cbSShengtan Mao /* SDHCI Modules */
690a9df6cbSShengtan Mao #define NPCM7XX_MMC_BA          (0xf0842000)
7077c05b0bSHao Wu 
712ddae9ccSHavard Skinnemoen /* Clock configuration values to be fixed up when bypassing bootloader */
722ddae9ccSHavard Skinnemoen 
732ddae9ccSHavard Skinnemoen /* Run PLL1 at 1600 MHz */
742ddae9ccSHavard Skinnemoen #define NPCM7XX_PLLCON1_FIXUP_VAL   (0x00402101)
752ddae9ccSHavard Skinnemoen /* Run the CPU from PLL1 and UART from PLL2 */
762ddae9ccSHavard Skinnemoen #define NPCM7XX_CLKSEL_FIXUP_VAL    (0x004aaba9)
772ddae9ccSHavard Skinnemoen 
782d8f048cSHavard Skinnemoen /*
792d8f048cSHavard Skinnemoen  * Interrupt lines going into the GIC. This does not include internal Cortex-A9
802d8f048cSHavard Skinnemoen  * interrupts.
812d8f048cSHavard Skinnemoen  */
822d8f048cSHavard Skinnemoen enum NPCM7xxInterrupt {
8377c05b0bSHao Wu     NPCM7XX_ADC_IRQ             = 0,
842d8f048cSHavard Skinnemoen     NPCM7XX_UART0_IRQ           = 2,
852d8f048cSHavard Skinnemoen     NPCM7XX_UART1_IRQ,
862d8f048cSHavard Skinnemoen     NPCM7XX_UART2_IRQ,
872d8f048cSHavard Skinnemoen     NPCM7XX_UART3_IRQ,
8821e5326aSHao Wu     NPCM7XX_GMAC1_IRQ           = 14,
8977586436SDoug Evans     NPCM7XX_EMC1RX_IRQ          = 15,
9077586436SDoug Evans     NPCM7XX_EMC1TX_IRQ,
9121e5326aSHao Wu     NPCM7XX_GMAC2_IRQ,
920a9df6cbSShengtan Mao     NPCM7XX_MMC_IRQ             = 26,
934d120d7dSHao Wu     NPCM7XX_PSPI2_IRQ           = 28,
944d120d7dSHao Wu     NPCM7XX_PSPI1_IRQ           = 31,
952d8f048cSHavard Skinnemoen     NPCM7XX_TIMER0_IRQ          = 32,   /* Timer Module 0 */
962d8f048cSHavard Skinnemoen     NPCM7XX_TIMER1_IRQ,
972d8f048cSHavard Skinnemoen     NPCM7XX_TIMER2_IRQ,
982d8f048cSHavard Skinnemoen     NPCM7XX_TIMER3_IRQ,
992d8f048cSHavard Skinnemoen     NPCM7XX_TIMER4_IRQ,
1002d8f048cSHavard Skinnemoen     NPCM7XX_TIMER5_IRQ,                 /* Timer Module 1 */
1012d8f048cSHavard Skinnemoen     NPCM7XX_TIMER6_IRQ,
1022d8f048cSHavard Skinnemoen     NPCM7XX_TIMER7_IRQ,
1032d8f048cSHavard Skinnemoen     NPCM7XX_TIMER8_IRQ,
1042d8f048cSHavard Skinnemoen     NPCM7XX_TIMER9_IRQ,
1052d8f048cSHavard Skinnemoen     NPCM7XX_TIMER10_IRQ,                /* Timer Module 2 */
1062d8f048cSHavard Skinnemoen     NPCM7XX_TIMER11_IRQ,
1072d8f048cSHavard Skinnemoen     NPCM7XX_TIMER12_IRQ,
1082d8f048cSHavard Skinnemoen     NPCM7XX_TIMER13_IRQ,
1092d8f048cSHavard Skinnemoen     NPCM7XX_TIMER14_IRQ,
1107d378ed6SHao Wu     NPCM7XX_WDG0_IRQ            = 47,   /* Timer Module 0 Watchdog */
1117d378ed6SHao Wu     NPCM7XX_WDG1_IRQ,                   /* Timer Module 1 Watchdog */
1127d378ed6SHao Wu     NPCM7XX_WDG2_IRQ,                   /* Timer Module 2 Watchdog */
113e23e7b12SHavard Skinnemoen     NPCM7XX_EHCI_IRQ            = 61,
114e23e7b12SHavard Skinnemoen     NPCM7XX_OHCI_IRQ            = 62,
11594e77879SHao Wu     NPCM7XX_SMBUS0_IRQ          = 64,
11694e77879SHao Wu     NPCM7XX_SMBUS1_IRQ,
11794e77879SHao Wu     NPCM7XX_SMBUS2_IRQ,
11894e77879SHao Wu     NPCM7XX_SMBUS3_IRQ,
11994e77879SHao Wu     NPCM7XX_SMBUS4_IRQ,
12094e77879SHao Wu     NPCM7XX_SMBUS5_IRQ,
12194e77879SHao Wu     NPCM7XX_SMBUS6_IRQ,
12294e77879SHao Wu     NPCM7XX_SMBUS7_IRQ,
12394e77879SHao Wu     NPCM7XX_SMBUS8_IRQ,
12494e77879SHao Wu     NPCM7XX_SMBUS9_IRQ,
12594e77879SHao Wu     NPCM7XX_SMBUS10_IRQ,
12694e77879SHao Wu     NPCM7XX_SMBUS11_IRQ,
12794e77879SHao Wu     NPCM7XX_SMBUS12_IRQ,
12894e77879SHao Wu     NPCM7XX_SMBUS13_IRQ,
12994e77879SHao Wu     NPCM7XX_SMBUS14_IRQ,
13094e77879SHao Wu     NPCM7XX_SMBUS15_IRQ,
1311e943c58SHao Wu     NPCM7XX_PWM0_IRQ            = 93,   /* PWM module 0 */
1321e943c58SHao Wu     NPCM7XX_PWM1_IRQ,                   /* PWM module 1 */
133fc11115fSHao Wu     NPCM7XX_MFT0_IRQ            = 96,   /* MFT module 0 */
134fc11115fSHao Wu     NPCM7XX_MFT1_IRQ,                   /* MFT module 1 */
135fc11115fSHao Wu     NPCM7XX_MFT2_IRQ,                   /* MFT module 2 */
136fc11115fSHao Wu     NPCM7XX_MFT3_IRQ,                   /* MFT module 3 */
137fc11115fSHao Wu     NPCM7XX_MFT4_IRQ,                   /* MFT module 4 */
138fc11115fSHao Wu     NPCM7XX_MFT5_IRQ,                   /* MFT module 5 */
139fc11115fSHao Wu     NPCM7XX_MFT6_IRQ,                   /* MFT module 6 */
140fc11115fSHao Wu     NPCM7XX_MFT7_IRQ,                   /* MFT module 7 */
14177586436SDoug Evans     NPCM7XX_EMC2RX_IRQ          = 114,
14277586436SDoug Evans     NPCM7XX_EMC2TX_IRQ,
143526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO0_IRQ           = 116,
144526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO1_IRQ,
145526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO2_IRQ,
146526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO3_IRQ,
147526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO4_IRQ,
148526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO5_IRQ,
149526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO6_IRQ,
150526dbbe0SHavard Skinnemoen     NPCM7XX_GPIO7_IRQ,
1512d8f048cSHavard Skinnemoen };
1522d8f048cSHavard Skinnemoen 
1532d8f048cSHavard Skinnemoen /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
1542d8f048cSHavard Skinnemoen #define NPCM7XX_NUM_IRQ         (160)
1552d8f048cSHavard Skinnemoen 
1562d8f048cSHavard Skinnemoen /* Register base address for each Timer Module */
1572d8f048cSHavard Skinnemoen static const hwaddr npcm7xx_tim_addr[] = {
1582d8f048cSHavard Skinnemoen     0xf0008000,
1592d8f048cSHavard Skinnemoen     0xf0009000,
1602d8f048cSHavard Skinnemoen     0xf000a000,
1612d8f048cSHavard Skinnemoen };
1622d8f048cSHavard Skinnemoen 
1632d8f048cSHavard Skinnemoen /* Register base address for each 16550 UART */
1642d8f048cSHavard Skinnemoen static const hwaddr npcm7xx_uart_addr[] = {
1652d8f048cSHavard Skinnemoen     0xf0001000,
1662d8f048cSHavard Skinnemoen     0xf0002000,
1672d8f048cSHavard Skinnemoen     0xf0003000,
1682d8f048cSHavard Skinnemoen     0xf0004000,
1692d8f048cSHavard Skinnemoen };
1702d8f048cSHavard Skinnemoen 
171b821242cSHavard Skinnemoen /* Direct memory-mapped access to SPI0 CS0-1. */
172b821242cSHavard Skinnemoen static const hwaddr npcm7xx_fiu0_flash_addr[] = {
173b821242cSHavard Skinnemoen     0x80000000, /* CS0 */
174b821242cSHavard Skinnemoen     0x88000000, /* CS1 */
175b821242cSHavard Skinnemoen };
176b821242cSHavard Skinnemoen 
177b821242cSHavard Skinnemoen /* Direct memory-mapped access to SPI3 CS0-3. */
178b821242cSHavard Skinnemoen static const hwaddr npcm7xx_fiu3_flash_addr[] = {
179b821242cSHavard Skinnemoen     0xa0000000, /* CS0 */
180b821242cSHavard Skinnemoen     0xa8000000, /* CS1 */
181b821242cSHavard Skinnemoen     0xb0000000, /* CS2 */
182b821242cSHavard Skinnemoen     0xb8000000, /* CS3 */
183b821242cSHavard Skinnemoen };
184b821242cSHavard Skinnemoen 
1851e943c58SHao Wu /* Register base address for each PWM Module */
1861e943c58SHao Wu static const hwaddr npcm7xx_pwm_addr[] = {
1871e943c58SHao Wu     0xf0103000,
1881e943c58SHao Wu     0xf0104000,
1891e943c58SHao Wu };
1901e943c58SHao Wu 
191fc11115fSHao Wu /* Register base address for each MFT Module */
192fc11115fSHao Wu static const hwaddr npcm7xx_mft_addr[] = {
193fc11115fSHao Wu     0xf0180000,
194fc11115fSHao Wu     0xf0181000,
195fc11115fSHao Wu     0xf0182000,
196fc11115fSHao Wu     0xf0183000,
197fc11115fSHao Wu     0xf0184000,
198fc11115fSHao Wu     0xf0185000,
199fc11115fSHao Wu     0xf0186000,
200fc11115fSHao Wu     0xf0187000,
201fc11115fSHao Wu };
202fc11115fSHao Wu 
20394e77879SHao Wu /* Direct memory-mapped access to each SMBus Module. */
20494e77879SHao Wu static const hwaddr npcm7xx_smbus_addr[] = {
20594e77879SHao Wu     0xf0080000,
20694e77879SHao Wu     0xf0081000,
20794e77879SHao Wu     0xf0082000,
20894e77879SHao Wu     0xf0083000,
20994e77879SHao Wu     0xf0084000,
21094e77879SHao Wu     0xf0085000,
21194e77879SHao Wu     0xf0086000,
21294e77879SHao Wu     0xf0087000,
21394e77879SHao Wu     0xf0088000,
21494e77879SHao Wu     0xf0089000,
21594e77879SHao Wu     0xf008a000,
21694e77879SHao Wu     0xf008b000,
21794e77879SHao Wu     0xf008c000,
21894e77879SHao Wu     0xf008d000,
21994e77879SHao Wu     0xf008e000,
22094e77879SHao Wu     0xf008f000,
22194e77879SHao Wu };
22294e77879SHao Wu 
22377586436SDoug Evans /* Register base address for each EMC Module */
22477586436SDoug Evans static const hwaddr npcm7xx_emc_addr[] = {
22577586436SDoug Evans     0xf0825000,
22677586436SDoug Evans     0xf0826000,
22777586436SDoug Evans };
22877586436SDoug Evans 
2294d120d7dSHao Wu /* Register base address for each PSPI Module */
2304d120d7dSHao Wu static const hwaddr npcm7xx_pspi_addr[] = {
2314d120d7dSHao Wu     0xf0200000,
2324d120d7dSHao Wu     0xf0201000,
2334d120d7dSHao Wu };
2344d120d7dSHao Wu 
23521e5326aSHao Wu /* Register base address for each GMAC Module */
23621e5326aSHao Wu static const hwaddr npcm7xx_gmac_addr[] = {
23721e5326aSHao Wu     0xf0802000,
23821e5326aSHao Wu     0xf0804000,
23921e5326aSHao Wu };
24021e5326aSHao Wu 
241b821242cSHavard Skinnemoen static const struct {
242526dbbe0SHavard Skinnemoen     hwaddr regs_addr;
243526dbbe0SHavard Skinnemoen     uint32_t unconnected_pins;
244526dbbe0SHavard Skinnemoen     uint32_t reset_pu;
245526dbbe0SHavard Skinnemoen     uint32_t reset_pd;
246526dbbe0SHavard Skinnemoen     uint32_t reset_osrc;
247526dbbe0SHavard Skinnemoen     uint32_t reset_odsc;
248526dbbe0SHavard Skinnemoen } npcm7xx_gpio[] = {
249526dbbe0SHavard Skinnemoen     {
250526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0010000,
251526dbbe0SHavard Skinnemoen         .reset_pu = 0xff03ffff,
252526dbbe0SHavard Skinnemoen         .reset_pd = 0x00fc0000,
253526dbbe0SHavard Skinnemoen     }, {
254526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0011000,
255526dbbe0SHavard Skinnemoen         .unconnected_pins = 0x0000001e,
256526dbbe0SHavard Skinnemoen         .reset_pu = 0xfefffe07,
257526dbbe0SHavard Skinnemoen         .reset_pd = 0x010001e0,
258526dbbe0SHavard Skinnemoen     }, {
259526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0012000,
260526dbbe0SHavard Skinnemoen         .reset_pu = 0x780fffff,
261526dbbe0SHavard Skinnemoen         .reset_pd = 0x07f00000,
262526dbbe0SHavard Skinnemoen         .reset_odsc = 0x00700000,
263526dbbe0SHavard Skinnemoen     }, {
264526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0013000,
265526dbbe0SHavard Skinnemoen         .reset_pu = 0x00fc0000,
266526dbbe0SHavard Skinnemoen         .reset_pd = 0xff000000,
267526dbbe0SHavard Skinnemoen     }, {
268526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0014000,
269526dbbe0SHavard Skinnemoen         .reset_pu = 0xffffffff,
270526dbbe0SHavard Skinnemoen     }, {
271526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0015000,
272526dbbe0SHavard Skinnemoen         .reset_pu = 0xbf83f801,
273526dbbe0SHavard Skinnemoen         .reset_pd = 0x007c0000,
274526dbbe0SHavard Skinnemoen         .reset_osrc = 0x000000f1,
275526dbbe0SHavard Skinnemoen         .reset_odsc = 0x3f9f80f1,
276526dbbe0SHavard Skinnemoen     }, {
277526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0016000,
278526dbbe0SHavard Skinnemoen         .reset_pu = 0xfc00f801,
279526dbbe0SHavard Skinnemoen         .reset_pd = 0x000007fe,
280526dbbe0SHavard Skinnemoen         .reset_odsc = 0x00000800,
281526dbbe0SHavard Skinnemoen     }, {
282526dbbe0SHavard Skinnemoen         .regs_addr = 0xf0017000,
283526dbbe0SHavard Skinnemoen         .unconnected_pins = 0xffffff00,
284526dbbe0SHavard Skinnemoen         .reset_pu = 0x0000007f,
285526dbbe0SHavard Skinnemoen         .reset_osrc = 0x0000007f,
286526dbbe0SHavard Skinnemoen         .reset_odsc = 0x0000007f,
287526dbbe0SHavard Skinnemoen     },
288526dbbe0SHavard Skinnemoen };
289526dbbe0SHavard Skinnemoen 
290526dbbe0SHavard Skinnemoen static const struct {
291b821242cSHavard Skinnemoen     const char *name;
292b821242cSHavard Skinnemoen     hwaddr regs_addr;
293b821242cSHavard Skinnemoen     int cs_count;
294b821242cSHavard Skinnemoen     const hwaddr *flash_addr;
295b821242cSHavard Skinnemoen } npcm7xx_fiu[] = {
296b821242cSHavard Skinnemoen     {
297b821242cSHavard Skinnemoen         .name = "fiu0",
298b821242cSHavard Skinnemoen         .regs_addr = 0xfb000000,
299b821242cSHavard Skinnemoen         .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
300b821242cSHavard Skinnemoen         .flash_addr = npcm7xx_fiu0_flash_addr,
301b821242cSHavard Skinnemoen     }, {
302b821242cSHavard Skinnemoen         .name = "fiu3",
303b821242cSHavard Skinnemoen         .regs_addr = 0xc0000000,
304b821242cSHavard Skinnemoen         .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
305b821242cSHavard Skinnemoen         .flash_addr = npcm7xx_fiu3_flash_addr,
306b821242cSHavard Skinnemoen     },
307b821242cSHavard Skinnemoen };
308b821242cSHavard Skinnemoen 
3092ddae9ccSHavard Skinnemoen static void npcm7xx_write_board_setup(ARMCPU *cpu,
3102ddae9ccSHavard Skinnemoen                                       const struct arm_boot_info *info)
3112ddae9ccSHavard Skinnemoen {
3122ddae9ccSHavard Skinnemoen     uint32_t board_setup[] = {
3132ddae9ccSHavard Skinnemoen         0xe59f0010,     /* ldr r0, clk_base_addr */
3142ddae9ccSHavard Skinnemoen         0xe59f1010,     /* ldr r1, pllcon1_value */
3152ddae9ccSHavard Skinnemoen         0xe5801010,     /* str r1, [r0, #16] */
3162ddae9ccSHavard Skinnemoen         0xe59f100c,     /* ldr r1, clksel_value */
3172ddae9ccSHavard Skinnemoen         0xe5801004,     /* str r1, [r0, #4] */
3182ddae9ccSHavard Skinnemoen         0xe12fff1e,     /* bx lr */
3192ddae9ccSHavard Skinnemoen         NPCM7XX_CLK_BA,
3202ddae9ccSHavard Skinnemoen         NPCM7XX_PLLCON1_FIXUP_VAL,
3212ddae9ccSHavard Skinnemoen         NPCM7XX_CLKSEL_FIXUP_VAL,
3222ddae9ccSHavard Skinnemoen     };
3232ddae9ccSHavard Skinnemoen     int i;
3242ddae9ccSHavard Skinnemoen 
3252ddae9ccSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
3262ddae9ccSHavard Skinnemoen         board_setup[i] = tswap32(board_setup[i]);
3272ddae9ccSHavard Skinnemoen     }
3282ddae9ccSHavard Skinnemoen     rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
3292ddae9ccSHavard Skinnemoen                        info->board_setup_addr);
3302ddae9ccSHavard Skinnemoen }
3312ddae9ccSHavard Skinnemoen 
3322d8f048cSHavard Skinnemoen static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
3332d8f048cSHavard Skinnemoen                                          const struct arm_boot_info *info)
3342d8f048cSHavard Skinnemoen {
3352d8f048cSHavard Skinnemoen     /*
3362d8f048cSHavard Skinnemoen      * The default smpboot stub halts the secondary CPU with a 'wfi'
3372d8f048cSHavard Skinnemoen      * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
3382d8f048cSHavard Skinnemoen      * does not send an IPI to wake it up, so the second CPU fails to boot. So
3392d8f048cSHavard Skinnemoen      * we need to provide our own smpboot stub that can not use 'wfi', it has
3402d8f048cSHavard Skinnemoen      * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
3412d8f048cSHavard Skinnemoen      */
3422d8f048cSHavard Skinnemoen     uint32_t smpboot[] = {
3432d8f048cSHavard Skinnemoen         0xe59f2018,     /* ldr r2, bootreg_addr */
3442d8f048cSHavard Skinnemoen         0xe3a00000,     /* mov r0, #0 */
3452d8f048cSHavard Skinnemoen         0xe5820000,     /* str r0, [r2] */
3462d8f048cSHavard Skinnemoen         0xe320f002,     /* wfe */
3472d8f048cSHavard Skinnemoen         0xe5921000,     /* ldr r1, [r2] */
3482d8f048cSHavard Skinnemoen         0xe1110001,     /* tst r1, r1 */
3492d8f048cSHavard Skinnemoen         0x0afffffb,     /* beq <wfe> */
3502d8f048cSHavard Skinnemoen         0xe12fff11,     /* bx r1 */
3512d8f048cSHavard Skinnemoen         NPCM7XX_SMP_BOOTREG_ADDR,
3522d8f048cSHavard Skinnemoen     };
3532d8f048cSHavard Skinnemoen     int i;
3542d8f048cSHavard Skinnemoen 
3552d8f048cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
3562d8f048cSHavard Skinnemoen         smpboot[i] = tswap32(smpboot[i]);
3572d8f048cSHavard Skinnemoen     }
3582d8f048cSHavard Skinnemoen 
3592d8f048cSHavard Skinnemoen     rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
3602d8f048cSHavard Skinnemoen                        NPCM7XX_SMP_LOADER_START);
3612d8f048cSHavard Skinnemoen }
3622d8f048cSHavard Skinnemoen 
3632d8f048cSHavard Skinnemoen static struct arm_boot_info npcm7xx_binfo = {
3642d8f048cSHavard Skinnemoen     .loader_start           = NPCM7XX_LOADER_START,
3652d8f048cSHavard Skinnemoen     .smp_loader_start       = NPCM7XX_SMP_LOADER_START,
3662d8f048cSHavard Skinnemoen     .smp_bootreg_addr       = NPCM7XX_SMP_BOOTREG_ADDR,
3672d8f048cSHavard Skinnemoen     .gic_cpu_if_addr        = NPCM7XX_GIC_CPU_IF_ADDR,
3682d8f048cSHavard Skinnemoen     .write_secondary_boot   = npcm7xx_write_secondary_boot,
3692d8f048cSHavard Skinnemoen     .board_id               = -1,
3702ddae9ccSHavard Skinnemoen     .board_setup_addr       = NPCM7XX_BOARD_SETUP_ADDR,
3712ddae9ccSHavard Skinnemoen     .write_board_setup      = npcm7xx_write_board_setup,
3722d8f048cSHavard Skinnemoen };
3732d8f048cSHavard Skinnemoen 
3742d8f048cSHavard Skinnemoen void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
3752d8f048cSHavard Skinnemoen {
3762d8f048cSHavard Skinnemoen     npcm7xx_binfo.ram_size = machine->ram_size;
3772d8f048cSHavard Skinnemoen 
3782d8f048cSHavard Skinnemoen     arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
3792d8f048cSHavard Skinnemoen }
3802d8f048cSHavard Skinnemoen 
381c752bb07SHavard Skinnemoen static void npcm7xx_init_fuses(NPCM7xxState *s)
382c752bb07SHavard Skinnemoen {
383c752bb07SHavard Skinnemoen     NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
384c752bb07SHavard Skinnemoen     uint32_t value;
385c752bb07SHavard Skinnemoen 
386c752bb07SHavard Skinnemoen     /*
387c752bb07SHavard Skinnemoen      * The initial mask of disabled modules indicates the chip derivative (e.g.
388c752bb07SHavard Skinnemoen      * NPCM750 or NPCM730).
389c752bb07SHavard Skinnemoen      */
390*eb656a60SPhilippe Mathieu-Daudé     value = cpu_to_le32(nc->disabled_modules);
391c752bb07SHavard Skinnemoen     npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
392c752bb07SHavard Skinnemoen                             sizeof(value));
393c752bb07SHavard Skinnemoen }
394c752bb07SHavard Skinnemoen 
39577c05b0bSHao Wu static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
39677c05b0bSHao Wu {
39777c05b0bSHao Wu     /* Both ADC and the fuse array must have realized. */
39877c05b0bSHao Wu     QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
39977c05b0bSHao Wu     npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
40077c05b0bSHao Wu             NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
40177c05b0bSHao Wu }
40277c05b0bSHao Wu 
4032d8f048cSHavard Skinnemoen static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
4042d8f048cSHavard Skinnemoen {
4052d8f048cSHavard Skinnemoen     return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
4062d8f048cSHavard Skinnemoen }
4072d8f048cSHavard Skinnemoen 
4082d8f048cSHavard Skinnemoen static void npcm7xx_init(Object *obj)
4092d8f048cSHavard Skinnemoen {
4102d8f048cSHavard Skinnemoen     NPCM7xxState *s = NPCM7XX(obj);
4112d8f048cSHavard Skinnemoen     int i;
4122d8f048cSHavard Skinnemoen 
4132d8f048cSHavard Skinnemoen     for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
4142d8f048cSHavard Skinnemoen         object_initialize_child(obj, "cpu[*]", &s->cpu[i],
4152d8f048cSHavard Skinnemoen                                 ARM_CPU_TYPE_NAME("cortex-a9"));
4162d8f048cSHavard Skinnemoen     }
4172d8f048cSHavard Skinnemoen 
4182d8f048cSHavard Skinnemoen     object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
4192d8f048cSHavard Skinnemoen     object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
4202d8f048cSHavard Skinnemoen     object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
4212d8f048cSHavard Skinnemoen                               "power-on-straps");
4222d8f048cSHavard Skinnemoen     object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
423c752bb07SHavard Skinnemoen     object_initialize_child(obj, "otp1", &s->key_storage,
424c752bb07SHavard Skinnemoen                             TYPE_NPCM7XX_KEY_STORAGE);
425c752bb07SHavard Skinnemoen     object_initialize_child(obj, "otp2", &s->fuse_array,
426c752bb07SHavard Skinnemoen                             TYPE_NPCM7XX_FUSE_ARRAY);
4271351f892SHavard Skinnemoen     object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
428326ccfe2SHavard Skinnemoen     object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
42977c05b0bSHao Wu     object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
4302d8f048cSHavard Skinnemoen 
4312d8f048cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
4322d8f048cSHavard Skinnemoen         object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
4332d8f048cSHavard Skinnemoen     }
434b821242cSHavard Skinnemoen 
435526dbbe0SHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
436526dbbe0SHavard Skinnemoen         object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
437526dbbe0SHavard Skinnemoen     }
438526dbbe0SHavard Skinnemoen 
43994e77879SHao Wu     for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
44094e77879SHao Wu         object_initialize_child(obj, "smbus[*]", &s->smbus[i],
44194e77879SHao Wu                                 TYPE_NPCM7XX_SMBUS);
44294e77879SHao Wu     }
44394e77879SHao Wu 
444e23e7b12SHavard Skinnemoen     object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
445e23e7b12SHavard Skinnemoen     object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
446e23e7b12SHavard Skinnemoen 
447b821242cSHavard Skinnemoen     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
448b821242cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
449b821242cSHavard Skinnemoen         object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
450b821242cSHavard Skinnemoen                                 TYPE_NPCM7XX_FIU);
451b821242cSHavard Skinnemoen     }
4521e943c58SHao Wu 
4531e943c58SHao Wu     for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
4541e943c58SHao Wu         object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
4551e943c58SHao Wu     }
45677586436SDoug Evans 
457fc11115fSHao Wu     for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
458fc11115fSHao Wu         object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
459fc11115fSHao Wu     }
460fc11115fSHao Wu 
46177586436SDoug Evans     for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
46277586436SDoug Evans         object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
46377586436SDoug Evans     }
4640a9df6cbSShengtan Mao 
4654d120d7dSHao Wu     for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
4664d120d7dSHao Wu         object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
4674d120d7dSHao Wu     }
4684d120d7dSHao Wu 
46921e5326aSHao Wu     for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
47021e5326aSHao Wu         object_initialize_child(obj, "gmac[*]", &s->gmac[i], TYPE_NPCM_GMAC);
47121e5326aSHao Wu     }
47221e5326aSHao Wu 
4730a9df6cbSShengtan Mao     object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
4742d8f048cSHavard Skinnemoen }
4752d8f048cSHavard Skinnemoen 
4762d8f048cSHavard Skinnemoen static void npcm7xx_realize(DeviceState *dev, Error **errp)
4772d8f048cSHavard Skinnemoen {
4782d8f048cSHavard Skinnemoen     NPCM7xxState *s = NPCM7XX(dev);
4792d8f048cSHavard Skinnemoen     NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
4802d8f048cSHavard Skinnemoen     int i;
4812d8f048cSHavard Skinnemoen 
4822d8f048cSHavard Skinnemoen     if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
4832d8f048cSHavard Skinnemoen         error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
4842d8f048cSHavard Skinnemoen                    " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
4852d8f048cSHavard Skinnemoen         return;
4862d8f048cSHavard Skinnemoen     }
4872d8f048cSHavard Skinnemoen 
4882d8f048cSHavard Skinnemoen     /* CPUs */
4892d8f048cSHavard Skinnemoen     for (i = 0; i < nc->num_cpus; i++) {
4902d8f048cSHavard Skinnemoen         object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
491750245edSRichard Henderson                                 arm_build_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
4922d8f048cSHavard Skinnemoen                                 &error_abort);
4932d8f048cSHavard Skinnemoen         object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
4942d8f048cSHavard Skinnemoen                                 NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
4952d8f048cSHavard Skinnemoen         object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
4962d8f048cSHavard Skinnemoen                                  &error_abort);
4972d8f048cSHavard Skinnemoen 
4982d8f048cSHavard Skinnemoen         /* Disable security extensions. */
4992d8f048cSHavard Skinnemoen         object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
5002d8f048cSHavard Skinnemoen                                  &error_abort);
5012d8f048cSHavard Skinnemoen 
5022d8f048cSHavard Skinnemoen         if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
5032d8f048cSHavard Skinnemoen             return;
5042d8f048cSHavard Skinnemoen         }
5052d8f048cSHavard Skinnemoen     }
5062d8f048cSHavard Skinnemoen 
5072d8f048cSHavard Skinnemoen     /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
5082d8f048cSHavard Skinnemoen     object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
5092d8f048cSHavard Skinnemoen                             &error_abort);
5102d8f048cSHavard Skinnemoen     object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
5112d8f048cSHavard Skinnemoen                             &error_abort);
5122d8f048cSHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
5132d8f048cSHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
5142d8f048cSHavard Skinnemoen 
5152d8f048cSHavard Skinnemoen     for (i = 0; i < nc->num_cpus; i++) {
5162d8f048cSHavard Skinnemoen         sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
5172d8f048cSHavard Skinnemoen                            qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
5182d8f048cSHavard Skinnemoen         sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
5192d8f048cSHavard Skinnemoen                            qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
5202d8f048cSHavard Skinnemoen     }
5212d8f048cSHavard Skinnemoen 
5222d8f048cSHavard Skinnemoen     /* L2 cache controller */
5232d8f048cSHavard Skinnemoen     sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
5242d8f048cSHavard Skinnemoen 
5252d8f048cSHavard Skinnemoen     /* System Global Control Registers (GCR). Can fail due to user input. */
5262d8f048cSHavard Skinnemoen     object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
5272d8f048cSHavard Skinnemoen                             nc->disabled_modules, &error_abort);
5282d8f048cSHavard Skinnemoen     object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
5292d8f048cSHavard Skinnemoen     if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
5302d8f048cSHavard Skinnemoen         return;
5312d8f048cSHavard Skinnemoen     }
5322d8f048cSHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
5332d8f048cSHavard Skinnemoen 
5342d8f048cSHavard Skinnemoen     /* Clock Control Registers (CLK). Cannot fail. */
5352d8f048cSHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
5362d8f048cSHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
5372d8f048cSHavard Skinnemoen 
538c752bb07SHavard Skinnemoen     /* OTP key storage and fuse strap array. Cannot fail. */
539c752bb07SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
540c752bb07SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
541c752bb07SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
542c752bb07SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
543c752bb07SHavard Skinnemoen     npcm7xx_init_fuses(s);
544c752bb07SHavard Skinnemoen 
5451351f892SHavard Skinnemoen     /* Fake Memory Controller (MC). Cannot fail. */
5461351f892SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
5471351f892SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
5481351f892SHavard Skinnemoen 
54977c05b0bSHao Wu     /* ADC Modules. Cannot fail. */
55077c05b0bSHao Wu     qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
55177c05b0bSHao Wu                           DEVICE(&s->clk), "adc-clock"));
55277c05b0bSHao Wu     sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
55377c05b0bSHao Wu     sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
55477c05b0bSHao Wu     sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
55577c05b0bSHao Wu             npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
55677c05b0bSHao Wu     npcm7xx_write_adc_calibration(s);
55777c05b0bSHao Wu 
5582d8f048cSHavard Skinnemoen     /* Timer Modules (TIM). Cannot fail. */
5592d8f048cSHavard Skinnemoen     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
5602d8f048cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
5612d8f048cSHavard Skinnemoen         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
5622d8f048cSHavard Skinnemoen         int first_irq;
5632d8f048cSHavard Skinnemoen         int j;
5642d8f048cSHavard Skinnemoen 
5650be12dc7SHao Wu         /* Connect the timer clock. */
5660be12dc7SHao Wu         qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
5670be12dc7SHao Wu                     DEVICE(&s->clk), "timer-clock"));
5680be12dc7SHao Wu 
5692d8f048cSHavard Skinnemoen         sysbus_realize(sbd, &error_abort);
5702d8f048cSHavard Skinnemoen         sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
5712d8f048cSHavard Skinnemoen 
5722d8f048cSHavard Skinnemoen         first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
5732d8f048cSHavard Skinnemoen         for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
5742d8f048cSHavard Skinnemoen             qemu_irq irq = npcm7xx_irq(s, first_irq + j);
5752d8f048cSHavard Skinnemoen             sysbus_connect_irq(sbd, j, irq);
5762d8f048cSHavard Skinnemoen         }
5777d378ed6SHao Wu 
5787d378ed6SHao Wu         /* IRQ for watchdogs */
5797d378ed6SHao Wu         sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL,
5807d378ed6SHao Wu                 npcm7xx_irq(s, NPCM7XX_WDG0_IRQ + i));
5817d378ed6SHao Wu         /* GPIO that connects clk module with watchdog */
5827d378ed6SHao Wu         qdev_connect_gpio_out_named(DEVICE(&s->tim[i]),
5837d378ed6SHao Wu                 NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0,
5847d378ed6SHao Wu                 qdev_get_gpio_in_named(DEVICE(&s->clk),
5857d378ed6SHao Wu                         NPCM7XX_WATCHDOG_RESET_GPIO_IN, i));
5862d8f048cSHavard Skinnemoen     }
5872d8f048cSHavard Skinnemoen 
5882d8f048cSHavard Skinnemoen     /* UART0..3 (16550 compatible) */
5892d8f048cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
5902d8f048cSHavard Skinnemoen         serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
5912d8f048cSHavard Skinnemoen                        npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
5922d8f048cSHavard Skinnemoen                        serial_hd(i), DEVICE_LITTLE_ENDIAN);
5932d8f048cSHavard Skinnemoen     }
5942d8f048cSHavard Skinnemoen 
595326ccfe2SHavard Skinnemoen     /* Random Number Generator. Cannot fail. */
596326ccfe2SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
597326ccfe2SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
598326ccfe2SHavard Skinnemoen 
599526dbbe0SHavard Skinnemoen     /* GPIO modules. Cannot fail. */
600526dbbe0SHavard Skinnemoen     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio));
601526dbbe0SHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
602526dbbe0SHavard Skinnemoen         Object *obj = OBJECT(&s->gpio[i]);
603526dbbe0SHavard Skinnemoen 
604526dbbe0SHavard Skinnemoen         object_property_set_uint(obj, "reset-pullup",
605526dbbe0SHavard Skinnemoen                                  npcm7xx_gpio[i].reset_pu, &error_abort);
606526dbbe0SHavard Skinnemoen         object_property_set_uint(obj, "reset-pulldown",
607526dbbe0SHavard Skinnemoen                                  npcm7xx_gpio[i].reset_pd, &error_abort);
608526dbbe0SHavard Skinnemoen         object_property_set_uint(obj, "reset-osrc",
609526dbbe0SHavard Skinnemoen                                  npcm7xx_gpio[i].reset_osrc, &error_abort);
610526dbbe0SHavard Skinnemoen         object_property_set_uint(obj, "reset-odsc",
611526dbbe0SHavard Skinnemoen                                  npcm7xx_gpio[i].reset_odsc, &error_abort);
612526dbbe0SHavard Skinnemoen         sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
613526dbbe0SHavard Skinnemoen         sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_gpio[i].regs_addr);
614526dbbe0SHavard Skinnemoen         sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
615526dbbe0SHavard Skinnemoen                            npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
616526dbbe0SHavard Skinnemoen     }
617526dbbe0SHavard Skinnemoen 
61894e77879SHao Wu     /* SMBus modules. Cannot fail. */
61994e77879SHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) != ARRAY_SIZE(s->smbus));
62094e77879SHao Wu     for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
62194e77879SHao Wu         Object *obj = OBJECT(&s->smbus[i]);
62294e77879SHao Wu 
62394e77879SHao Wu         sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
62494e77879SHao Wu         sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]);
62594e77879SHao Wu         sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
62694e77879SHao Wu                            npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i));
62794e77879SHao Wu     }
62894e77879SHao Wu 
629e23e7b12SHavard Skinnemoen     /* USB Host */
630e23e7b12SHavard Skinnemoen     object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
631e23e7b12SHavard Skinnemoen                              &error_abort);
632e23e7b12SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort);
633e23e7b12SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA);
634e23e7b12SHavard Skinnemoen     sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0,
635e23e7b12SHavard Skinnemoen                        npcm7xx_irq(s, NPCM7XX_EHCI_IRQ));
636e23e7b12SHavard Skinnemoen 
637e23e7b12SHavard Skinnemoen     object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0",
638e23e7b12SHavard Skinnemoen                             &error_abort);
639e23e7b12SHavard Skinnemoen     object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort);
640e23e7b12SHavard Skinnemoen     sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort);
641e23e7b12SHavard Skinnemoen     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA);
642e23e7b12SHavard Skinnemoen     sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
643e23e7b12SHavard Skinnemoen                        npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
644e23e7b12SHavard Skinnemoen 
6451e943c58SHao Wu     /* PWM Modules. Cannot fail. */
6461e943c58SHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
6471e943c58SHao Wu     for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
6481e943c58SHao Wu         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
6491e943c58SHao Wu 
6501e943c58SHao Wu         qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
6511e943c58SHao Wu                     DEVICE(&s->clk), "apb3-clock"));
6521e943c58SHao Wu         sysbus_realize(sbd, &error_abort);
6531e943c58SHao Wu         sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
6541e943c58SHao Wu         sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
6551e943c58SHao Wu     }
6561e943c58SHao Wu 
657fc11115fSHao Wu     /* MFT Modules. Cannot fail. */
658fc11115fSHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
659fc11115fSHao Wu     for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
660fc11115fSHao Wu         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
661fc11115fSHao Wu 
662fc11115fSHao Wu         qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
663fc11115fSHao Wu                               qdev_get_clock_out(DEVICE(&s->clk),
664fc11115fSHao Wu                                                  "apb4-clock"));
665fc11115fSHao Wu         sysbus_realize(sbd, &error_abort);
666fc11115fSHao Wu         sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
667fc11115fSHao Wu         sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
668fc11115fSHao Wu     }
669fc11115fSHao Wu 
670b821242cSHavard Skinnemoen     /*
67177586436SDoug Evans      * EMC Modules. Cannot fail.
672707a42e2SDavid Woodhouse      * Use the available NIC configurations in order, allowing 'emc0' and
673707a42e2SDavid Woodhouse      * 'emc1' to by used as aliases for the model= parameter to override.
674707a42e2SDavid Woodhouse      *
67577586436SDoug Evans      * This works around the inability to specify the netdev property for the
67677586436SDoug Evans      * emc device: it's not pluggable and thus the -device option can't be
67777586436SDoug Evans      * used.
67877586436SDoug Evans      */
67977586436SDoug Evans     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
68077586436SDoug Evans     QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
68177586436SDoug Evans     for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
68277586436SDoug Evans         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
683707a42e2SDavid Woodhouse         char alias[6];
684707a42e2SDavid Woodhouse 
685707a42e2SDavid Woodhouse         s->emc[i].emc_num = i;
686707a42e2SDavid Woodhouse         snprintf(alias, sizeof(alias), "emc%u", i);
687707a42e2SDavid Woodhouse         qemu_configure_nic_device(DEVICE(sbd), true, alias);
688707a42e2SDavid Woodhouse 
68977586436SDoug Evans         /*
69077586436SDoug Evans          * The device exists regardless of whether it's connected to a QEMU
69177586436SDoug Evans          * netdev backend. So always instantiate it even if there is no
69277586436SDoug Evans          * backend.
69377586436SDoug Evans          */
69477586436SDoug Evans         sysbus_realize(sbd, &error_abort);
69577586436SDoug Evans         sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
69677586436SDoug Evans         int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
69777586436SDoug Evans         int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
69877586436SDoug Evans         /*
69977586436SDoug Evans          * N.B. The values for the second argument sysbus_connect_irq are
70077586436SDoug Evans          * chosen to match the registration order in npcm7xx_emc_realize.
70177586436SDoug Evans          */
70277586436SDoug Evans         sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
70377586436SDoug Evans         sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
70477586436SDoug Evans     }
70577586436SDoug Evans 
70677586436SDoug Evans     /*
70721e5326aSHao Wu      * GMAC Modules. Cannot fail.
70821e5326aSHao Wu      */
70921e5326aSHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gmac_addr) != ARRAY_SIZE(s->gmac));
71021e5326aSHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->gmac) != 2);
71121e5326aSHao Wu     for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
71221e5326aSHao Wu         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
71321e5326aSHao Wu 
714243f865aSPeter Maydell         qemu_configure_nic_device(DEVICE(sbd), false, NULL);
71521e5326aSHao Wu         /*
71621e5326aSHao Wu          * The device exists regardless of whether it's connected to a QEMU
71721e5326aSHao Wu          * netdev backend. So always instantiate it even if there is no
71821e5326aSHao Wu          * backend.
71921e5326aSHao Wu          */
72021e5326aSHao Wu         sysbus_realize(sbd, &error_abort);
72121e5326aSHao Wu         sysbus_mmio_map(sbd, 0, npcm7xx_gmac_addr[i]);
72221e5326aSHao Wu         int irq = i == 0 ? NPCM7XX_GMAC1_IRQ : NPCM7XX_GMAC2_IRQ;
72321e5326aSHao Wu         /*
72421e5326aSHao Wu          * N.B. The values for the second argument sysbus_connect_irq are
72521e5326aSHao Wu          * chosen to match the registration order in npcm7xx_emc_realize.
72621e5326aSHao Wu          */
72721e5326aSHao Wu         sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
72821e5326aSHao Wu     }
72921e5326aSHao Wu 
73021e5326aSHao Wu     /*
731b821242cSHavard Skinnemoen      * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
732b821242cSHavard Skinnemoen      * specified, but this is a programming error.
733b821242cSHavard Skinnemoen      */
734b821242cSHavard Skinnemoen     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
735b821242cSHavard Skinnemoen     for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
736b821242cSHavard Skinnemoen         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
737b821242cSHavard Skinnemoen         int j;
738b821242cSHavard Skinnemoen 
739b821242cSHavard Skinnemoen         object_property_set_int(OBJECT(sbd), "cs-count",
740b821242cSHavard Skinnemoen                                 npcm7xx_fiu[i].cs_count, &error_abort);
741b821242cSHavard Skinnemoen         sysbus_realize(sbd, &error_abort);
742b821242cSHavard Skinnemoen 
743b821242cSHavard Skinnemoen         sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
744b821242cSHavard Skinnemoen         for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
745b821242cSHavard Skinnemoen             sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
746b821242cSHavard Skinnemoen         }
747b821242cSHavard Skinnemoen     }
748b821242cSHavard Skinnemoen 
7492d8f048cSHavard Skinnemoen     /* RAM2 (SRAM) */
7502d8f048cSHavard Skinnemoen     memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
7512d8f048cSHavard Skinnemoen                            NPCM7XX_RAM2_SZ, &error_abort);
7522d8f048cSHavard Skinnemoen     memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
7532d8f048cSHavard Skinnemoen 
7542d8f048cSHavard Skinnemoen     /* RAM3 (SRAM) */
7552d8f048cSHavard Skinnemoen     memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
7562d8f048cSHavard Skinnemoen                            NPCM7XX_RAM3_SZ, &error_abort);
7572d8f048cSHavard Skinnemoen     memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
7582d8f048cSHavard Skinnemoen 
7592d8f048cSHavard Skinnemoen     /* Internal ROM */
7602d8f048cSHavard Skinnemoen     memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
7612d8f048cSHavard Skinnemoen                            &error_abort);
7622d8f048cSHavard Skinnemoen     memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
7632d8f048cSHavard Skinnemoen 
7640a9df6cbSShengtan Mao     /* SDHCI */
7650a9df6cbSShengtan Mao     sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort);
7660a9df6cbSShengtan Mao     sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA);
7670a9df6cbSShengtan Mao     sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
7680a9df6cbSShengtan Mao             npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
7690a9df6cbSShengtan Mao 
7704d120d7dSHao Wu     /* PSPI */
7714d120d7dSHao Wu     QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pspi_addr) != ARRAY_SIZE(s->pspi));
7724d120d7dSHao Wu     for (i = 0; i < ARRAY_SIZE(s->pspi); i++) {
7734d120d7dSHao Wu         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pspi[i]);
7744d120d7dSHao Wu         int irq = (i == 0) ? NPCM7XX_PSPI1_IRQ : NPCM7XX_PSPI2_IRQ;
7754d120d7dSHao Wu 
7764d120d7dSHao Wu         sysbus_realize(sbd, &error_abort);
7774d120d7dSHao Wu         sysbus_mmio_map(sbd, 0, npcm7xx_pspi_addr[i]);
7784d120d7dSHao Wu         sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
7794d120d7dSHao Wu     }
7804d120d7dSHao Wu 
7812d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.shm",          0xc0001000,   4 * KiB);
7822d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.vdmx",         0xe0800000,   4 * KiB);
7832d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.pcierc",       0xe1000000,  64 * KiB);
7842d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.kcs",          0xf0007000,   4 * KiB);
7852d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.gfxi",         0xf000e000,   4 * KiB);
7862d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.espi",         0xf009f000,   4 * KiB);
7872d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.peci",         0xf0100000,   4 * KiB);
7882d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.siox[1]",      0xf0101000,   4 * KiB);
7892d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.siox[2]",      0xf0102000,   4 * KiB);
7902d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.ahbpci",       0xf0400000,   1 * MiB);
7912d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.mcphy",        0xf05f0000,  64 * KiB);
7922d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.vcd",          0xf0810000,  64 * KiB);
7932d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.ece",          0xf0820000,   8 * KiB);
7942d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.vdma",         0xf0822000,   8 * KiB);
7952d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[0]",      0xf0830000,   4 * KiB);
7962d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[1]",      0xf0831000,   4 * KiB);
7972d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[2]",      0xf0832000,   4 * KiB);
7982d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[3]",      0xf0833000,   4 * KiB);
7992d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[4]",      0xf0834000,   4 * KiB);
8002d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[5]",      0xf0835000,   4 * KiB);
8012d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[6]",      0xf0836000,   4 * KiB);
8022d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[7]",      0xf0837000,   4 * KiB);
8032d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[8]",      0xf0838000,   4 * KiB);
8042d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.usbd[9]",      0xf0839000,   4 * KiB);
8052d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.sd",           0xf0840000,   8 * KiB);
8062d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.pcimbx",       0xf0848000, 512 * KiB);
8072d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.aes",          0xf0858000,   4 * KiB);
8082d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.des",          0xf0859000,   4 * KiB);
8092d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.sha",          0xf085a000,   4 * KiB);
8102d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.secacc",       0xf085b000,   4 * KiB);
8112d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.spixcs0",      0xf8000000,  16 * MiB);
8122d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.spixcs1",      0xf9000000,  16 * MiB);
8132d8f048cSHavard Skinnemoen     create_unimplemented_device("npcm7xx.spix",         0xfb001000,   4 * KiB);
8142d8f048cSHavard Skinnemoen }
8152d8f048cSHavard Skinnemoen 
8162d8f048cSHavard Skinnemoen static Property npcm7xx_properties[] = {
8172d8f048cSHavard Skinnemoen     DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
8182d8f048cSHavard Skinnemoen                      MemoryRegion *),
8192d8f048cSHavard Skinnemoen     DEFINE_PROP_END_OF_LIST(),
8202d8f048cSHavard Skinnemoen };
8212d8f048cSHavard Skinnemoen 
8222d8f048cSHavard Skinnemoen static void npcm7xx_class_init(ObjectClass *oc, void *data)
8232d8f048cSHavard Skinnemoen {
8242d8f048cSHavard Skinnemoen     DeviceClass *dc = DEVICE_CLASS(oc);
8252d8f048cSHavard Skinnemoen 
8262d8f048cSHavard Skinnemoen     dc->realize = npcm7xx_realize;
8272d8f048cSHavard Skinnemoen     dc->user_creatable = false;
8282d8f048cSHavard Skinnemoen     device_class_set_props(dc, npcm7xx_properties);
8292d8f048cSHavard Skinnemoen }
8302d8f048cSHavard Skinnemoen 
8312d8f048cSHavard Skinnemoen static void npcm730_class_init(ObjectClass *oc, void *data)
8322d8f048cSHavard Skinnemoen {
8332d8f048cSHavard Skinnemoen     NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
8342d8f048cSHavard Skinnemoen 
8352d8f048cSHavard Skinnemoen     /* NPCM730 is optimized for data center use, so no graphics, etc. */
8362d8f048cSHavard Skinnemoen     nc->disabled_modules = 0x00300395;
8372d8f048cSHavard Skinnemoen     nc->num_cpus = 2;
8382d8f048cSHavard Skinnemoen }
8392d8f048cSHavard Skinnemoen 
8402d8f048cSHavard Skinnemoen static void npcm750_class_init(ObjectClass *oc, void *data)
8412d8f048cSHavard Skinnemoen {
8422d8f048cSHavard Skinnemoen     NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
8432d8f048cSHavard Skinnemoen 
8442d8f048cSHavard Skinnemoen     /* NPCM750 has 2 cores and a full set of peripherals */
8452d8f048cSHavard Skinnemoen     nc->disabled_modules = 0x00000000;
8462d8f048cSHavard Skinnemoen     nc->num_cpus = 2;
8472d8f048cSHavard Skinnemoen }
8482d8f048cSHavard Skinnemoen 
8492d8f048cSHavard Skinnemoen static const TypeInfo npcm7xx_soc_types[] = {
8502d8f048cSHavard Skinnemoen     {
8512d8f048cSHavard Skinnemoen         .name           = TYPE_NPCM7XX,
8522d8f048cSHavard Skinnemoen         .parent         = TYPE_DEVICE,
8532d8f048cSHavard Skinnemoen         .instance_size  = sizeof(NPCM7xxState),
8542d8f048cSHavard Skinnemoen         .instance_init  = npcm7xx_init,
8552d8f048cSHavard Skinnemoen         .class_size     = sizeof(NPCM7xxClass),
8562d8f048cSHavard Skinnemoen         .class_init     = npcm7xx_class_init,
8572d8f048cSHavard Skinnemoen         .abstract       = true,
8582d8f048cSHavard Skinnemoen     }, {
8592d8f048cSHavard Skinnemoen         .name           = TYPE_NPCM730,
8602d8f048cSHavard Skinnemoen         .parent         = TYPE_NPCM7XX,
8612d8f048cSHavard Skinnemoen         .class_init     = npcm730_class_init,
8622d8f048cSHavard Skinnemoen     }, {
8632d8f048cSHavard Skinnemoen         .name           = TYPE_NPCM750,
8642d8f048cSHavard Skinnemoen         .parent         = TYPE_NPCM7XX,
8652d8f048cSHavard Skinnemoen         .class_init     = npcm750_class_init,
8662d8f048cSHavard Skinnemoen     },
8672d8f048cSHavard Skinnemoen };
8682d8f048cSHavard Skinnemoen 
8692d8f048cSHavard Skinnemoen DEFINE_TYPES(npcm7xx_soc_types);
870