pcie_sriov: Release VFs failed to realize
[qemu/ar7.git] / hw / misc / aspeed_scu.c
blob451e837272d948f1a335dbefd5b0541ac2c06d05
1 /*
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"
19 #include "qemu/log.h"
20 #include "qemu/guest-random.h"
21 #include "qemu/module.h"
22 #include "trace.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)
252 uint32_t num;
253 qemu_guest_getrandom_nofail(&num, sizeof(num));
254 return 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)
268 / asc->apb_divider;
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)
277 / asc->apb_divider;
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)
286 / asc->apb_divider;
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)
295 / asc->apb_divider;
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]);
303 return hpll /
304 (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
305 / asc->apb_divider;
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",
316 __func__, offset);
317 return 0;
320 switch (reg) {
321 case RNG_DATA:
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();
327 break;
328 case WAKEUP_EN:
329 qemu_log_mask(LOG_GUEST_ERROR,
330 "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
331 __func__, offset);
332 break;
335 trace_aspeed_scu_read(offset, size, s->regs[reg]);
336 return 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",
348 __func__, offset);
349 return;
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);
359 switch (reg) {
360 case PROT_KEY:
361 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
362 return;
363 case SILICON_REV:
364 case FREQ_CNTR_EVAL:
365 case VGA_SCRATCH1 ... VGA_SCRATCH8:
366 case RNG_DATA:
367 case FREE_CNTR4:
368 case FREE_CNTR4_EXT:
369 qemu_log_mask(LOG_GUEST_ERROR,
370 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
371 __func__, offset);
372 return;
375 s->regs[reg] = data;
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",
387 __func__, offset);
388 return;
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__);
394 return;
397 trace_aspeed_scu_write(offset, size, data);
399 switch (reg) {
400 case PROT_KEY:
401 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
402 return;
403 case HW_STRAP1:
404 s->regs[HW_STRAP1] |= data;
405 return;
406 case SILICON_REV:
407 s->regs[HW_STRAP1] &= ~data;
408 return;
409 case FREQ_CNTR_EVAL:
410 case VGA_SCRATCH1 ... VGA_SCRATCH8:
411 case RNG_DATA:
412 case FREE_CNTR4:
413 case FREE_CNTR4_EXT:
414 case CHIP_ID0:
415 case CHIP_ID1:
416 qemu_log_mask(LOG_GUEST_ERROR,
417 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
418 __func__, offset);
419 return;
422 s->regs[reg] = data;
425 static const MemoryRegionOps aspeed_ast2400_scu_ops = {
426 .read = aspeed_scu_read,
427 .write = aspeed_ast2400_scu_write,
428 .endianness = DEVICE_LITTLE_ENDIAN,
429 .valid = {
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) {
448 return 25000000;
449 } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
450 return 48000000;
451 } else {
452 return 24000000;
457 * Strapped frequencies for the AST2400 in MHz. They depend on the
458 * clkin frequency.
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)
467 uint8_t freq_select;
468 bool clk_25m_in;
469 uint32_t clkin = aspeed_scu_get_clkin(s);
471 if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
472 return 0;
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;
489 /* HW strapping */
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) {
502 return 0;
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) {
522 return 0;
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)
566 int i;
568 for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
569 if (silicon_rev == aspeed_silicon_revs[i]) {
570 return true;
574 return false;
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,
585 s->silicon_rev);
586 return;
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",
597 .version_id = 2,
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),
629 .abstract = true,
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,
677 unsigned size)
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",
685 __func__, offset);
686 return 0;
689 switch (reg) {
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();
703 break;
706 trace_aspeed_scu_read(offset, size, s->regs[reg]);
707 return 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",
721 __func__, offset);
722 return;
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);
731 switch (reg) {
732 case AST2600_PROT_KEY:
733 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
734 return;
735 case AST2600_HW_STRAP1:
736 case AST2600_HW_STRAP2:
737 if (s->regs[reg + 2]) {
738 return;
740 /* fall through */
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;
747 return;
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
756 * the data register
758 s->regs[reg - 1] &= ~data;
759 return;
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",
769 __func__, offset);
770 return;
773 s->regs[reg] = data;
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
819 * sufficient.
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,
852 unsigned size)
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",
860 __func__, offset);
861 return 0;
864 switch (reg) {
865 default:
866 qemu_log_mask(LOG_GUEST_ERROR,
867 "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
868 __func__, offset);
871 trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
872 return 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",
886 __func__, offset);
887 return;
890 trace_aspeed_ast2700_scu_write(offset, size, data);
892 switch (reg) {
893 default:
894 qemu_log_mask(LOG_GUEST_ERROR,
895 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
896 __func__, offset);
897 break;
900 s->regs[reg] = data;
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,
961 unsigned size)
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",
968 __func__, offset);
969 return 0;
972 switch (reg) {
973 default:
974 qemu_log_mask(LOG_GUEST_ERROR,
975 "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
976 __func__, offset);
979 trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
980 return 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",
995 __func__, offset);
996 return;
999 trace_aspeed_ast2700_scuio_write(offset, size, data);
1001 switch (reg) {
1002 case AST2700_SCUIO_CLK_STOP_CTL_1:
1003 case AST2700_SCUIO_CLK_STOP_CTL_2:
1004 s->regs[reg] |= data;
1005 updated = true;
1006 break;
1007 case AST2700_SCUIO_CLK_STOP_CLR_1:
1008 case AST2700_SCUIO_CLK_STOP_CLR_2:
1009 s->regs[reg - 1] ^= data;
1010 updated = true;
1011 break;
1012 default:
1013 qemu_log_mask(LOG_GUEST_ERROR,
1014 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
1015 __func__, offset);
1016 break;
1019 if (!updated) {
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);