qemu

Форк
0
/
aspeed_scu.c 
1150 строк · 37.2 Кб
1
/*
2
 * ASPEED System Control Unit
3
 *
4
 * Andrew Jeffery <andrew@aj.id.au>
5
 *
6
 * Copyright 2016 IBM Corp.
7
 *
8
 * This code is licensed under the GPL version 2 or later.  See
9
 * the COPYING file in the top-level directory.
10
 */
11

12
#include "qemu/osdep.h"
13
#include "hw/misc/aspeed_scu.h"
14
#include "hw/qdev-properties.h"
15
#include "migration/vmstate.h"
16
#include "qapi/error.h"
17
#include "qapi/visitor.h"
18
#include "qemu/bitops.h"
19
#include "qemu/log.h"
20
#include "qemu/guest-random.h"
21
#include "qemu/module.h"
22
#include "trace.h"
23

24
#define TO_REG(offset) ((offset) >> 2)
25

26
#define PROT_KEY             TO_REG(0x00)
27
#define SYS_RST_CTRL         TO_REG(0x04)
28
#define CLK_SEL              TO_REG(0x08)
29
#define CLK_STOP_CTRL        TO_REG(0x0C)
30
#define FREQ_CNTR_CTRL       TO_REG(0x10)
31
#define FREQ_CNTR_EVAL       TO_REG(0x14)
32
#define IRQ_CTRL             TO_REG(0x18)
33
#define D2PLL_PARAM          TO_REG(0x1C)
34
#define MPLL_PARAM           TO_REG(0x20)
35
#define HPLL_PARAM           TO_REG(0x24)
36
#define FREQ_CNTR_RANGE      TO_REG(0x28)
37
#define MISC_CTRL1           TO_REG(0x2C)
38
#define PCI_CTRL1            TO_REG(0x30)
39
#define PCI_CTRL2            TO_REG(0x34)
40
#define PCI_CTRL3            TO_REG(0x38)
41
#define SYS_RST_STATUS       TO_REG(0x3C)
42
#define SOC_SCRATCH1         TO_REG(0x40)
43
#define SOC_SCRATCH2         TO_REG(0x44)
44
#define MAC_CLK_DELAY        TO_REG(0x48)
45
#define MISC_CTRL2           TO_REG(0x4C)
46
#define VGA_SCRATCH1         TO_REG(0x50)
47
#define VGA_SCRATCH2         TO_REG(0x54)
48
#define VGA_SCRATCH3         TO_REG(0x58)
49
#define VGA_SCRATCH4         TO_REG(0x5C)
50
#define VGA_SCRATCH5         TO_REG(0x60)
51
#define VGA_SCRATCH6         TO_REG(0x64)
52
#define VGA_SCRATCH7         TO_REG(0x68)
53
#define VGA_SCRATCH8         TO_REG(0x6C)
54
#define HW_STRAP1            TO_REG(0x70)
55
#define RNG_CTRL             TO_REG(0x74)
56
#define RNG_DATA             TO_REG(0x78)
57
#define SILICON_REV          TO_REG(0x7C)
58
#define PINMUX_CTRL1         TO_REG(0x80)
59
#define PINMUX_CTRL2         TO_REG(0x84)
60
#define PINMUX_CTRL3         TO_REG(0x88)
61
#define PINMUX_CTRL4         TO_REG(0x8C)
62
#define PINMUX_CTRL5         TO_REG(0x90)
63
#define PINMUX_CTRL6         TO_REG(0x94)
64
#define WDT_RST_CTRL         TO_REG(0x9C)
65
#define PINMUX_CTRL7         TO_REG(0xA0)
66
#define PINMUX_CTRL8         TO_REG(0xA4)
67
#define PINMUX_CTRL9         TO_REG(0xA8)
68
#define WAKEUP_EN            TO_REG(0xC0)
69
#define WAKEUP_CTRL          TO_REG(0xC4)
70
#define HW_STRAP2            TO_REG(0xD0)
71
#define FREE_CNTR4           TO_REG(0xE0)
72
#define FREE_CNTR4_EXT       TO_REG(0xE4)
73
#define CPU2_CTRL            TO_REG(0x100)
74
#define CPU2_BASE_SEG1       TO_REG(0x104)
75
#define CPU2_BASE_SEG2       TO_REG(0x108)
76
#define CPU2_BASE_SEG3       TO_REG(0x10C)
77
#define CPU2_BASE_SEG4       TO_REG(0x110)
78
#define CPU2_BASE_SEG5       TO_REG(0x114)
79
#define CPU2_CACHE_CTRL      TO_REG(0x118)
80
#define CHIP_ID0             TO_REG(0x150)
81
#define CHIP_ID1             TO_REG(0x154)
82
#define UART_HPLL_CLK        TO_REG(0x160)
83
#define PCIE_CTRL            TO_REG(0x180)
84
#define BMC_MMIO_CTRL        TO_REG(0x184)
85
#define RELOC_DECODE_BASE1   TO_REG(0x188)
86
#define RELOC_DECODE_BASE2   TO_REG(0x18C)
87
#define MAILBOX_DECODE_BASE  TO_REG(0x190)
88
#define SRAM_DECODE_BASE1    TO_REG(0x194)
89
#define SRAM_DECODE_BASE2    TO_REG(0x198)
90
#define BMC_REV              TO_REG(0x19C)
91
#define BMC_DEV_ID           TO_REG(0x1A4)
92

