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