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