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 #include "target/arm/arm-powerctl.h"
24
25 #define TO_REG(offset) ((offset) >> 2)
26
27 #define PROT_KEY TO_REG(0x00)
28 #define SYS_RST_CTRL TO_REG(0x04)
29 #define CLK_SEL TO_REG(0x08)
30 #define CLK_STOP_CTRL TO_REG(0x0C)
31 #define FREQ_CNTR_CTRL TO_REG(0x10)
32 #define FREQ_CNTR_EVAL TO_REG(0x14)
33 #define IRQ_CTRL TO_REG(0x18)
34 #define D2PLL_PARAM TO_REG(0x1C)
35 #define MPLL_PARAM TO_REG(0x20)
36 #define HPLL_PARAM TO_REG(0x24)
37 #define FREQ_CNTR_RANGE TO_REG(0x28)
38 #define MISC_CTRL1 TO_REG(0x2C)
39 #define PCI_CTRL1 TO_REG(0x30)
40 #define PCI_CTRL2 TO_REG(0x34)
41 #define PCI_CTRL3 TO_REG(0x38)
42 #define SYS_RST_STATUS TO_REG(0x3C)
43 #define SOC_SCRATCH1 TO_REG(0x40)
44 #define SOC_SCRATCH2 TO_REG(0x44)
45 #define MAC_CLK_DELAY TO_REG(0x48)
46 #define MISC_CTRL2 TO_REG(0x4C)
47 #define VGA_SCRATCH1 TO_REG(0x50)
48 #define VGA_SCRATCH2 TO_REG(0x54)
49 #define VGA_SCRATCH3 TO_REG(0x58)
50 #define VGA_SCRATCH4 TO_REG(0x5C)
51 #define VGA_SCRATCH5 TO_REG(0x60)
52 #define VGA_SCRATCH6 TO_REG(0x64)
53 #define VGA_SCRATCH7 TO_REG(0x68)
54 #define VGA_SCRATCH8 TO_REG(0x6C)
55 #define HW_STRAP1 TO_REG(0x70)
56 #define RNG_CTRL TO_REG(0x74)
57 #define RNG_DATA TO_REG(0x78)
58 #define SILICON_REV TO_REG(0x7C)
59 #define PINMUX_CTRL1 TO_REG(0x80)
60 #define PINMUX_CTRL2 TO_REG(0x84)
61 #define PINMUX_CTRL3 TO_REG(0x88)
62 #define PINMUX_CTRL4 TO_REG(0x8C)
63 #define PINMUX_CTRL5 TO_REG(0x90)
64 #define PINMUX_CTRL6 TO_REG(0x94)
65 #define WDT_RST_CTRL TO_REG(0x9C)
66 #define PINMUX_CTRL7 TO_REG(0xA0)
67 #define PINMUX_CTRL8 TO_REG(0xA4)
68 #define PINMUX_CTRL9 TO_REG(0xA8)
69 #define WAKEUP_EN TO_REG(0xC0)
70 #define WAKEUP_CTRL TO_REG(0xC4)
71 #define HW_STRAP2 TO_REG(0xD0)
72 #define FREE_CNTR4 TO_REG(0xE0)
73 #define FREE_CNTR4_EXT TO_REG(0xE4)
74 #define CPU2_CTRL TO_REG(0x100)
75 #define CPU2_BASE_SEG1 TO_REG(0x104)
76 #define CPU2_BASE_SEG2 TO_REG(0x108)
77 #define CPU2_BASE_SEG3 TO_REG(0x10C)
78 #define CPU2_BASE_SEG4 TO_REG(0x110)
79 #define CPU2_BASE_SEG5 TO_REG(0x114)
80 #define CPU2_CACHE_CTRL TO_REG(0x118)
81 #define CHIP_ID0 TO_REG(0x150)
82 #define CHIP_ID1 TO_REG(0x154)
83 #define UART_HPLL_CLK TO_REG(0x160)
84 #define PCIE_CTRL TO_REG(0x180)
85 #define BMC_MMIO_CTRL TO_REG(0x184)
86 #define RELOC_DECODE_BASE1 TO_REG(0x188)
87 #define RELOC_DECODE_BASE2 TO_REG(0x18C)
88 #define MAILBOX_DECODE_BASE TO_REG(0x190)
89 #define SRAM_DECODE_BASE1 TO_REG(0x194)
90 #define SRAM_DECODE_BASE2 TO_REG(0x198)
91 #define BMC_REV TO_REG(0x19C)
92 #define BMC_DEV_ID TO_REG(0x1A4)
93
94 #define AST2600_PROT_KEY TO_REG(0x00)
95 #define AST2600_PROT_KEY2 TO_REG(0x10)
96 #define AST2600_SILICON_REV TO_REG(0x04)
97 #define AST2600_SILICON_REV2 TO_REG(0x14)
98 #define AST2600_SYS_RST_CTRL TO_REG(0x40)
99 #define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44)
100 #define AST2600_SYS_RST_CTRL2 TO_REG(0x50)
101 #define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
102 #define AST2600_CLK_STOP_CTRL TO_REG(0x80)
103 #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
104 #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
105 #define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
106 #define AST2600_DEBUG_CTRL TO_REG(0xC8)
107 #define AST2600_DEBUG_CTRL2 TO_REG(0xD8)
108 #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
109 #define AST2600_HPLL_PARAM TO_REG(0x200)
110 #define AST2600_HPLL_EXT TO_REG(0x204)
111 #define AST2600_APLL_PARAM TO_REG(0x210)
112 #define AST2600_APLL_EXT TO_REG(0x214)
113 #define AST2600_MPLL_PARAM TO_REG(0x220)
114 #define AST2600_MPLL_EXT TO_REG(0x224)
115 #define AST2600_EPLL_PARAM TO_REG(0x240)
116 #define AST2600_EPLL_EXT TO_REG(0x244)
117 #define AST2600_DPLL_PARAM TO_REG(0x260)
118 #define AST2600_DPLL_EXT TO_REG(0x264)
119 #define AST2600_CLK_SEL TO_REG(0x300)
120 #define AST2600_CLK_SEL2 TO_REG(0x304)
121 #define AST2600_CLK_SEL3 TO_REG(0x308)
122 #define AST2600_CLK_SEL4 TO_REG(0x310)
123 #define AST2600_CLK_SEL5 TO_REG(0x314)
124 #define AST2600_UARTCLK TO_REG(0x338)
125 #define AST2600_HUARTCLK TO_REG(0x33C)
126 #define AST2600_HW_STRAP1 TO_REG(0x500)
127 #define AST2600_HW_STRAP1_CLR TO_REG(0x504)
128 #define AST2600_HW_STRAP1_PROT TO_REG(0x508)
129 #define AST2600_HW_STRAP2 TO_REG(0x510)
130 #define AST2600_HW_STRAP2_CLR TO_REG(0x514)
131 #define AST2600_HW_STRAP2_PROT TO_REG(0x518)
132 #define AST2600_RNG_CTRL TO_REG(0x524)
133 #define AST2600_RNG_DATA TO_REG(0x540)
134 #define AST2600_CHIP_ID0 TO_REG(0x5B0)
135 #define AST2600_CHIP_ID1 TO_REG(0x5B4)
136
137 #define AST2600_CLK TO_REG(0x40)
138
139 #define AST2700_SILICON_REV TO_REG(0x00)
140 #define AST2700_HW_STRAP1 TO_REG(0x10)
141 #define AST2700_HW_STRAP1_CLR TO_REG(0x14)
142 #define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
143 #define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
144 #define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
145 #define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
146
147 /* SSP TSP */
148 #define AST2700_SCU_SSP_CTRL_0 TO_REG(0x120)
149 #define AST2700_SCU_SSP_CTRL_1 TO_REG(0x124)
150 #define AST2700_SCU_SSP_CTRL_2 TO_REG(0x128)
151 #define AST2700_SCU_SSP_REMAP_ADDR_1 TO_REG(0x148)
152 #define AST2700_SCU_SSP_REMAP_SIZE_1 TO_REG(0x14c)
153 #define AST2700_SCU_SSP_REMAP_ADDR_2 TO_REG(0x150)
154 #define AST2700_SCU_SSP_REMAP_SIZE_2 TO_REG(0x154)
155 #define AST2700_SCU_TSP_CTRL_0 TO_REG(0x160)
156 #define AST2700_SCU_TSP_CTRL_1 TO_REG(0x168)
157 #define AST2700_SCU_TSP_REMAP_SIZE_2 TO_REG(0x194)
158 #define AST2700_SSP_TSP_ENABLE BIT(0)
159 #define AST2700_SSP_TSP_RST BIT(1)
160 #define AST2700_SSP_TSP_RST_RB BIT(8)
161 #define AST2700_SSP_TSP_RST_HOLD_RB BIT(9)
162 #define AST2700_SSP_TSP_RST_SRC_RB BIT(10)
163 #define AST2700_SCU_SYS_RST_CTRL_1 TO_REG(0x200)
164 #define AST2700_SCU_SYS_RST_CLR_1 TO_REG(0x204)
165 #define AST2700_SCU_SYS_RST_SSP BIT(30)
166 #define AST2700_SCU_SYS_RST_CTRL_2 TO_REG(0x220)
167 #define AST2700_SCU_SYS_RST_CLR_2 TO_REG(0x224)
168 #define AST2700_SCU_SYS_RST_TSP BIT(9)
169
170 #define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
171 #define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
172 #define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
173 #define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
174 #define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
175 #define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
176 #define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
177 #define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
178 #define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
179 #define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
180 #define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
181 #define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
182 #define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
183 #define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
184 #define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
185 #define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900)
186
187 #define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
188 #define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
189 #define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
190 #define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
191 #define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
192 #define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
193 #define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
194 #define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
195 #define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
196 #define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
197 #define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
198 #define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
199 #define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
200 #define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
201 #define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
202 #define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
203 #define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
204 #define AST2700_SCUIO_FREQ_CNT_CTL TO_REG(0x3A0)
205
206 #define SCU_IO_REGION_SIZE 0x1000
207
208 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
209 [SYS_RST_CTRL] = 0xFFCFFEDCU,
210 [CLK_SEL] = 0xF3F40000U,
211 [CLK_STOP_CTRL] = 0x19FC3E8BU,
212 [D2PLL_PARAM] = 0x00026108U,
213 [MPLL_PARAM] = 0x00030291U,
214 [HPLL_PARAM] = 0x00000291U,
215 [MISC_CTRL1] = 0x00000010U,
216 [PCI_CTRL1] = 0x20001A03U,
217 [PCI_CTRL2] = 0x20001A03U,
218 [PCI_CTRL3] = 0x04000030U,
219 [SYS_RST_STATUS] = 0x00000001U,
220 [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
221 [MISC_CTRL2] = 0x00000023U,
222 [RNG_CTRL] = 0x0000000EU,
223 [PINMUX_CTRL2] = 0x0000F000U,
224 [PINMUX_CTRL3] = 0x01000000U,
225 [PINMUX_CTRL4] = 0x000000FFU,
226 [PINMUX_CTRL5] = 0x0000A000U,
227 [WDT_RST_CTRL] = 0x003FFFF3U,
228 [PINMUX_CTRL8] = 0xFFFF0000U,
229 [PINMUX_CTRL9] = 0x000FFFFFU,
230 [FREE_CNTR4] = 0x000000FFU,
231 [FREE_CNTR4_EXT] = 0x000000FFU,
232 [CPU2_BASE_SEG1] = 0x80000000U,
233 [CPU2_BASE_SEG4] = 0x1E600000U,
234 [CPU2_BASE_SEG5] = 0xC0000000U,
235 [UART_HPLL_CLK] = 0x00001903U,
236 [PCIE_CTRL] = 0x0000007BU,
237 [BMC_DEV_ID] = 0x00002402U
238 };
239
240 /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
241 /* AST2500 revision A1 */
242
243 static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
244 [SYS_RST_CTRL] = 0xFFCFFEDCU,
245 [CLK_SEL] = 0xF3F40000U,
246 [CLK_STOP_CTRL] = 0x19FC3E8BU,
247 [D2PLL_PARAM] = 0x00026108U,
248 [MPLL_PARAM] = 0x00030291U,
249 [HPLL_PARAM] = 0x93000400U,
250 [MISC_CTRL1] = 0x00000010U,
251 [PCI_CTRL1] = 0x20001A03U,
252 [PCI_CTRL2] = 0x20001A03U,
253 [PCI_CTRL3] = 0x04000030U,
254 [SYS_RST_STATUS] = 0x00000001U,
255 [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
256 [MISC_CTRL2] = 0x00000023U,
257 [RNG_CTRL] = 0x0000000EU,
258 [PINMUX_CTRL2] = 0x0000F000U,
259 [PINMUX_CTRL3] = 0x03000000U,
260 [PINMUX_CTRL4] = 0x00000000U,
261 [PINMUX_CTRL5] = 0x0000A000U,
262 [WDT_RST_CTRL] = 0x023FFFF3U,
263 [PINMUX_CTRL8] = 0xFFFF0000U,
264 [PINMUX_CTRL9] = 0x000FFFFFU,
265 [FREE_CNTR4] = 0x000000FFU,
266 [FREE_CNTR4_EXT] = 0x000000FFU,
267 [CPU2_BASE_SEG1] = 0x80000000U,
268 [CPU2_BASE_SEG4] = 0x1E600000U,
269 [CPU2_BASE_SEG5] = 0xC0000000U,
270 [CHIP_ID0] = 0x1234ABCDU,
271 [CHIP_ID1] = 0x88884444U,
272 [UART_HPLL_CLK] = 0x00001903U,
273 [PCIE_CTRL] = 0x0000007BU,
274 [BMC_DEV_ID] = 0x00002402U
275 };
276
aspeed_scu_get_random(void)277 static uint32_t aspeed_scu_get_random(void)
278 {
279 uint32_t num;
280 qemu_guest_getrandom_nofail(&num, sizeof(num));
281 return num;
282 }
283
aspeed_scu_get_apb_freq(AspeedSCUState * s)284 uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
285 {
286 return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
287 }
288
aspeed_2400_scu_get_apb_freq(AspeedSCUState * s)289 static uint32_t aspeed_2400_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[HPLL_PARAM]);
293
294 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
295 / asc->apb_divider;
296 }
297
aspeed_2600_scu_get_apb_freq(AspeedSCUState * s)298 static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
299 {
300 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
301 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
302
303 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
304 / asc->apb_divider;
305 }
306
aspeed_1030_scu_get_apb_freq(AspeedSCUState * s)307 static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
308 {
309 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
310 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
311
312 return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
313 / asc->apb_divider;
314 }
315
aspeed_2700_scu_get_apb_freq(AspeedSCUState * s)316 static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
317 {
318 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
319 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
320
321 return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
322 / asc->apb_divider;
323 }
324
aspeed_2700_scuio_get_apb_freq(AspeedSCUState * s)325 static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
326 {
327 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
328 uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
329
330 return hpll /
331 (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
332 / asc->apb_divider;
333 }
334
aspeed_scu_read(void * opaque,hwaddr offset,unsigned size)335 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
336 {
337 AspeedSCUState *s = ASPEED_SCU(opaque);
338 int reg = TO_REG(offset);
339
340 if (reg >= ASPEED_SCU_NR_REGS) {
341 qemu_log_mask(LOG_GUEST_ERROR,
342 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
343 __func__, offset);
344 return 0;
345 }
346
347 switch (reg) {
348 case RNG_DATA:
349 /*
350 * On hardware, RNG_DATA works regardless of
351 * the state of the enable bit in RNG_CTRL
352 */
353 s->regs[RNG_DATA] = aspeed_scu_get_random();
354 break;
355 case WAKEUP_EN:
356 qemu_log_mask(LOG_GUEST_ERROR,
357 "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
358 __func__, offset);
359 break;
360 }
361
362 trace_aspeed_scu_read(offset, size, s->regs[reg]);
363 return s->regs[reg];
364 }
365
aspeed_ast2400_scu_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)366 static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
367 uint64_t data, unsigned size)
368 {
369 AspeedSCUState *s = ASPEED_SCU(opaque);
370 int reg = TO_REG(offset);
371
372 if (reg >= ASPEED_SCU_NR_REGS) {
373 qemu_log_mask(LOG_GUEST_ERROR,
374 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
375 __func__, offset);
376 return;
377 }
378
379 if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
380 !s->regs[PROT_KEY]) {
381 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
382 }
383
384 trace_aspeed_scu_write(offset, size, data);
385
386 switch (reg) {
387 case PROT_KEY:
388 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
389 return;
390 case SILICON_REV:
391 case FREQ_CNTR_EVAL:
392 case VGA_SCRATCH1 ... VGA_SCRATCH8:
393 case RNG_DATA:
394 case FREE_CNTR4:
395 case FREE_CNTR4_EXT:
396 qemu_log_mask(LOG_GUEST_ERROR,
397 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
398 __func__, offset);
399 return;
400 }
401
402 s->regs[reg] = data;
403 }
404
aspeed_ast2500_scu_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)405 static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
406 uint64_t data, unsigned size)
407 {
408 AspeedSCUState *s = ASPEED_SCU(opaque);
409 int reg = TO_REG(offset);
410
411 if (reg >= ASPEED_SCU_NR_REGS) {
412 qemu_log_mask(LOG_GUEST_ERROR,
413 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
414 __func__, offset);
415 return;
416 }
417
418 if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
419 !s->regs[PROT_KEY]) {
420 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
421 return;
422 }
423
424 trace_aspeed_scu_write(offset, size, data);
425
426 switch (reg) {
427 case PROT_KEY:
428 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
429 return;
430 case HW_STRAP1:
431 s->regs[HW_STRAP1] |= data;
432 return;
433 case SILICON_REV:
434 s->regs[HW_STRAP1] &= ~data;
435 return;
436 case FREQ_CNTR_EVAL:
437 case VGA_SCRATCH1 ... VGA_SCRATCH8:
438 case RNG_DATA:
439 case FREE_CNTR4:
440 case FREE_CNTR4_EXT:
441 case CHIP_ID0:
442 case CHIP_ID1:
443 qemu_log_mask(LOG_GUEST_ERROR,
444 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
445 __func__, offset);
446 return;
447 }
448
449 s->regs[reg] = data;
450 }
451
452 static const MemoryRegionOps aspeed_ast2400_scu_ops = {
453 .read = aspeed_scu_read,
454 .write = aspeed_ast2400_scu_write,
455 .endianness = DEVICE_LITTLE_ENDIAN,
456 .impl = {
457 .min_access_size = 4,
458 .max_access_size = 4,
459 },
460 .valid = {
461 .min_access_size = 1,
462 .max_access_size = 4,
463 },
464 };
465
466 static const MemoryRegionOps aspeed_ast2500_scu_ops = {
467 .read = aspeed_scu_read,
468 .write = aspeed_ast2500_scu_write,
469 .endianness = DEVICE_LITTLE_ENDIAN,
470 .impl.min_access_size = 4,
471 .impl.max_access_size = 4,
472 .valid.min_access_size = 1,
473 .valid.max_access_size = 4,
474 .valid.unaligned = false,
475 };
476
aspeed_scu_get_clkin(AspeedSCUState * s)477 static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
478 {
479 if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN ||
480 ASPEED_SCU_GET_CLASS(s)->clkin_25Mhz) {
481 return 25000000;
482 } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
483 return 48000000;
484 } else {
485 return 24000000;
486 }
487 }
488
489 /*
490 * Strapped frequencies for the AST2400 in MHz. They depend on the
491 * clkin frequency.
492 */
493 static const uint32_t hpll_ast2400_freqs[][4] = {
494 { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
495 { 400, 375, 350, 425 }, /* 25MHz */
496 };
497
aspeed_2400_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)498 static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
499 {
500 uint8_t freq_select;
501 bool clk_25m_in;
502 uint32_t clkin = aspeed_scu_get_clkin(s);
503
504 if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
505 return 0;
506 }
507
508 if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
509 uint32_t multiplier = 1;
510
511 if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
512 uint32_t n = (hpll_reg >> 5) & 0x3f;
513 uint32_t od = (hpll_reg >> 4) & 0x1;
514 uint32_t d = hpll_reg & 0xf;
515
516 multiplier = (2 - od) * ((n + 2) / (d + 1));
517 }
518
519 return clkin * multiplier;
520 }
521
522 /* HW strapping */
523 clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
524 freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
525
526 return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
527 }
528
aspeed_2500_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)529 static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
530 {
531 uint32_t multiplier = 1;
532 uint32_t clkin = aspeed_scu_get_clkin(s);
533
534 if (hpll_reg & SCU_H_PLL_OFF) {
535 return 0;
536 }
537
538 if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
539 uint32_t p = (hpll_reg >> 13) & 0x3f;
540 uint32_t m = (hpll_reg >> 5) & 0xff;
541 uint32_t n = hpll_reg & 0x1f;
542
543 multiplier = ((m + 1) / (n + 1)) / (p + 1);
544 }
545
546 return clkin * multiplier;
547 }
548
aspeed_2600_scu_calc_hpll(AspeedSCUState * s,uint32_t hpll_reg)549 static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
550 {
551 uint32_t multiplier = 1;
552 uint32_t clkin = aspeed_scu_get_clkin(s);
553
554 if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
555 return 0;
556 }
557
558 if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) {
559 uint32_t p = (hpll_reg >> 19) & 0xf;
560 uint32_t n = (hpll_reg >> 13) & 0x3f;
561 uint32_t m = hpll_reg & 0x1fff;
562
563 multiplier = ((m + 1) / (n + 1)) / (p + 1);
564 }
565
566 return clkin * multiplier;
567 }
568
aspeed_scu_reset(DeviceState * dev)569 static void aspeed_scu_reset(DeviceState *dev)
570 {
571 AspeedSCUState *s = ASPEED_SCU(dev);
572 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
573
574 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
575 s->regs[SILICON_REV] = s->silicon_rev;
576 s->regs[HW_STRAP1] = s->hw_strap1;
577 s->regs[HW_STRAP2] = s->hw_strap2;
578 s->regs[PROT_KEY] = s->hw_prot_key;
579 }
580
581 static uint32_t aspeed_silicon_revs[] = {
582 AST2400_A0_SILICON_REV,
583 AST2400_A1_SILICON_REV,
584 AST2500_A0_SILICON_REV,
585 AST2500_A1_SILICON_REV,
586 AST2600_A0_SILICON_REV,
587 AST2600_A1_SILICON_REV,
588 AST2600_A2_SILICON_REV,
589 AST2600_A3_SILICON_REV,
590 AST1030_A0_SILICON_REV,
591 AST1030_A1_SILICON_REV,
592 AST2700_A0_SILICON_REV,
593 AST2720_A0_SILICON_REV,
594 AST2750_A0_SILICON_REV,
595 AST2700_A1_SILICON_REV,
596 AST2750_A1_SILICON_REV,
597 };
598
is_supported_silicon_rev(uint32_t silicon_rev)599 bool is_supported_silicon_rev(uint32_t silicon_rev)
600 {
601 int i;
602
603 for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
604 if (silicon_rev == aspeed_silicon_revs[i]) {
605 return true;
606 }
607 }
608
609 return false;
610 }
611
aspeed_scu_realize(DeviceState * dev,Error ** errp)612 static void aspeed_scu_realize(DeviceState *dev, Error **errp)
613 {
614 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
615 AspeedSCUState *s = ASPEED_SCU(dev);
616 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
617
618 if (!is_supported_silicon_rev(s->silicon_rev)) {
619 error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
620 s->silicon_rev);
621 return;
622 }
623
624 memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
625 TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
626
627 sysbus_init_mmio(sbd, &s->iomem);
628 }
629
630 static const VMStateDescription vmstate_aspeed_scu = {
631 .name = "aspeed.scu",
632 .version_id = 3,
633 .minimum_version_id = 3,
634 .fields = (const VMStateField[]) {
635 VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
636 VMSTATE_END_OF_LIST()
637 }
638 };
639
640 static const Property aspeed_scu_properties[] = {
641 DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
642 DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
643 DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
644 DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
645 DEFINE_PROP_LINK("ssp-sdram-remap1", AspeedSCUState, ssp_sdram_remap1,
646 TYPE_MEMORY_REGION, MemoryRegion *),
647 DEFINE_PROP_LINK("ssp-sdram-remap2", AspeedSCUState, ssp_sdram_remap2,
648 TYPE_MEMORY_REGION, MemoryRegion *),
649 DEFINE_PROP_LINK("tsp-sdram-remap", AspeedSCUState, tsp_sdram_remap,
650 TYPE_MEMORY_REGION, MemoryRegion *),
651 };
652
aspeed_scu_class_init(ObjectClass * klass,const void * data)653 static void aspeed_scu_class_init(ObjectClass *klass, const void *data)
654 {
655 DeviceClass *dc = DEVICE_CLASS(klass);
656 dc->realize = aspeed_scu_realize;
657 device_class_set_legacy_reset(dc, aspeed_scu_reset);
658 dc->desc = "ASPEED System Control Unit";
659 dc->vmsd = &vmstate_aspeed_scu;
660 device_class_set_props(dc, aspeed_scu_properties);
661 }
662
663 static const TypeInfo aspeed_scu_info = {
664 .name = TYPE_ASPEED_SCU,
665 .parent = TYPE_SYS_BUS_DEVICE,
666 .instance_size = sizeof(AspeedSCUState),
667 .class_init = aspeed_scu_class_init,
668 .class_size = sizeof(AspeedSCUClass),
669 .abstract = true,
670 };
671
aspeed_2400_scu_class_init(ObjectClass * klass,const void * data)672 static void aspeed_2400_scu_class_init(ObjectClass *klass, const void *data)
673 {
674 DeviceClass *dc = DEVICE_CLASS(klass);
675 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
676
677 dc->desc = "ASPEED 2400 System Control Unit";
678 asc->resets = ast2400_a0_resets;
679 asc->calc_hpll = aspeed_2400_scu_calc_hpll;
680 asc->get_apb = aspeed_2400_scu_get_apb_freq;
681 asc->apb_divider = 2;
682 asc->nr_regs = ASPEED_SCU_NR_REGS;
683 asc->clkin_25Mhz = false;
684 asc->ops = &aspeed_ast2400_scu_ops;
685 }
686
687 static const TypeInfo aspeed_2400_scu_info = {
688 .name = TYPE_ASPEED_2400_SCU,
689 .parent = TYPE_ASPEED_SCU,
690 .instance_size = sizeof(AspeedSCUState),
691 .class_init = aspeed_2400_scu_class_init,
692 };
693
aspeed_2500_scu_class_init(ObjectClass * klass,const void * data)694 static void aspeed_2500_scu_class_init(ObjectClass *klass, const void *data)
695 {
696 DeviceClass *dc = DEVICE_CLASS(klass);
697 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
698
699 dc->desc = "ASPEED 2500 System Control Unit";
700 asc->resets = ast2500_a1_resets;
701 asc->calc_hpll = aspeed_2500_scu_calc_hpll;
702 asc->get_apb = aspeed_2400_scu_get_apb_freq;
703 asc->apb_divider = 4;
704 asc->nr_regs = ASPEED_SCU_NR_REGS;
705 asc->clkin_25Mhz = false;
706 asc->ops = &aspeed_ast2500_scu_ops;
707 }
708
709 static const TypeInfo aspeed_2500_scu_info = {
710 .name = TYPE_ASPEED_2500_SCU,
711 .parent = TYPE_ASPEED_SCU,
712 .instance_size = sizeof(AspeedSCUState),
713 .class_init = aspeed_2500_scu_class_init,
714 };
715
aspeed_ast2600_scu_read(void * opaque,hwaddr offset,unsigned size)716 static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
717 unsigned size)
718 {
719 AspeedSCUState *s = ASPEED_SCU(opaque);
720 int reg = TO_REG(offset);
721
722 if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
723 qemu_log_mask(LOG_GUEST_ERROR,
724 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
725 __func__, offset);
726 return 0;
727 }
728
729 switch (reg) {
730 case AST2600_HPLL_EXT:
731 case AST2600_EPLL_EXT:
732 case AST2600_MPLL_EXT:
733 /* PLLs are always "locked" */
734 return s->regs[reg] | BIT(31);
735 case AST2600_RNG_DATA:
736 /*
737 * On hardware, RNG_DATA works regardless of the state of the
738 * enable bit in RNG_CTRL
739 *
740 * TODO: Check this is true for ast2600
741 */
742 s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
743 break;
744 }
745
746 trace_aspeed_scu_read(offset, size, s->regs[reg]);
747 return s->regs[reg];
748 }
749
aspeed_ast2600_scu_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)750 static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
751 uint64_t data64, unsigned size)
752 {
753 AspeedSCUState *s = ASPEED_SCU(opaque);
754 int reg = TO_REG(offset);
755 /* Truncate here so bitwise operations below behave as expected */
756 uint32_t data = data64;
757 bool prot_data_state = data == ASPEED_SCU_PROT_KEY;
758 bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2];
759
760 if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
761 qemu_log_mask(LOG_GUEST_ERROR,
762 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
763 __func__, offset);
764 return;
765 }
766
767 if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) {
768 qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
769 return;
770 }
771
772 trace_aspeed_scu_write(offset, size, data);
773
774 switch (reg) {
775 case AST2600_PROT_KEY:
776 /*
777 * Writing a value to SCU000 will modify both protection
778 * registers to each protection register individually.
779 */
780 s->regs[AST2600_PROT_KEY] = prot_data_state;
781 s->regs[AST2600_PROT_KEY2] = prot_data_state;
782 return;
783 case AST2600_PROT_KEY2:
784 s->regs[AST2600_PROT_KEY2] = prot_data_state;
785 return;
786 case AST2600_HW_STRAP1:
787 case AST2600_HW_STRAP2:
788 if (s->regs[reg + 2]) {
789 return;
790 }
791 /* fall through */
792 case AST2600_SYS_RST_CTRL:
793 case AST2600_SYS_RST_CTRL2:
794 case AST2600_CLK_STOP_CTRL:
795 case AST2600_CLK_STOP_CTRL2:
796 /* W1S (Write 1 to set) registers */
797 s->regs[reg] |= data;
798 return;
799 case AST2600_SYS_RST_CTRL_CLR:
800 case AST2600_SYS_RST_CTRL2_CLR:
801 case AST2600_CLK_STOP_CTRL_CLR:
802 case AST2600_CLK_STOP_CTRL2_CLR:
803 case AST2600_HW_STRAP1_CLR:
804 case AST2600_HW_STRAP2_CLR:
805 /*
806 * W1C (Write 1 to clear) registers are offset by one address from
807 * the data register
808 */
809 s->regs[reg - 1] &= ~data;
810 return;
811
812 case AST2600_RNG_DATA:
813 case AST2600_SILICON_REV:
814 case AST2600_SILICON_REV2:
815 case AST2600_CHIP_ID0:
816 case AST2600_CHIP_ID1:
817 /* Add read only registers here */
818 qemu_log_mask(LOG_GUEST_ERROR,
819 "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
820 __func__, offset);
821 return;
822 }
823
824 s->regs[reg] = data;
825 }
826
827 static const MemoryRegionOps aspeed_ast2600_scu_ops = {
828 .read = aspeed_ast2600_scu_read,
829 .write = aspeed_ast2600_scu_write,
830 .endianness = DEVICE_LITTLE_ENDIAN,
831 .impl.min_access_size = 4,
832 .impl.max_access_size = 4,
833 .valid.min_access_size = 1,
834 .valid.max_access_size = 4,
835 .valid.unaligned = false,
836 };
837
838 static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
839 [AST2600_SYS_RST_CTRL] = 0xF7C3FED8,
840 [AST2600_SYS_RST_CTRL2] = 0x0DFFFFFC,
841 [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
842 [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
843 [AST2600_DEBUG_CTRL] = 0x00000FFF,
844 [AST2600_DEBUG_CTRL2] = 0x000000FF,
845 [AST2600_SDRAM_HANDSHAKE] = 0x00000000,
846 [AST2600_HPLL_PARAM] = 0x1000408F,
847 [AST2600_APLL_PARAM] = 0x1000405F,
848 [AST2600_MPLL_PARAM] = 0x1008405F,
849 [AST2600_EPLL_PARAM] = 0x1004077F,
850 [AST2600_DPLL_PARAM] = 0x1078405F,
851 [AST2600_CLK_SEL] = 0xF3940000,
852 [AST2600_CLK_SEL2] = 0x00700000,
853 [AST2600_CLK_SEL3] = 0x00000000,
854 [AST2600_CLK_SEL4] = 0xF3F40000,
855 [AST2600_CLK_SEL5] = 0x30000000,
856 [AST2600_UARTCLK] = 0x00014506,
857 [AST2600_HUARTCLK] = 0x000145C0,
858 [AST2600_CHIP_ID0] = 0x1234ABCD,
859 [AST2600_CHIP_ID1] = 0x88884444,
860 };
861
aspeed_ast2600_scu_reset(DeviceState * dev)862 static void aspeed_ast2600_scu_reset(DeviceState *dev)
863 {
864 AspeedSCUState *s = ASPEED_SCU(dev);
865 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
866
867 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
868
869 /*
870 * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
871 * of actual revision. QEMU and Linux only support A1 onwards so this is
872 * sufficient.
873 */
874 s->regs[AST2600_SILICON_REV] = AST2600_A3_SILICON_REV;
875 s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
876 s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
877 s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
878 s->regs[PROT_KEY] = s->hw_prot_key;
879 }
880
aspeed_2600_scu_class_init(ObjectClass * klass,const void * data)881 static void aspeed_2600_scu_class_init(ObjectClass *klass, const void *data)
882 {
883 DeviceClass *dc = DEVICE_CLASS(klass);
884 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
885
886 dc->desc = "ASPEED 2600 System Control Unit";
887 device_class_set_legacy_reset(dc, aspeed_ast2600_scu_reset);
888 asc->resets = ast2600_a3_resets;
889 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
890 asc->get_apb = aspeed_2600_scu_get_apb_freq;
891 asc->apb_divider = 4;
892 asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
893 asc->clkin_25Mhz = true;
894 asc->ops = &aspeed_ast2600_scu_ops;
895 }
896
897 static const TypeInfo aspeed_2600_scu_info = {
898 .name = TYPE_ASPEED_2600_SCU,
899 .parent = TYPE_ASPEED_SCU,
900 .instance_size = sizeof(AspeedSCUState),
901 .class_init = aspeed_2600_scu_class_init,
902 };
903
aspeed_ast2700_scu_read(void * opaque,hwaddr offset,unsigned size)904 static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
905 unsigned size)
906 {
907 AspeedSCUState *s = ASPEED_SCU(opaque);
908 int reg = TO_REG(offset);
909
910 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
911 qemu_log_mask(LOG_GUEST_ERROR,
912 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
913 __func__, offset);
914 return 0;
915 }
916
917 switch (reg) {
918 default:
919 qemu_log_mask(LOG_GUEST_ERROR,
920 "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
921 __func__, offset);
922 }
923
924 trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
925 return s->regs[reg];
926 }
927
handle_ssp_tsp_on(struct AspeedSCUState * s,int cpuid)928 static void handle_ssp_tsp_on(struct AspeedSCUState *s, int cpuid)
929 {
930 int reg = (cpuid == 4) ? AST2700_SCU_SSP_CTRL_0 : AST2700_SCU_TSP_CTRL_0;
931 uint32_t val = s->regs[reg];
932
933 val &= ~AST2700_SSP_TSP_RST_SRC_RB;
934 if (!(val & AST2700_SSP_TSP_RST_HOLD_RB)) {
935 val &= ~AST2700_SSP_TSP_RST_RB;
936 arm_set_cpu_on_and_reset(cpuid);
937 }
938
939 s->regs[reg] = val;
940 }
941
handle_ssp_tsp_off(struct AspeedSCUState * s,int cpuid)942 static void handle_ssp_tsp_off(struct AspeedSCUState *s, int cpuid)
943 {
944 int reg = (cpuid == 4) ? AST2700_SCU_SSP_CTRL_0 : AST2700_SCU_TSP_CTRL_0;
945 uint32_t val = s->regs[reg];
946
947 val |= AST2700_SSP_TSP_RST_RB;
948 val |= AST2700_SSP_TSP_RST_SRC_RB;
949 if (val & AST2700_SSP_TSP_RST) {
950 val |= AST2700_SSP_TSP_RST_HOLD_RB;
951 }
952 arm_set_cpu_off(cpuid);
953
954 s->regs[reg] = val;
955 }
956
aspeed_ast2700_scu_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)957 static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
958 uint64_t data64, unsigned size)
959 {
960 AspeedSCUState *s = ASPEED_SCU(opaque);
961 int reg = TO_REG(offset);
962 /* Truncate here so bitwise operations below behave as expected */
963 uint32_t data = data64;
964 MemoryRegion *mr;
965 uint32_t active;
966 uint32_t oldval;
967 int cpuid;
968
969 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
970 qemu_log_mask(LOG_GUEST_ERROR,
971 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
972 __func__, offset);
973 return;
974 }
975
976 trace_aspeed_ast2700_scu_write(offset, size, data);
977
978 switch (reg) {
979 case AST2700_SCU_SSP_CTRL_0:
980 case AST2700_SCU_TSP_CTRL_0:
981 cpuid = (reg == AST2700_SCU_SSP_CTRL_0) ? 4 : 5;
982 oldval = s->regs[reg];
983 data &= 0xff;
984 active = oldval ^ data;
985
986 /*
987 * If reset bit is being released (1 -> 0) and no other reset source
988 * is active, clear HOLD_RB and power on the corresponding CPU.
989 */
990 if ((active & AST2700_SSP_TSP_RST) && !(data & AST2700_SSP_TSP_RST)) {
991 s->regs[reg] &= ~AST2700_SSP_TSP_RST_HOLD_RB;
992 if ((oldval & AST2700_SSP_TSP_RST_RB) &&
993 !(oldval & AST2700_SSP_TSP_RST_SRC_RB)) {
994 handle_ssp_tsp_on(s, cpuid);
995 }
996 }
997
998 /*
999 * If ENABLE bit is newly set and reset state is ready,
1000 * clear HOLD_RB and power on the corresponding CPU.
1001 */
1002 if ((active & AST2700_SSP_TSP_ENABLE) &&
1003 (oldval & AST2700_SSP_TSP_RST_RB) &&
1004 (oldval & AST2700_SSP_TSP_RST_HOLD_RB) &&
1005 !(oldval & AST2700_SSP_TSP_RST_SRC_RB)) {
1006 s->regs[reg] &= ~AST2700_SSP_TSP_RST_HOLD_RB;
1007 handle_ssp_tsp_on(s, cpuid);
1008 }
1009
1010 /* Auto-clear the ENABLE bit (one-shot behavior) */
1011 data &= ~AST2700_SSP_TSP_ENABLE;
1012 s->regs[reg] = (s->regs[reg] & ~0xff) | (data & 0xff);
1013 return;
1014 case AST2700_SCU_SSP_CTRL_1:
1015 case AST2700_SCU_SSP_CTRL_2:
1016 mr = (reg == AST2700_SCU_SSP_CTRL_1) ?
1017 s->ssp_sdram_remap1 : s->ssp_sdram_remap2;
1018 if (mr == NULL) {
1019 return;
1020 }
1021 data &= 0x7fffffff;
1022 memory_region_set_alias_offset(mr, (uint64_t) data << 4);
1023 break;
1024 case AST2700_SCU_SSP_REMAP_ADDR_1:
1025 case AST2700_SCU_SSP_REMAP_ADDR_2:
1026 mr = (reg == AST2700_SCU_SSP_REMAP_ADDR_1) ?
1027 s->ssp_sdram_remap1 : s->ssp_sdram_remap2;
1028 if (mr == NULL) {
1029 return;
1030 }
1031 data &= 0x3fffffff;
1032 memory_region_set_address(mr, data);
1033 break;
1034 case AST2700_SCU_SSP_REMAP_SIZE_1:
1035 case AST2700_SCU_SSP_REMAP_SIZE_2:
1036 mr = (reg == AST2700_SCU_SSP_REMAP_SIZE_1) ?
1037 s->ssp_sdram_remap1 : s->ssp_sdram_remap2;
1038 if (mr == NULL) {
1039 return;
1040 }
1041 data &= 0x3fffffff;
1042 memory_region_set_size(mr, data);
1043 break;
1044 case AST2700_SCU_TSP_CTRL_1:
1045 if (s->tsp_sdram_remap == NULL) {
1046 return;
1047 }
1048 data &= 0x7fffffff;
1049 /* remapped to SOC DRAM by adding data << 4 */
1050 memory_region_set_alias_offset(s->tsp_sdram_remap,
1051 (uint64_t) data << 4);
1052 break;
1053 case AST2700_SCU_TSP_REMAP_SIZE_2:
1054 if (s->tsp_sdram_remap == NULL) {
1055 return;
1056 }
1057 data &= 0x3fffffff;
1058 memory_region_set_size(s->tsp_sdram_remap, data);
1059 break;
1060 case AST2700_SCU_SYS_RST_CTRL_1:
1061 oldval = s->regs[reg];
1062 active = data & ~oldval;
1063 if (active & AST2700_SCU_SYS_RST_SSP) {
1064 handle_ssp_tsp_off(s, 4);
1065 }
1066 s->regs[reg] |= active;
1067 return;
1068 case AST2700_SCU_SYS_RST_CLR_1:
1069 oldval = s->regs[AST2700_SCU_SYS_RST_CTRL_1];
1070 active = data & oldval;
1071 if (active & AST2700_SCU_SYS_RST_SSP) {
1072 handle_ssp_tsp_on(s, 4);
1073 }
1074 s->regs[AST2700_SCU_SYS_RST_CTRL_1] &= ~active;
1075 return;
1076 case AST2700_SCU_SYS_RST_CTRL_2:
1077 data &= 0x00001fff;
1078 oldval = s->regs[reg];
1079 active = data & ~oldval;
1080 if (data & AST2700_SCU_SYS_RST_TSP) {
1081 handle_ssp_tsp_off(s, 5);
1082 }
1083 s->regs[reg] |= data;
1084 return;
1085 case AST2700_SCU_SYS_RST_CLR_2:
1086 data &= 0x00001fff;
1087 oldval = s->regs[AST2700_SCU_SYS_RST_CTRL_2];
1088 active = data & oldval;
1089 if (active & AST2700_SCU_SYS_RST_TSP) {
1090 handle_ssp_tsp_on(s, 5);
1091 }
1092 s->regs[AST2700_SCU_SYS_RST_CTRL_2] &= ~active;
1093 return;
1094 default:
1095 qemu_log_mask(LOG_GUEST_ERROR,
1096 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
1097 __func__, offset);
1098 break;
1099 }
1100
1101 s->regs[reg] = data;
1102 }
1103
1104 static const MemoryRegionOps aspeed_ast2700_scu_ops = {
1105 .read = aspeed_ast2700_scu_read,
1106 .write = aspeed_ast2700_scu_write,
1107 .endianness = DEVICE_LITTLE_ENDIAN,
1108 .impl.min_access_size = 4,
1109 .impl.max_access_size = 4,
1110 .valid.min_access_size = 1,
1111 .valid.max_access_size = 8,
1112 .valid.unaligned = false,
1113 };
1114
1115 static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
1116 [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
1117 [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
1118 [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
1119 [AST2700_HW_STRAP1_SEC2] = 0x00000000,
1120 [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
1121 [AST2700_SCU_SSP_CTRL_0] = 0x000007FE,
1122 [AST2700_SCU_SSP_CTRL_1] = 0x40000000,
1123 [AST2700_SCU_SSP_CTRL_2] = 0x42C00000,
1124 [AST2700_SCU_SSP_REMAP_ADDR_1] = 0x02000000,
1125 [AST2700_SCU_SSP_REMAP_SIZE_1] = 0x02000000,
1126 [AST2700_SCU_SSP_REMAP_ADDR_2] = 0x00000000,
1127 [AST2700_SCU_SSP_REMAP_SIZE_2] = 0x02000000,
1128 [AST2700_SCU_TSP_CTRL_0] = 0x000007FE,
1129 [AST2700_SCU_TSP_CTRL_1] = 0x42E00000,
1130 [AST2700_SCU_TSP_REMAP_SIZE_2] = 0x02000000,
1131 [AST2700_SCU_SYS_RST_CTRL_1] = 0xFFC37FDC,
1132 [AST2700_SCU_SYS_RST_CTRL_2] = 0x00001FFF,
1133 [AST2700_SCU_HPLL_PARAM] = 0x0000009f,
1134 [AST2700_SCU_HPLL_EXT_PARAM] = 0x8000004f,
1135 [AST2700_SCU_DPLL_PARAM] = 0x0080009f,
1136 [AST2700_SCU_DPLL_EXT_PARAM] = 0x8000004f,
1137 [AST2700_SCU_MPLL_PARAM] = 0x00000040,
1138 [AST2700_SCU_MPLL_EXT_PARAM] = 0x80000000,
1139 [AST2700_SCU_D1CLK_PARAM] = 0x00050002,
1140 [AST2700_SCU_D2CLK_PARAM] = 0x00050002,
1141 [AST2700_SCU_CRT1CLK_PARAM] = 0x00050002,
1142 [AST2700_SCU_CRT2CLK_PARAM] = 0x00050002,
1143 [AST2700_SCU_MPHYCLK_PARAM] = 0x0000004c,
1144 [AST2700_SCU_FREQ_CNTR] = 0x000375eb,
1145 [AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
1146 [AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
1147 [AST2700_SCU_VGA_SCRATCH_0] = 0x00000040,
1148 };
1149
aspeed_ast2700_scu_reset(DeviceState * dev)1150 static void aspeed_ast2700_scu_reset(DeviceState *dev)
1151 {
1152 AspeedSCUState *s = ASPEED_SCU(dev);
1153 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
1154
1155 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1156 s->regs[AST2700_SILICON_REV] = s->silicon_rev;
1157 s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
1158 }
1159
aspeed_2700_scu_class_init(ObjectClass * klass,const void * data)1160 static void aspeed_2700_scu_class_init(ObjectClass *klass, const void *data)
1161 {
1162 DeviceClass *dc = DEVICE_CLASS(klass);
1163 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1164
1165 dc->desc = "ASPEED 2700 System Control Unit";
1166 device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
1167 asc->resets = ast2700_a0_resets;
1168 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1169 asc->get_apb = aspeed_2700_scu_get_apb_freq;
1170 asc->apb_divider = 4;
1171 asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
1172 asc->clkin_25Mhz = true;
1173 asc->ops = &aspeed_ast2700_scu_ops;
1174 }
1175
aspeed_ast2700_scuio_read(void * opaque,hwaddr offset,unsigned size)1176 static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
1177 unsigned size)
1178 {
1179 AspeedSCUState *s = ASPEED_SCU(opaque);
1180 int reg = TO_REG(offset);
1181 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
1182 qemu_log_mask(LOG_GUEST_ERROR,
1183 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
1184 __func__, offset);
1185 return 0;
1186 }
1187
1188 switch (reg) {
1189 default:
1190 qemu_log_mask(LOG_GUEST_ERROR,
1191 "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
1192 __func__, offset);
1193 }
1194
1195 trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
1196 return s->regs[reg];
1197 }
1198
aspeed_ast2700_scuio_write(void * opaque,hwaddr offset,uint64_t data64,unsigned size)1199 static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
1200 uint64_t data64, unsigned size)
1201 {
1202 AspeedSCUState *s = ASPEED_SCU(opaque);
1203 int reg = TO_REG(offset);
1204 /* Truncate here so bitwise operations below behave as expected */
1205 uint32_t data = data64;
1206 bool updated = false;
1207
1208 if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
1209 qemu_log_mask(LOG_GUEST_ERROR,
1210 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
1211 __func__, offset);
1212 return;
1213 }
1214
1215 trace_aspeed_ast2700_scuio_write(offset, size, data);
1216
1217 switch (reg) {
1218 case AST2700_SCUIO_CLK_STOP_CTL_1:
1219 case AST2700_SCUIO_CLK_STOP_CTL_2:
1220 s->regs[reg] |= data;
1221 updated = true;
1222 break;
1223 case AST2700_SCUIO_CLK_STOP_CLR_1:
1224 case AST2700_SCUIO_CLK_STOP_CLR_2:
1225 s->regs[reg - 1] ^= data;
1226 updated = true;
1227 break;
1228 case AST2700_SCUIO_FREQ_CNT_CTL:
1229 s->regs[reg] = deposit32(s->regs[reg], 6, 1, !!(data & BIT(1)));
1230 updated = true;
1231 break;
1232 default:
1233 qemu_log_mask(LOG_GUEST_ERROR,
1234 "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
1235 __func__, offset);
1236 break;
1237 }
1238
1239 if (!updated) {
1240 s->regs[reg] = data;
1241 }
1242 }
1243
1244 static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
1245 .read = aspeed_ast2700_scuio_read,
1246 .write = aspeed_ast2700_scuio_write,
1247 .endianness = DEVICE_LITTLE_ENDIAN,
1248 .impl.min_access_size = 4,
1249 .impl.max_access_size = 4,
1250 .valid.min_access_size = 1,
1251 .valid.max_access_size = 8,
1252 .valid.unaligned = false,
1253 };
1254
1255 static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
1256 [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
1257 [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
1258 [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
1259 [AST2700_HW_STRAP1_SEC2] = 0x00000000,
1260 [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
1261 [AST2700_SCUIO_CLK_STOP_CTL_1] = 0xffff8400,
1262 [AST2700_SCUIO_CLK_STOP_CTL_2] = 0x00005f30,
1263 [AST2700_SCUIO_CLK_SEL_1] = 0x86900000,
1264 [AST2700_SCUIO_CLK_SEL_2] = 0x00400000,
1265 [AST2700_SCUIO_HPLL_PARAM] = 0x10000027,
1266 [AST2700_SCUIO_HPLL_EXT_PARAM] = 0x80000014,
1267 [AST2700_SCUIO_APLL_PARAM] = 0x1000001f,
1268 [AST2700_SCUIO_APLL_EXT_PARAM] = 0x8000000f,
1269 [AST2700_SCUIO_DPLL_PARAM] = 0x106e42ce,
1270 [AST2700_SCUIO_DPLL_EXT_PARAM] = 0x80000167,
1271 [AST2700_SCUIO_DPLL_PARAM_READ] = 0x106e42ce,
1272 [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
1273 [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
1274 [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
1275 [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
1276 [AST2700_SCUIO_FREQ_CNT_CTL] = 0x00000080,
1277 };
1278
aspeed_2700_scuio_class_init(ObjectClass * klass,const void * data)1279 static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)
1280 {
1281 DeviceClass *dc = DEVICE_CLASS(klass);
1282 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1283
1284 dc->desc = "ASPEED 2700 System Control Unit I/O";
1285 device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
1286 asc->resets = ast2700_a0_resets_io;
1287 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1288 asc->get_apb = aspeed_2700_scuio_get_apb_freq;
1289 asc->apb_divider = 2;
1290 asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
1291 asc->clkin_25Mhz = true;
1292 asc->ops = &aspeed_ast2700_scuio_ops;
1293 }
1294
1295 static const TypeInfo aspeed_2700_scu_info = {
1296 .name = TYPE_ASPEED_2700_SCU,
1297 .parent = TYPE_ASPEED_SCU,
1298 .instance_size = sizeof(AspeedSCUState),
1299 .class_init = aspeed_2700_scu_class_init,
1300 };
1301
1302 static const TypeInfo aspeed_2700_scuio_info = {
1303 .name = TYPE_ASPEED_2700_SCUIO,
1304 .parent = TYPE_ASPEED_SCU,
1305 .instance_size = sizeof(AspeedSCUState),
1306 .class_init = aspeed_2700_scuio_class_init,
1307 };
1308
1309 static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
1310 [AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
1311 [AST2600_SYS_RST_CTRL2] = 0x09FFFFFC,
1312 [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
1313 [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
1314 [AST2600_DEBUG_CTRL2] = 0x00000000,
1315 [AST2600_HPLL_PARAM] = 0x10004077,
1316 [AST2600_HPLL_EXT] = 0x00000031,
1317 [AST2600_CLK_SEL4] = 0x43F90900,
1318 [AST2600_CLK_SEL5] = 0x40000000,
1319 [AST2600_CHIP_ID0] = 0xDEADBEEF,
1320 [AST2600_CHIP_ID1] = 0x0BADCAFE,
1321 };
1322
aspeed_ast1030_scu_reset(DeviceState * dev)1323 static void aspeed_ast1030_scu_reset(DeviceState *dev)
1324 {
1325 AspeedSCUState *s = ASPEED_SCU(dev);
1326 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
1327
1328 memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1329
1330 s->regs[AST2600_SILICON_REV] = AST1030_A1_SILICON_REV;
1331 s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
1332 s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
1333 s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
1334 s->regs[PROT_KEY] = s->hw_prot_key;
1335 }
1336
aspeed_1030_scu_class_init(ObjectClass * klass,const void * data)1337 static void aspeed_1030_scu_class_init(ObjectClass *klass, const void *data)
1338 {
1339 DeviceClass *dc = DEVICE_CLASS(klass);
1340 AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1341
1342 dc->desc = "ASPEED 1030 System Control Unit";
1343 device_class_set_legacy_reset(dc, aspeed_ast1030_scu_reset);
1344 asc->resets = ast1030_a1_resets;
1345 asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1346 asc->get_apb = aspeed_1030_scu_get_apb_freq;
1347 asc->apb_divider = 2;
1348 asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
1349 asc->clkin_25Mhz = true;
1350 asc->ops = &aspeed_ast2600_scu_ops;
1351 }
1352
1353 static const TypeInfo aspeed_1030_scu_info = {
1354 .name = TYPE_ASPEED_1030_SCU,
1355 .parent = TYPE_ASPEED_SCU,
1356 .instance_size = sizeof(AspeedSCUState),
1357 .class_init = aspeed_1030_scu_class_init,
1358 };
1359
aspeed_scu_register_types(void)1360 static void aspeed_scu_register_types(void)
1361 {
1362 type_register_static(&aspeed_scu_info);
1363 type_register_static(&aspeed_2400_scu_info);
1364 type_register_static(&aspeed_2500_scu_info);
1365 type_register_static(&aspeed_2600_scu_info);
1366 type_register_static(&aspeed_1030_scu_info);
1367 type_register_static(&aspeed_2700_scu_info);
1368 type_register_static(&aspeed_2700_scuio_info);
1369 }
1370
1371 type_init(aspeed_scu_register_types);
1372