2 * ASPEED System Control Unit
4 * Andrew Jeffery <andrew@aj.id.au>
6 * Copyright 2016 IBM Corp.
8 * This code is licensed under the GPL version 2 or later. See
9 * the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "hw/misc/aspeed_scu.h"
14 #include "hw/qdev-properties.h"
15 #include "migration/vmstate.h"
16 #include "qapi/error.h"
17 #include "qapi/visitor.h"
18 #include "qemu/bitops.h"
20 #include "qemu/guest-random.h"
21 #include "qemu/module.h"
24 #define TO_REG(offset) ((offset) >> 2)
26 #define PROT_KEY TO_REG(0x00)
27 #define SYS_RST_CTRL TO_REG(0x04)
28 #define CLK_SEL TO_REG(0x08)
29 #define CLK_STOP_CTRL TO_REG(0x0C)
30 #define FREQ_CNTR_CTRL TO_REG(0x10)
31 #define FREQ_CNTR_EVAL TO_REG(0x14)
32 #define IRQ_CTRL TO_REG(0x18)
33 #define D2PLL_PARAM TO_REG(0x1C)
34 #define MPLL_PARAM TO_REG(0x20)
35 #define HPLL_PARAM TO_REG(0x24)
36 #define FREQ_CNTR_RANGE TO_REG(0x28)
37 #define MISC_CTRL1 TO_REG(0x2C)
38 #define PCI_CTRL1 TO_REG(0x30)
39 #define PCI_CTRL2 TO_REG(0x34)
40 #define PCI_CTRL3 TO_REG(0x38)
41 #define SYS_RST_STATUS TO_REG(0x3C)
42 #define SOC_SCRATCH1 TO_REG(0x40)
43 #define SOC_SCRATCH2 TO_REG(0x44)
44 #define MAC_CLK_DELAY TO_REG(0x48)
45 #define MISC_CTRL2 TO_REG(0x4C)
46 #define VGA_SCRATCH1 TO_REG(0x50)
47 #define VGA_SCRATCH2 TO_REG(0x54)
48 #define VGA_SCRATCH3 TO_REG(0x58)
49 #define VGA_SCRATCH4 TO_REG(0x5C)
50 #define VGA_SCRATCH5 TO_REG(0x60)
51 #define VGA_SCRATCH6 TO_REG(0x64)
52 #define VGA_SCRATCH7 TO_REG(0x68)
53 #define VGA_SCRATCH8 TO_REG(0x6C)
54 #define HW_STRAP1 TO_REG(0x70)
55 #define RNG_CTRL TO_REG(0x74)
56 #define RNG_DATA TO_REG(0x78)
57 #define SILICON_REV TO_REG(0x7C)
58 #define PINMUX_CTRL1 TO_REG(0x80)
59 #define PINMUX_CTRL2 TO_REG(0x84)
60 #define PINMUX_CTRL3 TO_REG(0x88)
61 #define PINMUX_CTRL4 TO_REG(0x8C)
62 #define PINMUX_CTRL5 TO_REG(0x90)
63 #define PINMUX_CTRL6 TO_REG(0x94)
64 #define WDT_RST_CTRL TO_REG(0x9C)
65 #define PINMUX_CTRL7 TO_REG(0xA0)
66 #define PINMUX_CTRL8 TO_REG(0xA4)
67 #define PINMUX_CTRL9 TO_REG(0xA8)
68 #define WAKEUP_EN TO_REG(0xC0)
69 #define WAKEUP_CTRL TO_REG(0xC4)
70 #define HW_STRAP2 TO_REG(0xD0)
71 #define FREE_CNTR4 TO_REG(0xE0)
72 #define FREE_CNTR4_EXT TO_REG(0xE4)
73 #define CPU2_CTRL TO_REG(0x100)
74 #define CPU2_BASE_SEG1 TO_REG(0x104)
75 #define CPU2_BASE_SEG2 TO_REG(0x108)
76 #define CPU2_BASE_SEG3 TO_REG(0x10C)
77 #define CPU2_BASE_SEG4 TO_REG(0x110)
78 #define CPU2_BASE_SEG5 TO_REG(0x114)
79 #define CPU2_CACHE_CTRL TO_REG(0x118)
80 #define CHIP_ID0 TO_REG(0x150)
81 #define CHIP_ID1 TO_REG(0x154)
82 #define UART_HPLL_CLK TO_REG(0x160)
83 #define PCIE_CTRL TO_REG(0x180)
84 #define BMC_MMIO_CTRL TO_REG(0x184)
85 #define RELOC_DECODE_BASE1 TO_REG(0x188)
86 #define RELOC_DECODE_BASE2 TO_REG(0x18C)
87 #define MAILBOX_DECODE_BASE TO_REG(0x190)
88 #define SRAM_DECODE_BASE1 TO_REG(0x194)
89 #define SRAM_DECODE_BASE2 TO_REG(0x198)
90 #define BMC_REV TO_REG(0x19C)
91 #define BMC_DEV_ID TO_REG(0x1A4)
93 #define AST2600_PROT_KEY TO_REG(0x00)
94 #define AST2600_SILICON_REV TO_REG(0x04)
95 #define AST2600_SILICON_REV2 TO_REG(0x14)
96 #define AST2600_SYS_RST_CTRL TO_REG(0x40)
97 #define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44)
98 #define AST2600_SYS_RST_CTRL2 TO_REG(0x50)
99 #define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
100 #define AST2600_CLK_STOP_CTRL TO_REG(0x80)
101 #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
102 #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
103 #define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
104 #define AST2600_DEBUG_CTRL TO_REG(0xC8)
105 #define AST2600_DEBUG_CTRL2 TO_REG(0xD8)
106 #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
107 #define AST2600_HPLL_PARAM TO_REG(0x200)
108 #define AST2600_HPLL_EXT TO_REG(0x204)
109 #define AST2600_APLL_PARAM TO_REG(0x210)
110 #define AST2600_APLL_EXT TO_REG(0x214)
111 #define AST2600_MPLL_PARAM TO_REG(0x220)
112 #define AST2600_MPLL_EXT TO_REG(0x224)
113 #define AST2600_EPLL_PARAM TO_REG(0x240)
114 #define AST2600_EPLL_EXT TO_REG(0x244)
115 #define AST2600_DPLL_PARAM TO_REG(0x260)
116 #define AST2600_DPLL_EXT TO_REG(0x264)
117 #define AST2600_CLK_SEL TO_REG(0x300)
118 #define AST2600_CLK_SEL2 TO_REG(0x304)
119 #define AST2600_CLK_SEL3 TO_REG(0x308)
120 #define AST2600_CLK_SEL4 TO_REG(0x310)
121 #define AST2600_CLK_SEL5 TO_REG(0x314)
122 #define AST2600_UARTCLK TO_REG(0x338)
123 #define AST2600_HUARTCLK TO_REG(0x33C)
124 #define AST2600_HW_STRAP1 TO_REG(0x500)
125 #define AST2600_HW_STRAP1_CLR TO_REG(0x504)
126 #define AST2600_HW_STRAP1_PROT TO_REG(0x508)
127 #define AST2600_HW_STRAP2 TO_REG(0x510)
128 #define AST2600_HW_STRAP2_CLR TO_REG(0x514)
129 #define AST2600_HW_STRAP2_PROT TO_REG(0x518)
130 #define AST2600_RNG_CTRL TO_REG(0x524)
131 #define AST2600_RNG_DATA TO_REG(0x540)
132 #define AST2600_CHIP_ID0 TO_REG(0x5B0)
133 #define AST2600_CHIP_ID1 TO_REG(0x5B4)
135 #define AST2600_CLK TO_REG(0x40)
137 #define AST2700_SILICON_REV TO_REG(0x00)
138 #define AST2700_HW_STRAP1 TO_REG(0x10)
139 #define AST2700_HW_STRAP1_CLR TO_REG(0x14)
140 #define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
141 #define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
142 #define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
143 #define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
145 #define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
146 #define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
147 #define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
148 #define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
149 #define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
150 #define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
151 #define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
152 #define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
153 #define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
154 #define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
155 #define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
156 #define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
157 #define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
158 #define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
159 #define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
161 #define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
162 #define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
163 #define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
164 #define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
165 #define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
166 #define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
167 #define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
168 #define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
169 #define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
170 #define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
171 #define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
172 #define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
173 #define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
174 #define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
175 #define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
176 #define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
177 #define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
179 #define SCU_IO_REGION_SIZE 0x1000
181 static const uint32_t ast2400_a0_resets
[ASPEED_SCU_NR_REGS
] = {
182 [SYS_RST_CTRL
] = 0xFFCFFEDCU
,
183 [CLK_SEL
] = 0xF3F40000U
,
184 [CLK_STOP_CTRL
] = 0x19FC3E8BU
,
185 [D2PLL_PARAM
] = 0x00026108U
,
186 [MPLL_PARAM
] = 0x00030291U
,
187 [HPLL_PARAM
] = 0x00000291U
,
188 [MISC_CTRL1
] = 0x00000010U
,
189 [PCI_CTRL1
] = 0x20001A03U
,
190 [PCI_CTRL2
] = 0x20001A03U
,
191 [PCI_CTRL3
] = 0x04000030U
,
192 [SYS_RST_STATUS
] = 0x00000001U
,
193 [SOC_SCRATCH1
] = 0x000000C0U
, /* SoC completed DRAM init */
194 [MISC_CTRL2
] = 0x00000023U
,
195 [RNG_CTRL
] = 0x0000000EU
,
196 [PINMUX_CTRL2
] = 0x0000F000U
,
197 [PINMUX_CTRL3
] = 0x01000000U
,
198 [PINMUX_CTRL4
] = 0x000000FFU
,
199 [PINMUX_CTRL5
] = 0x0000A000U
,
200 [WDT_RST_CTRL
] = 0x003FFFF3U
,
201 [PINMUX_CTRL8
] = 0xFFFF0000U
,
202 [PINMUX_CTRL9
] = 0x000FFFFFU
,
203 [FREE_CNTR4
] = 0x000000FFU
,
204 [FREE_CNTR4_EXT
] = 0x000000FFU
,
205 [CPU2_BASE_SEG1
] = 0x80000000U
,
206 [CPU2_BASE_SEG4
] = 0x1E600000U
,
207 [CPU2_BASE_SEG5
] = 0xC0000000U
,
208 [UART_HPLL_CLK
] = 0x00001903U
,
209 [PCIE_CTRL
] = 0x0000007BU
,
210 [BMC_DEV_ID
] = 0x00002402U
213 /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
214 /* AST2500 revision A1 */
216 static const uint32_t ast2500_a1_resets
[ASPEED_SCU_NR_REGS
] = {
217 [SYS_RST_CTRL
] = 0xFFCFFEDCU
,
218 [CLK_SEL
] = 0xF3F40000U
,
219 [CLK_STOP_CTRL
] = 0x19FC3E8BU
,
220 [D2PLL_PARAM
] = 0x00026108U
,
221 [MPLL_PARAM
] = 0x00030291U
,
222 [HPLL_PARAM
] = 0x93000400U
,
223 [MISC_CTRL1
] = 0x00000010U
,
224 [PCI_CTRL1
] = 0x20001A03U
,
225 [PCI_CTRL2
] = 0x20001A03U
,
226 [PCI_CTRL3
] = 0x04000030U
,
227 [SYS_RST_STATUS
] = 0x00000001U
,
228 [SOC_SCRATCH1
] = 0x000000C0U
, /* SoC completed DRAM init */
229 [MISC_CTRL2
] = 0x00000023U
,
230 [RNG_CTRL
] = 0x0000000EU
,
231 [PINMUX_CTRL2
] = 0x0000F000U
,
232 [PINMUX_CTRL3
] = 0x03000000U
,
233 [PINMUX_CTRL4
] = 0x00000000U
,
234 [PINMUX_CTRL5
] = 0x0000A000U
,
235 [WDT_RST_CTRL
] = 0x023FFFF3U
,
236 [PINMUX_CTRL8
] = 0xFFFF0000U
,
237 [PINMUX_CTRL9
] = 0x000FFFFFU
,
238 [FREE_CNTR4
] = 0x000000FFU
,
239 [FREE_CNTR4_EXT
] = 0x000000FFU
,
240 [CPU2_BASE_SEG1
] = 0x80000000U
,
241 [CPU2_BASE_SEG4
] = 0x1E600000U
,
242 [CPU2_BASE_SEG5
] = 0xC0000000U
,
243 [CHIP_ID0
] = 0x1234ABCDU
,
244 [CHIP_ID1
] = 0x88884444U
,
245 [UART_HPLL_CLK
] = 0x00001903U
,
246 [PCIE_CTRL
] = 0x0000007BU
,
247 [BMC_DEV_ID
] = 0x00002402U
250 static uint32_t aspeed_scu_get_random(void)
253 qemu_guest_getrandom_nofail(&num
, sizeof(num
));
257 uint32_t aspeed_scu_get_apb_freq(AspeedSCUState
*s
)
259 return ASPEED_SCU_GET_CLASS(s
)->get_apb(s
);
262 static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState
*s
)
264 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(s
);
265 uint32_t hpll
= asc
->calc_hpll(s
, s
->regs
[HPLL_PARAM
]);
267 return hpll
/ (SCU_CLK_GET_PCLK_DIV(s
->regs
[CLK_SEL
]) + 1)
271 static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState
*s
)
273 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(s
);
274 uint32_t hpll
= asc
->calc_hpll(s
, s
->regs
[AST2600_HPLL_PARAM
]);
276 return hpll
/ (SCU_CLK_GET_PCLK_DIV(s
->regs
[AST2600_CLK_SEL
]) + 1)
280 static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState
*s
)
282 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(s
);
283 uint32_t hpll
= asc
->calc_hpll(s
, s
->regs
[AST2600_HPLL_PARAM
]);
285 return hpll
/ (SCU_AST1030_CLK_GET_PCLK_DIV(s
->regs
[AST2600_CLK_SEL4
]) + 1)
289 static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState
*s
)
291 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(s
);
292 uint32_t hpll
= asc
->calc_hpll(s
, s
->regs
[AST2700_SCU_HPLL_PARAM
]);
294 return hpll
/ (SCU_CLK_GET_PCLK_DIV(s
->regs
[AST2700_SCU_CLK_SEL_1
]) + 1)
298 static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState
*s
)
300 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(s
);
301 uint32_t hpll
= asc
->calc_hpll(s
, s
->regs
[AST2700_SCUIO_HPLL_PARAM
]);
304 (SCUIO_AST2700_CLK_GET_PCLK_DIV(s
->regs
[AST2700_SCUIO_CLK_SEL_1
]) + 1)
308 static uint64_t aspeed_scu_read(void *opaque
, hwaddr offset
, unsigned size
)
310 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
311 int reg
= TO_REG(offset
);
313 if (reg
>= ASPEED_SCU_NR_REGS
) {
314 qemu_log_mask(LOG_GUEST_ERROR
,
315 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx
"\n",
323 * On hardware, RNG_DATA works regardless of
324 * the state of the enable bit in RNG_CTRL
326 s
->regs
[RNG_DATA
] = aspeed_scu_get_random();
329 qemu_log_mask(LOG_GUEST_ERROR
,
330 "%s: Read of write-only offset 0x%" HWADDR_PRIx
"\n",
335 trace_aspeed_scu_read(offset
, size
, s
->regs
[reg
]);
339 static void aspeed_ast2400_scu_write(void *opaque
, hwaddr offset
,
340 uint64_t data
, unsigned size
)
342 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
343 int reg
= TO_REG(offset
);
345 if (reg
>= ASPEED_SCU_NR_REGS
) {
346 qemu_log_mask(LOG_GUEST_ERROR
,
347 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
352 if (reg
> PROT_KEY
&& reg
< CPU2_BASE_SEG1
&&
353 !s
->regs
[PROT_KEY
]) {
354 qemu_log_mask(LOG_GUEST_ERROR
, "%s: SCU is locked!\n", __func__
);
357 trace_aspeed_scu_write(offset
, size
, data
);
361 s
->regs
[reg
] = (data
== ASPEED_SCU_PROT_KEY
) ? 1 : 0;
365 case VGA_SCRATCH1
... VGA_SCRATCH8
:
369 qemu_log_mask(LOG_GUEST_ERROR
,
370 "%s: Write to read-only offset 0x%" HWADDR_PRIx
"\n",
378 static void aspeed_ast2500_scu_write(void *opaque
, hwaddr offset
,
379 uint64_t data
, unsigned size
)
381 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
382 int reg
= TO_REG(offset
);
384 if (reg
>= ASPEED_SCU_NR_REGS
) {
385 qemu_log_mask(LOG_GUEST_ERROR
,
386 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
391 if (reg
> PROT_KEY
&& reg
< CPU2_BASE_SEG1
&&
392 !s
->regs
[PROT_KEY
]) {
393 qemu_log_mask(LOG_GUEST_ERROR
, "%s: SCU is locked!\n", __func__
);
397 trace_aspeed_scu_write(offset
, size
, data
);
401 s
->regs
[reg
] = (data
== ASPEED_SCU_PROT_KEY
) ? 1 : 0;
404 s
->regs
[HW_STRAP1
] |= data
;
407 s
->regs
[HW_STRAP1
] &= ~data
;
410 case VGA_SCRATCH1
... VGA_SCRATCH8
:
416 qemu_log_mask(LOG_GUEST_ERROR
,
417 "%s: Write to read-only offset 0x%" HWADDR_PRIx
"\n",
425 static const MemoryRegionOps aspeed_ast2400_scu_ops
= {
426 .read
= aspeed_scu_read
,
427 .write
= aspeed_ast2400_scu_write
,
428 .endianness
= DEVICE_LITTLE_ENDIAN
,
430 .min_access_size
= 1,
431 .max_access_size
= 4,
435 static const MemoryRegionOps aspeed_ast2500_scu_ops
= {
436 .read
= aspeed_scu_read
,
437 .write
= aspeed_ast2500_scu_write
,
438 .endianness
= DEVICE_LITTLE_ENDIAN
,
439 .valid
.min_access_size
= 4,
440 .valid
.max_access_size
= 4,
441 .valid
.unaligned
= false,
444 static uint32_t aspeed_scu_get_clkin(AspeedSCUState
*s
)
446 if (s
->hw_strap1
& SCU_HW_STRAP_CLK_25M_IN
||
447 ASPEED_SCU_GET_CLASS(s
)->clkin_25Mhz
) {
449 } else if (s
->hw_strap1
& SCU_HW_STRAP_CLK_48M_IN
) {
457 * Strapped frequencies for the AST2400 in MHz. They depend on the
460 static const uint32_t hpll_ast2400_freqs
[][4] = {
461 { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
462 { 400, 375, 350, 425 }, /* 25MHz */
465 static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState
*s
, uint32_t hpll_reg
)
469 uint32_t clkin
= aspeed_scu_get_clkin(s
);
471 if (hpll_reg
& SCU_AST2400_H_PLL_OFF
) {
475 if (hpll_reg
& SCU_AST2400_H_PLL_PROGRAMMED
) {
476 uint32_t multiplier
= 1;
478 if (!(hpll_reg
& SCU_AST2400_H_PLL_BYPASS_EN
)) {
479 uint32_t n
= (hpll_reg
>> 5) & 0x3f;
480 uint32_t od
= (hpll_reg
>> 4) & 0x1;
481 uint32_t d
= hpll_reg
& 0xf;
483 multiplier
= (2 - od
) * ((n
+ 2) / (d
+ 1));
486 return clkin
* multiplier
;
490 clk_25m_in
= !!(s
->hw_strap1
& SCU_HW_STRAP_CLK_25M_IN
);
491 freq_select
= SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s
->hw_strap1
);
493 return hpll_ast2400_freqs
[clk_25m_in
][freq_select
] * 1000000;
496 static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState
*s
, uint32_t hpll_reg
)
498 uint32_t multiplier
= 1;
499 uint32_t clkin
= aspeed_scu_get_clkin(s
);
501 if (hpll_reg
& SCU_H_PLL_OFF
) {
505 if (!(hpll_reg
& SCU_H_PLL_BYPASS_EN
)) {
506 uint32_t p
= (hpll_reg
>> 13) & 0x3f;
507 uint32_t m
= (hpll_reg
>> 5) & 0xff;
508 uint32_t n
= hpll_reg
& 0x1f;
510 multiplier
= ((m
+ 1) / (n
+ 1)) / (p
+ 1);
513 return clkin
* multiplier
;
516 static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState
*s
, uint32_t hpll_reg
)
518 uint32_t multiplier
= 1;
519 uint32_t clkin
= aspeed_scu_get_clkin(s
);
521 if (hpll_reg
& SCU_AST2600_H_PLL_OFF
) {
525 if (!(hpll_reg
& SCU_AST2600_H_PLL_BYPASS_EN
)) {
526 uint32_t p
= (hpll_reg
>> 19) & 0xf;
527 uint32_t n
= (hpll_reg
>> 13) & 0x3f;
528 uint32_t m
= hpll_reg
& 0x1fff;
530 multiplier
= ((m
+ 1) / (n
+ 1)) / (p
+ 1);
533 return clkin
* multiplier
;
536 static void aspeed_scu_reset(DeviceState
*dev
)
538 AspeedSCUState
*s
= ASPEED_SCU(dev
);
539 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(dev
);
541 memcpy(s
->regs
, asc
->resets
, asc
->nr_regs
* 4);
542 s
->regs
[SILICON_REV
] = s
->silicon_rev
;
543 s
->regs
[HW_STRAP1
] = s
->hw_strap1
;
544 s
->regs
[HW_STRAP2
] = s
->hw_strap2
;
545 s
->regs
[PROT_KEY
] = s
->hw_prot_key
;
548 static uint32_t aspeed_silicon_revs
[] = {
549 AST2400_A0_SILICON_REV
,
550 AST2400_A1_SILICON_REV
,
551 AST2500_A0_SILICON_REV
,
552 AST2500_A1_SILICON_REV
,
553 AST2600_A0_SILICON_REV
,
554 AST2600_A1_SILICON_REV
,
555 AST2600_A2_SILICON_REV
,
556 AST2600_A3_SILICON_REV
,
557 AST1030_A0_SILICON_REV
,
558 AST1030_A1_SILICON_REV
,
559 AST2700_A0_SILICON_REV
,
560 AST2720_A0_SILICON_REV
,
561 AST2750_A0_SILICON_REV
,
564 bool is_supported_silicon_rev(uint32_t silicon_rev
)
568 for (i
= 0; i
< ARRAY_SIZE(aspeed_silicon_revs
); i
++) {
569 if (silicon_rev
== aspeed_silicon_revs
[i
]) {
577 static void aspeed_scu_realize(DeviceState
*dev
, Error
**errp
)
579 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
580 AspeedSCUState
*s
= ASPEED_SCU(dev
);
581 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(dev
);
583 if (!is_supported_silicon_rev(s
->silicon_rev
)) {
584 error_setg(errp
, "Unknown silicon revision: 0x%" PRIx32
,
589 memory_region_init_io(&s
->iomem
, OBJECT(s
), asc
->ops
, s
,
590 TYPE_ASPEED_SCU
, SCU_IO_REGION_SIZE
);
592 sysbus_init_mmio(sbd
, &s
->iomem
);
595 static const VMStateDescription vmstate_aspeed_scu
= {
596 .name
= "aspeed.scu",
598 .minimum_version_id
= 2,
599 .fields
= (const VMStateField
[]) {
600 VMSTATE_UINT32_ARRAY(regs
, AspeedSCUState
, ASPEED_AST2600_SCU_NR_REGS
),
601 VMSTATE_END_OF_LIST()
605 static Property aspeed_scu_properties
[] = {
606 DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState
, silicon_rev
, 0),
607 DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState
, hw_strap1
, 0),
608 DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState
, hw_strap2
, 0),
609 DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState
, hw_prot_key
, 0),
610 DEFINE_PROP_END_OF_LIST(),
613 static void aspeed_scu_class_init(ObjectClass
*klass
, void *data
)
615 DeviceClass
*dc
= DEVICE_CLASS(klass
);
616 dc
->realize
= aspeed_scu_realize
;
617 dc
->reset
= aspeed_scu_reset
;
618 dc
->desc
= "ASPEED System Control Unit";
619 dc
->vmsd
= &vmstate_aspeed_scu
;
620 device_class_set_props(dc
, aspeed_scu_properties
);
623 static const TypeInfo aspeed_scu_info
= {
624 .name
= TYPE_ASPEED_SCU
,
625 .parent
= TYPE_SYS_BUS_DEVICE
,
626 .instance_size
= sizeof(AspeedSCUState
),
627 .class_init
= aspeed_scu_class_init
,
628 .class_size
= sizeof(AspeedSCUClass
),
632 static void aspeed_2400_scu_class_init(ObjectClass
*klass
, void *data
)
634 DeviceClass
*dc
= DEVICE_CLASS(klass
);
635 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
637 dc
->desc
= "ASPEED 2400 System Control Unit";
638 asc
->resets
= ast2400_a0_resets
;
639 asc
->calc_hpll
= aspeed_2400_scu_calc_hpll
;
640 asc
->get_apb
= aspeed_2400_scu_get_apb_freq
;
641 asc
->apb_divider
= 2;
642 asc
->nr_regs
= ASPEED_SCU_NR_REGS
;
643 asc
->clkin_25Mhz
= false;
644 asc
->ops
= &aspeed_ast2400_scu_ops
;
647 static const TypeInfo aspeed_2400_scu_info
= {
648 .name
= TYPE_ASPEED_2400_SCU
,
649 .parent
= TYPE_ASPEED_SCU
,
650 .instance_size
= sizeof(AspeedSCUState
),
651 .class_init
= aspeed_2400_scu_class_init
,
654 static void aspeed_2500_scu_class_init(ObjectClass
*klass
, void *data
)
656 DeviceClass
*dc
= DEVICE_CLASS(klass
);
657 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
659 dc
->desc
= "ASPEED 2500 System Control Unit";
660 asc
->resets
= ast2500_a1_resets
;
661 asc
->calc_hpll
= aspeed_2500_scu_calc_hpll
;
662 asc
->get_apb
= aspeed_2400_scu_get_apb_freq
;
663 asc
->apb_divider
= 4;
664 asc
->nr_regs
= ASPEED_SCU_NR_REGS
;
665 asc
->clkin_25Mhz
= false;
666 asc
->ops
= &aspeed_ast2500_scu_ops
;
669 static const TypeInfo aspeed_2500_scu_info
= {
670 .name
= TYPE_ASPEED_2500_SCU
,
671 .parent
= TYPE_ASPEED_SCU
,
672 .instance_size
= sizeof(AspeedSCUState
),
673 .class_init
= aspeed_2500_scu_class_init
,
676 static uint64_t aspeed_ast2600_scu_read(void *opaque
, hwaddr offset
,
679 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
680 int reg
= TO_REG(offset
);
682 if (reg
>= ASPEED_AST2600_SCU_NR_REGS
) {
683 qemu_log_mask(LOG_GUEST_ERROR
,
684 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx
"\n",
690 case AST2600_HPLL_EXT
:
691 case AST2600_EPLL_EXT
:
692 case AST2600_MPLL_EXT
:
693 /* PLLs are always "locked" */
694 return s
->regs
[reg
] | BIT(31);
695 case AST2600_RNG_DATA
:
697 * On hardware, RNG_DATA works regardless of the state of the
698 * enable bit in RNG_CTRL
700 * TODO: Check this is true for ast2600
702 s
->regs
[AST2600_RNG_DATA
] = aspeed_scu_get_random();
706 trace_aspeed_scu_read(offset
, size
, s
->regs
[reg
]);
710 static void aspeed_ast2600_scu_write(void *opaque
, hwaddr offset
,
711 uint64_t data64
, unsigned size
)
713 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
714 int reg
= TO_REG(offset
);
715 /* Truncate here so bitwise operations below behave as expected */
716 uint32_t data
= data64
;
718 if (reg
>= ASPEED_AST2600_SCU_NR_REGS
) {
719 qemu_log_mask(LOG_GUEST_ERROR
,
720 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
725 if (reg
> PROT_KEY
&& !s
->regs
[PROT_KEY
]) {
726 qemu_log_mask(LOG_GUEST_ERROR
, "%s: SCU is locked!\n", __func__
);
729 trace_aspeed_scu_write(offset
, size
, data
);
732 case AST2600_PROT_KEY
:
733 s
->regs
[reg
] = (data
== ASPEED_SCU_PROT_KEY
) ? 1 : 0;
735 case AST2600_HW_STRAP1
:
736 case AST2600_HW_STRAP2
:
737 if (s
->regs
[reg
+ 2]) {
741 case AST2600_SYS_RST_CTRL
:
742 case AST2600_SYS_RST_CTRL2
:
743 case AST2600_CLK_STOP_CTRL
:
744 case AST2600_CLK_STOP_CTRL2
:
745 /* W1S (Write 1 to set) registers */
746 s
->regs
[reg
] |= data
;
748 case AST2600_SYS_RST_CTRL_CLR
:
749 case AST2600_SYS_RST_CTRL2_CLR
:
750 case AST2600_CLK_STOP_CTRL_CLR
:
751 case AST2600_CLK_STOP_CTRL2_CLR
:
752 case AST2600_HW_STRAP1_CLR
:
753 case AST2600_HW_STRAP2_CLR
:
755 * W1C (Write 1 to clear) registers are offset by one address from
758 s
->regs
[reg
- 1] &= ~data
;
761 case AST2600_RNG_DATA
:
762 case AST2600_SILICON_REV
:
763 case AST2600_SILICON_REV2
:
764 case AST2600_CHIP_ID0
:
765 case AST2600_CHIP_ID1
:
766 /* Add read only registers here */
767 qemu_log_mask(LOG_GUEST_ERROR
,
768 "%s: Write to read-only offset 0x%" HWADDR_PRIx
"\n",
776 static const MemoryRegionOps aspeed_ast2600_scu_ops
= {
777 .read
= aspeed_ast2600_scu_read
,
778 .write
= aspeed_ast2600_scu_write
,
779 .endianness
= DEVICE_LITTLE_ENDIAN
,
780 .valid
.min_access_size
= 4,
781 .valid
.max_access_size
= 4,
782 .valid
.unaligned
= false,
785 static const uint32_t ast2600_a3_resets
[ASPEED_AST2600_SCU_NR_REGS
] = {
786 [AST2600_SYS_RST_CTRL
] = 0xF7C3FED8,
787 [AST2600_SYS_RST_CTRL2
] = 0x0DFFFFFC,
788 [AST2600_CLK_STOP_CTRL
] = 0xFFFF7F8A,
789 [AST2600_CLK_STOP_CTRL2
] = 0xFFF0FFF0,
790 [AST2600_DEBUG_CTRL
] = 0x00000FFF,
791 [AST2600_DEBUG_CTRL2
] = 0x000000FF,
792 [AST2600_SDRAM_HANDSHAKE
] = 0x00000000,
793 [AST2600_HPLL_PARAM
] = 0x1000408F,
794 [AST2600_APLL_PARAM
] = 0x1000405F,
795 [AST2600_MPLL_PARAM
] = 0x1008405F,
796 [AST2600_EPLL_PARAM
] = 0x1004077F,
797 [AST2600_DPLL_PARAM
] = 0x1078405F,
798 [AST2600_CLK_SEL
] = 0xF3940000,
799 [AST2600_CLK_SEL2
] = 0x00700000,
800 [AST2600_CLK_SEL3
] = 0x00000000,
801 [AST2600_CLK_SEL4
] = 0xF3F40000,
802 [AST2600_CLK_SEL5
] = 0x30000000,
803 [AST2600_UARTCLK
] = 0x00014506,
804 [AST2600_HUARTCLK
] = 0x000145C0,
805 [AST2600_CHIP_ID0
] = 0x1234ABCD,
806 [AST2600_CHIP_ID1
] = 0x88884444,
809 static void aspeed_ast2600_scu_reset(DeviceState
*dev
)
811 AspeedSCUState
*s
= ASPEED_SCU(dev
);
812 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(dev
);
814 memcpy(s
->regs
, asc
->resets
, asc
->nr_regs
* 4);
817 * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
818 * of actual revision. QEMU and Linux only support A1 onwards so this is
821 s
->regs
[AST2600_SILICON_REV
] = AST2600_A3_SILICON_REV
;
822 s
->regs
[AST2600_SILICON_REV2
] = s
->silicon_rev
;
823 s
->regs
[AST2600_HW_STRAP1
] = s
->hw_strap1
;
824 s
->regs
[AST2600_HW_STRAP2
] = s
->hw_strap2
;
825 s
->regs
[PROT_KEY
] = s
->hw_prot_key
;
828 static void aspeed_2600_scu_class_init(ObjectClass
*klass
, void *data
)
830 DeviceClass
*dc
= DEVICE_CLASS(klass
);
831 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
833 dc
->desc
= "ASPEED 2600 System Control Unit";
834 dc
->reset
= aspeed_ast2600_scu_reset
;
835 asc
->resets
= ast2600_a3_resets
;
836 asc
->calc_hpll
= aspeed_2600_scu_calc_hpll
;
837 asc
->get_apb
= aspeed_2600_scu_get_apb_freq
;
838 asc
->apb_divider
= 4;
839 asc
->nr_regs
= ASPEED_AST2600_SCU_NR_REGS
;
840 asc
->clkin_25Mhz
= true;
841 asc
->ops
= &aspeed_ast2600_scu_ops
;
844 static const TypeInfo aspeed_2600_scu_info
= {
845 .name
= TYPE_ASPEED_2600_SCU
,
846 .parent
= TYPE_ASPEED_SCU
,
847 .instance_size
= sizeof(AspeedSCUState
),
848 .class_init
= aspeed_2600_scu_class_init
,
851 static uint64_t aspeed_ast2700_scu_read(void *opaque
, hwaddr offset
,
854 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
855 int reg
= TO_REG(offset
);
857 if (reg
>= ASPEED_AST2700_SCU_NR_REGS
) {
858 qemu_log_mask(LOG_GUEST_ERROR
,
859 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx
"\n",
866 qemu_log_mask(LOG_GUEST_ERROR
,
867 "%s: Unhandled read at offset 0x%" HWADDR_PRIx
"\n",
871 trace_aspeed_ast2700_scu_read(offset
, size
, s
->regs
[reg
]);
875 static void aspeed_ast2700_scu_write(void *opaque
, hwaddr offset
,
876 uint64_t data64
, unsigned size
)
878 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
879 int reg
= TO_REG(offset
);
880 /* Truncate here so bitwise operations below behave as expected */
881 uint32_t data
= data64
;
883 if (reg
>= ASPEED_AST2700_SCU_NR_REGS
) {
884 qemu_log_mask(LOG_GUEST_ERROR
,
885 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
890 trace_aspeed_ast2700_scu_write(offset
, size
, data
);
894 qemu_log_mask(LOG_GUEST_ERROR
,
895 "%s: Unhandled write at offset 0x%" HWADDR_PRIx
"\n",
903 static const MemoryRegionOps aspeed_ast2700_scu_ops
= {
904 .read
= aspeed_ast2700_scu_read
,
905 .write
= aspeed_ast2700_scu_write
,
906 .endianness
= DEVICE_LITTLE_ENDIAN
,
907 .valid
.min_access_size
= 1,
908 .valid
.max_access_size
= 8,
909 .valid
.unaligned
= false,
912 static const uint32_t ast2700_a0_resets
[ASPEED_AST2700_SCU_NR_REGS
] = {
913 [AST2700_SILICON_REV
] = AST2700_A0_SILICON_REV
,
914 [AST2700_HW_STRAP1
] = 0x00000800,
915 [AST2700_HW_STRAP1_CLR
] = 0xFFF0FFF0,
916 [AST2700_HW_STRAP1_LOCK
] = 0x00000FFF,
917 [AST2700_HW_STRAP1_SEC1
] = 0x000000FF,
918 [AST2700_HW_STRAP1_SEC2
] = 0x00000000,
919 [AST2700_HW_STRAP1_SEC3
] = 0x1000408F,
920 [AST2700_SCU_HPLL_PARAM
] = 0x0000009f,
921 [AST2700_SCU_HPLL_EXT_PARAM
] = 0x8000004f,
922 [AST2700_SCU_DPLL_PARAM
] = 0x0080009f,
923 [AST2700_SCU_DPLL_EXT_PARAM
] = 0x8000004f,
924 [AST2700_SCU_MPLL_PARAM
] = 0x00000040,
925 [AST2700_SCU_MPLL_EXT_PARAM
] = 0x80000000,
926 [AST2700_SCU_D1CLK_PARAM
] = 0x00050002,
927 [AST2700_SCU_D2CLK_PARAM
] = 0x00050002,
928 [AST2700_SCU_CRT1CLK_PARAM
] = 0x00050002,
929 [AST2700_SCU_CRT2CLK_PARAM
] = 0x00050002,
930 [AST2700_SCU_MPHYCLK_PARAM
] = 0x0000004c,
931 [AST2700_SCU_FREQ_CNTR
] = 0x000375eb,
932 [AST2700_SCU_CPU_SCRATCH_0
] = 0x00000000,
933 [AST2700_SCU_CPU_SCRATCH_1
] = 0x00000004,
936 static void aspeed_ast2700_scu_reset(DeviceState
*dev
)
938 AspeedSCUState
*s
= ASPEED_SCU(dev
);
939 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(dev
);
941 memcpy(s
->regs
, asc
->resets
, asc
->nr_regs
* 4);
944 static void aspeed_2700_scu_class_init(ObjectClass
*klass
, void *data
)
946 DeviceClass
*dc
= DEVICE_CLASS(klass
);
947 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
949 dc
->desc
= "ASPEED 2700 System Control Unit";
950 dc
->reset
= aspeed_ast2700_scu_reset
;
951 asc
->resets
= ast2700_a0_resets
;
952 asc
->calc_hpll
= aspeed_2600_scu_calc_hpll
;
953 asc
->get_apb
= aspeed_2700_scu_get_apb_freq
;
954 asc
->apb_divider
= 4;
955 asc
->nr_regs
= ASPEED_AST2700_SCU_NR_REGS
;
956 asc
->clkin_25Mhz
= true;
957 asc
->ops
= &aspeed_ast2700_scu_ops
;
960 static uint64_t aspeed_ast2700_scuio_read(void *opaque
, hwaddr offset
,
963 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
964 int reg
= TO_REG(offset
);
965 if (reg
>= ASPEED_AST2700_SCU_NR_REGS
) {
966 qemu_log_mask(LOG_GUEST_ERROR
,
967 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx
"\n",
974 qemu_log_mask(LOG_GUEST_ERROR
,
975 "%s: Unhandled read at offset 0x%" HWADDR_PRIx
"\n",
979 trace_aspeed_ast2700_scuio_read(offset
, size
, s
->regs
[reg
]);
983 static void aspeed_ast2700_scuio_write(void *opaque
, hwaddr offset
,
984 uint64_t data64
, unsigned size
)
986 AspeedSCUState
*s
= ASPEED_SCU(opaque
);
987 int reg
= TO_REG(offset
);
988 /* Truncate here so bitwise operations below behave as expected */
989 uint32_t data
= data64
;
990 bool updated
= false;
992 if (reg
>= ASPEED_AST2700_SCU_NR_REGS
) {
993 qemu_log_mask(LOG_GUEST_ERROR
,
994 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx
"\n",
999 trace_aspeed_ast2700_scuio_write(offset
, size
, data
);
1002 case AST2700_SCUIO_CLK_STOP_CTL_1
:
1003 case AST2700_SCUIO_CLK_STOP_CTL_2
:
1004 s
->regs
[reg
] |= data
;
1007 case AST2700_SCUIO_CLK_STOP_CLR_1
:
1008 case AST2700_SCUIO_CLK_STOP_CLR_2
:
1009 s
->regs
[reg
- 1] ^= data
;
1013 qemu_log_mask(LOG_GUEST_ERROR
,
1014 "%s: Unhandled write at offset 0x%" HWADDR_PRIx
"\n",
1020 s
->regs
[reg
] = data
;
1024 static const MemoryRegionOps aspeed_ast2700_scuio_ops
= {
1025 .read
= aspeed_ast2700_scuio_read
,
1026 .write
= aspeed_ast2700_scuio_write
,
1027 .endianness
= DEVICE_LITTLE_ENDIAN
,
1028 .valid
.min_access_size
= 1,
1029 .valid
.max_access_size
= 8,
1030 .valid
.unaligned
= false,
1033 static const uint32_t ast2700_a0_resets_io
[ASPEED_AST2700_SCU_NR_REGS
] = {
1034 [AST2700_SILICON_REV
] = 0x06000003,
1035 [AST2700_HW_STRAP1
] = 0x00000504,
1036 [AST2700_HW_STRAP1_CLR
] = 0xFFF0FFF0,
1037 [AST2700_HW_STRAP1_LOCK
] = 0x00000FFF,
1038 [AST2700_HW_STRAP1_SEC1
] = 0x000000FF,
1039 [AST2700_HW_STRAP1_SEC2
] = 0x00000000,
1040 [AST2700_HW_STRAP1_SEC3
] = 0x1000408F,
1041 [AST2700_SCUIO_CLK_STOP_CTL_1
] = 0xffff8400,
1042 [AST2700_SCUIO_CLK_STOP_CTL_2
] = 0x00005f30,
1043 [AST2700_SCUIO_CLK_SEL_1
] = 0x86900000,
1044 [AST2700_SCUIO_CLK_SEL_2
] = 0x00400000,
1045 [AST2700_SCUIO_HPLL_PARAM
] = 0x10000027,
1046 [AST2700_SCUIO_HPLL_EXT_PARAM
] = 0x80000014,
1047 [AST2700_SCUIO_APLL_PARAM
] = 0x1000001f,
1048 [AST2700_SCUIO_APLL_EXT_PARAM
] = 0x8000000f,
1049 [AST2700_SCUIO_DPLL_PARAM
] = 0x106e42ce,
1050 [AST2700_SCUIO_DPLL_EXT_PARAM
] = 0x80000167,
1051 [AST2700_SCUIO_DPLL_PARAM_READ
] = 0x106e42ce,
1052 [AST2700_SCUIO_DPLL_EXT_PARAM_READ
] = 0x80000167,
1053 [AST2700_SCUIO_UARTCLK_GEN
] = 0x00014506,
1054 [AST2700_SCUIO_HUARTCLK_GEN
] = 0x000145c0,
1055 [AST2700_SCUIO_CLK_DUTY_MEAS_RST
] = 0x0c9100d2,
1058 static void aspeed_2700_scuio_class_init(ObjectClass
*klass
, void *data
)
1060 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1061 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
1063 dc
->desc
= "ASPEED 2700 System Control Unit I/O";
1064 dc
->reset
= aspeed_ast2700_scu_reset
;
1065 asc
->resets
= ast2700_a0_resets_io
;
1066 asc
->calc_hpll
= aspeed_2600_scu_calc_hpll
;
1067 asc
->get_apb
= aspeed_2700_scuio_get_apb_freq
;
1068 asc
->apb_divider
= 2;
1069 asc
->nr_regs
= ASPEED_AST2700_SCU_NR_REGS
;
1070 asc
->clkin_25Mhz
= true;
1071 asc
->ops
= &aspeed_ast2700_scuio_ops
;
1074 static const TypeInfo aspeed_2700_scu_info
= {
1075 .name
= TYPE_ASPEED_2700_SCU
,
1076 .parent
= TYPE_ASPEED_SCU
,
1077 .instance_size
= sizeof(AspeedSCUState
),
1078 .class_init
= aspeed_2700_scu_class_init
,
1081 static const TypeInfo aspeed_2700_scuio_info
= {
1082 .name
= TYPE_ASPEED_2700_SCUIO
,
1083 .parent
= TYPE_ASPEED_SCU
,
1084 .instance_size
= sizeof(AspeedSCUState
),
1085 .class_init
= aspeed_2700_scuio_class_init
,
1088 static const uint32_t ast1030_a1_resets
[ASPEED_AST2600_SCU_NR_REGS
] = {
1089 [AST2600_SYS_RST_CTRL
] = 0xFFC3FED8,
1090 [AST2600_SYS_RST_CTRL2
] = 0x09FFFFFC,
1091 [AST2600_CLK_STOP_CTRL
] = 0xFFFF7F8A,
1092 [AST2600_CLK_STOP_CTRL2
] = 0xFFF0FFF0,
1093 [AST2600_DEBUG_CTRL2
] = 0x00000000,
1094 [AST2600_HPLL_PARAM
] = 0x10004077,
1095 [AST2600_HPLL_EXT
] = 0x00000031,
1096 [AST2600_CLK_SEL4
] = 0x43F90900,
1097 [AST2600_CLK_SEL5
] = 0x40000000,
1098 [AST2600_CHIP_ID0
] = 0xDEADBEEF,
1099 [AST2600_CHIP_ID1
] = 0x0BADCAFE,
1102 static void aspeed_ast1030_scu_reset(DeviceState
*dev
)
1104 AspeedSCUState
*s
= ASPEED_SCU(dev
);
1105 AspeedSCUClass
*asc
= ASPEED_SCU_GET_CLASS(dev
);
1107 memcpy(s
->regs
, asc
->resets
, asc
->nr_regs
* 4);
1109 s
->regs
[AST2600_SILICON_REV
] = AST1030_A1_SILICON_REV
;
1110 s
->regs
[AST2600_SILICON_REV2
] = s
->silicon_rev
;
1111 s
->regs
[AST2600_HW_STRAP1
] = s
->hw_strap1
;
1112 s
->regs
[AST2600_HW_STRAP2
] = s
->hw_strap2
;
1113 s
->regs
[PROT_KEY
] = s
->hw_prot_key
;
1116 static void aspeed_1030_scu_class_init(ObjectClass
*klass
, void *data
)
1118 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1119 AspeedSCUClass
*asc
= ASPEED_SCU_CLASS(klass
);
1121 dc
->desc
= "ASPEED 1030 System Control Unit";
1122 dc
->reset
= aspeed_ast1030_scu_reset
;
1123 asc
->resets
= ast1030_a1_resets
;
1124 asc
->calc_hpll
= aspeed_2600_scu_calc_hpll
;
1125 asc
->get_apb
= aspeed_1030_scu_get_apb_freq
;
1126 asc
->apb_divider
= 2;
1127 asc
->nr_regs
= ASPEED_AST2600_SCU_NR_REGS
;
1128 asc
->clkin_25Mhz
= true;
1129 asc
->ops
= &aspeed_ast2600_scu_ops
;
1132 static const TypeInfo aspeed_1030_scu_info
= {
1133 .name
= TYPE_ASPEED_1030_SCU
,
1134 .parent
= TYPE_ASPEED_SCU
,
1135 .instance_size
= sizeof(AspeedSCUState
),
1136 .class_init
= aspeed_1030_scu_class_init
,
1139 static void aspeed_scu_register_types(void)
1141 type_register_static(&aspeed_scu_info
);
1142 type_register_static(&aspeed_2400_scu_info
);
1143 type_register_static(&aspeed_2500_scu_info
);
1144 type_register_static(&aspeed_2600_scu_info
);
1145 type_register_static(&aspeed_1030_scu_info
);
1146 type_register_static(&aspeed_2700_scu_info
);
1147 type_register_static(&aspeed_2700_scuio_info
);
1150 type_init(aspeed_scu_register_types
);