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