93
#define AST2600_PROT_KEY          TO_REG(0x00)
94
#define AST2600_SILICON_REV       TO_REG(0x04)
95
#define AST2600_SILICON_REV2      TO_REG(0x14)
96
#define AST2600_SYS_RST_CTRL      TO_REG(0x40)
97
#define AST2600_SYS_RST_CTRL_CLR  TO_REG(0x44)
98
#define AST2600_SYS_RST_CTRL2     TO_REG(0x50)
99
#define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
100
#define AST2600_CLK_STOP_CTRL     TO_REG(0x80)
101
#define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
102
#define AST2600_CLK_STOP_CTRL2     TO_REG(0x90)
103
#define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
104
#define AST2600_DEBUG_CTRL        TO_REG(0xC8)
105
#define AST2600_DEBUG_CTRL2       TO_REG(0xD8)
106
#define AST2600_SDRAM_HANDSHAKE   TO_REG(0x100)
107
#define AST2600_HPLL_PARAM        TO_REG(0x200)
108
#define AST2600_HPLL_EXT          TO_REG(0x204)
109
#define AST2600_APLL_PARAM        TO_REG(0x210)
110
#define AST2600_APLL_EXT          TO_REG(0x214)
111
#define AST2600_MPLL_PARAM        TO_REG(0x220)
112
#define AST2600_MPLL_EXT          TO_REG(0x224)
113
#define AST2600_EPLL_PARAM        TO_REG(0x240)
114
#define AST2600_EPLL_EXT          TO_REG(0x244)
115
#define AST2600_DPLL_PARAM        TO_REG(0x260)
116
#define AST2600_DPLL_EXT          TO_REG(0x264)
117
#define AST2600_CLK_SEL           TO_REG(0x300)
118
#define AST2600_CLK_SEL2          TO_REG(0x304)
119
#define AST2600_CLK_SEL3          TO_REG(0x308)
120
#define AST2600_CLK_SEL4          TO_REG(0x310)
121
#define AST2600_CLK_SEL5          TO_REG(0x314)
122
#define AST2600_UARTCLK           TO_REG(0x338)
123
#define AST2600_HUARTCLK          TO_REG(0x33C)
124
#define AST2600_HW_STRAP1         TO_REG(0x500)
125
#define AST2600_HW_STRAP1_CLR     TO_REG(0x504)
126
#define AST2600_HW_STRAP1_PROT    TO_REG(0x508)
127
#define AST2600_HW_STRAP2         TO_REG(0x510)
128
#define AST2600_HW_STRAP2_CLR     TO_REG(0x514)
129
#define AST2600_HW_STRAP2_PROT    TO_REG(0x518)
130
#define AST2600_RNG_CTRL          TO_REG(0x524)
131
#define AST2600_RNG_DATA          TO_REG(0x540)
132
#define AST2600_CHIP_ID0          TO_REG(0x5B0)
133
#define AST2600_CHIP_ID1          TO_REG(0x5B4)
134

135
#define AST2600_CLK TO_REG(0x40)
136

137
#define AST2700_SILICON_REV       TO_REG(0x00)
138
#define AST2700_HW_STRAP1         TO_REG(0x10)
139
#define AST2700_HW_STRAP1_CLR     TO_REG(0x14)
140
#define AST2700_HW_STRAP1_LOCK    TO_REG(0x20)
141
#define AST2700_HW_STRAP1_SEC1    TO_REG(0x24)
142
#define AST2700_HW_STRAP1_SEC2    TO_REG(0x28)
143
#define AST2700_HW_STRAP1_SEC3    TO_REG(0x2C)
144

145
#define AST2700_SCU_CLK_SEL_1       TO_REG(0x280)
146
#define AST2700_SCU_HPLL_PARAM      TO_REG(0x300)
147
#define AST2700_SCU_HPLL_EXT_PARAM  TO_REG(0x304)
148
#define AST2700_SCU_DPLL_PARAM      TO_REG(0x308)
149
#define AST2700_SCU_DPLL_EXT_PARAM  TO_REG(0x30c)
150
#define AST2700_SCU_MPLL_PARAM      TO_REG(0x310)
151
#define AST2700_SCU_MPLL_EXT_PARAM  TO_REG(0x314)
152
#define AST2700_SCU_D1CLK_PARAM     TO_REG(0x320)
153
#define AST2700_SCU_D2CLK_PARAM     TO_REG(0x330)
154
#define AST2700_SCU_CRT1CLK_PARAM   TO_REG(0x340)
155
#define AST2700_SCU_CRT2CLK_PARAM   TO_REG(0x350)
156
#define AST2700_SCU_MPHYCLK_PARAM   TO_REG(0x360)
157
#define AST2700_SCU_FREQ_CNTR       TO_REG(0x3b0)
158
#define AST2700_SCU_CPU_SCRATCH_0   TO_REG(0x780)
159
#define AST2700_SCU_CPU_SCRATCH_1   TO_REG(0x784)
160

161
#define AST2700_SCUIO_CLK_STOP_CTL_1    TO_REG(0x240)
162
#define AST2700_SCUIO_CLK_STOP_CLR_1    TO_REG(0x244)
163
#define AST2700_SCUIO_CLK_STOP_CTL_2    TO_REG(0x260)
164
#define AST2700_SCUIO_CLK_STOP_CLR_2    TO_REG(0x264)
165
#define AST2700_SCUIO_CLK_SEL_1         TO_REG(0x280)
166
#define AST2700_SCUIO_CLK_SEL_2         TO_REG(0x284)
167
#define AST2700_SCUIO_HPLL_PARAM        TO_REG(0x300)
168
#define AST2700_SCUIO_HPLL_EXT_PARAM    TO_REG(0x304)
169
#define AST2700_SCUIO_APLL_PARAM        TO_REG(0x310)
170
#define AST2700_SCUIO_APLL_EXT_PARAM    TO_REG(0x314)
171
#define AST2700_SCUIO_DPLL_PARAM        TO_REG(0x320)
172
#define AST2700_SCUIO_DPLL_EXT_PARAM    TO_REG(0x324)
173
#define AST2700_SCUIO_DPLL_PARAM_READ   TO_REG(0x328)
174
#define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
175
#define AST2700_SCUIO_UARTCLK_GEN       TO_REG(0x330)
176
#define AST2700_SCUIO_HUARTCLK_GEN      TO_REG(0x334)
177
#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
178

179
#define SCU_IO_REGION_SIZE 0x1000
180

181
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
182
     [SYS_RST_CTRL]    = 0xFFCFFEDCU,
183
     [CLK_SEL]         = 0xF3F40000U,
184
     [CLK_STOP_CTRL]   = 0x19FC3E8BU,
185
     [D2PLL_PARAM]     = 0x00026108U,
186
     [MPLL_PARAM]      = 0x00030291U,
