qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

aspeed_scu.c (27114B)


      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 SCU_IO_REGION_SIZE 0x1000
    138 
    139 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
    140      [SYS_RST_CTRL]    = 0xFFCFFEDCU,
    141      [CLK_SEL]         = 0xF3F40000U,
    142      [CLK_STOP_CTRL]   = 0x19FC3E8BU,
    143      [D2PLL_PARAM]     = 0x00026108U,
    144      [MPLL_PARAM]      = 0x00030291U,
    145      [HPLL_PARAM]      = 0x00000291U,
    146      [MISC_CTRL1]      = 0x00000010U,
    147      [PCI_CTRL1]       = 0x20001A03U,
    148      [PCI_CTRL2]       = 0x20001A03U,
    149      [PCI_CTRL3]       = 0x04000030U,
    150      [SYS_RST_STATUS]  = 0x00000001U,
    151      [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
    152      [MISC_CTRL2]      = 0x00000023U,
    153      [RNG_CTRL]        = 0x0000000EU,
    154      [PINMUX_CTRL2]    = 0x0000F000U,
    155      [PINMUX_CTRL3]    = 0x01000000U,
    156      [PINMUX_CTRL4]    = 0x000000FFU,
    157      [PINMUX_CTRL5]    = 0x0000A000U,
    158      [WDT_RST_CTRL]    = 0x003FFFF3U,
    159      [PINMUX_CTRL8]    = 0xFFFF0000U,
    160      [PINMUX_CTRL9]    = 0x000FFFFFU,
    161      [FREE_CNTR4]      = 0x000000FFU,
    162      [FREE_CNTR4_EXT]  = 0x000000FFU,
    163      [CPU2_BASE_SEG1]  = 0x80000000U,
    164      [CPU2_BASE_SEG4]  = 0x1E600000U,
    165      [CPU2_BASE_SEG5]  = 0xC0000000U,
    166      [UART_HPLL_CLK]   = 0x00001903U,
    167      [PCIE_CTRL]       = 0x0000007BU,
    168      [BMC_DEV_ID]      = 0x00002402U
    169 };
    170 
    171 /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
    172 /* AST2500 revision A1 */
    173 
    174 static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
    175      [SYS_RST_CTRL]    = 0xFFCFFEDCU,
    176      [CLK_SEL]         = 0xF3F40000U,
    177      [CLK_STOP_CTRL]   = 0x19FC3E8BU,
    178      [D2PLL_PARAM]     = 0x00026108U,
    179      [MPLL_PARAM]      = 0x00030291U,
    180      [HPLL_PARAM]      = 0x93000400U,
    181      [MISC_CTRL1]      = 0x00000010U,
    182      [PCI_CTRL1]       = 0x20001A03U,
    183      [PCI_CTRL2]       = 0x20001A03U,
    184      [PCI_CTRL3]       = 0x04000030U,
    185      [SYS_RST_STATUS]  = 0x00000001U,
    186      [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
    187      [MISC_CTRL2]      = 0x00000023U,
    188      [RNG_CTRL]        = 0x0000000EU,
    189      [PINMUX_CTRL2]    = 0x0000F000U,
    190      [PINMUX_CTRL3]    = 0x03000000U,
    191      [PINMUX_CTRL4]    = 0x00000000U,
    192      [PINMUX_CTRL5]    = 0x0000A000U,
    193      [WDT_RST_CTRL]    = 0x023FFFF3U,
    194      [PINMUX_CTRL8]    = 0xFFFF0000U,
    195      [PINMUX_CTRL9]    = 0x000FFFFFU,
    196      [FREE_CNTR4]      = 0x000000FFU,
    197      [FREE_CNTR4_EXT]  = 0x000000FFU,
    198      [CPU2_BASE_SEG1]  = 0x80000000U,
    199      [CPU2_BASE_SEG4]  = 0x1E600000U,
    200      [CPU2_BASE_SEG5]  = 0xC0000000U,
    201      [CHIP_ID0]        = 0x1234ABCDU,
    202      [CHIP_ID1]        = 0x88884444U,
    203      [UART_HPLL_CLK]   = 0x00001903U,
    204      [PCIE_CTRL]       = 0x0000007BU,
    205      [BMC_DEV_ID]      = 0x00002402U
    206 };
    207 
    208 static uint32_t aspeed_scu_get_random(void)
    209 {
    210     uint32_t num;
    211     qemu_guest_getrandom_nofail(&num, sizeof(num));
    212     return num;
    213 }
    214 
    215 uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
    216 {
    217     return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
    218 }
    219 
    220 static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState *s)
    221 {
    222     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
    223     uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
    224 
    225     return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
    226         / asc->apb_divider;
    227 }
    228 
    229 static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
    230 {
    231     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
    232     uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
    233 
    234     return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
    235         / asc->apb_divider;
    236 }
    237 
    238 static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
    239 {
    240     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
    241     uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
    242 
    243     return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
    244         / asc->apb_divider;
    245 }
    246 
    247 static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
    248 {
    249     AspeedSCUState *s = ASPEED_SCU(opaque);
    250     int reg = TO_REG(offset);
    251 
    252     if (reg >= ASPEED_SCU_NR_REGS) {
    253         qemu_log_mask(LOG_GUEST_ERROR,
    254                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
    255                       __func__, offset);
    256         return 0;
    257     }
    258 
    259     switch (reg) {
    260     case RNG_DATA:
    261         /* On hardware, RNG_DATA works regardless of
    262          * the state of the enable bit in RNG_CTRL
    263          */
    264         s->regs[RNG_DATA] = aspeed_scu_get_random();
    265         break;
    266     case WAKEUP_EN:
    267         qemu_log_mask(LOG_GUEST_ERROR,
    268                       "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
    269                       __func__, offset);
    270         break;
    271     }
    272 
    273     trace_aspeed_scu_read(offset, size, s->regs[reg]);
    274     return s->regs[reg];
    275 }
    276 
    277 static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
    278                                      uint64_t data, unsigned size)
    279 {
    280     AspeedSCUState *s = ASPEED_SCU(opaque);
    281     int reg = TO_REG(offset);
    282 
    283     if (reg >= ASPEED_SCU_NR_REGS) {
    284         qemu_log_mask(LOG_GUEST_ERROR,
    285                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
    286                       __func__, offset);
    287         return;
    288     }
    289 
    290     if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
    291             !s->regs[PROT_KEY]) {
    292         qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
    293     }
    294 
    295     trace_aspeed_scu_write(offset, size, data);
    296 
    297     switch (reg) {
    298     case PROT_KEY:
    299         s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
    300         return;
    301     case SILICON_REV:
    302     case FREQ_CNTR_EVAL:
    303     case VGA_SCRATCH1 ... VGA_SCRATCH8:
    304     case RNG_DATA:
    305     case FREE_CNTR4:
    306     case FREE_CNTR4_EXT:
    307         qemu_log_mask(LOG_GUEST_ERROR,
    308                       "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
    309                       __func__, offset);
    310         return;
    311     }
    312 
    313     s->regs[reg] = data;
    314 }
    315 
    316 static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
    317                                      uint64_t data, unsigned size)
    318 {
    319     AspeedSCUState *s = ASPEED_SCU(opaque);
    320     int reg = TO_REG(offset);
    321 
    322     if (reg >= ASPEED_SCU_NR_REGS) {
    323         qemu_log_mask(LOG_GUEST_ERROR,
    324                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
    325                       __func__, offset);
    326         return;
    327     }
    328 
    329     if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
    330             !s->regs[PROT_KEY]) {
    331         qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
    332         return;
    333     }
    334 
    335     trace_aspeed_scu_write(offset, size, data);
    336 
    337     switch (reg) {
    338     case PROT_KEY:
    339         s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
    340         return;
    341     case HW_STRAP1:
    342         s->regs[HW_STRAP1] |= data;
    343         return;
    344     case SILICON_REV:
    345         s->regs[HW_STRAP1] &= ~data;
    346         return;
    347     case FREQ_CNTR_EVAL:
    348     case VGA_SCRATCH1 ... VGA_SCRATCH8:
    349     case RNG_DATA:
    350     case FREE_CNTR4:
    351     case FREE_CNTR4_EXT:
    352     case CHIP_ID0:
    353     case CHIP_ID1:
    354         qemu_log_mask(LOG_GUEST_ERROR,
    355                       "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
    356                       __func__, offset);
    357         return;
    358     }
    359 
    360     s->regs[reg] = data;
    361 }
    362 
    363 static const MemoryRegionOps aspeed_ast2400_scu_ops = {
    364     .read = aspeed_scu_read,
    365     .write = aspeed_ast2400_scu_write,
    366     .endianness = DEVICE_LITTLE_ENDIAN,
    367     .valid = {
    368         .min_access_size = 1,
    369         .max_access_size = 4,
    370     },
    371 };
    372 
    373 static const MemoryRegionOps aspeed_ast2500_scu_ops = {
    374     .read = aspeed_scu_read,
    375     .write = aspeed_ast2500_scu_write,
    376     .endianness = DEVICE_LITTLE_ENDIAN,
    377     .valid.min_access_size = 4,
    378     .valid.max_access_size = 4,
    379     .valid.unaligned = false,
    380 };
    381 
    382 static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
    383 {
    384     if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN ||
    385         ASPEED_SCU_GET_CLASS(s)->clkin_25Mhz) {
    386         return 25000000;
    387     } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
    388         return 48000000;
    389     } else {
    390         return 24000000;
    391     }
    392 }
    393 
    394 /*
    395  * Strapped frequencies for the AST2400 in MHz. They depend on the
    396  * clkin frequency.
    397  */
    398 static const uint32_t hpll_ast2400_freqs[][4] = {
    399     { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
    400     { 400, 375, 350, 425 }, /* 25MHz */
    401 };
    402 
    403 static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
    404 {
    405     uint8_t freq_select;
    406     bool clk_25m_in;
    407     uint32_t clkin = aspeed_scu_get_clkin(s);
    408 
    409     if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
    410         return 0;
    411     }
    412 
    413     if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
    414         uint32_t multiplier = 1;
    415 
    416         if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
    417             uint32_t n  = (hpll_reg >> 5) & 0x3f;
    418             uint32_t od = (hpll_reg >> 4) & 0x1;
    419             uint32_t d  = hpll_reg & 0xf;
    420 
    421             multiplier = (2 - od) * ((n + 2) / (d + 1));
    422         }
    423 
    424         return clkin * multiplier;
    425     }
    426 
    427     /* HW strapping */
    428     clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
    429     freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
    430 
    431     return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
    432 }
    433 
    434 static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
    435 {
    436     uint32_t multiplier = 1;
    437     uint32_t clkin = aspeed_scu_get_clkin(s);
    438 
    439     if (hpll_reg & SCU_H_PLL_OFF) {
    440         return 0;
    441     }
    442 
    443     if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
    444         uint32_t p = (hpll_reg >> 13) & 0x3f;
    445         uint32_t m = (hpll_reg >> 5) & 0xff;
    446         uint32_t n = hpll_reg & 0x1f;
    447 
    448         multiplier = ((m + 1) / (n + 1)) / (p + 1);
    449     }
    450 
    451     return clkin * multiplier;
    452 }
    453 
    454 static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
    455 {
    456     uint32_t multiplier = 1;
    457     uint32_t clkin = aspeed_scu_get_clkin(s);
    458 
    459     if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
    460         return 0;
    461     }
    462 
    463     if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) {
    464         uint32_t p = (hpll_reg >> 19) & 0xf;
    465         uint32_t n = (hpll_reg >> 13) & 0x3f;
    466         uint32_t m = hpll_reg & 0x1fff;
    467 
    468         multiplier = ((m + 1) / (n + 1)) / (p + 1);
    469     }
    470 
    471     return clkin * multiplier;
    472 }
    473 
    474 static void aspeed_scu_reset(DeviceState *dev)
    475 {
    476     AspeedSCUState *s = ASPEED_SCU(dev);
    477     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
    478 
    479     memcpy(s->regs, asc->resets, asc->nr_regs * 4);
    480     s->regs[SILICON_REV] = s->silicon_rev;
    481     s->regs[HW_STRAP1] = s->hw_strap1;
    482     s->regs[HW_STRAP2] = s->hw_strap2;
    483     s->regs[PROT_KEY] = s->hw_prot_key;
    484 }
    485 
    486 static uint32_t aspeed_silicon_revs[] = {
    487     AST2400_A0_SILICON_REV,
    488     AST2400_A1_SILICON_REV,
    489     AST2500_A0_SILICON_REV,
    490     AST2500_A1_SILICON_REV,
    491     AST2600_A0_SILICON_REV,
    492     AST2600_A1_SILICON_REV,
    493     AST2600_A2_SILICON_REV,
    494     AST2600_A3_SILICON_REV,
    495     AST1030_A0_SILICON_REV,
    496     AST1030_A1_SILICON_REV,
    497 };
    498 
    499 bool is_supported_silicon_rev(uint32_t silicon_rev)
    500 {
    501     int i;
    502 
    503     for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
    504         if (silicon_rev == aspeed_silicon_revs[i]) {
    505             return true;
    506         }
    507     }
    508 
    509     return false;
    510 }
    511 
    512 static void aspeed_scu_realize(DeviceState *dev, Error **errp)
    513 {
    514     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    515     AspeedSCUState *s = ASPEED_SCU(dev);
    516     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
    517 
    518     if (!is_supported_silicon_rev(s->silicon_rev)) {
    519         error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
    520                 s->silicon_rev);
    521         return;
    522     }
    523 
    524     memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
    525                           TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
    526 
    527     sysbus_init_mmio(sbd, &s->iomem);
    528 }
    529 
    530 static const VMStateDescription vmstate_aspeed_scu = {
    531     .name = "aspeed.scu",
    532     .version_id = 2,
    533     .minimum_version_id = 2,
    534     .fields = (VMStateField[]) {
    535         VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
    536         VMSTATE_END_OF_LIST()
    537     }
    538 };
    539 
    540 static Property aspeed_scu_properties[] = {
    541     DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
    542     DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
    543     DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
    544     DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
    545     DEFINE_PROP_END_OF_LIST(),
    546 };
    547 
    548 static void aspeed_scu_class_init(ObjectClass *klass, void *data)
    549 {
    550     DeviceClass *dc = DEVICE_CLASS(klass);
    551     dc->realize = aspeed_scu_realize;
    552     dc->reset = aspeed_scu_reset;
    553     dc->desc = "ASPEED System Control Unit";
    554     dc->vmsd = &vmstate_aspeed_scu;
    555     device_class_set_props(dc, aspeed_scu_properties);
    556 }
    557 
    558 static const TypeInfo aspeed_scu_info = {
    559     .name = TYPE_ASPEED_SCU,
    560     .parent = TYPE_SYS_BUS_DEVICE,
    561     .instance_size = sizeof(AspeedSCUState),
    562     .class_init = aspeed_scu_class_init,
    563     .class_size    = sizeof(AspeedSCUClass),
    564     .abstract      = true,
    565 };
    566 
    567 static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
    568 {
    569     DeviceClass *dc = DEVICE_CLASS(klass);
    570     AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
    571 
    572     dc->desc = "ASPEED 2400 System Control Unit";
    573     asc->resets = ast2400_a0_resets;
    574     asc->calc_hpll = aspeed_2400_scu_calc_hpll;
    575     asc->get_apb = aspeed_2400_scu_get_apb_freq;
    576     asc->apb_divider = 2;
    577     asc->nr_regs = ASPEED_SCU_NR_REGS;
    578     asc->clkin_25Mhz = false;
    579     asc->ops = &aspeed_ast2400_scu_ops;
    580 }
    581 
    582 static const TypeInfo aspeed_2400_scu_info = {
    583     .name = TYPE_ASPEED_2400_SCU,
    584     .parent = TYPE_ASPEED_SCU,
    585     .instance_size = sizeof(AspeedSCUState),
    586     .class_init = aspeed_2400_scu_class_init,
    587 };
    588 
    589 static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
    590 {
    591     DeviceClass *dc = DEVICE_CLASS(klass);
    592     AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
    593 
    594     dc->desc = "ASPEED 2500 System Control Unit";
    595     asc->resets = ast2500_a1_resets;
    596     asc->calc_hpll = aspeed_2500_scu_calc_hpll;
    597     asc->get_apb = aspeed_2400_scu_get_apb_freq;
    598     asc->apb_divider = 4;
    599     asc->nr_regs = ASPEED_SCU_NR_REGS;
    600     asc->clkin_25Mhz = false;
    601     asc->ops = &aspeed_ast2500_scu_ops;
    602 }
    603 
    604 static const TypeInfo aspeed_2500_scu_info = {
    605     .name = TYPE_ASPEED_2500_SCU,
    606     .parent = TYPE_ASPEED_SCU,
    607     .instance_size = sizeof(AspeedSCUState),
    608     .class_init = aspeed_2500_scu_class_init,
    609 };
    610 
    611 static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
    612                                         unsigned size)
    613 {
    614     AspeedSCUState *s = ASPEED_SCU(opaque);
    615     int reg = TO_REG(offset);
    616 
    617     if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
    618         qemu_log_mask(LOG_GUEST_ERROR,
    619                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
    620                       __func__, offset);
    621         return 0;
    622     }
    623 
    624     switch (reg) {
    625     case AST2600_HPLL_EXT:
    626     case AST2600_EPLL_EXT:
    627     case AST2600_MPLL_EXT:
    628         /* PLLs are always "locked" */
    629         return s->regs[reg] | BIT(31);
    630     case AST2600_RNG_DATA:
    631         /*
    632          * On hardware, RNG_DATA works regardless of the state of the
    633          * enable bit in RNG_CTRL
    634          *
    635          * TODO: Check this is true for ast2600
    636          */
    637         s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
    638         break;
    639     }
    640 
    641     trace_aspeed_scu_read(offset, size, s->regs[reg]);
    642     return s->regs[reg];
    643 }
    644 
    645 static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
    646                                      uint64_t data64, unsigned size)
    647 {
    648     AspeedSCUState *s = ASPEED_SCU(opaque);
    649     int reg = TO_REG(offset);
    650     /* Truncate here so bitwise operations below behave as expected */
    651     uint32_t data = data64;
    652 
    653     if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
    654         qemu_log_mask(LOG_GUEST_ERROR,
    655                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
    656                       __func__, offset);
    657         return;
    658     }
    659 
    660     if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
    661         qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
    662     }
    663 
    664     trace_aspeed_scu_write(offset, size, data);
    665 
    666     switch (reg) {
    667     case AST2600_PROT_KEY:
    668         s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
    669         return;
    670     case AST2600_HW_STRAP1:
    671     case AST2600_HW_STRAP2:
    672         if (s->regs[reg + 2]) {
    673             return;
    674         }
    675         /* fall through */
    676     case AST2600_SYS_RST_CTRL:
    677     case AST2600_SYS_RST_CTRL2:
    678     case AST2600_CLK_STOP_CTRL:
    679     case AST2600_CLK_STOP_CTRL2:
    680         /* W1S (Write 1 to set) registers */
    681         s->regs[reg] |= data;
    682         return;
    683     case AST2600_SYS_RST_CTRL_CLR:
    684     case AST2600_SYS_RST_CTRL2_CLR:
    685     case AST2600_CLK_STOP_CTRL_CLR:
    686     case AST2600_CLK_STOP_CTRL2_CLR:
    687     case AST2600_HW_STRAP1_CLR:
    688     case AST2600_HW_STRAP2_CLR:
    689         /*
    690          * W1C (Write 1 to clear) registers are offset by one address from
    691          * the data register
    692          */
    693         s->regs[reg - 1] &= ~data;
    694         return;
    695 
    696     case AST2600_RNG_DATA:
    697     case AST2600_SILICON_REV:
    698     case AST2600_SILICON_REV2:
    699     case AST2600_CHIP_ID0:
    700     case AST2600_CHIP_ID1:
    701         /* Add read only registers here */
    702         qemu_log_mask(LOG_GUEST_ERROR,
    703                       "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
    704                       __func__, offset);
    705         return;
    706     }
    707 
    708     s->regs[reg] = data;
    709 }
    710 
    711 static const MemoryRegionOps aspeed_ast2600_scu_ops = {
    712     .read = aspeed_ast2600_scu_read,
    713     .write = aspeed_ast2600_scu_write,
    714     .endianness = DEVICE_LITTLE_ENDIAN,
    715     .valid.min_access_size = 4,
    716     .valid.max_access_size = 4,
    717     .valid.unaligned = false,
    718 };
    719 
    720 static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
    721     [AST2600_SYS_RST_CTRL]      = 0xF7C3FED8,
    722     [AST2600_SYS_RST_CTRL2]     = 0x0DFFFFFC,
    723     [AST2600_CLK_STOP_CTRL]     = 0xFFFF7F8A,
    724     [AST2600_CLK_STOP_CTRL2]    = 0xFFF0FFF0,
    725     [AST2600_DEBUG_CTRL]        = 0x00000FFF,
    726     [AST2600_DEBUG_CTRL2]       = 0x000000FF,
    727     [AST2600_SDRAM_HANDSHAKE]   = 0x00000000,
    728     [AST2600_HPLL_PARAM]        = 0x1000408F,
    729     [AST2600_APLL_PARAM]        = 0x1000405F,
    730     [AST2600_MPLL_PARAM]        = 0x1008405F,
    731     [AST2600_EPLL_PARAM]        = 0x1004077F,
    732     [AST2600_DPLL_PARAM]        = 0x1078405F,
    733     [AST2600_CLK_SEL]           = 0xF3940000,
    734     [AST2600_CLK_SEL2]          = 0x00700000,
    735     [AST2600_CLK_SEL3]          = 0x00000000,
    736     [AST2600_CLK_SEL4]          = 0xF3F40000,
    737     [AST2600_CLK_SEL5]          = 0x30000000,
    738     [AST2600_UARTCLK]           = 0x00014506,
    739     [AST2600_HUARTCLK]          = 0x000145C0,
    740     [AST2600_CHIP_ID0]          = 0x1234ABCD,
    741     [AST2600_CHIP_ID1]          = 0x88884444,
    742 };
    743 
    744 static void aspeed_ast2600_scu_reset(DeviceState *dev)
    745 {
    746     AspeedSCUState *s = ASPEED_SCU(dev);
    747     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
    748 
    749     memcpy(s->regs, asc->resets, asc->nr_regs * 4);
    750 
    751     /*
    752      * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
    753      * of actual revision. QEMU and Linux only support A1 onwards so this is
    754      * sufficient.
    755      */
    756     s->regs[AST2600_SILICON_REV] = AST2600_A3_SILICON_REV;
    757     s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
    758     s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
    759     s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
    760     s->regs[PROT_KEY] = s->hw_prot_key;
    761 }
    762 
    763 static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
    764 {
    765     DeviceClass *dc = DEVICE_CLASS(klass);
    766     AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
    767 
    768     dc->desc = "ASPEED 2600 System Control Unit";
    769     dc->reset = aspeed_ast2600_scu_reset;
    770     asc->resets = ast2600_a3_resets;
    771     asc->calc_hpll = aspeed_2600_scu_calc_hpll;
    772     asc->get_apb = aspeed_2600_scu_get_apb_freq;
    773     asc->apb_divider = 4;
    774     asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
    775     asc->clkin_25Mhz = true;
    776     asc->ops = &aspeed_ast2600_scu_ops;
    777 }
    778 
    779 static const TypeInfo aspeed_2600_scu_info = {
    780     .name = TYPE_ASPEED_2600_SCU,
    781     .parent = TYPE_ASPEED_SCU,
    782     .instance_size = sizeof(AspeedSCUState),
    783     .class_init = aspeed_2600_scu_class_init,
    784 };
    785 
    786 static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
    787     [AST2600_SYS_RST_CTRL]      = 0xFFC3FED8,
    788     [AST2600_SYS_RST_CTRL2]     = 0x09FFFFFC,
    789     [AST2600_CLK_STOP_CTRL]     = 0xFFFF7F8A,
    790     [AST2600_CLK_STOP_CTRL2]    = 0xFFF0FFF0,
    791     [AST2600_DEBUG_CTRL2]       = 0x00000000,
    792     [AST2600_HPLL_PARAM]        = 0x10004077,
    793     [AST2600_HPLL_EXT]          = 0x00000031,
    794     [AST2600_CLK_SEL4]          = 0x43F90900,
    795     [AST2600_CLK_SEL5]          = 0x40000000,
    796     [AST2600_CHIP_ID0]          = 0xDEADBEEF,
    797     [AST2600_CHIP_ID1]          = 0x0BADCAFE,
    798 };
    799 
    800 static void aspeed_ast1030_scu_reset(DeviceState *dev)
    801 {
    802     AspeedSCUState *s = ASPEED_SCU(dev);
    803     AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
    804 
    805     memcpy(s->regs, asc->resets, asc->nr_regs * 4);
    806 
    807     s->regs[AST2600_SILICON_REV] = AST1030_A1_SILICON_REV;
    808     s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
    809     s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
    810     s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
    811     s->regs[PROT_KEY] = s->hw_prot_key;
    812 }
    813 
    814 static void aspeed_1030_scu_class_init(ObjectClass *klass, void *data)
    815 {
    816     DeviceClass *dc = DEVICE_CLASS(klass);
    817     AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
    818 
    819     dc->desc = "ASPEED 1030 System Control Unit";
    820     dc->reset = aspeed_ast1030_scu_reset;
    821     asc->resets = ast1030_a1_resets;
    822     asc->calc_hpll = aspeed_2600_scu_calc_hpll;
    823     asc->get_apb = aspeed_1030_scu_get_apb_freq;
    824     asc->apb_divider = 2;
    825     asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
    826     asc->clkin_25Mhz = true;
    827     asc->ops = &aspeed_ast2600_scu_ops;
    828 }
    829 
    830 static const TypeInfo aspeed_1030_scu_info = {
    831     .name = TYPE_ASPEED_1030_SCU,
    832     .parent = TYPE_ASPEED_SCU,
    833     .instance_size = sizeof(AspeedSCUState),
    834     .class_init = aspeed_1030_scu_class_init,
    835 };
    836 
    837 static void aspeed_scu_register_types(void)
    838 {
    839     type_register_static(&aspeed_scu_info);
    840     type_register_static(&aspeed_2400_scu_info);
    841     type_register_static(&aspeed_2500_scu_info);
    842     type_register_static(&aspeed_2600_scu_info);
    843     type_register_static(&aspeed_1030_scu_info);
    844 }
    845 
    846 type_init(aspeed_scu_register_types);