1ae0c4d1aSHao Wu /* 2ae0c4d1aSHao Wu * Nuvoton NPCM8xx SoC family. 3ae0c4d1aSHao Wu * 4ae0c4d1aSHao Wu * Copyright 2022 Google LLC 5ae0c4d1aSHao Wu * 6ae0c4d1aSHao Wu * This program is free software; you can redistribute it and/or modify it 7ae0c4d1aSHao Wu * under the terms of the GNU General Public License as published by the 8ae0c4d1aSHao Wu * Free Software Foundation; either version 2 of the License, or 9ae0c4d1aSHao Wu * (at your option) any later version. 10ae0c4d1aSHao Wu * 11ae0c4d1aSHao Wu * This program is distributed in the hope that it will be useful, but WITHOUT 12ae0c4d1aSHao Wu * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13ae0c4d1aSHao Wu * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14ae0c4d1aSHao Wu * for more details. 15ae0c4d1aSHao Wu */ 16ae0c4d1aSHao Wu 17ae0c4d1aSHao Wu #include "qemu/osdep.h" 18ae0c4d1aSHao Wu 19ae0c4d1aSHao Wu #include "hw/boards.h" 20ae0c4d1aSHao Wu #include "hw/arm/boot.h" 21ae0c4d1aSHao Wu #include "hw/arm/bsa.h" 22ae0c4d1aSHao Wu #include "hw/arm/npcm8xx.h" 23ae0c4d1aSHao Wu #include "hw/char/serial-mm.h" 24ae0c4d1aSHao Wu #include "hw/intc/arm_gic.h" 25ae0c4d1aSHao Wu #include "hw/loader.h" 26ae0c4d1aSHao Wu #include "hw/misc/unimp.h" 27ae0c4d1aSHao Wu #include "hw/qdev-clock.h" 28ae0c4d1aSHao Wu #include "hw/qdev-properties.h" 29ae0c4d1aSHao Wu #include "qapi/error.h" 30ae0c4d1aSHao Wu #include "qemu/units.h" 31ae0c4d1aSHao Wu #include "system/system.h" 32ae0c4d1aSHao Wu 33ae0c4d1aSHao Wu /* 34ae0c4d1aSHao Wu * This covers the whole MMIO space. We'll use this to catch any MMIO accesses 35ae0c4d1aSHao Wu * that aren't handled by a device. 36ae0c4d1aSHao Wu */ 37ae0c4d1aSHao Wu #define NPCM8XX_MMIO_BA 0x80000000 38ae0c4d1aSHao Wu #define NPCM8XX_MMIO_SZ 0x7ffd0000 39ae0c4d1aSHao Wu 40ae0c4d1aSHao Wu /* OTP fuse array */ 41ae0c4d1aSHao Wu #define NPCM8XX_OTP_BA 0xf0189000 42ae0c4d1aSHao Wu 43ae0c4d1aSHao Wu /* GIC Distributor */ 44ae0c4d1aSHao Wu #define NPCM8XX_GICD_BA 0xdfff9000 45ae0c4d1aSHao Wu #define NPCM8XX_GICC_BA 0xdfffa000 46ae0c4d1aSHao Wu 47ae0c4d1aSHao Wu /* Core system modules. */ 48ae0c4d1aSHao Wu #define NPCM8XX_CPUP_BA 0xf03fe000 49ae0c4d1aSHao Wu #define NPCM8XX_GCR_BA 0xf0800000 50ae0c4d1aSHao Wu #define NPCM8XX_CLK_BA 0xf0801000 51ae0c4d1aSHao Wu #define NPCM8XX_MC_BA 0xf0824000 52ae0c4d1aSHao Wu #define NPCM8XX_RNG_BA 0xf000b000 53ae0c4d1aSHao Wu 54ae0c4d1aSHao Wu /* ADC Module */ 55ae0c4d1aSHao Wu #define NPCM8XX_ADC_BA 0xf000c000 56ae0c4d1aSHao Wu 57ae0c4d1aSHao Wu /* Internal AHB SRAM */ 58ae0c4d1aSHao Wu #define NPCM8XX_RAM3_BA 0xc0008000 59ae0c4d1aSHao Wu #define NPCM8XX_RAM3_SZ (4 * KiB) 60ae0c4d1aSHao Wu 61ae0c4d1aSHao Wu /* Memory blocks at the end of the address space */ 62ae0c4d1aSHao Wu #define NPCM8XX_RAM2_BA 0xfffb0000 63ae0c4d1aSHao Wu #define NPCM8XX_RAM2_SZ (256 * KiB) 64ae0c4d1aSHao Wu #define NPCM8XX_ROM_BA 0xffff0100 65ae0c4d1aSHao Wu #define NPCM8XX_ROM_SZ (64 * KiB) 66ae0c4d1aSHao Wu 67ae0c4d1aSHao Wu /* SDHCI Modules */ 68ae0c4d1aSHao Wu #define NPCM8XX_MMC_BA 0xf0842000 69ae0c4d1aSHao Wu 70ae0c4d1aSHao Wu /* Run PLL1 at 1600 MHz */ 71ae0c4d1aSHao Wu #define NPCM8XX_PLLCON1_FIXUP_VAL 0x00402101 72ae0c4d1aSHao Wu /* Run the CPU from PLL1 and UART from PLL2 */ 73ae0c4d1aSHao Wu #define NPCM8XX_CLKSEL_FIXUP_VAL 0x004aaba9 74ae0c4d1aSHao Wu 75ae0c4d1aSHao Wu /* Clock configuration values to be fixed up when bypassing bootloader */ 76ae0c4d1aSHao Wu 77ae0c4d1aSHao Wu /* 78ae0c4d1aSHao Wu * Interrupt lines going into the GIC. This does not include internal Cortex-A35 79ae0c4d1aSHao Wu * interrupts. 80ae0c4d1aSHao Wu */ 81ae0c4d1aSHao Wu enum NPCM8xxInterrupt { 82ae0c4d1aSHao Wu NPCM8XX_ADC_IRQ = 0, 83ae0c4d1aSHao Wu NPCM8XX_PECI_IRQ = 6, 84ae0c4d1aSHao Wu NPCM8XX_KCS_HIB_IRQ = 9, 85ae0c4d1aSHao Wu NPCM8XX_MMC_IRQ = 26, 86ae0c4d1aSHao Wu NPCM8XX_TIMER0_IRQ = 32, /* Timer Module 0 */ 87ae0c4d1aSHao Wu NPCM8XX_TIMER1_IRQ, 88ae0c4d1aSHao Wu NPCM8XX_TIMER2_IRQ, 89ae0c4d1aSHao Wu NPCM8XX_TIMER3_IRQ, 90ae0c4d1aSHao Wu NPCM8XX_TIMER4_IRQ, 91ae0c4d1aSHao Wu NPCM8XX_TIMER5_IRQ, /* Timer Module 1 */ 92ae0c4d1aSHao Wu NPCM8XX_TIMER6_IRQ, 93ae0c4d1aSHao Wu NPCM8XX_TIMER7_IRQ, 94ae0c4d1aSHao Wu NPCM8XX_TIMER8_IRQ, 95ae0c4d1aSHao Wu NPCM8XX_TIMER9_IRQ, 96ae0c4d1aSHao Wu NPCM8XX_TIMER10_IRQ, /* Timer Module 2 */ 97ae0c4d1aSHao Wu NPCM8XX_TIMER11_IRQ, 98ae0c4d1aSHao Wu NPCM8XX_TIMER12_IRQ, 99ae0c4d1aSHao Wu NPCM8XX_TIMER13_IRQ, 100ae0c4d1aSHao Wu NPCM8XX_TIMER14_IRQ, 101ae0c4d1aSHao Wu NPCM8XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */ 102ae0c4d1aSHao Wu NPCM8XX_WDG1_IRQ, /* Timer Module 1 Watchdog */ 103ae0c4d1aSHao Wu NPCM8XX_WDG2_IRQ, /* Timer Module 2 Watchdog */ 104ae0c4d1aSHao Wu NPCM8XX_EHCI1_IRQ = 61, 105ae0c4d1aSHao Wu NPCM8XX_OHCI1_IRQ, 106ae0c4d1aSHao Wu NPCM8XX_EHCI2_IRQ, 107ae0c4d1aSHao Wu NPCM8XX_OHCI2_IRQ, 108ae0c4d1aSHao Wu NPCM8XX_PWM0_IRQ = 93, /* PWM module 0 */ 109ae0c4d1aSHao Wu NPCM8XX_PWM1_IRQ, /* PWM module 1 */ 110ae0c4d1aSHao Wu NPCM8XX_MFT0_IRQ = 96, /* MFT module 0 */ 111ae0c4d1aSHao Wu NPCM8XX_MFT1_IRQ, /* MFT module 1 */ 112ae0c4d1aSHao Wu NPCM8XX_MFT2_IRQ, /* MFT module 2 */ 113ae0c4d1aSHao Wu NPCM8XX_MFT3_IRQ, /* MFT module 3 */ 114ae0c4d1aSHao Wu NPCM8XX_MFT4_IRQ, /* MFT module 4 */ 115ae0c4d1aSHao Wu NPCM8XX_MFT5_IRQ, /* MFT module 5 */ 116ae0c4d1aSHao Wu NPCM8XX_MFT6_IRQ, /* MFT module 6 */ 117ae0c4d1aSHao Wu NPCM8XX_MFT7_IRQ, /* MFT module 7 */ 118ae0c4d1aSHao Wu NPCM8XX_PCI_MBOX1_IRQ = 105, 119ae0c4d1aSHao Wu NPCM8XX_PCI_MBOX2_IRQ, 120ae0c4d1aSHao Wu NPCM8XX_GPIO0_IRQ = 116, 121ae0c4d1aSHao Wu NPCM8XX_GPIO1_IRQ, 122ae0c4d1aSHao Wu NPCM8XX_GPIO2_IRQ, 123ae0c4d1aSHao Wu NPCM8XX_GPIO3_IRQ, 124ae0c4d1aSHao Wu NPCM8XX_GPIO4_IRQ, 125ae0c4d1aSHao Wu NPCM8XX_GPIO5_IRQ, 126ae0c4d1aSHao Wu NPCM8XX_GPIO6_IRQ, 127ae0c4d1aSHao Wu NPCM8XX_GPIO7_IRQ, 128ae0c4d1aSHao Wu NPCM8XX_SMBUS0_IRQ = 128, 129ae0c4d1aSHao Wu NPCM8XX_SMBUS1_IRQ, 130ae0c4d1aSHao Wu NPCM8XX_SMBUS2_IRQ, 131ae0c4d1aSHao Wu NPCM8XX_SMBUS3_IRQ, 132ae0c4d1aSHao Wu NPCM8XX_SMBUS4_IRQ, 133ae0c4d1aSHao Wu NPCM8XX_SMBUS5_IRQ, 134ae0c4d1aSHao Wu NPCM8XX_SMBUS6_IRQ, 135ae0c4d1aSHao Wu NPCM8XX_SMBUS7_IRQ, 136ae0c4d1aSHao Wu NPCM8XX_SMBUS8_IRQ, 137ae0c4d1aSHao Wu NPCM8XX_SMBUS9_IRQ, 138ae0c4d1aSHao Wu NPCM8XX_SMBUS10_IRQ, 139ae0c4d1aSHao Wu NPCM8XX_SMBUS11_IRQ, 140ae0c4d1aSHao Wu NPCM8XX_SMBUS12_IRQ, 141ae0c4d1aSHao Wu NPCM8XX_SMBUS13_IRQ, 142ae0c4d1aSHao Wu NPCM8XX_SMBUS14_IRQ, 143ae0c4d1aSHao Wu NPCM8XX_SMBUS15_IRQ, 144ae0c4d1aSHao Wu NPCM8XX_SMBUS16_IRQ, 145ae0c4d1aSHao Wu NPCM8XX_SMBUS17_IRQ, 146ae0c4d1aSHao Wu NPCM8XX_SMBUS18_IRQ, 147ae0c4d1aSHao Wu NPCM8XX_SMBUS19_IRQ, 148ae0c4d1aSHao Wu NPCM8XX_SMBUS20_IRQ, 149ae0c4d1aSHao Wu NPCM8XX_SMBUS21_IRQ, 150ae0c4d1aSHao Wu NPCM8XX_SMBUS22_IRQ, 151ae0c4d1aSHao Wu NPCM8XX_SMBUS23_IRQ, 152ae0c4d1aSHao Wu NPCM8XX_SMBUS24_IRQ, 153ae0c4d1aSHao Wu NPCM8XX_SMBUS25_IRQ, 154ae0c4d1aSHao Wu NPCM8XX_SMBUS26_IRQ, 155ae0c4d1aSHao Wu NPCM8XX_UART0_IRQ = 192, 156ae0c4d1aSHao Wu NPCM8XX_UART1_IRQ, 157ae0c4d1aSHao Wu NPCM8XX_UART2_IRQ, 158ae0c4d1aSHao Wu NPCM8XX_UART3_IRQ, 159ae0c4d1aSHao Wu NPCM8XX_UART4_IRQ, 160ae0c4d1aSHao Wu NPCM8XX_UART5_IRQ, 161ae0c4d1aSHao Wu NPCM8XX_UART6_IRQ, 162ae0c4d1aSHao Wu }; 163ae0c4d1aSHao Wu 164ae0c4d1aSHao Wu /* Total number of GIC interrupts, including internal Cortex-A35 interrupts. */ 165ae0c4d1aSHao Wu #define NPCM8XX_NUM_IRQ (288) 166ae0c4d1aSHao Wu #define NPCM8XX_PPI_BASE(cpu) \ 167ae0c4d1aSHao Wu ((NPCM8XX_NUM_IRQ - GIC_INTERNAL) + (cpu) * GIC_INTERNAL) 168ae0c4d1aSHao Wu 169ae0c4d1aSHao Wu /* Register base address for each Timer Module */ 170ae0c4d1aSHao Wu static const hwaddr npcm8xx_tim_addr[] = { 171ae0c4d1aSHao Wu 0xf0008000, 172ae0c4d1aSHao Wu 0xf0009000, 173ae0c4d1aSHao Wu 0xf000a000, 174ae0c4d1aSHao Wu }; 175ae0c4d1aSHao Wu 176ae0c4d1aSHao Wu /* Register base address for each 16550 UART */ 177ae0c4d1aSHao Wu static const hwaddr npcm8xx_uart_addr[] = { 178ae0c4d1aSHao Wu 0xf0000000, 179ae0c4d1aSHao Wu 0xf0001000, 180ae0c4d1aSHao Wu 0xf0002000, 181ae0c4d1aSHao Wu 0xf0003000, 182ae0c4d1aSHao Wu 0xf0004000, 183ae0c4d1aSHao Wu 0xf0005000, 184ae0c4d1aSHao Wu 0xf0006000, 185ae0c4d1aSHao Wu }; 186ae0c4d1aSHao Wu 187ae0c4d1aSHao Wu /* Direct memory-mapped access to SPI0 CS0-1. */ 188ae0c4d1aSHao Wu static const hwaddr npcm8xx_fiu0_flash_addr[] = { 189ae0c4d1aSHao Wu 0x80000000, /* CS0 */ 190ae0c4d1aSHao Wu 0x88000000, /* CS1 */ 191ae0c4d1aSHao Wu }; 192ae0c4d1aSHao Wu 193ae0c4d1aSHao Wu /* Direct memory-mapped access to SPI1 CS0-3. */ 194ae0c4d1aSHao Wu static const hwaddr npcm8xx_fiu1_flash_addr[] = { 195ae0c4d1aSHao Wu 0x90000000, /* CS0 */ 196ae0c4d1aSHao Wu 0x91000000, /* CS1 */ 197ae0c4d1aSHao Wu 0x92000000, /* CS2 */ 198ae0c4d1aSHao Wu 0x93000000, /* CS3 */ 199ae0c4d1aSHao Wu }; 200ae0c4d1aSHao Wu 201ae0c4d1aSHao Wu /* Direct memory-mapped access to SPI3 CS0-3. */ 202ae0c4d1aSHao Wu static const hwaddr npcm8xx_fiu3_flash_addr[] = { 203ae0c4d1aSHao Wu 0xa0000000, /* CS0 */ 204ae0c4d1aSHao Wu 0xa8000000, /* CS1 */ 205ae0c4d1aSHao Wu 0xb0000000, /* CS2 */ 206ae0c4d1aSHao Wu 0xb8000000, /* CS3 */ 207ae0c4d1aSHao Wu }; 208ae0c4d1aSHao Wu 209ae0c4d1aSHao Wu /* Register base address for each PWM Module */ 210ae0c4d1aSHao Wu static const hwaddr npcm8xx_pwm_addr[] = { 211ae0c4d1aSHao Wu 0xf0103000, 212ae0c4d1aSHao Wu 0xf0104000, 213ae0c4d1aSHao Wu 0xf0105000, 214ae0c4d1aSHao Wu }; 215ae0c4d1aSHao Wu 216ae0c4d1aSHao Wu /* Register base address for each MFT Module */ 217ae0c4d1aSHao Wu static const hwaddr npcm8xx_mft_addr[] = { 218ae0c4d1aSHao Wu 0xf0180000, 219ae0c4d1aSHao Wu 0xf0181000, 220ae0c4d1aSHao Wu 0xf0182000, 221ae0c4d1aSHao Wu 0xf0183000, 222ae0c4d1aSHao Wu 0xf0184000, 223ae0c4d1aSHao Wu 0xf0185000, 224ae0c4d1aSHao Wu 0xf0186000, 225ae0c4d1aSHao Wu 0xf0187000, 226ae0c4d1aSHao Wu }; 227ae0c4d1aSHao Wu 228ae0c4d1aSHao Wu /* Direct memory-mapped access to each SMBus Module. */ 229ae0c4d1aSHao Wu static const hwaddr npcm8xx_smbus_addr[] = { 230ae0c4d1aSHao Wu 0xf0080000, 231ae0c4d1aSHao Wu 0xf0081000, 232ae0c4d1aSHao Wu 0xf0082000, 233ae0c4d1aSHao Wu 0xf0083000, 234ae0c4d1aSHao Wu 0xf0084000, 235ae0c4d1aSHao Wu 0xf0085000, 236ae0c4d1aSHao Wu 0xf0086000, 237ae0c4d1aSHao Wu 0xf0087000, 238ae0c4d1aSHao Wu 0xf0088000, 239ae0c4d1aSHao Wu 0xf0089000, 240ae0c4d1aSHao Wu 0xf008a000, 241ae0c4d1aSHao Wu 0xf008b000, 242ae0c4d1aSHao Wu 0xf008c000, 243ae0c4d1aSHao Wu 0xf008d000, 244ae0c4d1aSHao Wu 0xf008e000, 245ae0c4d1aSHao Wu 0xf008f000, 246ae0c4d1aSHao Wu 0xfff00000, 247ae0c4d1aSHao Wu 0xfff01000, 248ae0c4d1aSHao Wu 0xfff02000, 249ae0c4d1aSHao Wu 0xfff03000, 250ae0c4d1aSHao Wu 0xfff04000, 251ae0c4d1aSHao Wu 0xfff05000, 252ae0c4d1aSHao Wu 0xfff06000, 253ae0c4d1aSHao Wu 0xfff07000, 254ae0c4d1aSHao Wu 0xfff08000, 255ae0c4d1aSHao Wu 0xfff09000, 256ae0c4d1aSHao Wu 0xfff0a000, 257ae0c4d1aSHao Wu }; 258ae0c4d1aSHao Wu 259ae0c4d1aSHao Wu /* Register base address for each USB host EHCI registers */ 260ae0c4d1aSHao Wu static const hwaddr npcm8xx_ehci_addr[] = { 261ae0c4d1aSHao Wu 0xf0828100, 262ae0c4d1aSHao Wu 0xf082a100, 263ae0c4d1aSHao Wu }; 264ae0c4d1aSHao Wu 265ae0c4d1aSHao Wu /* Register base address for each USB host OHCI registers */ 266ae0c4d1aSHao Wu static const hwaddr npcm8xx_ohci_addr[] = { 267ae0c4d1aSHao Wu 0xf0829000, 268ae0c4d1aSHao Wu 0xf082b000, 269ae0c4d1aSHao Wu }; 270ae0c4d1aSHao Wu 271ae0c4d1aSHao Wu static const struct { 272ae0c4d1aSHao Wu hwaddr regs_addr; 273ae0c4d1aSHao Wu uint32_t reset_pu; 274ae0c4d1aSHao Wu uint32_t reset_pd; 275ae0c4d1aSHao Wu uint32_t reset_osrc; 276ae0c4d1aSHao Wu uint32_t reset_odsc; 277ae0c4d1aSHao Wu } npcm8xx_gpio[] = { 278ae0c4d1aSHao Wu { 279ae0c4d1aSHao Wu .regs_addr = 0xf0010000, 280ae0c4d1aSHao Wu .reset_pu = 0x00000300, 281ae0c4d1aSHao Wu .reset_pd = 0x000f0000, 282ae0c4d1aSHao Wu }, { 283ae0c4d1aSHao Wu .regs_addr = 0xf0011000, 284ae0c4d1aSHao Wu .reset_pu = 0xe0fefe01, 285ae0c4d1aSHao Wu .reset_pd = 0x07000000, 286ae0c4d1aSHao Wu }, { 287ae0c4d1aSHao Wu .regs_addr = 0xf0012000, 288ae0c4d1aSHao Wu .reset_pu = 0xc00fffff, 289ae0c4d1aSHao Wu .reset_pd = 0x3ff00000, 290ae0c4d1aSHao Wu }, { 291ae0c4d1aSHao Wu .regs_addr = 0xf0013000, 292ae0c4d1aSHao Wu .reset_pd = 0x00003000, 293ae0c4d1aSHao Wu }, { 294ae0c4d1aSHao Wu .regs_addr = 0xf0014000, 295ae0c4d1aSHao Wu .reset_pu = 0xffff0000, 296ae0c4d1aSHao Wu }, { 297ae0c4d1aSHao Wu .regs_addr = 0xf0015000, 298ae0c4d1aSHao Wu .reset_pu = 0xff8387fe, 299ae0c4d1aSHao Wu .reset_pd = 0x007c0001, 300ae0c4d1aSHao Wu .reset_osrc = 0x08000000, 301ae0c4d1aSHao Wu }, { 302ae0c4d1aSHao Wu .regs_addr = 0xf0016000, 303ae0c4d1aSHao Wu .reset_pu = 0x00000801, 304ae0c4d1aSHao Wu .reset_pd = 0x00000302, 305ae0c4d1aSHao Wu }, { 306ae0c4d1aSHao Wu .regs_addr = 0xf0017000, 307ae0c4d1aSHao Wu .reset_pu = 0x000002ff, 308ae0c4d1aSHao Wu .reset_pd = 0x00000c00, 309ae0c4d1aSHao Wu }, 310ae0c4d1aSHao Wu }; 311ae0c4d1aSHao Wu 312ae0c4d1aSHao Wu static const struct { 313ae0c4d1aSHao Wu const char *name; 314ae0c4d1aSHao Wu hwaddr regs_addr; 315ae0c4d1aSHao Wu int cs_count; 316ae0c4d1aSHao Wu const hwaddr *flash_addr; 317ae0c4d1aSHao Wu size_t flash_size; 318ae0c4d1aSHao Wu } npcm8xx_fiu[] = { 319ae0c4d1aSHao Wu { 320ae0c4d1aSHao Wu .name = "fiu0", 321ae0c4d1aSHao Wu .regs_addr = 0xfb000000, 322ae0c4d1aSHao Wu .cs_count = ARRAY_SIZE(npcm8xx_fiu0_flash_addr), 323ae0c4d1aSHao Wu .flash_addr = npcm8xx_fiu0_flash_addr, 324ae0c4d1aSHao Wu .flash_size = 128 * MiB, 325ae0c4d1aSHao Wu }, 326ae0c4d1aSHao Wu { 327ae0c4d1aSHao Wu .name = "fiu1", 328ae0c4d1aSHao Wu .regs_addr = 0xfb002000, 329ae0c4d1aSHao Wu .cs_count = ARRAY_SIZE(npcm8xx_fiu1_flash_addr), 330ae0c4d1aSHao Wu .flash_addr = npcm8xx_fiu1_flash_addr, 331ae0c4d1aSHao Wu .flash_size = 16 * MiB, 332ae0c4d1aSHao Wu }, { 333ae0c4d1aSHao Wu .name = "fiu3", 334ae0c4d1aSHao Wu .regs_addr = 0xc0000000, 335ae0c4d1aSHao Wu .cs_count = ARRAY_SIZE(npcm8xx_fiu3_flash_addr), 336ae0c4d1aSHao Wu .flash_addr = npcm8xx_fiu3_flash_addr, 337ae0c4d1aSHao Wu .flash_size = 128 * MiB, 338ae0c4d1aSHao Wu }, 339ae0c4d1aSHao Wu }; 340ae0c4d1aSHao Wu 341ae0c4d1aSHao Wu static struct arm_boot_info npcm8xx_binfo = { 342ae0c4d1aSHao Wu .loader_start = NPCM8XX_LOADER_START, 343ae0c4d1aSHao Wu .smp_loader_start = NPCM8XX_SMP_LOADER_START, 344ae0c4d1aSHao Wu .smp_bootreg_addr = NPCM8XX_SMP_BOOTREG_ADDR, 345ae0c4d1aSHao Wu .gic_cpu_if_addr = NPCM8XX_GICC_BA, 346ae0c4d1aSHao Wu .secure_boot = false, 347ae0c4d1aSHao Wu .board_id = -1, 348ae0c4d1aSHao Wu .board_setup_addr = NPCM8XX_BOARD_SETUP_ADDR, 349ae0c4d1aSHao Wu }; 350ae0c4d1aSHao Wu 351ae0c4d1aSHao Wu void npcm8xx_load_kernel(MachineState *machine, NPCM8xxState *soc) 352ae0c4d1aSHao Wu { 353ae0c4d1aSHao Wu npcm8xx_binfo.ram_size = machine->ram_size; 354ae0c4d1aSHao Wu 355ae0c4d1aSHao Wu arm_load_kernel(&soc->cpu[0], machine, &npcm8xx_binfo); 356ae0c4d1aSHao Wu } 357ae0c4d1aSHao Wu 358ae0c4d1aSHao Wu static void npcm8xx_init_fuses(NPCM8xxState *s) 359ae0c4d1aSHao Wu { 360ae0c4d1aSHao Wu NPCM8xxClass *nc = NPCM8XX_GET_CLASS(s); 361ae0c4d1aSHao Wu uint32_t value; 362ae0c4d1aSHao Wu 363ae0c4d1aSHao Wu /* 364ae0c4d1aSHao Wu * The initial mask of disabled modules indicates the chip derivative (e.g. 365ae0c4d1aSHao Wu * NPCM750 or NPCM730). 366ae0c4d1aSHao Wu */ 367ae0c4d1aSHao Wu value = cpu_to_le32(nc->disabled_modules); 368ae0c4d1aSHao Wu npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE, 369ae0c4d1aSHao Wu sizeof(value)); 370ae0c4d1aSHao Wu } 371ae0c4d1aSHao Wu 372ae0c4d1aSHao Wu static void npcm8xx_write_adc_calibration(NPCM8xxState *s) 373ae0c4d1aSHao Wu { 374ae0c4d1aSHao Wu /* Both ADC and the fuse array must have realized. */ 375ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4); 376ae0c4d1aSHao Wu npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values, 377ae0c4d1aSHao Wu NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values)); 378ae0c4d1aSHao Wu } 379ae0c4d1aSHao Wu 380ae0c4d1aSHao Wu static qemu_irq npcm8xx_irq(NPCM8xxState *s, int n) 381ae0c4d1aSHao Wu { 382ae0c4d1aSHao Wu return qdev_get_gpio_in(DEVICE(&s->gic), n); 383ae0c4d1aSHao Wu } 384ae0c4d1aSHao Wu 385ae0c4d1aSHao Wu static void npcm8xx_init(Object *obj) 386ae0c4d1aSHao Wu { 387ae0c4d1aSHao Wu NPCM8xxState *s = NPCM8XX(obj); 388ae0c4d1aSHao Wu int i; 389ae0c4d1aSHao Wu 390ae0c4d1aSHao Wu object_initialize_child(obj, "cpu-cluster", &s->cpu_cluster, 391ae0c4d1aSHao Wu TYPE_CPU_CLUSTER); 392ae0c4d1aSHao Wu for (i = 0; i < NPCM8XX_MAX_NUM_CPUS; i++) { 393ae0c4d1aSHao Wu object_initialize_child(OBJECT(&s->cpu_cluster), "cpu[*]", &s->cpu[i], 394ae0c4d1aSHao Wu ARM_CPU_TYPE_NAME("cortex-a35")); 395ae0c4d1aSHao Wu } 396ae0c4d1aSHao Wu object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC); 397ae0c4d1aSHao Wu object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM8XX_GCR); 398ae0c4d1aSHao Wu object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr), 399ae0c4d1aSHao Wu "power-on-straps"); 400ae0c4d1aSHao Wu object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM8XX_CLK); 401ae0c4d1aSHao Wu object_initialize_child(obj, "otp", &s->fuse_array, 402ae0c4d1aSHao Wu TYPE_NPCM7XX_FUSE_ARRAY); 403ae0c4d1aSHao Wu object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC); 404ae0c4d1aSHao Wu object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG); 405ae0c4d1aSHao Wu object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC); 406ae0c4d1aSHao Wu 407ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->tim); i++) { 408ae0c4d1aSHao Wu object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER); 409ae0c4d1aSHao Wu } 410ae0c4d1aSHao Wu 411ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->gpio); i++) { 412ae0c4d1aSHao Wu object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO); 413ae0c4d1aSHao Wu } 414ae0c4d1aSHao Wu 415ae0c4d1aSHao Wu 416ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->smbus); i++) { 417ae0c4d1aSHao Wu object_initialize_child(obj, "smbus[*]", &s->smbus[i], 418ae0c4d1aSHao Wu TYPE_NPCM7XX_SMBUS); 419ae0c4d1aSHao Wu DEVICE(&s->smbus[i])->id = g_strdup_printf("smbus[%d]", i); 420ae0c4d1aSHao Wu } 421ae0c4d1aSHao Wu 422ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->ehci); i++) { 423ae0c4d1aSHao Wu object_initialize_child(obj, "ehci[*]", &s->ehci[i], TYPE_NPCM7XX_EHCI); 424ae0c4d1aSHao Wu } 425ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->ohci); i++) { 426ae0c4d1aSHao Wu object_initialize_child(obj, "ohci[*]", &s->ohci[i], TYPE_SYSBUS_OHCI); 427ae0c4d1aSHao Wu } 428ae0c4d1aSHao Wu 429ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_fiu) != ARRAY_SIZE(s->fiu)); 430ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { 431ae0c4d1aSHao Wu object_initialize_child(obj, npcm8xx_fiu[i].name, &s->fiu[i], 432ae0c4d1aSHao Wu TYPE_NPCM7XX_FIU); 433ae0c4d1aSHao Wu } 434ae0c4d1aSHao Wu 435ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->pwm); i++) { 436ae0c4d1aSHao Wu object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM); 437ae0c4d1aSHao Wu } 438ae0c4d1aSHao Wu 439ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->mft); i++) { 440ae0c4d1aSHao Wu object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT); 441ae0c4d1aSHao Wu } 442ae0c4d1aSHao Wu 443ae0c4d1aSHao Wu object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI); 444ae0c4d1aSHao Wu } 445ae0c4d1aSHao Wu 446ae0c4d1aSHao Wu static void npcm8xx_realize(DeviceState *dev, Error **errp) 447ae0c4d1aSHao Wu { 448ae0c4d1aSHao Wu NPCM8xxState *s = NPCM8XX(dev); 449ae0c4d1aSHao Wu NPCM8xxClass *nc = NPCM8XX_GET_CLASS(s); 450ae0c4d1aSHao Wu int i; 451ae0c4d1aSHao Wu 452ae0c4d1aSHao Wu if (memory_region_size(s->dram) > NPCM8XX_DRAM_SZ) { 453ae0c4d1aSHao Wu error_setg(errp, "%s: NPCM8xx cannot address more than %" PRIu64 454ae0c4d1aSHao Wu " MiB of DRAM", __func__, NPCM8XX_DRAM_SZ / MiB); 455ae0c4d1aSHao Wu return; 456ae0c4d1aSHao Wu } 457ae0c4d1aSHao Wu 458ae0c4d1aSHao Wu /* CPUs */ 459ae0c4d1aSHao Wu for (i = 0; i < nc->num_cpus; i++) { 460ae0c4d1aSHao Wu object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity", 461ae0c4d1aSHao Wu arm_build_mp_affinity(i, NPCM8XX_MAX_NUM_CPUS), 462ae0c4d1aSHao Wu &error_abort); 463ae0c4d1aSHao Wu object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true, 464ae0c4d1aSHao Wu &error_abort); 465ae0c4d1aSHao Wu object_property_set_int(OBJECT(&s->cpu[i]), "core-count", 466ae0c4d1aSHao Wu nc->num_cpus, &error_abort); 467ae0c4d1aSHao Wu 468ae0c4d1aSHao Wu /* Disable security extensions. */ 469ae0c4d1aSHao Wu object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false, 470ae0c4d1aSHao Wu &error_abort); 471ae0c4d1aSHao Wu 472ae0c4d1aSHao Wu if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) { 473ae0c4d1aSHao Wu return; 474ae0c4d1aSHao Wu } 475ae0c4d1aSHao Wu } 476ae0c4d1aSHao Wu 477ae0c4d1aSHao Wu /* ARM GIC for Cortex A35. Can only fail if we pass bad parameters here. */ 478ae0c4d1aSHao Wu object_property_set_uint(OBJECT(&s->gic), "num-cpu", nc->num_cpus, errp); 479ae0c4d1aSHao Wu object_property_set_uint(OBJECT(&s->gic), "num-irq", NPCM8XX_NUM_IRQ, errp); 480ae0c4d1aSHao Wu object_property_set_uint(OBJECT(&s->gic), "revision", 2, errp); 481ae0c4d1aSHao Wu object_property_set_bool(OBJECT(&s->gic), "has-security-extensions", true, 482ae0c4d1aSHao Wu errp); 483ae0c4d1aSHao Wu if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) { 484ae0c4d1aSHao Wu return; 485ae0c4d1aSHao Wu } 486ae0c4d1aSHao Wu for (i = 0; i < nc->num_cpus; i++) { 487ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i, 488ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ)); 489ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + nc->num_cpus, 490ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ)); 491ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + nc->num_cpus * 2, 492ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_VIRQ)); 493ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + nc->num_cpus * 3, 494ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_VFIQ)); 495ae0c4d1aSHao Wu 496ae0c4d1aSHao Wu qdev_connect_gpio_out(DEVICE(&s->cpu[i]), GTIMER_PHYS, 497ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->gic), 498ae0c4d1aSHao Wu NPCM8XX_PPI_BASE(i) + ARCH_TIMER_NS_EL1_IRQ)); 499ae0c4d1aSHao Wu qdev_connect_gpio_out(DEVICE(&s->cpu[i]), GTIMER_VIRT, 500ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->gic), 501ae0c4d1aSHao Wu NPCM8XX_PPI_BASE(i) + ARCH_TIMER_VIRT_IRQ)); 502ae0c4d1aSHao Wu qdev_connect_gpio_out(DEVICE(&s->cpu[i]), GTIMER_HYP, 503ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->gic), 504ae0c4d1aSHao Wu NPCM8XX_PPI_BASE(i) + ARCH_TIMER_NS_EL2_IRQ)); 505ae0c4d1aSHao Wu qdev_connect_gpio_out(DEVICE(&s->cpu[i]), GTIMER_SEC, 506ae0c4d1aSHao Wu qdev_get_gpio_in(DEVICE(&s->gic), 507ae0c4d1aSHao Wu NPCM8XX_PPI_BASE(i) + ARCH_TIMER_S_EL1_IRQ)); 508ae0c4d1aSHao Wu } 509ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, NPCM8XX_GICD_BA); 510ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, NPCM8XX_GICC_BA); 511ae0c4d1aSHao Wu 512ae0c4d1aSHao Wu /* CPU cluster */ 513ae0c4d1aSHao Wu qdev_prop_set_uint32(DEVICE(&s->cpu_cluster), "cluster-id", 0); 514ae0c4d1aSHao Wu qdev_realize(DEVICE(&s->cpu_cluster), NULL, &error_fatal); 515ae0c4d1aSHao Wu 516ae0c4d1aSHao Wu /* System Global Control Registers (GCR). Can fail due to user input. */ 517ae0c4d1aSHao Wu object_property_set_int(OBJECT(&s->gcr), "disabled-modules", 518ae0c4d1aSHao Wu nc->disabled_modules, &error_abort); 519ae0c4d1aSHao Wu object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram)); 520ae0c4d1aSHao Wu if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) { 521ae0c4d1aSHao Wu return; 522ae0c4d1aSHao Wu } 523ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM8XX_GCR_BA); 524ae0c4d1aSHao Wu 525ae0c4d1aSHao Wu /* Clock Control Registers (CLK). Cannot fail. */ 526ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort); 527ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM8XX_CLK_BA); 528ae0c4d1aSHao Wu 529ae0c4d1aSHao Wu /* OTP fuse strap array. Cannot fail. */ 530ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort); 531ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM8XX_OTP_BA); 532ae0c4d1aSHao Wu npcm8xx_init_fuses(s); 533ae0c4d1aSHao Wu 534ae0c4d1aSHao Wu /* Fake Memory Controller (MC). Cannot fail. */ 535ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort); 536ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM8XX_MC_BA); 537ae0c4d1aSHao Wu 538ae0c4d1aSHao Wu /* ADC Modules. Cannot fail. */ 539ae0c4d1aSHao Wu qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out( 540ae0c4d1aSHao Wu DEVICE(&s->clk), "adc-clock")); 541ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort); 542ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM8XX_ADC_BA); 543ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, 544ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_ADC_IRQ)); 545ae0c4d1aSHao Wu npcm8xx_write_adc_calibration(s); 546ae0c4d1aSHao Wu 547ae0c4d1aSHao Wu /* Timer Modules (TIM). Cannot fail. */ 548ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_tim_addr) != ARRAY_SIZE(s->tim)); 549ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->tim); i++) { 550ae0c4d1aSHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]); 551ae0c4d1aSHao Wu int first_irq; 552ae0c4d1aSHao Wu int j; 553ae0c4d1aSHao Wu 554ae0c4d1aSHao Wu /* Connect the timer clock. */ 555ae0c4d1aSHao Wu qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out( 556ae0c4d1aSHao Wu DEVICE(&s->clk), "timer-clock")); 557ae0c4d1aSHao Wu 558ae0c4d1aSHao Wu sysbus_realize(sbd, &error_abort); 559ae0c4d1aSHao Wu sysbus_mmio_map(sbd, 0, npcm8xx_tim_addr[i]); 560ae0c4d1aSHao Wu 561ae0c4d1aSHao Wu first_irq = NPCM8XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL; 562ae0c4d1aSHao Wu for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) { 563ae0c4d1aSHao Wu qemu_irq irq = npcm8xx_irq(s, first_irq + j); 564ae0c4d1aSHao Wu sysbus_connect_irq(sbd, j, irq); 565ae0c4d1aSHao Wu } 566ae0c4d1aSHao Wu 567ae0c4d1aSHao Wu /* IRQ for watchdogs */ 568ae0c4d1aSHao Wu sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL, 569ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_WDG0_IRQ + i)); 570ae0c4d1aSHao Wu /* GPIO that connects clk module with watchdog */ 571ae0c4d1aSHao Wu qdev_connect_gpio_out_named(DEVICE(&s->tim[i]), 572ae0c4d1aSHao Wu NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0, 573ae0c4d1aSHao Wu qdev_get_gpio_in_named(DEVICE(&s->clk), 574ae0c4d1aSHao Wu NPCM7XX_WATCHDOG_RESET_GPIO_IN, i)); 575ae0c4d1aSHao Wu } 576ae0c4d1aSHao Wu 577ae0c4d1aSHao Wu /* UART0..6 (16550 compatible) */ 578ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(npcm8xx_uart_addr); i++) { 579ae0c4d1aSHao Wu serial_mm_init(get_system_memory(), npcm8xx_uart_addr[i], 2, 580ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_UART0_IRQ + i), 115200, 581ae0c4d1aSHao Wu serial_hd(i), DEVICE_LITTLE_ENDIAN); 582ae0c4d1aSHao Wu } 583ae0c4d1aSHao Wu 584ae0c4d1aSHao Wu /* Random Number Generator. Cannot fail. */ 585ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort); 586ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM8XX_RNG_BA); 587ae0c4d1aSHao Wu 588ae0c4d1aSHao Wu /* GPIO modules. Cannot fail. */ 589ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_gpio) != ARRAY_SIZE(s->gpio)); 590ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->gpio); i++) { 591ae0c4d1aSHao Wu Object *obj = OBJECT(&s->gpio[i]); 592ae0c4d1aSHao Wu 593ae0c4d1aSHao Wu object_property_set_uint(obj, "reset-pullup", 594ae0c4d1aSHao Wu npcm8xx_gpio[i].reset_pu, &error_abort); 595ae0c4d1aSHao Wu object_property_set_uint(obj, "reset-pulldown", 596ae0c4d1aSHao Wu npcm8xx_gpio[i].reset_pd, &error_abort); 597ae0c4d1aSHao Wu object_property_set_uint(obj, "reset-osrc", 598ae0c4d1aSHao Wu npcm8xx_gpio[i].reset_osrc, &error_abort); 599ae0c4d1aSHao Wu object_property_set_uint(obj, "reset-odsc", 600ae0c4d1aSHao Wu npcm8xx_gpio[i].reset_odsc, &error_abort); 601ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort); 602ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm8xx_gpio[i].regs_addr); 603ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0, 604ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_GPIO0_IRQ + i)); 605ae0c4d1aSHao Wu } 606ae0c4d1aSHao Wu 607ae0c4d1aSHao Wu /* SMBus modules. Cannot fail. */ 608ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_smbus_addr) != ARRAY_SIZE(s->smbus)); 609ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->smbus); i++) { 610ae0c4d1aSHao Wu Object *obj = OBJECT(&s->smbus[i]); 611ae0c4d1aSHao Wu 612ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort); 613ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm8xx_smbus_addr[i]); 614ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0, 615ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_SMBUS0_IRQ + i)); 616ae0c4d1aSHao Wu } 617ae0c4d1aSHao Wu 618ae0c4d1aSHao Wu /* USB Host */ 619ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->ohci) != ARRAY_SIZE(s->ehci)); 620ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->ehci); i++) { 621ae0c4d1aSHao Wu object_property_set_bool(OBJECT(&s->ehci[i]), "companion-enable", true, 622ae0c4d1aSHao Wu &error_abort); 623ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), &error_abort); 624ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0, npcm8xx_ehci_addr[i]); 625ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0, 626ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_EHCI1_IRQ + 2 * i)); 627ae0c4d1aSHao Wu } 628ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->ohci); i++) { 629ae0c4d1aSHao Wu object_property_set_str(OBJECT(&s->ohci[i]), "masterbus", "usb-bus.0", 630ae0c4d1aSHao Wu &error_abort); 631ae0c4d1aSHao Wu object_property_set_uint(OBJECT(&s->ohci[i]), "num-ports", 1, 632ae0c4d1aSHao Wu &error_abort); 633ae0c4d1aSHao Wu object_property_set_uint(OBJECT(&s->ohci[i]), "firstport", i, 634ae0c4d1aSHao Wu &error_abort); 635ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->ohci[i]), &error_abort); 636ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci[i]), 0, npcm8xx_ohci_addr[i]); 637ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci[i]), 0, 638ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_OHCI1_IRQ + 2 * i)); 639ae0c4d1aSHao Wu } 640ae0c4d1aSHao Wu 641ae0c4d1aSHao Wu /* PWM Modules. Cannot fail. */ 642ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_pwm_addr) != ARRAY_SIZE(s->pwm)); 643ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->pwm); i++) { 644ae0c4d1aSHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]); 645ae0c4d1aSHao Wu 646ae0c4d1aSHao Wu qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out( 647ae0c4d1aSHao Wu DEVICE(&s->clk), "apb3-clock")); 648ae0c4d1aSHao Wu sysbus_realize(sbd, &error_abort); 649ae0c4d1aSHao Wu sysbus_mmio_map(sbd, 0, npcm8xx_pwm_addr[i]); 650ae0c4d1aSHao Wu sysbus_connect_irq(sbd, i, npcm8xx_irq(s, NPCM8XX_PWM0_IRQ + i)); 651ae0c4d1aSHao Wu } 652ae0c4d1aSHao Wu 653ae0c4d1aSHao Wu /* MFT Modules. Cannot fail. */ 654ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_mft_addr) != ARRAY_SIZE(s->mft)); 655ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->mft); i++) { 656ae0c4d1aSHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]); 657ae0c4d1aSHao Wu 658ae0c4d1aSHao Wu qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in", 659ae0c4d1aSHao Wu qdev_get_clock_out(DEVICE(&s->clk), 660ae0c4d1aSHao Wu "apb4-clock")); 661ae0c4d1aSHao Wu sysbus_realize(sbd, &error_abort); 662ae0c4d1aSHao Wu sysbus_mmio_map(sbd, 0, npcm8xx_mft_addr[i]); 663ae0c4d1aSHao Wu sysbus_connect_irq(sbd, 0, npcm8xx_irq(s, NPCM8XX_MFT0_IRQ + i)); 664ae0c4d1aSHao Wu } 665ae0c4d1aSHao Wu 666ae0c4d1aSHao Wu /* 667ae0c4d1aSHao Wu * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects 668ae0c4d1aSHao Wu * specified, but this is a programming error. 669ae0c4d1aSHao Wu */ 670ae0c4d1aSHao Wu QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm8xx_fiu) != ARRAY_SIZE(s->fiu)); 671ae0c4d1aSHao Wu for (i = 0; i < ARRAY_SIZE(s->fiu); i++) { 672ae0c4d1aSHao Wu SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]); 673ae0c4d1aSHao Wu int j; 674ae0c4d1aSHao Wu 675ae0c4d1aSHao Wu object_property_set_int(OBJECT(sbd), "cs-count", 676ae0c4d1aSHao Wu npcm8xx_fiu[i].cs_count, &error_abort); 677ae0c4d1aSHao Wu object_property_set_int(OBJECT(sbd), "flash-size", 678ae0c4d1aSHao Wu npcm8xx_fiu[i].flash_size, &error_abort); 679ae0c4d1aSHao Wu sysbus_realize(sbd, &error_abort); 680ae0c4d1aSHao Wu 681ae0c4d1aSHao Wu sysbus_mmio_map(sbd, 0, npcm8xx_fiu[i].regs_addr); 682ae0c4d1aSHao Wu for (j = 0; j < npcm8xx_fiu[i].cs_count; j++) { 683ae0c4d1aSHao Wu sysbus_mmio_map(sbd, j + 1, npcm8xx_fiu[i].flash_addr[j]); 684ae0c4d1aSHao Wu } 685ae0c4d1aSHao Wu } 686ae0c4d1aSHao Wu 687ae0c4d1aSHao Wu /* RAM2 (SRAM) */ 688ae0c4d1aSHao Wu memory_region_init_ram(&s->sram, OBJECT(dev), "ram2", 689ae0c4d1aSHao Wu NPCM8XX_RAM2_SZ, &error_abort); 690ae0c4d1aSHao Wu memory_region_add_subregion(get_system_memory(), NPCM8XX_RAM2_BA, &s->sram); 691ae0c4d1aSHao Wu 692ae0c4d1aSHao Wu /* RAM3 (SRAM) */ 693ae0c4d1aSHao Wu memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3", 694ae0c4d1aSHao Wu NPCM8XX_RAM3_SZ, &error_abort); 695ae0c4d1aSHao Wu memory_region_add_subregion(get_system_memory(), NPCM8XX_RAM3_BA, &s->ram3); 696ae0c4d1aSHao Wu 697ae0c4d1aSHao Wu /* Internal ROM */ 698ae0c4d1aSHao Wu memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM8XX_ROM_SZ, 699ae0c4d1aSHao Wu &error_abort); 700ae0c4d1aSHao Wu memory_region_add_subregion(get_system_memory(), NPCM8XX_ROM_BA, &s->irom); 701ae0c4d1aSHao Wu 702ae0c4d1aSHao Wu /* SDHCI */ 703ae0c4d1aSHao Wu sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort); 704ae0c4d1aSHao Wu sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM8XX_MMC_BA); 705ae0c4d1aSHao Wu sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0, 706ae0c4d1aSHao Wu npcm8xx_irq(s, NPCM8XX_MMC_IRQ)); 707ae0c4d1aSHao Wu 708ae0c4d1aSHao Wu 709ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.shm", 0xc0001000, 4 * KiB); 710ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gicextra", 0xdfffa000, 24 * KiB); 711ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.vdmx", 0xe0800000, 4 * KiB); 712ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.pcierc", 0xe1000000, 64 * KiB); 713ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.rootc", 0xe8000000, 128 * MiB); 714ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.kcs", 0xf0007000, 4 * KiB); 715ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gfxi", 0xf000e000, 4 * KiB); 716ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.fsw", 0xf000f000, 4 * KiB); 717ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.bt", 0xf0030000, 4 * KiB); 718ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.espi", 0xf009f000, 4 * KiB); 719ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.peci", 0xf0100000, 4 * KiB); 720ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.siox[1]", 0xf0101000, 4 * KiB); 721ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.siox[2]", 0xf0102000, 4 * KiB); 722ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.tmps", 0xf0188000, 4 * KiB); 723ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.pspi", 0xf0201000, 4 * KiB); 724ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.viru1", 0xf0204000, 4 * KiB); 725ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.viru2", 0xf0205000, 4 * KiB); 726ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.jtm1", 0xf0208000, 4 * KiB); 727ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.jtm2", 0xf0209000, 4 * KiB); 728ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.flm0", 0xf0210000, 4 * KiB); 729ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.flm1", 0xf0211000, 4 * KiB); 730ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.flm2", 0xf0212000, 4 * KiB); 731ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.flm3", 0xf0213000, 4 * KiB); 732ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.ahbpci", 0xf0400000, 1 * MiB); 733ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.dap", 0xf0500000, 960 * KiB); 734ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.mcphy", 0xf05f0000, 64 * KiB); 735ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.pcs", 0xf0780000, 256 * KiB); 736ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.tsgen", 0xf07fc000, 8 * KiB); 737ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gmac1", 0xf0802000, 8 * KiB); 738ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gmac2", 0xf0804000, 8 * KiB); 739ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gmac3", 0xf0806000, 8 * KiB); 740ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gmac4", 0xf0808000, 8 * KiB); 741ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.copctl", 0xf080c000, 4 * KiB); 742ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.tipctl", 0xf080d000, 4 * KiB); 743ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.rst", 0xf080e000, 4 * KiB); 744ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.vcd", 0xf0810000, 64 * KiB); 745ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.ece", 0xf0820000, 8 * KiB); 746ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.vdma", 0xf0822000, 8 * KiB); 747ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[0]", 0xf0830000, 4 * KiB); 748ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[1]", 0xf0831000, 4 * KiB); 749ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[2]", 0xf0832000, 4 * KiB); 750ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[3]", 0xf0833000, 4 * KiB); 751ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[4]", 0xf0834000, 4 * KiB); 752ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[5]", 0xf0835000, 4 * KiB); 753ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[6]", 0xf0836000, 4 * KiB); 754ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[7]", 0xf0837000, 4 * KiB); 755ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[8]", 0xf0838000, 4 * KiB); 756ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.usbd[9]", 0xf0839000, 4 * KiB); 757ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.pci_mbox1", 0xf0848000, 64 * KiB); 758ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gdma0", 0xf0850000, 4 * KiB); 759ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gdma1", 0xf0851000, 4 * KiB); 760ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.gdma2", 0xf0852000, 4 * KiB); 761ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.aes", 0xf0858000, 4 * KiB); 762ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.des", 0xf0859000, 4 * KiB); 763ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.sha", 0xf085a000, 4 * KiB); 764ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.pci_mbox2", 0xf0868000, 64 * KiB); 765ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c0", 0xfff10000, 4 * KiB); 766ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c1", 0xfff11000, 4 * KiB); 767ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c2", 0xfff12000, 4 * KiB); 768ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c3", 0xfff13000, 4 * KiB); 769ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c4", 0xfff14000, 4 * KiB); 770ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.i3c5", 0xfff15000, 4 * KiB); 771ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.spixcs0", 0xf8000000, 16 * MiB); 772ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.spixcs1", 0xf9000000, 16 * MiB); 773ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.spix", 0xfb001000, 4 * KiB); 774ae0c4d1aSHao Wu create_unimplemented_device("npcm8xx.vect", 0xffff0000, 256); 775ae0c4d1aSHao Wu } 776ae0c4d1aSHao Wu 777ae0c4d1aSHao Wu static const Property npcm8xx_properties[] = { 778ae0c4d1aSHao Wu DEFINE_PROP_LINK("dram-mr", NPCM8xxState, dram, TYPE_MEMORY_REGION, 779ae0c4d1aSHao Wu MemoryRegion *), 780ae0c4d1aSHao Wu }; 781ae0c4d1aSHao Wu 782*12d1a768SPhilippe Mathieu-Daudé static void npcm8xx_class_init(ObjectClass *oc, const void *data) 783ae0c4d1aSHao Wu { 784ae0c4d1aSHao Wu DeviceClass *dc = DEVICE_CLASS(oc); 785ae0c4d1aSHao Wu NPCM8xxClass *nc = NPCM8XX_CLASS(oc); 786ae0c4d1aSHao Wu 787ae0c4d1aSHao Wu dc->realize = npcm8xx_realize; 788ae0c4d1aSHao Wu dc->user_creatable = false; 789ae0c4d1aSHao Wu nc->disabled_modules = 0x00000000; 790ae0c4d1aSHao Wu nc->num_cpus = NPCM8XX_MAX_NUM_CPUS; 791ae0c4d1aSHao Wu device_class_set_props(dc, npcm8xx_properties); 792ae0c4d1aSHao Wu } 793ae0c4d1aSHao Wu 794ae0c4d1aSHao Wu static const TypeInfo npcm8xx_soc_types[] = { 795ae0c4d1aSHao Wu { 796ae0c4d1aSHao Wu .name = TYPE_NPCM8XX, 797ae0c4d1aSHao Wu .parent = TYPE_DEVICE, 798ae0c4d1aSHao Wu .instance_size = sizeof(NPCM8xxState), 799ae0c4d1aSHao Wu .instance_init = npcm8xx_init, 800ae0c4d1aSHao Wu .class_size = sizeof(NPCM8xxClass), 801ae0c4d1aSHao Wu .class_init = npcm8xx_class_init, 802ae0c4d1aSHao Wu }, 803ae0c4d1aSHao Wu }; 804ae0c4d1aSHao Wu 805ae0c4d1aSHao Wu DEFINE_TYPES(npcm8xx_soc_types); 806