187
     [HPLL_PARAM]      = 0x00000291U,
188
     [MISC_CTRL1]      = 0x00000010U,
189
     [PCI_CTRL1]       = 0x20001A03U,
190
     [PCI_CTRL2]       = 0x20001A03U,
191
     [PCI_CTRL3]       = 0x04000030U,
192
     [SYS_RST_STATUS]  = 0x00000001U,
193
     [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
194
     [MISC_CTRL2]      = 0x00000023U,
195
     [RNG_CTRL]        = 0x0000000EU,
196
     [PINMUX_CTRL2]    = 0x0000F000U,
197
     [PINMUX_CTRL3]    = 0x01000000U,
198
     [PINMUX_CTRL4]    = 0x000000FFU,
199
     [PINMUX_CTRL5]    = 0x0000A000U,
200
     [WDT_RST_CTRL]    = 0x003FFFF3U,
201
     [PINMUX_CTRL8]    = 0xFFFF0000U,
202
     [PINMUX_CTRL9]    = 0x000FFFFFU,
203
     [FREE_CNTR4]      = 0x000000FFU,
204
     [FREE_CNTR4_EXT]  = 0x000000FFU,
205
     [CPU2_BASE_SEG1]  = 0x80000000U,
206
     [CPU2_BASE_SEG4]  = 0x1E600000U,
207
     [CPU2_BASE_SEG5]  = 0xC0000000U,
208
     [UART_HPLL_CLK]   = 0x00001903U,
209
     [PCIE_CTRL]       = 0x0000007BU,
210
     [BMC_DEV_ID]      = 0x00002402U
211
};
212

213
/* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
214
/* AST2500 revision A1 */
215

216
static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
217
     [SYS_RST_CTRL]    = 0xFFCFFEDCU,
218
     [CLK_SEL]         = 0xF3F40000U,
219
     [CLK_STOP_CTRL]   = 0x19FC3E8BU,
220
     [D2PLL_PARAM]     = 0x00026108U,
221
     [MPLL_PARAM]      = 0x00030291U,
222
     [HPLL_PARAM]      = 0x93000400U,
223
     [MISC_CTRL1]      = 0x00000010U,
224
     [PCI_CTRL1]       = 0x20001A03U,
225
     [PCI_CTRL2]       = 0x20001A03U,
226
     [PCI_CTRL3]       = 0x04000030U,
227
     [SYS_RST_STATUS]  = 0x00000001U,
228
     [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
229
     [MISC_CTRL2]      = 0x00000023U,
230
     [RNG_CTRL]        = 0x0000000EU,
231
     [PINMUX_CTRL2]    = 0x0000F000U,
232
     [PINMUX_CTRL3]    = 0x03000000U,
233
     [PINMUX_CTRL4]    = 0x00000000U,
234
     [PINMUX_CTRL5]    = 0x0000A000U,
235
     [WDT_RST_CTRL]    = 0x023FFFF3U,
236
     [PINMUX_CTRL8]    = 0xFFFF0000U,
237
     [PINMUX_CTRL9]    = 0x000FFFFFU,
238
     [FREE_CNTR4]      = 0x000000FFU,
239
     [FREE_CNTR4_EXT]  = 0x000000FFU,
240
     [CPU2_BASE_SEG1]  = 0x80000000U,
241
     [CPU2_BASE_SEG4]  = 0x1E600000U,
242
     [CPU2_BASE_SEG5]  = 0xC0000000U,
243
     [CHIP_ID0]        = 0x1234ABCDU,
244
     [CHIP_ID1]        = 0x88884444U,
245
     [UART_HPLL_CLK]   = 0x00001903U,
246
     [PCIE_CTRL]       = 0x0000007BU,
247
     [BMC_DEV_ID]      = 0x00002402U
248
};
249

250
static uint32_t aspeed_scu_get_random(void)
251
{
252
    uint32_t num;
253
    qemu_guest_getrandom_nofail(&num, sizeof(num));
254
    return num;
255
}
256

257
uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
258
{
259
    return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
260
}
261

262
static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState *s)
263
{
264
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
265
    uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
266

267
    return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
268
        / asc->apb_divider;
269
}
270

271
static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
272
{
273
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
274
    uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
275

276
    return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
277
        / asc->apb_divider;
278
}
279

280
static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
281
{
282
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
283
    uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
284

285
    return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
286
        / asc->apb_divider;
287
}
288

289
static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
290
{
291
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
292
    uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
293

294
    return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
295
           / asc->apb_divider;
296
}
297

298
static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
299
{
300
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
301
    uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
302

303
    return hpll /
304
        (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
305
        / asc->apb_divider;
306
}
307

308
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
309
{
310
    AspeedSCUState *s = ASPEED_SCU(opaque);
311
    int reg = TO_REG(offset);
312

313
    if (reg >= ASPEED_SCU_NR_REGS) {
314
        qemu_log_mask(LOG_GUEST_ERROR,
315
                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
316
                      __func__, offset);
317
        return 0;
318
    }
319

320
    switch (reg) {
321
    case RNG_DATA:
322
        /*
323
         * On hardware, RNG_DATA works regardless of
324
         * the state of the enable bit in RNG_CTRL
325
         */
326
        s->regs[RNG_DATA] = aspeed_scu_get_random();
327
        break;
328
    case WAKEUP_EN:
329
        qemu_log_mask(LOG_GUEST_ERROR,
330
                      "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
331
                      __func__, offset);
332
        break;
333
    }
334

335
    trace_aspeed_scu_read(offset, size, s->regs[reg]);
336
    return s->regs[reg];
337
}
338

339
static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
340
                                     uint64_t data, unsigned size)
341
{
342
    AspeedSCUState *s = ASPEED_SCU(opaque);
343
    int reg = TO_REG(offset);
344

345
    if (reg >= ASPEED_SCU_NR_REGS) {
346
        qemu_log_mask(LOG_GUEST_ERROR,
347
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
348
                      __func__, offset);
349
        return;
350
    }
351

352
    if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
353
            !s->regs[PROT_KEY]) {
354
        qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
355
    }
356

357
    trace_aspeed_scu_write(offset, size, data);
