master
c 1,191 lines 39 KB
Raw
1 /*
2 * ASPEED System Control Unit
3 *
4 * Andrew Jeffery <andrew@aj.id.au>
5 *
6 * Copyright 2016 IBM Corp.
7 *
8 * This code is licensed under the GPL version 2 or later. See
9 * the COPYING file in the top-level directory.
10 */
11
12 #include "qemu/osdep.h"
13 #include "hw/misc/aspeed_scu.h"
14 #include "hw/core/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"
23
24 #define TO_REG(offset) ((offset) >> 2)
25
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)
92
93 #define AST2600_PROT_KEY TO_REG(0x00)
94 #define AST2600_PROT_KEY2 TO_REG(0x10)
95 #define AST2600_SILICON_REV TO_REG(0x04)
96 #define AST2600_SILICON_REV2 TO_REG(0x14)
97 #define AST2600_SYS_RST_CTRL TO_REG(0x40)
98 #define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44)
99 #define AST2600_SYS_RST_CTRL2 TO_REG(0x50)
100 #define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
101 #define AST2600_CLK_STOP_CTRL TO_REG(0x80)
102 #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
103 #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
104 #define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
105 #define AST2600_DEBUG_CTRL TO_REG(0xC8)
106 #define AST2600_DEBUG_CTRL2 TO_REG(0xD8)
107 #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
108 #define AST2600_HPLL_PARAM TO_REG(0x200)
109 #define AST2600_HPLL_EXT TO_REG(0x204)
110 #define AST2600_APLL_PARAM TO_REG(0x210)
111 #define AST2600_APLL_EXT TO_REG(0x214)
112 #define AST2600_MPLL_PARAM TO_REG(0x220)
113 #define AST2600_MPLL_EXT TO_REG(0x224)
114 #define AST2600_EPLL_PARAM TO_REG(0x240)
115 #define AST2600_EPLL_EXT TO_REG(0x244)
116 #define AST2600_DPLL_PARAM TO_REG(0x260)
117 #define AST2600_DPLL_EXT TO_REG(0x264)
118 #define AST2600_CLK_SEL TO_REG(0x300)
119 #define AST2600_CLK_SEL2 TO_REG(0x304)
120 #define AST2600_CLK_SEL3 TO_REG(0x308)
121 #define AST2600_CLK_SEL4 TO_REG(0x310)
122 #define AST2600_CLK_SEL5 TO_REG(0x314)
123 #define AST2600_UARTCLK TO_REG(0x338)
124 #define AST2600_HUARTCLK TO_REG(0x33C)
125 #define AST2600_HW_STRAP1 TO_REG(0x500)
126 #define AST2600_HW_STRAP1_CLR TO_REG(0x504)
127 #define AST2600_HW_STRAP1_PROT TO_REG(0x508)
128 #define AST2600_HW_STRAP2 TO_REG(0x510)
129 #define AST2600_HW_STRAP2_CLR TO_REG(0x514)
130 #define AST2600_HW_STRAP2_PROT TO_REG(0x518)
131 #define AST2600_RNG_CTRL TO_REG(0x520)
132 #define AST2600_RNG_DATA TO_REG(0x524)
133 #define AST2600_CHIP_ID0 TO_REG(0x5B0)
134 #define AST2600_CHIP_ID1 TO_REG(0x5B4)
135
136 #define AST2600_CLK TO_REG(0x40)
137
138 #define AST2700_SILICON_REV TO_REG(0x00)
139 #define AST2700_HW_STRAP1 TO_REG(0x10)
140 #define AST2700_HW_STRAP1_CLR TO_REG(0x14)
141 #define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
142 #define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
143 #define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
144 #define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
145
146 #define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
147 #define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
148 #define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
149 #define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
150 #define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
151 #define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
152 #define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
153 #define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
154 #define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
155 #define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
156 #define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
157 #define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
158 #define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
159 #define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
160 #define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
161 #define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900)
162
163 #define AST2700_SCUIO_RNG_CTRL TO_REG(0xF0)
164 #define AST2700_SCUIO_RNG_CTRL_MASK 0x2F
165 #define AST2700_SCUIO_RNG_CTRL_DIS BIT(0)
166 #define AST2700_SCUIO_RNG_CTRL_VLD BIT(31)
167 #define AST2700_SCUIO_RNG_DATA TO_REG(0xF4)
168 #define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
169 #define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
170 #define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
171 #define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
172 #define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
173 #define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
174 #define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
175 #define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
176 #define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
177 #define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
178 #define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
179 #define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
180 #define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
181 #define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
182 #define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
183 #define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
184 #define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
185 #define AST2700_SCUIO_FREQ_CNT_CTL TO_REG(0x3A0)
186
187 #define SCU_IO_REGION_SIZE 0x1000
188
189 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
190 [SYS_RST_CTRL] = 0xFFCFFEDCU,
191 [CLK_SEL] = 0xF3F40000U,
192 [CLK_STOP_CTRL] = 0x19FC3E8BU,
193 [D2PLL_PARAM] = 0x00026108U,
194 [MPLL_PARAM] = 0x00030291U,
195 [HPLL_PARAM] = 0x00000291U,
196 [MISC_CTRL1] = 0x00000010U,
197 [PCI_CTRL1] = 0x20001A03U,
198 [PCI_CTRL2] = 0x20001A03U,
199 [PCI_CTRL3] = 0x04000030U,
200 [SYS_RST_STATUS] = 0x00000001U,
201 [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
202 [MISC_CTRL2] = 0x00000023U,
203 [RNG_CTRL] = 0x0000000EU,
204 [PINMUX_CTRL2] = 0x0000F000U,
205 [PINMUX_CTRL3] = 0x01000000U,
206 [PINMUX_CTRL4] = 0x000000FFU,
207 [PINMUX_CTRL5] = 0x0000A000U,
208 [WDT_RST_CTRL] = 0x003FFFF3U,
209 [PINMUX_CTRL8] = 0xFFFF0000U,
210 [PINMUX_CTRL9] = 0x000FFFFFU,
211 [FREE_CNTR4] = 0x000000FFU,
212 [FREE_CNTR4_EXT] = 0x000000FFU,
213 [CPU2_BASE_SEG1] = 0x80000000U,
214 [CPU2_BASE_SEG4] = 0x1E600000U,
215 [CPU2_BASE_SEG5] = 0xC0000000U,
216 [UART_HPLL_CLK] = 0x00001903U,
217 [PCIE_CTRL] = 0x0000007BU,
218 [BMC_DEV_ID] = 0x00002402U
219 };
220
221 /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
222 /* AST2500 revision A1 */
223
224 static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
225 [SYS_RST_CTRL] = 0xFFCFFEDCU,
226 [CLK_SEL] = 0xF3F40000U,
227 [CLK_STOP_CTRL] = 0x19FC3E8BU,
228 [D2PLL_PARAM] = 0x00026108U,
229 [MPLL_PARAM] = 0x00030291U,
230 [HPLL_PARAM] = 0x93000400U,
231 [MISC_CTRL1] = 0x00000010U,
232 [PCI_CTRL1] = 0x20001A03U,
233 [PCI_CTRL2] = 0x20001A03U,
234 [PCI_CTRL3] = 0x04000030U,
235 [SYS_RST_STATUS] = 0x00000001U,
236 [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
237 [MISC_CTRL2] = 0x00000023U,
238 [RNG_CTRL] = 0x0000000EU,
239 [PINMUX_CTRL2] = 0x0000F000U,
240 [PINMUX_CTRL3] = 0x03000000U,
241 [PINMUX_CTRL4] = 0x00000000U,
242 [PINMUX_CTRL5] = 0x0000A000U,
243 [WDT_RST_CTRL] = 0x023FFFF3U,
244 [PINMUX_CTRL8] = 0xFFFF0000U,
245 [PINMUX_CTRL9] = 0x000FFFFFU,
246 [FREE_CNTR4] = 0x000000FFU,
247 [FREE_CNTR4_EXT] = 0x000000FFU,
248 [CPU2_BASE_SEG1] = 0x80000000U,
249 [CPU2_BASE_SEG4] = 0x1E600000U,
250 [CPU2_BASE_SEG5] = 0xC0000000U,
251 [CHIP_ID0] = 0x1234ABCDU,
252 [CHIP_ID1] = 0x88884444U,
253 [UART_HPLL_CLK] = 0x00001903U,
254 [PCIE_CTRL] = 0x0000007BU,
255 [BMC_DEV_ID] = 0x00002402U
256 };
257
258 static uint32_t aspeed_scu_get_random(void)
259 {
260 uint32_t num;
261 qemu_guest_getrandom_nofail(&num, sizeof(num));
262 return num;
263 }
264
265 uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
266 {
267 return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
268 }
269
270 static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState *s)
271 {
272 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
273 uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
274
275 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
276 / asc->apb_divider;
277 }
278
279 static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
280 {
281 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
282 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
283
284 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
285 / asc->apb_divider;
286 }
287
288 static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
289 {
290 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
291 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
292
293 return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
294 / asc->apb_divider;
295 }
296
297 static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
298 {
299 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
300 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
301
302 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
303 / asc->apb_divider;
304 }
305
306 static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
307 {
308 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
309 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
310
311 return hpll /
312 (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
313 / asc->apb_divider;
314 }
315
316 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
317 {
318 AspeedSCUState *s = ASPEED_SCU(opaque);
319 int reg = TO_REG(offset);
320
321 if (reg >= ASPEED_SCU_NR_REGS) {
322 qemu_log_mask(LOG_GUEST_ERROR,
323 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
324 __func__, offset);
325 return 0;
326 }
327
328 switch (reg) {
329 case RNG_DATA:
330 /*
331 * On hardware, RNG_DATA works regardless of
332 * the state of the enable bit in RNG_CTRL
333 */
334 s->regs[RNG_DATA] = aspeed_scu_get_random();
335 break;
336 case WAKEUP_EN:
337 qemu_log_mask(LOG_GUEST_ERROR,
338 "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
339 __func__, offset);
340 break;
341 }
342
343 trace_aspeed_scu_read(offset, size, s->regs[reg]);
344 return s->regs[reg];
345 }
346
347 static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
348 uint64_t data, unsigned size)
349 {
350 AspeedSCUState *s = ASPEED_SCU(opaque);
351 int reg = TO_REG(offset);
352
353 if (reg >= ASPEED_SCU_NR_REGS) {
354 qemu_log_mask(LOG_GUEST_ERROR,
355 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
356 __func__, offset);
357 return;
358 }
359
360 if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
361 !s->regs[PROT_KEY]) {
362 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
363 }
364
365 trace_aspeed_scu_write(offset, size, data);
366
367 switch (reg) {
368 case PROT_KEY:
369 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
370 return;
371 case SILICON_REV:
372 case FREQ_CNTR_EVAL:
373 case VGA_SCRATCH1 ... VGA_SCRATCH8:
374 case RNG_DATA:
375 case FREE_CNTR4:
376 case FREE_CNTR4_EXT:
377 qemu_log_mask(LOG_GUEST_ERROR,
378 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
379 __func__, offset);
380 return;
381 }
382
383 s->regs[reg] = data;
384 }
385
386 static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
387 uint64_t data, unsigned size)
388 {
389 AspeedSCUState *s = ASPEED_SCU(opaque);
390 int reg = TO_REG(offset);
391
392 if (reg >= ASPEED_SCU_NR_REGS) {
393 qemu_log_mask(LOG_GUEST_ERROR,
394 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
395 __func__, offset);
396 return;
397 }
398
399 if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
400 !s->regs[PROT_KEY]) {
401 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
402 return;
403 }
404
405 trace_aspeed_scu_write(offset, size, data);
406
407 switch (reg) {
408 case PROT_KEY:
409 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
410 return;
411 case HW_STRAP1:
412 s->regs[HW_STRAP1] |= data;
413 return;
414 case SILICON_REV:
415 s->regs[HW_STRAP1] &= ~data;
416 return;
417 case FREQ_CNTR_EVAL:
418 case VGA_SCRATCH1 ... VGA_SCRATCH8:
419 case RNG_DATA:
420 case FREE_CNTR4:
421 case FREE_CNTR4_EXT:
422 case CHIP_ID0:
423 case CHIP_ID1:
424 qemu_log_mask(LOG_GUEST_ERROR,
425 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
426 __func__, offset);
427 return;
428 }
429
430 s->regs[reg] = data;
431 }
432
433 static const MemoryRegionOps aspeed_ast2400_scu_ops = {
434 .read = aspeed_scu_read,
435 .write = aspeed_ast2400_scu_write,
436 .endianness = DEVICE_LITTLE_ENDIAN,
437 .impl = {
438 .min_access_size = 4,
439 .max_access_size = 4,
440 },
441 .valid = {
442 .min_access_size = 1,
443 .max_access_size = 4,
444 },
445 };
446
447 static const MemoryRegionOps aspeed_ast2500_scu_ops = {
448 .read = aspeed_scu_read,
449 .write = aspeed_ast2500_scu_write,
450 .endianness = DEVICE_LITTLE_ENDIAN,
451 .impl.min_access_size = 4,
452 .impl.max_access_size = 4,
453 .valid.min_access_size = 1,
454 .valid.max_access_size = 4,
455 .valid.unaligned = false,
456 };
457
458 static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
459 {
460 if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN ||
461 ASPEED_SCU_GET_CLASS(s)->clkin_25Mhz) {
462 return 25000000;
463 } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
464 return 48000000;
465 } else {
466 return 24000000;
467 }
468 }
469
470 /*
471 * Strapped frequencies for the AST2400 in MHz. They depend on the
472 * clkin frequency.
473 */
474 static const uint32_t hpll_ast2400_freqs[][4] = {
475 { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
476 { 400, 375, 350, 425 }, /* 25MHz */
477 };
478
479 static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
480 {
481 uint8_t freq_select;
482 bool clk_25m_in;
483 uint32_t clkin = aspeed_scu_get_clkin(s);
484
485 if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
486 return 0;
487 }
488
489 if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
490 uint32_t multiplier = 1;
491
492 if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
493 uint32_t n = (hpll_reg >> 5) & 0x3f;
494 uint32_t od = (hpll_reg >> 4) & 0x1;
495 uint32_t d = hpll_reg & 0xf;
496
497 multiplier = (2 - od) * ((n + 2) / (d + 1));
498 }
499
500 return clkin * multiplier;
501 }
502
503 /* HW strapping */
504 clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
505 freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
506
507 return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
508 }
509
510 static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
511 {
512 uint32_t multiplier = 1;
513 uint32_t clkin = aspeed_scu_get_clkin(s);
514
515 if (hpll_reg & SCU_H_PLL_OFF) {
516 return 0;
517 }
518
519 if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
520 uint32_t p = (hpll_reg >> 13) & 0x3f;
521 uint32_t m = (hpll_reg >> 5) & 0xff;
522 uint32_t n = hpll_reg & 0x1f;
523
524 multiplier = ((m + 1) / (n + 1)) / (p + 1);
525 }
526
527 return clkin * multiplier;
528 }
529
530 static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
531 {
532 uint32_t multiplier = 1;
533 uint32_t clkin = aspeed_scu_get_clkin(s);
534
535 if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
536 return 0;
537 }
538
539 if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) {
540 uint32_t p = (hpll_reg >> 19) & 0xf;
541 uint32_t n = (hpll_reg >> 13) & 0x3f;
542 uint32_t m = hpll_reg & 0x1fff;
543
544 multiplier = ((m + 1) / (n + 1)) / (p + 1);
545 }
546
547 return clkin * multiplier;
548 }
549
550 static void aspeed_scu_reset_hold(Object *obj, ResetType type)
551 {
552 AspeedSCUState *s = ASPEED_SCU(obj);
553 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
554
555 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
556 s->regs[SILICON_REV] = s->silicon_rev;
557 s->regs[HW_STRAP1] = s->hw_strap1;
558 s->regs[HW_STRAP2] = s->hw_strap2;
559 s->regs[PROT_KEY] = s->hw_prot_key;
560 }
561
562 static uint32_t aspeed_silicon_revs[] = {
563 AST2400_A1_SILICON_REV,
564 AST2500_A1_SILICON_REV,
565 AST2600_A3_SILICON_REV,
566 AST1030_A1_SILICON_REV,
567 AST1060_A2_SILICON_REV,
568 AST2700_A1_SILICON_REV,
569 AST2700_A2_SILICON_REV,
570 AST1040_A0_SILICON_REV,
571 };
572
573 bool is_supported_silicon_rev(uint32_t silicon_rev)
574 {
575 int i;
576
577 for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
578 if (silicon_rev == aspeed_silicon_revs[i]) {
579 return true;
580 }
581 }
582
583 return false;
584 }
585
586 static void aspeed_scu_realize(DeviceState *dev, Error **errp)
587 {
588 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
589 AspeedSCUState *s = ASPEED_SCU(dev);
590 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
591
592 if (!is_supported_silicon_rev(s->silicon_rev)) {
593 error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
594 s->silicon_rev);
595 return;
596 }
597
598 memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
599 TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
600
601 sysbus_init_mmio(sbd, &s->iomem);
602 }
603
604 static const VMStateDescription vmstate_aspeed_scu = {
605 .name = "aspeed.scu",
606 .version_id = 2,
607 .minimum_version_id = 2,
608 .fields = (const VMStateField[]) {
609 VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
610 VMSTATE_END_OF_LIST()
611 }
612 };
613
614 static const Property aspeed_scu_properties[] = {
615 DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
616 DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
617 DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
618 DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
619 };
620
621 static void aspeed_scu_class_init(ObjectClass *klass, const void *data)
622 {
623 DeviceClass *dc = DEVICE_CLASS(klass);
624 ResettableClass *rc = RESETTABLE_CLASS(klass);
625 dc->realize = aspeed_scu_realize;
626 rc->phases.hold = aspeed_scu_reset_hold;
627 dc->desc = "ASPEED System Control Unit";
628 dc->vmsd = &vmstate_aspeed_scu;
629 device_class_set_props(dc, aspeed_scu_properties);
630 }
631
632 static void aspeed_2400_scu_class_init(ObjectClass *klass, const void *data)
633 {
634 DeviceClass *dc = DEVICE_CLASS(klass);
635 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
636
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;
645 }
646
647 static void aspeed_2500_scu_class_init(ObjectClass *klass, const void *data)
648 {
649 DeviceClass *dc = DEVICE_CLASS(klass);
650 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
651
652 dc->desc = "ASPEED 2500 System Control Unit";
653 asc->resets = ast2500_a1_resets;
654 asc->calc_hpll = aspeed_2500_scu_calc_hpll;
655 asc->get_apb = aspeed_2400_scu_get_apb_freq;
656 asc->apb_divider = 4;
657 asc->nr_regs = ASPEED_SCU_NR_REGS;
658 asc->clkin_25Mhz = false;
659 asc->ops = &aspeed_ast2500_scu_ops;
660 }
661
662 static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
663 unsigned size)
664 {
665 AspeedSCUState *s = ASPEED_SCU(opaque);
666 int reg = TO_REG(offset);
667
668 if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
669 qemu_log_mask(LOG_GUEST_ERROR,
670 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
671 __func__, offset);
672 return 0;
673 }
674
675 switch (reg) {
676 case AST2600_HPLL_EXT:
677 case AST2600_EPLL_EXT:
678 case AST2600_MPLL_EXT:
679 /* PLLs are always "locked" */
680 return s->regs[reg] | BIT(31);
681 case AST2600_RNG_DATA:
682 /*
683 * On hardware, RNG_DATA works regardless of the state of the
684 * enable bit in RNG_CTRL
685 *
686 * TODO: Check this is true for ast2600
687 */
688 s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
689 break;
690 }
691
692 trace_aspeed_scu_read(offset, size, s->regs[reg]);
693 return s->regs[reg];
694 }
695
696 static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
697 uint64_t data64, unsigned size)
698 {
699 AspeedSCUState *s = ASPEED_SCU(opaque);
700 int reg = TO_REG(offset);
701 /* Truncate here so bitwise operations below behave as expected */
702 uint32_t data = data64;
703 bool prot_data_state = data == ASPEED_SCU_PROT_KEY;
704 bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2];
705
706 if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
707 qemu_log_mask(LOG_GUEST_ERROR,
708 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
709 __func__, offset);
710 return;
711 }
712
713 if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) {
714 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
715 return;
716 }
717
718 trace_aspeed_scu_write(offset, size, data);
719
720 switch (reg) {
721 case AST2600_PROT_KEY:
722 /*
723 * Writing a value to SCU000 will modify both protection
724 * registers to each protection register individually.
725 */
726 s->regs[AST2600_PROT_KEY] = prot_data_state;
727 s->regs[AST2600_PROT_KEY2] = prot_data_state;
728 return;
729 case AST2600_PROT_KEY2:
730 s->regs[AST2600_PROT_KEY2] = prot_data_state;
731 return;
732 case AST2600_HW_STRAP1:
733 case AST2600_HW_STRAP2:
734 if (s->regs[reg + 2]) {
735 return;
736 }
737 /* fall through */
738 case AST2600_SYS_RST_CTRL:
739 case AST2600_SYS_RST_CTRL2:
740 case AST2600_CLK_STOP_CTRL:
741 case AST2600_CLK_STOP_CTRL2:
742 /* W1S (Write 1 to set) registers */
743 s->regs[reg] |= data;
744 return;
745 case AST2600_SYS_RST_CTRL_CLR:
746 case AST2600_SYS_RST_CTRL2_CLR:
747 case AST2600_CLK_STOP_CTRL_CLR:
748 case AST2600_CLK_STOP_CTRL2_CLR:
749 case AST2600_HW_STRAP1_CLR:
750 case AST2600_HW_STRAP2_CLR:
751 /*
752 * W1C (Write 1 to clear) registers are offset by one address from
753 * the data register
754 */
755 s->regs[reg - 1] &= ~data;
756 return;
757
758 case AST2600_RNG_DATA:
759 case AST2600_SILICON_REV:
760 case AST2600_SILICON_REV2:
761 case AST2600_CHIP_ID0:
762 case AST2600_CHIP_ID1:
763 /* Add read only registers here */
764 qemu_log_mask(LOG_GUEST_ERROR,
765 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
766 __func__, offset);
767 return;
768 }
769
770 s->regs[reg] = data;
771 }
772
773 static const MemoryRegionOps aspeed_ast2600_scu_ops = {
774 .read = aspeed_ast2600_scu_read,
775 .write = aspeed_ast2600_scu_write,
776 .endianness = DEVICE_LITTLE_ENDIAN,
777 .impl.min_access_size = 4,
778 .impl.max_access_size = 4,
779 .valid.min_access_size = 1,
780 .valid.max_access_size = 4,
781 .valid.unaligned = false,
782 };
783
784 static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
785 [AST2600_SYS_RST_CTRL] = 0xF7C3FED8,
786 [AST2600_SYS_RST_CTRL2] = 0x0DFFFFFC,
787 [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
788 [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
789 [AST2600_DEBUG_CTRL] = 0x00000FFF,
790 [AST2600_DEBUG_CTRL2] = 0x000000FF,
791 [AST2600_SDRAM_HANDSHAKE] = 0x00000000,
792 [AST2600_HPLL_PARAM] = 0x1000408F,
793 [AST2600_APLL_PARAM] = 0x1000405F,
794 [AST2600_MPLL_PARAM] = 0x1008405F,
795 [AST2600_EPLL_PARAM] = 0x1004077F,
796 [AST2600_DPLL_PARAM] = 0x1078405F,
797 [AST2600_CLK_SEL] = 0xF3940000,
798 [AST2600_CLK_SEL2] = 0x00700000,
799 [AST2600_CLK_SEL3] = 0x00000000,
800 [AST2600_CLK_SEL4] = 0xF3F40000,
801 [AST2600_CLK_SEL5] = 0x30000000,
802 [AST2600_UARTCLK] = 0x00014506,
803 [AST2600_HUARTCLK] = 0x000145C0,
804 [AST2600_CHIP_ID0] = 0x1234ABCD,
805 [AST2600_CHIP_ID1] = 0x88884444,
806 };
807
808 static void aspeed_ast2600_scu_reset_hold(Object *obj, ResetType type)
809 {
810 AspeedSCUState *s = ASPEED_SCU(obj);
811 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
812
813 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
814
815 /*
816 * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
817 * of actual revision. QEMU and Linux only support A1 onwards so this is
818 * sufficient.
819 */
820 s->regs[AST2600_SILICON_REV] = s->silicon_rev;
821 s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
822 s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
823 s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
824 s->regs[PROT_KEY] = s->hw_prot_key;
825 }
826
827 static void aspeed_2600_scu_class_init(ObjectClass *klass, const void *data)
828 {
829 DeviceClass *dc = DEVICE_CLASS(klass);
830 ResettableClass *rc = RESETTABLE_CLASS(klass);
831 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
832
833 dc->desc = "ASPEED 2600 System Control Unit";
834 rc->phases.hold = aspeed_ast2600_scu_reset_hold;
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;
842 }
843
844 static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
845 unsigned size)
846 {
847 AspeedSCUState *s = ASPEED_SCU(opaque);
848 int reg = TO_REG(offset);
849
850 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
851 qemu_log_mask(LOG_GUEST_ERROR,
852 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
853 __func__, offset);
854 return 0;
855 }
856
857 trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
858 return s->regs[reg];
859 }
860
861 static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
862 uint64_t data64, unsigned size)
863 {
864 AspeedSCUState *s = ASPEED_SCU(opaque);
865 int reg = TO_REG(offset);
866 /* Truncate here so bitwise operations below behave as expected */
867 uint32_t data = data64;
868
869 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
870 qemu_log_mask(LOG_GUEST_ERROR,
871 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
872 __func__, offset);
873 return;
874 }
875
876 trace_aspeed_ast2700_scu_write(offset, size, data);
877
878 switch (reg) {
879 default:
880 qemu_log_mask(LOG_GUEST_ERROR,
881 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
882 __func__, offset);
883 break;
884 }
885
886 s->regs[reg] = data;
887 }
888
889 static const MemoryRegionOps aspeed_ast2700_scu_ops = {
890 .read = aspeed_ast2700_scu_read,
891 .write = aspeed_ast2700_scu_write,
892 .endianness = DEVICE_LITTLE_ENDIAN,
893 .impl.min_access_size = 4,
894 .impl.max_access_size = 4,
895 .valid.min_access_size = 1,
896 .valid.max_access_size = 8,
897 .valid.unaligned = false,
898 };
899
900 static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
901 [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
902 [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
903 [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
904 [AST2700_HW_STRAP1_SEC2] = 0x00000000,
905 [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
906 [AST2700_SCU_HPLL_PARAM] = 0x0000009f,
907 [AST2700_SCU_HPLL_EXT_PARAM] = 0x8000004f,
908 [AST2700_SCU_DPLL_PARAM] = 0x0080009f,
909 [AST2700_SCU_DPLL_EXT_PARAM] = 0x8000004f,
910 [AST2700_SCU_MPLL_PARAM] = 0x00000040,
911 [AST2700_SCU_MPLL_EXT_PARAM] = 0x80000000,
912 [AST2700_SCU_D1CLK_PARAM] = 0x00050002,
913 [AST2700_SCU_D2CLK_PARAM] = 0x00050002,
914 [AST2700_SCU_CRT1CLK_PARAM] = 0x00050002,
915 [AST2700_SCU_CRT2CLK_PARAM] = 0x00050002,
916 [AST2700_SCU_MPHYCLK_PARAM] = 0x0000004c,
917 [AST2700_SCU_FREQ_CNTR] = 0x000375eb,
918 [AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
919 [AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
920 [AST2700_SCU_VGA_SCRATCH_0] = 0x00000040,
921 };
922
923 static void aspeed_ast2700_scu_reset_hold(Object *obj, ResetType type)
924 {
925 AspeedSCUState *s = ASPEED_SCU(obj);
926 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
927
928 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
929 s->regs[AST2700_SILICON_REV] = s->silicon_rev;
930 s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
931 }
932
933 static void aspeed_2700_scu_realize(DeviceState *dev, Error **errp)
934 {
935 aspeed_scu_realize(dev, errp);
936 }
937
938 static void aspeed_2700_scu_class_init(ObjectClass *klass, const void *data)
939 {
940 DeviceClass *dc = DEVICE_CLASS(klass);
941 ResettableClass *rc = RESETTABLE_CLASS(klass);
942 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
943
944 dc->desc = "ASPEED 2700 System Control Unit";
945 dc->realize = aspeed_2700_scu_realize;
946 rc->phases.hold = aspeed_ast2700_scu_reset_hold;
947 asc->resets = ast2700_a0_resets;
948 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
949 asc->get_apb = aspeed_2700_scu_get_apb_freq;
950 asc->apb_divider = 4;
951 asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
952 asc->clkin_25Mhz = true;
953 asc->ops = &aspeed_ast2700_scu_ops;
954 }
955
956 static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
957 unsigned size)
958 {
959 AspeedSCUState *s = ASPEED_SCU(opaque);
960 int reg = TO_REG(offset);
961 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
962 qemu_log_mask(LOG_GUEST_ERROR,
963 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
964 __func__, offset);
965 return 0;
966 }
967
968 switch (reg) {
969 case AST2700_SCUIO_RNG_DATA:
970 if (!(s->regs[AST2700_SCUIO_RNG_CTRL] & AST2700_SCUIO_RNG_CTRL_DIS)) {
971 s->regs[AST2700_SCUIO_RNG_DATA] = aspeed_scu_get_random();
972 }
973 break;
974 }
975
976 trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
977 return s->regs[reg];
978 }
979
980 static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
981 uint64_t data64, unsigned size)
982 {
983 AspeedSCUState *s = ASPEED_SCU(opaque);
984 int reg = TO_REG(offset);
985 /* Truncate here so bitwise operations below behave as expected */
986 uint32_t data = data64;
987 bool updated = false;
988
989 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
990 qemu_log_mask(LOG_GUEST_ERROR,
991 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
992 __func__, offset);
993 return;
994 }
995
996 trace_aspeed_ast2700_scuio_write(offset, size, data);
997
998 switch (reg) {
999 case AST2700_SCUIO_RNG_CTRL:
1000 data &= AST2700_SCUIO_RNG_CTRL_MASK;
1001 if (data & AST2700_SCUIO_RNG_CTRL_DIS) {
1002 data &= ~AST2700_SCUIO_RNG_CTRL_VLD;
1003 s->regs[AST2700_SCUIO_RNG_DATA] = 0;
1004 } else {
1005 s->regs[AST2700_SCUIO_RNG_DATA] = aspeed_scu_get_random();
1006 data |= AST2700_SCUIO_RNG_CTRL_VLD;
1007 }
1008 s->regs[reg] = data;
1009 updated = true;
1010 break;
1011 case AST2700_SCUIO_CLK_STOP_CTL_1:
1012 case AST2700_SCUIO_CLK_STOP_CTL_2:
1013 s->regs[reg] |= data;
1014 updated = true;
1015 break;
1016 case AST2700_SCUIO_CLK_STOP_CLR_1:
1017 case AST2700_SCUIO_CLK_STOP_CLR_2:
1018 s->regs[reg - 1] ^= data;
1019 updated = true;
1020 break;
1021 case AST2700_SCUIO_FREQ_CNT_CTL:
1022 s->regs[reg] = deposit32(s->regs[reg], 6, 1, !!(data & BIT(1)));
1023 updated = true;
1024 break;
1025 default:
1026 qemu_log_mask(LOG_GUEST_ERROR,
1027 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
1028 __func__, offset);
1029 break;
1030 }
1031
1032 if (!updated) {
1033 s->regs[reg] = data;
1034 }
1035 }
1036
1037 static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
1038 .read = aspeed_ast2700_scuio_read,
1039 .write = aspeed_ast2700_scuio_write,
1040 .endianness = DEVICE_LITTLE_ENDIAN,
1041 .impl.min_access_size = 4,
1042 .impl.max_access_size = 4,
1043 .valid.min_access_size = 1,
1044 .valid.max_access_size = 8,
1045 .valid.unaligned = false,
1046 };
1047
1048 static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
1049 [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
1050 [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
1051 [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
1052 [AST2700_HW_STRAP1_SEC2] = 0x00000000,
1053 [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
1054 [AST2700_SCUIO_CLK_STOP_CTL_1] = 0xffff8400,
1055 [AST2700_SCUIO_CLK_STOP_CTL_2] = 0x00005f30,
1056 [AST2700_SCUIO_CLK_SEL_1] = 0x86900000,
1057 [AST2700_SCUIO_CLK_SEL_2] = 0x00400000,
1058 [AST2700_SCUIO_HPLL_PARAM] = 0x10000027,
1059 [AST2700_SCUIO_HPLL_EXT_PARAM] = 0x80000014,
1060 [AST2700_SCUIO_APLL_PARAM] = 0x1000001f,
1061 [AST2700_SCUIO_APLL_EXT_PARAM] = 0x8000000f,
1062 [AST2700_SCUIO_DPLL_PARAM] = 0x106e42ce,
1063 [AST2700_SCUIO_DPLL_EXT_PARAM] = 0x80000167,
1064 [AST2700_SCUIO_DPLL_PARAM_READ] = 0x106e42ce,
1065 [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
1066 [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
1067 [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
1068 [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
1069 [AST2700_SCUIO_FREQ_CNT_CTL] = 0x00000080,
1070 };
1071
1072 static void aspeed_ast2700_scuio_reset_hold(Object *obj, ResetType type)
1073 {
1074 AspeedSCUState *s = ASPEED_SCU(obj);
1075 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
1076
1077 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1078 s->regs[AST2700_SILICON_REV] = s->silicon_rev;
1079 s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
1080 }
1081
1082 static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)
1083 {
1084 DeviceClass *dc = DEVICE_CLASS(klass);
1085 ResettableClass *rc = RESETTABLE_CLASS(klass);
1086 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1087
1088 dc->desc = "ASPEED 2700 System Control Unit I/O";
1089 rc->phases.hold = aspeed_ast2700_scuio_reset_hold;
1090 asc->resets = ast2700_a0_resets_io;
1091 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1092 asc->get_apb = aspeed_2700_scuio_get_apb_freq;
1093 asc->apb_divider = 2;
1094 asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
1095 asc->clkin_25Mhz = true;
1096 asc->ops = &aspeed_ast2700_scuio_ops;
1097 }
1098
1099 static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
1100 [AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
1101 [AST2600_SYS_RST_CTRL2] = 0x09FFFFFC,
1102 [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
1103 [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
1104 [AST2600_DEBUG_CTRL2] = 0x00000000,
1105 [AST2600_HPLL_PARAM] = 0x10004077,
1106 [AST2600_HPLL_EXT] = 0x00000031,
1107 [AST2600_CLK_SEL4] = 0x43F90900,
1108 [AST2600_CLK_SEL5] = 0x40000000,
1109 [AST2600_CHIP_ID0] = 0xDEADBEEF,
1110 [AST2600_CHIP_ID1] = 0x0BADCAFE,
1111 };
1112
1113 static void aspeed_ast1030_scu_reset_hold(Object *obj, ResetType type)
1114 {
1115 AspeedSCUState *s = ASPEED_SCU(obj);
1116 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(obj);
1117
1118 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1119
1120 s->regs[AST2600_SILICON_REV] = s->silicon_rev;
1121 s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
1122 s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
1123 s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
1124 s->regs[PROT_KEY] = s->hw_prot_key;
1125 }
1126
1127 static void aspeed_1030_scu_class_init(ObjectClass *klass, const void *data)
1128 {
1129 DeviceClass *dc = DEVICE_CLASS(klass);
1130 ResettableClass *rc = RESETTABLE_CLASS(klass);
1131 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1132
1133 dc->desc = "ASPEED 1030 System Control Unit";
1134 rc->phases.hold = aspeed_ast1030_scu_reset_hold;
1135 asc->resets = ast1030_a1_resets;
1136 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1137 asc->get_apb = aspeed_1030_scu_get_apb_freq;
1138 asc->apb_divider = 2;
1139 asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
1140 asc->clkin_25Mhz = true;
1141 asc->ops = &aspeed_ast2600_scu_ops;
1142 }
1143
1144 static const TypeInfo aspeed_scu_types[] = {
1145 {
1146 .name = TYPE_ASPEED_SCU,
1147 .parent = TYPE_SYS_BUS_DEVICE,
1148 .instance_size = sizeof(AspeedSCUState),
1149 .class_init = aspeed_scu_class_init,
1150 .class_size = sizeof(AspeedSCUClass),
1151 .abstract = true,
1152 },
1153 {
1154 .name = TYPE_ASPEED_1030_SCU,
1155 .parent = TYPE_ASPEED_SCU,
1156 .instance_size = sizeof(AspeedSCUState),
1157 .class_init = aspeed_1030_scu_class_init,
1158 },
1159 {
1160 .name = TYPE_ASPEED_2400_SCU,
1161 .parent = TYPE_ASPEED_SCU,
1162 .instance_size = sizeof(AspeedSCUState),
1163 .class_init = aspeed_2400_scu_class_init,
1164 },
1165 {
1166 .name = TYPE_ASPEED_2500_SCU,
1167 .parent = TYPE_ASPEED_SCU,
1168 .instance_size = sizeof(AspeedSCUState),
1169 .class_init = aspeed_2500_scu_class_init,
1170 },
1171 {
1172 .name = TYPE_ASPEED_2600_SCU,
1173 .parent = TYPE_ASPEED_SCU,
1174 .instance_size = sizeof(AspeedSCUState),
1175 .class_init = aspeed_2600_scu_class_init,
1176 },
1177 {
1178 .name = TYPE_ASPEED_2700_SCU,
1179 .parent = TYPE_ASPEED_SCU,
1180 .instance_size = sizeof(Aspeed2700SCUState),
1181 .class_init = aspeed_2700_scu_class_init,
1182 },
1183 {
1184 .name = TYPE_ASPEED_2700_SCUIO,
1185 .parent = TYPE_ASPEED_SCU,
1186 .instance_size = sizeof(AspeedSCUState),
1187 .class_init = aspeed_2700_scuio_class_init,
1188 }
1189 };
1190
1191 DEFINE_TYPES(aspeed_scu_types)