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