358

359
    switch (reg) {
360
    case PROT_KEY:
361
        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
362
        return;
363
    case SILICON_REV:
364
    case FREQ_CNTR_EVAL:
365
    case VGA_SCRATCH1 ... VGA_SCRATCH8:
366
    case RNG_DATA:
367
    case FREE_CNTR4:
368
    case FREE_CNTR4_EXT:
369
        qemu_log_mask(LOG_GUEST_ERROR,
370
                      "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
371
                      __func__, offset);
372
        return;
373
    }
374

375
    s->regs[reg] = data;
376
}
377

378
static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
379
                                     uint64_t data, unsigned size)
380
{
381
    AspeedSCUState *s = ASPEED_SCU(opaque);
382
    int reg = TO_REG(offset);
383

384
    if (reg >= ASPEED_SCU_NR_REGS) {
385
        qemu_log_mask(LOG_GUEST_ERROR,
386
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
387
                      __func__, offset);
388
        return;
389
    }
390

391
    if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
392
            !s->regs[PROT_KEY]) {
393
        qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
394
        return;
395
    }
396

397
    trace_aspeed_scu_write(offset, size, data);
398

399
    switch (reg) {
400
    case PROT_KEY:
401
        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
402
        return;
403
    case HW_STRAP1:
404
        s->regs[HW_STRAP1] |= data;
405
        return;
406
    case SILICON_REV:
407
        s->regs[HW_STRAP1] &= ~data;
408
        return;
409
    case FREQ_CNTR_EVAL:
410
    case VGA_SCRATCH1 ... VGA_SCRATCH8:
411
    case RNG_DATA:
412
    case FREE_CNTR4:
413
    case FREE_CNTR4_EXT:
414
    case CHIP_ID0:
415
    case CHIP_ID1:
416
        qemu_log_mask(LOG_GUEST_ERROR,
417
                      "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
418
                      __func__, offset);
419
        return;
420
    }
421

422
    s->regs[reg] = data;
423
}
424

425
static const MemoryRegionOps aspeed_ast2400_scu_ops = {
426
    .read = aspeed_scu_read,
427
    .write = aspeed_ast2400_scu_write,
428
    .endianness = DEVICE_LITTLE_ENDIAN,
429
    .valid = {
430
        .min_access_size = 1,
431
        .max_access_size = 4,
432
    },
433
};
434

435
static const MemoryRegionOps aspeed_ast2500_scu_ops = {
436
    .read = aspeed_scu_read,
437
    .write = aspeed_ast2500_scu_write,
438
    .endianness = DEVICE_LITTLE_ENDIAN,
439
    .valid.min_access_size = 4,
440
    .valid.max_access_size = 4,
441
    .valid.unaligned = false,
442
};
443

444
static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
445
{
446
    if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN ||
447
        ASPEED_SCU_GET_CLASS(s)->clkin_25Mhz) {
448
        return 25000000;
449
    } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
450
        return 48000000;
451
    } else {
452
        return 24000000;
453
    }
454
}
455

456
/*
457
 * Strapped frequencies for the AST2400 in MHz. They depend on the
458
 * clkin frequency.
459
 */
460
static const uint32_t hpll_ast2400_freqs[][4] = {
461
    { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
462
    { 400, 375, 350, 425 }, /* 25MHz */
463
};
464

465
static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
466
{
467
    uint8_t freq_select;
468
    bool clk_25m_in;
469
    uint32_t clkin = aspeed_scu_get_clkin(s);
470

471
    if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
472
        return 0;
473
    }
474

475
    if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
476
        uint32_t multiplier = 1;
477

478
        if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
479
            uint32_t n  = (hpll_reg >> 5) & 0x3f;
480
            uint32_t od = (hpll_reg >> 4) & 0x1;
481
            uint32_t d  = hpll_reg & 0xf;
482

483
            multiplier = (2 - od) * ((n + 2) / (d + 1));
484
        }
485

486
        return clkin * multiplier;
487
    }
488

489
    /* HW strapping */
490
    clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
491
    freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
492

493
    return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
494
}
495

496
static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
497
{
498
    uint32_t multiplier = 1;
499
    uint32_t clkin = aspeed_scu_get_clkin(s);
500

501
    if (hpll_reg & SCU_H_PLL_OFF) {
502
        return 0;
503
    }
504

505
    if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
506
        uint32_t p = (hpll_reg >> 13) & 0x3f;
507
        uint32_t m = (hpll_reg >> 5) & 0xff;
508
        uint32_t n = hpll_reg & 0x1f;
509

510
        multiplier = ((m + 1) / (n + 1)) / (p + 1);
511
    }
512

513
    return clkin * multiplier;
514
}
515

516
static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
517
{
518
    uint32_t multiplier = 1;
519
    uint32_t clkin = aspeed_scu_get_clkin(s);
520

521
    if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
522
        return 0;
523
    }
524

525
    if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) {
526
        uint32_t p = (hpll_reg >> 19) & 0xf;
527
        uint32_t n = (hpll_reg >> 13) & 0x3f;
528
        uint32_t m = hpll_reg & 0x1fff;
529

530
        multiplier = ((m + 1) / (n + 1)) / (p + 1);
531
    }
532

533
    return clkin * multiplier;
534
}
535

536
static void aspeed_scu_reset(DeviceState *dev)
537
{
538
    AspeedSCUState *s = ASPEED_SCU(dev);
539
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
540

541
    memcpy(s->regs, asc->resets, asc->nr_regs * 4);
542
    s->regs[SILICON_REV] = s->silicon_rev;
543
    s->regs[HW_STRAP1] = s->hw_strap1;
544
    s->regs[HW_STRAP2] = s->hw_strap2;
545
    s->regs[PROT_KEY] = s->hw_prot_key;
546
}
547

