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/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_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)
134
135 #define AST2600_CLK TO_REG(0x40)
136
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)
144
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)
160
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)
178
179 #define SCU_IO_REGION_SIZE 0x1000
180
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
211 };
212
213 /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
214 /* AST2500 revision A1 */
215
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
248 };
249
aspeed_scu_get_random(void)250 static uint32_t aspeed_scu_get_random(void)
251 {
252 uint32_t num;
253 qemu_guest_getrandom_nofail(&num, sizeof(num));
254 return num;
255 }
256
aspeed_scu_get_apb_freq(AspeedSCUState * s)257 uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
258 {
259 return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
260 }
261
aspeed_2400_scu_get_apb_freq(AspeedSCUState * s)262 static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState *s)
263 {
264 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
265 uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
266
267 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
268 / asc->apb_divider;
269 }
270
aspeed_2600_scu_get_apb_freq(AspeedSCUState * s)271 static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
272 {
273 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
274 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
275
276 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
277 / asc->apb_divider;
278 }
279
aspeed_1030_scu_get_apb_freq(AspeedSCUState * s)280 static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
281 {
282 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
283 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
284
285 return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
286 / asc->apb_divider;
287 }
288
aspeed_2700_scu_get_apb_freq(AspeedSCUState * s)289 static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
290 {
291 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
292 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
293
294 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
295 / asc->apb_divider;
296 }
297
aspeed_2700_scuio_get_apb_freq(AspeedSCUState * s)298 static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
299 {
300 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
301 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
302
303 return hpll /
304 (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
305 / asc->apb_divider;
306 }
307
aspeed_scu_read(void * opaque,hwaddr offset,unsigned size)308 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
309 {
310 AspeedSCUState *s = ASPEED_SCU(opaque);
311 int reg = TO_REG(offset);
312
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;
318 }
319
320 switch (reg) {
321 case RNG_DATA:
322 /*
323 * On hardware, RNG_DATA works regardless of
324 * the state of the enable bit in RNG_CTRL
325 */
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;
333 }
334
335 trace_aspeed_scu_read(offset, size, s->regs[reg]);
336 return s->regs[reg];
337 }
338
aspeed_ast2400_scu_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)339 static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
340 uint64_t data, unsigned size)
341 {
342 AspeedSCUState *s = ASPEED_SCU(opaque);
343 int reg = TO_REG(offset);
344
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;
350 }
351
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__);
355 }
356
357 trace_aspeed_scu_write(offset, size, data);
358
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;
373 }
374
375 s->regs[reg] = data;
376 }
377
aspeed_ast2500_scu_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)378 static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
379 uint64_t data, unsigned size)
380 {
381 AspeedSCUState *s = ASPEED_SCU(opaque);
382 int reg = TO_REG(offset);
383
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;
389 }
390
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;
395 }
396
397 trace_aspeed_scu_write(offset, size, data);
398
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;
420 }
421
422 s->regs[reg] = data;
423 }
424
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,
432 },
433 };
434
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,
442 };
443
aspeed_scu_get_clkin(AspeedSCUState * s)444 static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
445 {
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;
453 }
454 }
455
456 /*
457 * Strapped frequencies for the AST2400 in MHz. They depend on the
458 * clkin frequency.
459 */
460 static const uint32_t hpll_ast2400_freqs[][4] = {
461 { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
462 { 400, 375, 350, 425 }, /* 25MHz */
463 };
464
aspeed_2400_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)465 static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
466 {
467 uint8_t freq_select;
468 bool clk_25m_in;
469 uint32_t clkin = aspeed_scu_get_clkin(s);
470
471 if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
472 return 0;
473 }
474
475 if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
476 uint32_t multiplier = 1;
477
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;
482
483 multiplier = (2 - od) * ((n + 2) / (d + 1));
484 }
485
486 return clkin * multiplier;
487 }
488
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);
492
493 return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
494 }
495
aspeed_2500_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)496 static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
497 {
498 uint32_t multiplier = 1;
499 uint32_t clkin = aspeed_scu_get_clkin(s);
500
501 if (hpll_reg & SCU_H_PLL_OFF) {
502 return 0;
503 }
504
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;
509
510 multiplier = ((m + 1) / (n + 1)) / (p + 1);
511 }
512
513 return clkin * multiplier;
514 }
515
aspeed_2600_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)516 static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
517 {
518 uint32_t multiplier = 1;
519 uint32_t clkin = aspeed_scu_get_clkin(s);
520
521 if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
522 return 0;
523 }
524
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;
529
530 multiplier = ((m + 1) / (n + 1)) / (p + 1);
531 }
532
533 return clkin * multiplier;
534 }
535
aspeed_scu_reset(DeviceState * dev)536 static void aspeed_scu_reset(DeviceState *dev)
537 {
538 AspeedSCUState *s = ASPEED_SCU(dev);
539 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
540
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;
546 }
547
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,
562 };
563
is_supported_silicon_rev(uint32_t silicon_rev)564 bool is_supported_silicon_rev(uint32_t silicon_rev)
565 {
566 int i;
567
568 for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
569 if (silicon_rev == aspeed_silicon_revs[i]) {
570 return true;
571 }
572 }
573
574 return false;
575 }
576
aspeed_scu_realize(DeviceState * dev,Error ** errp)577 static void aspeed_scu_realize(DeviceState *dev, Error **errp)
578 {
579 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
580 AspeedSCUState *s = ASPEED_SCU(dev);
581 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
582
583 if (!is_supported_silicon_rev(s->silicon_rev)) {
584 error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
585 s->silicon_rev);
586 return;
587 }
588
589 memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
590 TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
591
592 sysbus_init_mmio(sbd, &s->iomem);
593 }
594
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()
602 }
603 };
604
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(),
611 };
612
aspeed_scu_class_init(ObjectClass * klass,void * data)613 static void aspeed_scu_class_init(ObjectClass *klass, void *data)
614 {
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);
621 }
622
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,
630 };
631
aspeed_2400_scu_class_init(ObjectClass * klass,void * data)632 static void aspeed_2400_scu_class_init(ObjectClass *klass, 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 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,
652 };
653
aspeed_2500_scu_class_init(ObjectClass * klass,void * data)654 static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
655 {
656 DeviceClass *dc = DEVICE_CLASS(klass);
657 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
658
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;
667 }
668
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,
674 };
675
aspeed_ast2600_scu_read(void * opaque,hwaddr offset,unsigned size)676 static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
677 unsigned size)
678 {
679 AspeedSCUState *s = ASPEED_SCU(opaque);
680 int reg = TO_REG(offset);
681
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;
687 }
688
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:
696 /*
697 * On hardware, RNG_DATA works regardless of the state of the
698 * enable bit in RNG_CTRL
699 *
700 * TODO: Check this is true for ast2600
701 */
702 s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
703 break;
704 }
705
706 trace_aspeed_scu_read(offset, size, s->regs[reg]);
707 return s->regs[reg];
708 }
709
aspeed_ast2600_scu_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)710 static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
711 uint64_t data64, unsigned size)
712 {
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;
717
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;
723 }
724
725 if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
726 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
727 }
728
729 trace_aspeed_scu_write(offset, size, data);
730
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;
739 }
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:
754 /*
755 * W1C (Write 1 to clear) registers are offset by one address from
756 * the data register
757 */
758 s->regs[reg - 1] &= ~data;
759 return;
760
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;
771 }
772
773 s->regs[reg] = data;
774 }
775
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,
783 };
784
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,
807 };
808
aspeed_ast2600_scu_reset(DeviceState * dev)809 static void aspeed_ast2600_scu_reset(DeviceState *dev)
810 {
811 AspeedSCUState *s = ASPEED_SCU(dev);
812 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
813
814 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
815
816 /*
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.
820 */
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;
826 }
827
aspeed_2600_scu_class_init(ObjectClass * klass,void * data)828 static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
829 {
830 DeviceClass *dc = DEVICE_CLASS(klass);
831 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
832
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;
842 }
843
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,
849 };
850
aspeed_ast2700_scu_read(void * opaque,hwaddr offset,unsigned size)851 static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
852 unsigned size)
853 {
854 AspeedSCUState *s = ASPEED_SCU(opaque);
855 int reg = TO_REG(offset);
856
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;
862 }
863
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);
869 }
870
871 trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
872 return s->regs[reg];
873 }
874
aspeed_ast2700_scu_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)875 static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
876 uint64_t data64, unsigned size)
877 {
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;
882
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;
888 }
889
890 trace_aspeed_ast2700_scu_write(offset, size, data);
891
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;
898 }
899
900 s->regs[reg] = data;
901 }
902
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,
910 };
911
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,
934 };
935
aspeed_ast2700_scu_reset(DeviceState * dev)936 static void aspeed_ast2700_scu_reset(DeviceState *dev)
937 {
938 AspeedSCUState *s = ASPEED_SCU(dev);
939 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
940
941 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
942 }
943
aspeed_2700_scu_class_init(ObjectClass * klass,void * data)944 static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
945 {
946 DeviceClass *dc = DEVICE_CLASS(klass);
947 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
948
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;
958 }
959
aspeed_ast2700_scuio_read(void * opaque,hwaddr offset,unsigned size)960 static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
961 unsigned size)
962 {
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;
970 }
971
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);
977 }
978
979 trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
980 return s->regs[reg];
981 }
982
aspeed_ast2700_scuio_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)983 static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
984 uint64_t data64, unsigned size)
985 {
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;
991
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;
997 }
998
999 trace_aspeed_ast2700_scuio_write(offset, size, data);
1000
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;
1017 }
1018
1019 if (!updated) {
1020 s->regs[reg] = data;
1021 }
1022 }
1023
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,
1031 };
1032
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,
1056 };
1057
aspeed_2700_scuio_class_init(ObjectClass * klass,void * data)1058 static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
1059 {
1060 DeviceClass *dc = DEVICE_CLASS(klass);
1061 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1062
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;
1072 }
1073
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,
1079 };
1080
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,
1086 };
1087
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,
1100 };
1101
aspeed_ast1030_scu_reset(DeviceState * dev)1102 static void aspeed_ast1030_scu_reset(DeviceState *dev)
1103 {
1104 AspeedSCUState *s = ASPEED_SCU(dev);
1105 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
1106
1107 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1108
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;
1114 }
1115
aspeed_1030_scu_class_init(ObjectClass * klass,void * data)1116 static void aspeed_1030_scu_class_init(ObjectClass *klass, void *data)
1117 {
1118 DeviceClass *dc = DEVICE_CLASS(klass);
1119 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1120
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;
1130 }
1131
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,
1137 };
1138
aspeed_scu_register_types(void)1139 static void aspeed_scu_register_types(void)
1140 {
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);
1148 }
1149
1150 type_init(aspeed_scu_register_types);
1151