1 /* 2 * ASPEED PCIe Host Controller 3 * 4 * Copyright (C) 2025 ASPEED Technology Inc. 5 * Copyright (c) 2022 Cédric Le Goater <clg@kaod.org> 6 * 7 * Jamin Lin <jamin_lin@aspeedtech.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 * 11 * This file is based on Cédric Le Goater's patch: 12 * "pci: Add Aspeed host bridge (WIP)" 13 * https://github.com/legoater/qemu/commit/d1b97b0c7844219d847122410dc189854f9d26df 14 * 15 * Modifications have been made to support the Aspeed AST2600 and AST2700 16 * platforms. 17 */ 18 19 #include "qemu/osdep.h" 20 #include "qemu/log.h" 21 #include "qapi/error.h" 22 #include "hw/qdev-properties.h" 23 #include "hw/registerfields.h" 24 #include "hw/irq.h" 25 #include "hw/pci/pci_host.h" 26 #include "hw/pci-host/aspeed_pcie.h" 27 #include "hw/pci/msi.h" 28 #include "trace.h" 29 30 /* 31 * PCIe Root 32 */ 33 34 static void aspeed_pcie_root_class_init(ObjectClass *klass, const void *data) 35 { 36 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 37 DeviceClass *dc = DEVICE_CLASS(klass); 38 39 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 40 dc->desc = "ASPEED PCIe Host Bridge"; 41 k->vendor_id = PCI_VENDOR_ID_ASPEED; 42 k->device_id = 0x1150; 43 k->class_id = PCI_CLASS_BRIDGE_HOST; 44 k->revision = 0; 45 46 /* 47 * PCI-facing part of the host bridge, 48 * not usable without the host-facing part 49 */ 50 dc->user_creatable = false; 51 } 52 53 static const TypeInfo aspeed_pcie_root_info = { 54 .name = TYPE_ASPEED_PCIE_ROOT, 55 .parent = TYPE_PCI_DEVICE, 56 .instance_size = sizeof(AspeedPCIERootState), 57 .class_init = aspeed_pcie_root_class_init, 58 .interfaces = (const InterfaceInfo[]) { 59 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 60 { }, 61 }, 62 }; 63 64 /* 65 * PCIe Root Complex (RC) 66 */ 67 68 #define ASPEED_PCIE_CFG_RC_MAX_MSI 64 69 70 static void aspeed_pcie_rc_set_irq(void *opaque, int irq, int level) 71 { 72 AspeedPCIERcState *rc = (AspeedPCIERcState *) opaque; 73 AspeedPCIECfgState *cfg = 74 container_of(rc, AspeedPCIECfgState, rc); 75 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(cfg); 76 const AspeedPCIERcRegs *rc_regs; 77 bool intx; 78 79 assert(irq < PCI_NUM_PINS); 80 81 rc_regs = &apc->reg_map->rc; 82 83 if (level) { 84 cfg->regs[rc_regs->int_sts_reg] |= BIT(irq); 85 } else { 86 cfg->regs[rc_regs->int_sts_reg] &= ~BIT(irq); 87 } 88 89 intx = !!(cfg->regs[rc_regs->int_sts_reg] & cfg->regs[rc_regs->int_en_reg]); 90 trace_aspeed_pcie_rc_intx_set_irq(cfg->id, irq, intx); 91 qemu_set_irq(rc->irq, intx); 92 } 93 94 static int aspeed_pcie_rc_map_irq(PCIDevice *pci_dev, int irq_num) 95 { 96 return irq_num % PCI_NUM_PINS; 97 } 98 99 static void aspeed_pcie_rc_msi_notify(AspeedPCIERcState *rc, uint64_t data) 100 { 101 AspeedPCIECfgState *cfg = 102 container_of(rc, AspeedPCIECfgState, rc); 103 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(cfg); 104 const AspeedPCIERcRegs *rc_regs; 105 uint32_t reg; 106 107 /* Written data is the HW IRQ number */ 108 assert(data < ASPEED_PCIE_CFG_RC_MAX_MSI); 109 110 rc_regs = &apc->reg_map->rc; 111 112 reg = (data < 32) ? rc_regs->msi_sts0_reg : rc_regs->msi_sts1_reg; 113 cfg->regs[reg] |= BIT(data % 32); 114 115 trace_aspeed_pcie_rc_msi_set_irq(cfg->id, data, 1); 116 qemu_set_irq(rc->irq, 1); 117 } 118 119 static void aspeed_pcie_rc_msi_write(void *opaque, hwaddr addr, uint64_t data, 120 unsigned int size) 121 { 122 AspeedPCIERcState *rc = ASPEED_PCIE_RC(opaque); 123 AspeedPCIECfgState *cfg = 124 container_of(rc, AspeedPCIECfgState, rc); 125 126 trace_aspeed_pcie_rc_msi_notify(cfg->id, addr + rc->msi_addr, data); 127 aspeed_pcie_rc_msi_notify(rc, data); 128 } 129 130 static const MemoryRegionOps aspeed_pcie_rc_msi_ops = { 131 .write = aspeed_pcie_rc_msi_write, 132 .read = NULL, 133 .endianness = DEVICE_LITTLE_ENDIAN, 134 .valid = { 135 .min_access_size = 4, 136 .max_access_size = 4, 137 }, 138 .impl = { 139 .min_access_size = 4, 140 .max_access_size = 4, 141 }, 142 }; 143 144 static AddressSpace *aspeed_pcie_rc_get_as(PCIBus *bus, void *opaque, int devfn) 145 { 146 AspeedPCIERcState *rc = ASPEED_PCIE_RC(opaque); 147 return &rc->iommu_as; 148 } 149 150 static const PCIIOMMUOps aspeed_pcie_rc_iommu_ops = { 151 .get_address_space = aspeed_pcie_rc_get_as, 152 }; 153 154 static void aspeed_pcie_rc_realize(DeviceState *dev, Error **errp) 155 { 156 PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev); 157 AspeedPCIERcState *rc = ASPEED_PCIE_RC(dev); 158 AspeedPCIECfgState *cfg = 159 container_of(rc, AspeedPCIECfgState, rc); 160 PCIHostState *pci = PCI_HOST_BRIDGE(dev); 161 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 162 g_autofree char *name; 163 164 /* PCI configuration space */ 165 pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX); 166 sysbus_init_mmio(sbd, &pex->mmio); 167 168 /* MMIO and IO region */ 169 memory_region_init(&rc->mmio, OBJECT(rc), "mmio", UINT64_MAX); 170 memory_region_init(&rc->io, OBJECT(rc), "io", 0x10000); 171 172 name = g_strdup_printf("pcie.%d.mmio_window", cfg->id); 173 memory_region_init_io(&rc->mmio_window, OBJECT(rc), &unassigned_io_ops, 174 OBJECT(rc), name, UINT64_MAX); 175 name = g_strdup_printf("pcie.%d.ioport_window", cfg->id); 176 memory_region_init_io(&rc->io_window, OBJECT(rc), &unassigned_io_ops, 177 OBJECT(rc), name, 0x10000); 178 179 memory_region_add_subregion(&rc->mmio_window, 0, &rc->mmio); 180 memory_region_add_subregion(&rc->io_window, 0, &rc->io); 181 sysbus_init_mmio(sbd, &rc->mmio_window); 182 sysbus_init_mmio(sbd, &rc->io_window); 183 184 sysbus_init_irq(sbd, &rc->irq); 185 pci->bus = pci_register_root_bus(dev, NULL, aspeed_pcie_rc_set_irq, 186 aspeed_pcie_rc_map_irq, rc, &rc->mmio, 187 &rc->io, 0, 4, TYPE_PCIE_BUS); 188 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; 189 190 /* 191 * PCIe memory view setup 192 * 193 * Background: 194 * - On AST2700, all Root Complexes use the same MSI address. This MSI 195 * address is not normal system RAM - it is a PCI system memory address. 196 * If we map the MSI/MSI-X window into real system memory, a write from 197 * one EP can be seen by all RCs and wrongly trigger interrupts on them. 198 * 199 * Design: 200 * - MSI/MSI-X here is just a placeholder address so RC and EP can talk. 201 * We make a separate MMIO space (iommu_root) for the MSI window so the 202 * writes stay local to each RC. 203 * 204 * DMA: 205 * - EPs still need access to real system memory for DMA. We add a DRAM 206 * alias in the PCI space so DMA works as expected. 207 */ 208 name = g_strdup_printf("pcie.%d.iommu_root", cfg->id); 209 memory_region_init(&rc->iommu_root, OBJECT(rc), name, UINT64_MAX); 210 address_space_init(&rc->iommu_as, &rc->iommu_root, name); 211 /* setup MSI */ 212 memory_region_init_io(&rc->msi_window, OBJECT(rc), 213 &aspeed_pcie_rc_msi_ops, rc, 214 "msi_window", 4); 215 memory_region_add_subregion(&rc->iommu_root, rc->msi_addr, 216 &rc->msi_window); 217 /* setup DRAM for DMA */ 218 assert(rc->dram_mr != NULL); 219 name = g_strdup_printf("pcie.%d.dram_alias", cfg->id); 220 memory_region_init_alias(&rc->dram_alias, OBJECT(rc), name, rc->dram_mr, 221 0, memory_region_size(rc->dram_mr)); 222 memory_region_add_subregion(&rc->iommu_root, rc->dram_base, 223 &rc->dram_alias); 224 pci_setup_iommu(pci->bus, &aspeed_pcie_rc_iommu_ops, rc); 225 226 qdev_realize(DEVICE(&rc->root), BUS(pci->bus), &error_fatal); 227 } 228 229 static const char *aspeed_pcie_rc_root_bus_path(PCIHostState *host_bridge, 230 PCIBus *rootbus) 231 { 232 AspeedPCIERcState *s = ASPEED_PCIE_RC(host_bridge); 233 234 snprintf(s->name, sizeof(s->name), "0000:%02x", s->bus_nr); 235 236 return s->name; 237 } 238 239 static void aspeed_pcie_rc_instance_init(Object *obj) 240 { 241 AspeedPCIERcState *s = ASPEED_PCIE_RC(obj); 242 AspeedPCIERootState *root = &s->root; 243 244 object_initialize_child(obj, "root", root, TYPE_ASPEED_PCIE_ROOT); 245 qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); 246 qdev_prop_set_bit(DEVICE(root), "multifunction", false); 247 } 248 249 static const Property aspeed_pcie_rc_props[] = { 250 DEFINE_PROP_UINT32("bus-nr", AspeedPCIERcState, bus_nr, 0), 251 DEFINE_PROP_UINT32("msi-addr", AspeedPCIERcState, msi_addr, 0), 252 DEFINE_PROP_UINT64("dram-base", AspeedPCIERcState, dram_base, 0), 253 DEFINE_PROP_LINK("dram", AspeedPCIERcState, dram_mr, TYPE_MEMORY_REGION, 254 MemoryRegion *), 255 }; 256 257 static void aspeed_pcie_rc_class_init(ObjectClass *klass, const void *data) 258 { 259 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); 260 DeviceClass *dc = DEVICE_CLASS(klass); 261 262 dc->desc = "ASPEED PCIe RC"; 263 dc->realize = aspeed_pcie_rc_realize; 264 dc->fw_name = "pci"; 265 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 266 267 hc->root_bus_path = aspeed_pcie_rc_root_bus_path; 268 device_class_set_props(dc, aspeed_pcie_rc_props); 269 270 msi_nonbroken = true; 271 } 272 273 static const TypeInfo aspeed_pcie_rc_info = { 274 .name = TYPE_ASPEED_PCIE_RC, 275 .parent = TYPE_PCIE_HOST_BRIDGE, 276 .instance_size = sizeof(AspeedPCIERcState), 277 .instance_init = aspeed_pcie_rc_instance_init, 278 .class_init = aspeed_pcie_rc_class_init, 279 }; 280 281 /* 282 * PCIe Config 283 * 284 * AHB to PCIe Bus Bridge (H2X) 285 * 286 * On the AST2600: 287 * NOTE: rc_l is not supported by this model. 288 * - Registers 0x00 - 0x7F are shared by both PCIe0 (rc_l) and PCIe1 (rc_h). 289 * - Registers 0x80 - 0xBF are specific to PCIe0. 290 * - Registers 0xC0 - 0xFF are specific to PCIe1. 291 */ 292 293 /* AST2600 */ 294 REG32(H2X_CTRL, 0x00) 295 FIELD(H2X_CTRL, CLEAR_RX, 4, 1) 296 REG32(H2X_TX_CLEAR, 0x08) 297 FIELD(H2X_TX_CLEAR, IDLE, 0, 1) 298 REG32(H2X_RDATA, 0x0C) 299 REG32(H2X_TX_DESC0, 0x10) 300 REG32(H2X_TX_DESC1, 0x14) 301 REG32(H2X_TX_DESC2, 0x18) 302 REG32(H2X_TX_DESC3, 0x1C) 303 REG32(H2X_TX_DATA, 0x20) 304 REG32(H2X_TX_STS, 0x24) 305 FIELD(H2X_TX_STS, IDLE, 31, 1) 306 FIELD(H2X_TX_STS, RC_L_TX_COMP, 24, 1) 307 FIELD(H2X_TX_STS, RC_H_TX_COMP, 25, 1) 308 FIELD(H2X_TX_STS, TRIG, 0, 1) 309 REG32(H2X_RC_H_CTRL, 0xC0) 310 REG32(H2X_RC_H_INT_EN, 0xC4) 311 REG32(H2X_RC_H_INT_STS, 0xC8) 312 SHARED_FIELD(H2X_RC_INT_INTDONE, 4, 1) 313 SHARED_FIELD(H2X_RC_INT_INTX, 0, 4) 314 REG32(H2X_RC_H_RDATA, 0xCC) 315 REG32(H2X_RC_H_MSI_EN0, 0xE0) 316 REG32(H2X_RC_H_MSI_EN1, 0xE4) 317 REG32(H2X_RC_H_MSI_STS0, 0xE8) 318 REG32(H2X_RC_H_MSI_STS1, 0xEC) 319 320 #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ 321 #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ 322 #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */ 323 #define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */ 324 325 #define PCIE_CFG_FMTTYPE_MASK(x) (((x) >> 24) & 0xff) 326 #define PCIE_CFG_BYTE_EN(x) ((x) & 0xf) 327 328 static const AspeedPCIERegMap aspeed_regmap = { 329 .rc = { 330 .int_en_reg = R_H2X_RC_H_INT_EN, 331 .int_sts_reg = R_H2X_RC_H_INT_STS, 332 .msi_sts0_reg = R_H2X_RC_H_MSI_STS0, 333 .msi_sts1_reg = R_H2X_RC_H_MSI_STS1, 334 }, 335 }; 336 337 static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr, 338 unsigned int size) 339 { 340 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(opaque); 341 uint32_t reg = addr >> 2; 342 uint32_t value = 0; 343 344 value = s->regs[reg]; 345 346 trace_aspeed_pcie_cfg_read(s->id, addr, value); 347 348 return value; 349 } 350 351 static void aspeed_pcie_cfg_translate_write(uint8_t byte_en, uint32_t *addr, 352 uint64_t *val, int *len) 353 { 354 uint64_t packed_val = 0; 355 int first_bit = -1; 356 int index = 0; 357 int i; 358 359 *len = ctpop8(byte_en); 360 361 if (*len == 0 || *len > 4) { 362 goto err; 363 } 364 365 /* Special case: full 4-byte write must be 4-byte aligned */ 366 if (byte_en == 0x0f) { 367 if (*addr % 4 != 0) { 368 goto err; 369 } 370 *val = *val & 0xffffffff; 371 return; 372 } 373 374 for (i = 0; i < 4; i++) { 375 if (byte_en & (1 << i)) { 376 if (first_bit < 0) { 377 first_bit = i; 378 } 379 packed_val |= ((*val >> (i * 8)) & 0xff) << (index * 8); 380 index++; 381 } 382 } 383 384 *addr += first_bit; 385 *val = packed_val; 386 387 return; 388 389 err: 390 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid byte enable: 0x%x\n", 391 __func__, byte_en); 392 } 393 394 static void aspeed_pcie_cfg_readwrite(AspeedPCIECfgState *s, 395 const AspeedPCIECfgTxDesc *desc) 396 { 397 AspeedPCIERcState *rc = &s->rc; 398 PCIHostState *pci; 399 uint32_t cfg_addr; 400 PCIDevice *pdev; 401 uint32_t offset; 402 uint8_t byte_en; 403 bool is_write; 404 uint8_t devfn; 405 uint64_t val; 406 uint8_t bus; 407 int len; 408 409 val = ~0; 410 is_write = !!(desc->desc0 & BIT(30)); 411 cfg_addr = desc->desc2; 412 413 bus = (cfg_addr >> 24) & 0xff; 414 devfn = (cfg_addr >> 16) & 0xff; 415 offset = cfg_addr & 0xffc; 416 417 pci = PCI_HOST_BRIDGE(rc); 418 419 /* 420 * On the AST2600, the RC_H bus number ranges from 0x80 to 0xFF, and its 421 * root port uses bus number 0x80 instead of the standard 0x00. To locate 422 * the device at root port 0, remap bus number 0x80 to 0x00 so that the 423 * PCI subsystem can correctly discover the devices. 424 */ 425 if (bus == rc->bus_nr) { 426 bus = 0; 427 } 428 429 pdev = pci_find_device(pci->bus, bus, devfn); 430 if (!pdev) { 431 s->regs[desc->rdata_reg] = ~0; 432 goto out; 433 } 434 435 switch (PCIE_CFG_FMTTYPE_MASK(desc->desc0)) { 436 case TLP_FMTTYPE_CFGWR0: 437 case TLP_FMTTYPE_CFGWR1: 438 byte_en = PCIE_CFG_BYTE_EN(desc->desc1); 439 val = desc->wdata; 440 aspeed_pcie_cfg_translate_write(byte_en, &offset, &val, &len); 441 pci_host_config_write_common(pdev, offset, pci_config_size(pdev), 442 val, len); 443 break; 444 case TLP_FMTTYPE_CFGRD0: 445 case TLP_FMTTYPE_CFGRD1: 446 val = pci_host_config_read_common(pdev, offset, 447 pci_config_size(pdev), 4); 448 s->regs[desc->rdata_reg] = val; 449 break; 450 default: 451 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CFG type. DESC0=0x%x\n", 452 __func__, desc->desc0); 453 } 454 455 out: 456 trace_aspeed_pcie_cfg_rw(s->id, is_write ? "write" : "read", bus, devfn, 457 cfg_addr, val); 458 } 459 460 static void aspeed_pcie_cfg_write(void *opaque, hwaddr addr, uint64_t data, 461 unsigned int size) 462 { 463 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(opaque); 464 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s); 465 AspeedPCIECfgTxDesc desc; 466 uint32_t reg = addr >> 2; 467 uint32_t rc_reg; 468 469 trace_aspeed_pcie_cfg_write(s->id, addr, data); 470 471 switch (reg) { 472 case R_H2X_CTRL: 473 if (data & R_H2X_CTRL_CLEAR_RX_MASK) { 474 s->regs[R_H2X_RDATA] = ~0; 475 } 476 break; 477 case R_H2X_TX_CLEAR: 478 if (data & R_H2X_TX_CLEAR_IDLE_MASK) { 479 s->regs[R_H2X_TX_STS] &= ~R_H2X_TX_STS_IDLE_MASK; 480 } 481 break; 482 case R_H2X_TX_STS: 483 if (data & R_H2X_TX_STS_TRIG_MASK) { 484 desc.desc0 = s->regs[R_H2X_TX_DESC0]; 485 desc.desc1 = s->regs[R_H2X_TX_DESC1]; 486 desc.desc2 = s->regs[R_H2X_TX_DESC2]; 487 desc.desc3 = s->regs[R_H2X_TX_DESC3]; 488 desc.wdata = s->regs[R_H2X_TX_DATA]; 489 desc.rdata_reg = R_H2X_RC_H_RDATA; 490 aspeed_pcie_cfg_readwrite(s, &desc); 491 rc_reg = apc->reg_map->rc.int_sts_reg; 492 s->regs[rc_reg] |= H2X_RC_INT_INTDONE_MASK; 493 s->regs[R_H2X_TX_STS] |= 494 BIT(R_H2X_TX_STS_RC_H_TX_COMP_SHIFT); 495 s->regs[R_H2X_TX_STS] |= R_H2X_TX_STS_IDLE_MASK; 496 } 497 break; 498 /* preserve INTx status */ 499 case R_H2X_RC_H_INT_STS: 500 if (data & H2X_RC_INT_INTDONE_MASK) { 501 s->regs[R_H2X_TX_STS] &= ~R_H2X_TX_STS_RC_H_TX_COMP_MASK; 502 } 503 s->regs[reg] &= ~data | H2X_RC_INT_INTX_MASK; 504 break; 505 /* 506 * These status registers are used for notify sources ISR are executed. 507 * If one source ISR is executed, it will clear one bit. 508 * If it clear all bits, it means to initialize this register status 509 * rather than sources ISR are executed. 510 */ 511 case R_H2X_RC_H_MSI_STS0: 512 case R_H2X_RC_H_MSI_STS1: 513 if (data == 0) { 514 return ; 515 } 516 517 s->regs[reg] &= ~data; 518 if (data == 0xffffffff) { 519 return; 520 } 521 522 if (!s->regs[R_H2X_RC_H_MSI_STS0] && 523 !s->regs[R_H2X_RC_H_MSI_STS1]) { 524 trace_aspeed_pcie_rc_msi_clear_irq(s->id, 0); 525 qemu_set_irq(s->rc.irq, 0); 526 } 527 break; 528 default: 529 s->regs[reg] = data; 530 break; 531 } 532 } 533 534 static const MemoryRegionOps aspeed_pcie_cfg_ops = { 535 .read = aspeed_pcie_cfg_read, 536 .write = aspeed_pcie_cfg_write, 537 .endianness = DEVICE_LITTLE_ENDIAN, 538 .valid = { 539 .min_access_size = 1, 540 .max_access_size = 4, 541 }, 542 }; 543 544 static void aspeed_pcie_cfg_instance_init(Object *obj) 545 { 546 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(obj); 547 548 object_initialize_child(obj, "rc", &s->rc, TYPE_ASPEED_PCIE_RC); 549 object_property_add_alias(obj, "dram", OBJECT(&s->rc), "dram"); 550 object_property_add_alias(obj, "dram-base", OBJECT(&s->rc), "dram-base"); 551 552 return; 553 } 554 555 static void aspeed_pcie_cfg_reset(DeviceState *dev) 556 { 557 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev); 558 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s); 559 560 memset(s->regs, 0, apc->nr_regs << 2); 561 } 562 563 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp) 564 { 565 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 566 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev); 567 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s); 568 g_autofree char *name; 569 570 s->regs = g_new(uint32_t, apc->nr_regs); 571 name = g_strdup_printf(TYPE_ASPEED_PCIE_CFG ".regs.%d", s->id); 572 memory_region_init_io(&s->mmio, OBJECT(s), apc->reg_ops, s, name, 573 apc->nr_regs << 2); 574 sysbus_init_mmio(sbd, &s->mmio); 575 576 object_property_set_int(OBJECT(&s->rc), "bus-nr", 577 apc->rc_bus_nr, 578 &error_abort); 579 object_property_set_int(OBJECT(&s->rc), "msi-addr", 580 apc->rc_msi_addr, 581 &error_abort); 582 if (!sysbus_realize(SYS_BUS_DEVICE(&s->rc), errp)) { 583 return; 584 } 585 } 586 587 static void aspeed_pcie_cfg_unrealize(DeviceState *dev) 588 { 589 AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev); 590 591 g_free(s->regs); 592 s->regs = NULL; 593 } 594 595 static const Property aspeed_pcie_cfg_props[] = { 596 DEFINE_PROP_UINT32("id", AspeedPCIECfgState, id, 0), 597 }; 598 599 static void aspeed_pcie_cfg_class_init(ObjectClass *klass, const void *data) 600 { 601 DeviceClass *dc = DEVICE_CLASS(klass); 602 AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_CLASS(klass); 603 604 dc->desc = "ASPEED PCIe Config"; 605 dc->realize = aspeed_pcie_cfg_realize; 606 dc->unrealize = aspeed_pcie_cfg_unrealize; 607 device_class_set_legacy_reset(dc, aspeed_pcie_cfg_reset); 608 device_class_set_props(dc, aspeed_pcie_cfg_props); 609 610 apc->reg_ops = &aspeed_pcie_cfg_ops; 611 apc->reg_map = &aspeed_regmap; 612 apc->nr_regs = 0x100 >> 2; 613 apc->rc_msi_addr = 0x1e77005C; 614 apc->rc_bus_nr = 0x80; 615 } 616 617 static const TypeInfo aspeed_pcie_cfg_info = { 618 .name = TYPE_ASPEED_PCIE_CFG, 619 .parent = TYPE_SYS_BUS_DEVICE, 620 .instance_init = aspeed_pcie_cfg_instance_init, 621 .instance_size = sizeof(AspeedPCIECfgState), 622 .class_init = aspeed_pcie_cfg_class_init, 623 .class_size = sizeof(AspeedPCIECfgClass), 624 }; 625 626 /* 627 * PCIe PHY 628 * 629 * PCIe Host Controller (PCIEH) 630 */ 631 632 /* AST2600 */ 633 REG32(PEHR_ID, 0x00) 634 FIELD(PEHR_ID, DEV, 16, 16) 635 REG32(PEHR_CLASS_CODE, 0x04) 636 REG32(PEHR_DATALINK, 0x10) 637 REG32(PEHR_PROTECT, 0x7C) 638 FIELD(PEHR_PROTECT, LOCK, 0, 8) 639 REG32(PEHR_LINK, 0xC0) 640 FIELD(PEHR_LINK, STS, 5, 1) 641 642 #define ASPEED_PCIE_PHY_UNLOCK 0xA8 643 644 static uint64_t aspeed_pcie_phy_read(void *opaque, hwaddr addr, 645 unsigned int size) 646 { 647 AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(opaque); 648 uint32_t reg = addr >> 2; 649 uint32_t value = 0; 650 651 value = s->regs[reg]; 652 653 trace_aspeed_pcie_phy_read(s->id, addr, value); 654 655 return value; 656 } 657 658 static void aspeed_pcie_phy_write(void *opaque, hwaddr addr, uint64_t data, 659 unsigned int size) 660 { 661 AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(opaque); 662 uint32_t reg = addr >> 2; 663 664 trace_aspeed_pcie_phy_write(s->id, addr, data); 665 666 switch (reg) { 667 case R_PEHR_PROTECT: 668 data &= R_PEHR_PROTECT_LOCK_MASK; 669 s->regs[reg] = !!(data == ASPEED_PCIE_PHY_UNLOCK); 670 break; 671 default: 672 s->regs[reg] = data; 673 break; 674 } 675 } 676 677 static const MemoryRegionOps aspeed_pcie_phy_ops = { 678 .read = aspeed_pcie_phy_read, 679 .write = aspeed_pcie_phy_write, 680 .endianness = DEVICE_LITTLE_ENDIAN, 681 .valid = { 682 .min_access_size = 1, 683 .max_access_size = 4, 684 }, 685 }; 686 687 static void aspeed_pcie_phy_reset(DeviceState *dev) 688 { 689 AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev); 690 AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_GET_CLASS(s); 691 692 memset(s->regs, 0, apc->nr_regs << 2); 693 694 s->regs[R_PEHR_ID] = 695 (0x1150 << R_PEHR_ID_DEV_SHIFT) | PCI_VENDOR_ID_ASPEED; 696 s->regs[R_PEHR_CLASS_CODE] = 0x06040006; 697 s->regs[R_PEHR_DATALINK] = 0xD7040022; 698 s->regs[R_PEHR_LINK] = R_PEHR_LINK_STS_MASK; 699 } 700 701 static void aspeed_pcie_phy_realize(DeviceState *dev, Error **errp) 702 { 703 AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev); 704 AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_GET_CLASS(s); 705 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 706 g_autofree char *name; 707 708 s->regs = g_new(uint32_t, apc->nr_regs); 709 name = g_strdup_printf(TYPE_ASPEED_PCIE_PHY ".regs.%d", s->id); 710 memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_pcie_phy_ops, s, name, 711 apc->nr_regs << 2); 712 sysbus_init_mmio(sbd, &s->mmio); 713 } 714 715 static void aspeed_pcie_phy_unrealize(DeviceState *dev) 716 { 717 AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev); 718 719 g_free(s->regs); 720 s->regs = NULL; 721 } 722 723 static const Property aspeed_pcie_phy_props[] = { 724 DEFINE_PROP_UINT32("id", AspeedPCIEPhyState, id, 0), 725 }; 726 727 static void aspeed_pcie_phy_class_init(ObjectClass *klass, const void *data) 728 { 729 DeviceClass *dc = DEVICE_CLASS(klass); 730 AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_CLASS(klass); 731 732 dc->desc = "ASPEED PCIe Phy"; 733 dc->realize = aspeed_pcie_phy_realize; 734 dc->unrealize = aspeed_pcie_phy_unrealize; 735 device_class_set_legacy_reset(dc, aspeed_pcie_phy_reset); 736 device_class_set_props(dc, aspeed_pcie_phy_props); 737 738 apc->nr_regs = 0x100 >> 2; 739 } 740 741 static const TypeInfo aspeed_pcie_phy_info = { 742 .name = TYPE_ASPEED_PCIE_PHY, 743 .parent = TYPE_SYS_BUS_DEVICE, 744 .instance_size = sizeof(AspeedPCIEPhyState), 745 .class_init = aspeed_pcie_phy_class_init, 746 .class_size = sizeof(AspeedPCIEPhyClass), 747 }; 748 749 static void aspeed_pcie_register_types(void) 750 { 751 type_register_static(&aspeed_pcie_root_info); 752 type_register_static(&aspeed_pcie_rc_info); 753 type_register_static(&aspeed_pcie_cfg_info); 754 type_register_static(&aspeed_pcie_phy_info); 755 } 756 757 type_init(aspeed_pcie_register_types); 758 759