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