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