548
static uint32_t aspeed_silicon_revs[] = {
549
    AST2400_A0_SILICON_REV,
550
    AST2400_A1_SILICON_REV,
551
    AST2500_A0_SILICON_REV,
552
    AST2500_A1_SILICON_REV,
553
    AST2600_A0_SILICON_REV,
554
    AST2600_A1_SILICON_REV,
555
    AST2600_A2_SILICON_REV,
556
    AST2600_A3_SILICON_REV,
557
    AST1030_A0_SILICON_REV,
558
    AST1030_A1_SILICON_REV,
559
    AST2700_A0_SILICON_REV,
560
    AST2720_A0_SILICON_REV,
561
    AST2750_A0_SILICON_REV,
562
};
563

564
bool is_supported_silicon_rev(uint32_t silicon_rev)
565
{
566
    int i;
567

568
    for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
569
        if (silicon_rev == aspeed_silicon_revs[i]) {
570
            return true;
571
        }
572
    }
573

574
    return false;
575
}
576

577
static void aspeed_scu_realize(DeviceState *dev, Error **errp)
578
{
579
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
580
    AspeedSCUState *s = ASPEED_SCU(dev);
581
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
582

583
    if (!is_supported_silicon_rev(s->silicon_rev)) {
584
        error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
585
                s->silicon_rev);
586
        return;
587
    }
588

589
    memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
590
                          TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
591

592
    sysbus_init_mmio(sbd, &s->iomem);
593
}
594

595
static const VMStateDescription vmstate_aspeed_scu = {
596
    .name = "aspeed.scu",
597
    .version_id = 2,
598
    .minimum_version_id = 2,
599
    .fields = (const VMStateField[]) {
600
        VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
601
        VMSTATE_END_OF_LIST()
602
    }
603
};
604

605
static Property aspeed_scu_properties[] = {
606
    DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
607
    DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
608
    DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
609
    DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
610
    DEFINE_PROP_END_OF_LIST(),
611
};
612

613
static void aspeed_scu_class_init(ObjectClass *klass, void *data)
614
{
615
    DeviceClass *dc = DEVICE_CLASS(klass);
616
    dc->realize = aspeed_scu_realize;
617
    dc->reset = aspeed_scu_reset;
618
    dc->desc = "ASPEED System Control Unit";
619
    dc->vmsd = &vmstate_aspeed_scu;
620
    device_class_set_props(dc, aspeed_scu_properties);
621
}
622

623
static const TypeInfo aspeed_scu_info = {
624
    .name = TYPE_ASPEED_SCU,
625
    .parent = TYPE_SYS_BUS_DEVICE,
626
    .instance_size = sizeof(AspeedSCUState),
627
    .class_init = aspeed_scu_class_init,
628
    .class_size    = sizeof(AspeedSCUClass),
629
    .abstract      = true,
630
};
631

632
static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
633
{
634
    DeviceClass *dc = DEVICE_CLASS(klass);
635
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
636

637
    dc->desc = "ASPEED 2400 System Control Unit";
638
    asc->resets = ast2400_a0_resets;
639
    asc->calc_hpll = aspeed_2400_scu_calc_hpll;
640
    asc->get_apb = aspeed_2400_scu_get_apb_freq;
641
    asc->apb_divider = 2;
642
    asc->nr_regs = ASPEED_SCU_NR_REGS;
643
    asc->clkin_25Mhz = false;
644
    asc->ops = &aspeed_ast2400_scu_ops;
645
}
646

647
static const TypeInfo aspeed_2400_scu_info = {
648
    .name = TYPE_ASPEED_2400_SCU,
649
    .parent = TYPE_ASPEED_SCU,
650
    .instance_size = sizeof(AspeedSCUState),
651
    .class_init = aspeed_2400_scu_class_init,
652
};
653

654
static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
655
{
656
    DeviceClass *dc = DEVICE_CLASS(klass);
657
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
658

659
    dc->desc = "ASPEED 2500 System Control Unit";
660
    asc->resets = ast2500_a1_resets;
661
    asc->calc_hpll = aspeed_2500_scu_calc_hpll;
662
    asc->get_apb = aspeed_2400_scu_get_apb_freq;
663
    asc->apb_divider = 4;
664
    asc->nr_regs = ASPEED_SCU_NR_REGS;
665
    asc->clkin_25Mhz = false;
666
    asc->ops = &aspeed_ast2500_scu_ops;
667
}
668

669
static const TypeInfo aspeed_2500_scu_info = {
670
    .name = TYPE_ASPEED_2500_SCU,
671
    .parent = TYPE_ASPEED_SCU,
672
    .instance_size = sizeof(AspeedSCUState),
673
    .class_init = aspeed_2500_scu_class_init,
674
};
675

676
static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
677
                                        unsigned size)
678
{
679
    AspeedSCUState *s = ASPEED_SCU(opaque);
680
    int reg = TO_REG(offset);
681

682
    if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
683
        qemu_log_mask(LOG_GUEST_ERROR,
684
                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
685
                      __func__, offset);
686
        return 0;
687
    }
688

689
    switch (reg) {
690
    case AST2600_HPLL_EXT:
691
    case AST2600_EPLL_EXT:
692
    case AST2600_MPLL_EXT:
693
        /* PLLs are always "locked" */
694
        return s->regs[reg] | BIT(31);
695
    case AST2600_RNG_DATA:
696
        /*
697
         * On hardware, RNG_DATA works regardless of the state of the
698
         * enable bit in RNG_CTRL
699
         *
700
         * TODO: Check this is true for ast2600
701
         */
702
        s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
703
        break;
704
    }
705

706
    trace_aspeed_scu_read(offset, size, s->regs[reg]);
707
    return s->regs[reg];
708
}
709

710
static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
711
                                     uint64_t data64, unsigned size)
712
{
713
    AspeedSCUState *s = ASPEED_SCU(opaque);
714
    int reg = TO_REG(offset);
715
    /* Truncate here so bitwise operations below behave as expected */
716
    uint32_t data = data64;
717

718
    if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
719
        qemu_log_mask(LOG_GUEST_ERROR,
720
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
721
                      __func__, offset);
722
        return;
723
    }
724

725
    if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
726
        qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
727
    }
728

729
    trace_aspeed_scu_write(offset, size, data);
730

