xref: /openbmc/qemu/hw/misc/aspeed_scu.c (revision e293bf876c0173b659ece4d2b9b3945372d709c7)
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