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