731
    switch (reg) {
732
    case AST2600_PROT_KEY:
733
        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
734
        return;
735
    case AST2600_HW_STRAP1:
736
    case AST2600_HW_STRAP2:
737
        if (s->regs[reg + 2]) {
738
            return;
739
        }
740
        /* fall through */
741
    case AST2600_SYS_RST_CTRL:
742
    case AST2600_SYS_RST_CTRL2:
743
    case AST2600_CLK_STOP_CTRL:
744
    case AST2600_CLK_STOP_CTRL2:
745
        /* W1S (Write 1 to set) registers */
746
        s->regs[reg] |= data;
747
        return;
748
    case AST2600_SYS_RST_CTRL_CLR:
749
    case AST2600_SYS_RST_CTRL2_CLR:
750
    case AST2600_CLK_STOP_CTRL_CLR:
751
    case AST2600_CLK_STOP_CTRL2_CLR:
752
    case AST2600_HW_STRAP1_CLR:
753
    case AST2600_HW_STRAP2_CLR:
754
        /*
755
         * W1C (Write 1 to clear) registers are offset by one address from
756
         * the data register
757
         */
758
        s->regs[reg - 1] &= ~data;
759
        return;
760

761
    case AST2600_RNG_DATA:
762
    case AST2600_SILICON_REV:
763
    case AST2600_SILICON_REV2:
764
    case AST2600_CHIP_ID0:
765
    case AST2600_CHIP_ID1:
766
        /* Add read only registers here */
767
        qemu_log_mask(LOG_GUEST_ERROR,
768
                      "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
769
                      __func__, offset);
770
        return;
771
    }
772

773
    s->regs[reg] = data;
774
}
775

776
static const MemoryRegionOps aspeed_ast2600_scu_ops = {
777
    .read = aspeed_ast2600_scu_read,
778
    .write = aspeed_ast2600_scu_write,
779
    .endianness = DEVICE_LITTLE_ENDIAN,
780
    .valid.min_access_size = 4,
781
    .valid.max_access_size = 4,
782
    .valid.unaligned = false,
783
};
784

785
static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
786
    [AST2600_SYS_RST_CTRL]      = 0xF7C3FED8,
787
    [AST2600_SYS_RST_CTRL2]     = 0x0DFFFFFC,
788
    [AST2600_CLK_STOP_CTRL]     = 0xFFFF7F8A,
789
    [AST2600_CLK_STOP_CTRL2]    = 0xFFF0FFF0,
790
    [AST2600_DEBUG_CTRL]        = 0x00000FFF,
791
    [AST2600_DEBUG_CTRL2]       = 0x000000FF,
792
    [AST2600_SDRAM_HANDSHAKE]   = 0x00000000,
793
    [AST2600_HPLL_PARAM]        = 0x1000408F,
794
    [AST2600_APLL_PARAM]        = 0x1000405F,
795
    [AST2600_MPLL_PARAM]        = 0x1008405F,
796
    [AST2600_EPLL_PARAM]        = 0x1004077F,
797
    [AST2600_DPLL_PARAM]        = 0x1078405F,
798
    [AST2600_CLK_SEL]           = 0xF3940000,
799
    [AST2600_CLK_SEL2]          = 0x00700000,
800
    [AST2600_CLK_SEL3]          = 0x00000000,
801
    [AST2600_CLK_SEL4]          = 0xF3F40000,
802
    [AST2600_CLK_SEL5]          = 0x30000000,
803
    [AST2600_UARTCLK]           = 0x00014506,
804
    [AST2600_HUARTCLK]          = 0x000145C0,
805
    [AST2600_CHIP_ID0]          = 0x1234ABCD,
806
    [AST2600_CHIP_ID1]          = 0x88884444,
807
};
808

809
static void aspeed_ast2600_scu_reset(DeviceState *dev)
810
{
811
    AspeedSCUState *s = ASPEED_SCU(dev);
812
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
813

814
    memcpy(s->regs, asc->resets, asc->nr_regs * 4);
815

816
    /*
817
     * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
818
     * of actual revision. QEMU and Linux only support A1 onwards so this is
819
     * sufficient.
820
     */
821
    s->regs[AST2600_SILICON_REV] = AST2600_A3_SILICON_REV;
822
    s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
823
    s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
824
    s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
825
    s->regs[PROT_KEY] = s->hw_prot_key;
826
}
827

828
static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
829
{
830
    DeviceClass *dc = DEVICE_CLASS(klass);
831
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
832

833
    dc->desc = "ASPEED 2600 System Control Unit";
834
    dc->reset = aspeed_ast2600_scu_reset;
835
    asc->resets = ast2600_a3_resets;
836
    asc->calc_hpll = aspeed_2600_scu_calc_hpll;
837
    asc->get_apb = aspeed_2600_scu_get_apb_freq;
838
    asc->apb_divider = 4;
839
    asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
840
    asc->clkin_25Mhz = true;
841
    asc->ops = &aspeed_ast2600_scu_ops;
842
}
843

844
static const TypeInfo aspeed_2600_scu_info = {
845
    .name = TYPE_ASPEED_2600_SCU,
846
    .parent = TYPE_ASPEED_SCU,
847
    .instance_size = sizeof(AspeedSCUState),
848
    .class_init = aspeed_2600_scu_class_init,
849
};
850

851
static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
852
                                        unsigned size)
853
{
854
    AspeedSCUState *s = ASPEED_SCU(opaque);
855
    int reg = TO_REG(offset);
856

857
    if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
858
        qemu_log_mask(LOG_GUEST_ERROR,
859
                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
860
                __func__, offset);
861
        return 0;
862
    }
863

864
    switch (reg) {
865
    default:
866
        qemu_log_mask(LOG_GUEST_ERROR,
867
                      "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
868
                      __func__, offset);
869
    }
870

871
    trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
872
    return s->regs[reg];
873
}
874

875
static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
876
                                     uint64_t data64, unsigned size)
877
{
878
    AspeedSCUState *s = ASPEED_SCU(opaque);
879
    int reg = TO_REG(offset);
880
    /* Truncate here so bitwise operations below behave as expected */
881
    uint32_t data = data64;
882

883
    if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
884
        qemu_log_mask(LOG_GUEST_ERROR,
885
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
886
                __func__, offset);
887
        return;
888
    }
889

890
    trace_aspeed_ast2700_scu_write(offset, size, data);
891

892
    switch (reg) {
893
    default:
894
        qemu_log_mask(LOG_GUEST_ERROR,
895
                      "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
896
                      __func__, offset);
897
        break;
898
    }
899

900
    s->regs[reg] = data;
901
}
902

903
static const MemoryRegionOps aspeed_ast2700_scu_ops = {
904
    .read = aspeed_ast2700_scu_read,
905
    .write = aspeed_ast2700_scu_write,
906
    .endianness = DEVICE_LITTLE_ENDIAN,
907
    .valid.min_access_size = 1,
908
    .valid.max_access_size = 8,
909
    .valid.unaligned = false,
910
};
911

912
static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
913
    [AST2700_SILICON_REV]           = AST2700_A0_SILICON_REV,
914
    [AST2700_HW_STRAP1]             = 0x00000800,
915
    [AST2700_HW_STRAP1_CLR]         = 0xFFF0FFF0,
916
    [AST2700_HW_STRAP1_LOCK]        = 0x00000FFF,
917
    [AST2700_HW_STRAP1_SEC1]        = 0x000000FF,
918
    [AST2700_HW_STRAP1_SEC2]        = 0x00000000,
919
    [AST2700_HW_STRAP1_SEC3]        = 0x1000408F,
920
    [AST2700_SCU_HPLL_PARAM]        = 0x0000009f,
921
    [AST2700_SCU_HPLL_EXT_PARAM]    = 0x8000004f,
922
    [AST2700_SCU_DPLL_PARAM]        = 0x0080009f,
923
    [AST2700_SCU_DPLL_EXT_PARAM]    = 0x8000004f,
924
    [AST2700_SCU_MPLL_PARAM]        = 0x00000040,
925
    [AST2700_SCU_MPLL_EXT_PARAM]    = 0x80000000,
926
    [AST2700_SCU_D1CLK_PARAM]       = 0x00050002,
927
    [AST2700_SCU_D2CLK_PARAM]       = 0x00050002,
928
    [AST2700_SCU_CRT1CLK_PARAM]     = 0x00050002,
929
    [AST2700_SCU_CRT2CLK_PARAM]     = 0x00050002,
930
    [AST2700_SCU_MPHYCLK_PARAM]     = 0x0000004c,
931
    [AST2700_SCU_FREQ_CNTR]         = 0x000375eb,
932
    [AST2700_SCU_CPU_SCRATCH_0]     = 0x00000000,
933
    [AST2700_SCU_CPU_SCRATCH_1]     = 0x00000004,
934
};
935

936
static void aspeed_ast2700_scu_reset(DeviceState *dev)
937
{
938
    AspeedSCUState *s = ASPEED_SCU(dev);
939
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
940

941
    memcpy(s->regs, asc->resets, asc->nr_regs * 4);
942
}
943

944
static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
945
{
946
    DeviceClass *dc = DEVICE_CLASS(klass);
947
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
948

949
    dc->desc = "ASPEED 2700 System Control Unit";
950
    dc->reset = aspeed_ast2700_scu_reset;
951
    asc->resets = ast2700_a0_resets;
952
    asc->calc_hpll = aspeed_2600_scu_calc_hpll;
953
    asc->get_apb = aspeed_2700_scu_get_apb_freq;
954
    asc->apb_divider = 4;
955
    asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
956
    asc->clkin_25Mhz = true;
957
    asc->ops = &aspeed_ast2700_scu_ops;
958
}
959

960
static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
961
                                        unsigned size)
962
{
963
    AspeedSCUState *s = ASPEED_SCU(opaque);
964
    int reg = TO_REG(offset);
965
    if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
966
        qemu_log_mask(LOG_GUEST_ERROR,
967
                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
968
                __func__, offset);
969
        return 0;
970
    }
971

972
    switch (reg) {
973
    default:
974
        qemu_log_mask(LOG_GUEST_ERROR,
975
                      "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
976
                      __func__, offset);
977
    }
978

979
    trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
980
    return s->regs[reg];
981
}
982

983
static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
984
                                     uint64_t data64, unsigned size)
985
{
986
    AspeedSCUState *s = ASPEED_SCU(opaque);
987
    int reg = TO_REG(offset);
988
    /* Truncate here so bitwise operations below behave as expected */
989
    uint32_t data = data64;
990
    bool updated = false;
991

992
    if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
993
        qemu_log_mask(LOG_GUEST_ERROR,
994
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
995
                __func__, offset);
996
        return;
997
    }
998

999
    trace_aspeed_ast2700_scuio_write(offset, size, data);
1000

1001
    switch (reg) {
1002
    case AST2700_SCUIO_CLK_STOP_CTL_1:
1003
    case AST2700_SCUIO_CLK_STOP_CTL_2:
1004
        s->regs[reg] |= data;
1005
        updated = true;
1006
        break;
1007
    case AST2700_SCUIO_CLK_STOP_CLR_1:
1008
    case AST2700_SCUIO_CLK_STOP_CLR_2:
1009
        s->regs[reg - 1] ^= data;
1010
        updated = true;
1011
        break;
1012
    default:
1013
        qemu_log_mask(LOG_GUEST_ERROR,
1014
                      "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
1015
                      __func__, offset);
1016
        break;
1017
    }
1018

1019
    if (!updated) {
1020
        s->regs[reg] = data;
1021
    }
1022
}
1023

1024
static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
1025
    .read = aspeed_ast2700_scuio_read,
1026
    .write = aspeed_ast2700_scuio_write,
1027
    .endianness = DEVICE_LITTLE_ENDIAN,
1028
    .valid.min_access_size = 1,
1029
    .valid.max_access_size = 8,
1030
    .valid.unaligned = false,
1031
};
1032

1033
static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
1034
    [AST2700_SILICON_REV]               = 0x06000003,
1035
    [AST2700_HW_STRAP1]                 = 0x00000504,
1036
    [AST2700_HW_STRAP1_CLR]             = 0xFFF0FFF0,
1037
    [AST2700_HW_STRAP1_LOCK]            = 0x00000FFF,
1038
    [AST2700_HW_STRAP1_SEC1]            = 0x000000FF,
1039
    [AST2700_HW_STRAP1_SEC2]            = 0x00000000,
1040
    [AST2700_HW_STRAP1_SEC3]            = 0x1000408F,
1041
    [AST2700_SCUIO_CLK_STOP_CTL_1]      = 0xffff8400,
1042
    [AST2700_SCUIO_CLK_STOP_CTL_2]      = 0x00005f30,
1043
    [AST2700_SCUIO_CLK_SEL_1]           = 0x86900000,
1044
    [AST2700_SCUIO_CLK_SEL_2]           = 0x00400000,
1045
    [AST2700_SCUIO_HPLL_PARAM]          = 0x10000027,
1046
    [AST2700_SCUIO_HPLL_EXT_PARAM]      = 0x80000014,
1047
    [AST2700_SCUIO_APLL_PARAM]          = 0x1000001f,
1048
    [AST2700_SCUIO_APLL_EXT_PARAM]      = 0x8000000f,
1049
    [AST2700_SCUIO_DPLL_PARAM]          = 0x106e42ce,
1050
    [AST2700_SCUIO_DPLL_EXT_PARAM]      = 0x80000167,
1051
    [AST2700_SCUIO_DPLL_PARAM_READ]     = 0x106e42ce,
1052
    [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
1053
    [AST2700_SCUIO_UARTCLK_GEN]         = 0x00014506,
1054
    [AST2700_SCUIO_HUARTCLK_GEN]        = 0x000145c0,
1055
    [AST2700_SCUIO_CLK_DUTY_MEAS_RST]   = 0x0c9100d2,
1056
};
1057

1058
static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
1059
{
1060
    DeviceClass *dc = DEVICE_CLASS(klass);
1061
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1062

1063
    dc->desc = "ASPEED 2700 System Control Unit I/O";
1064
    dc->reset = aspeed_ast2700_scu_reset;
1065
    asc->resets = ast2700_a0_resets_io;
1066
    asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1067
    asc->get_apb = aspeed_2700_scuio_get_apb_freq;
1068
    asc->apb_divider = 2;
1069
    asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
1070
    asc->clkin_25Mhz = true;
1071
    asc->ops = &aspeed_ast2700_scuio_ops;
1072
}
1073

1074
static const TypeInfo aspeed_2700_scu_info = {
1075
    .name = TYPE_ASPEED_2700_SCU,
1076
    .parent = TYPE_ASPEED_SCU,
1077
    .instance_size = sizeof(AspeedSCUState),
1078
    .class_init = aspeed_2700_scu_class_init,
1079
};
1080

1081
static const TypeInfo aspeed_2700_scuio_info = {
1082
    .name = TYPE_ASPEED_2700_SCUIO,
1083
    .parent = TYPE_ASPEED_SCU,
1084
    .instance_size = sizeof(AspeedSCUState),
1085
    .class_init = aspeed_2700_scuio_class_init,
1086
};
1087

1088
static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
1089
    [AST2600_SYS_RST_CTRL]      = 0xFFC3FED8,
1090
    [AST2600_SYS_RST_CTRL2]     = 0x09FFFFFC,
1091
    [AST2600_CLK_STOP_CTRL]     = 0xFFFF7F8A,
1092
    [AST2600_CLK_STOP_CTRL2]    = 0xFFF0FFF0,
1093
    [AST2600_DEBUG_CTRL2]       = 0x00000000,
1094
    [AST2600_HPLL_PARAM]        = 0x10004077,
1095
    [AST2600_HPLL_EXT]          = 0x00000031,
1096
    [AST2600_CLK_SEL4]          = 0x43F90900,
1097
    [AST2600_CLK_SEL5]          = 0x40000000,
1098
    [AST2600_CHIP_ID0]          = 0xDEADBEEF,
1099
    [AST2600_CHIP_ID1]          = 0x0BADCAFE,
1100
};
1101

1102
static void aspeed_ast1030_scu_reset(DeviceState *dev)
1103
{
1104
    AspeedSCUState *s = ASPEED_SCU(dev);
1105
    AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
1106

1107
    memcpy(s->regs, asc->resets, asc->nr_regs * 4);
1108

1109
    s->regs[AST2600_SILICON_REV] = AST1030_A1_SILICON_REV;
1110
    s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
1111
    s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
1112
    s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
1113
    s->regs[PROT_KEY] = s->hw_prot_key;
1114
}
1115

1116
static void aspeed_1030_scu_class_init(ObjectClass *klass, void *data)
1117
{
1118
    DeviceClass *dc = DEVICE_CLASS(klass);
1119
    AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
1120

1121
    dc->desc = "ASPEED 1030 System Control Unit";
1122
    dc->reset = aspeed_ast1030_scu_reset;
1123
    asc->resets = ast1030_a1_resets;
1124
    asc->calc_hpll = aspeed_2600_scu_calc_hpll;
1125
    asc->get_apb = aspeed_1030_scu_get_apb_freq;
1126
    asc->apb_divider = 2;
1127
    asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
1128
    asc->clkin_25Mhz = true;
1129
    asc->ops = &aspeed_ast2600_scu_ops;
1130
}
1131

1132
static const TypeInfo aspeed_1030_scu_info = {
1133
    .name = TYPE_ASPEED_1030_SCU,
1134
    .parent = TYPE_ASPEED_SCU,
1135
    .instance_size = sizeof(AspeedSCUState),
1136
    .class_init = aspeed_1030_scu_class_init,
1137
};
1138

1139
static void aspeed_scu_register_types(void)
1140
{
1141
    type_register_static(&aspeed_scu_info);
1142
    type_register_static(&aspeed_2400_scu_info);
1143
    type_register_static(&aspeed_2500_scu_info);
1144
    type_register_static(&aspeed_2600_scu_info);
1145
    type_register_static(&aspeed_1030_scu_info);
1146
    type_register_static(&aspeed_2700_scu_info);
1147
    type_register_static(&aspeed_2700_scuio_info);
1148
}
1149

1150
type_init(aspeed_scu_register_types);
1151

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.