1 /* 2 * Aspeed PCIe host controller 3 * 4 * Copyright (c) 2022 Cédric Le Goater <clg@kaod.org> 5 * 6 * This code is licensed under the GPL version 2 or later. See 7 * the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qemu/module.h" 12 #include "qemu/units.h" 13 #include "qemu/log.h" 14 #include "qapi/error.h" 15 #include "hw/qdev-properties.h" 16 #include "hw/irq.h" 17 #include "hw/pci-host/aspeed_pcie.h" 18 #include "hw/pci/msi.h" 19 20 #include "trace.h" 21 22 #define TO_REG(offset) ((offset) >> 2) 23 24 #define PCI_VENDOR_ID_ASPEED 0x1A03 25 #define PCI_DEVICE_ID_AST2600_RC 0x1150 26 27 /* 28 * RC 29 */ 30 31 #define ASPEED_PCIE_RC_CTRL 0x00 32 #define ASPEED_PCIE_RC_CTRL_RCL BIT(0) 33 #define ASPEED_PCIE_RC_CTRL_RCL_RX BIT(1) 34 #define ASPEED_PCIE_RC_CTRL_RX_WAIT_FW BIT(2) 35 #define ASPEED_PCIE_RC_CTRL_RX_UNLOCK BIT(4) 36 #define ASPEED_PCIE_RC_CTRL_RX_MSI BIT(6) 37 #define ASPEED_PCIE_RC_CTRL_RX_MSI_SELECT BIT(7) 38 #define ASPEED_PCIE_RC_CTRL_RX_LINEAR BIT(8) 39 #define ASPEED_PCIE_RC_CTRL_RX_DMA BIT(9) 40 #define ASPEED_PCIE_RC_CTRL_RX_TAG_MASK 0x00ff0000 41 42 #define ASPEED_PCIE_RC_INT_ENABLE 0x04 43 #define ASPEED_PCIE_RC_INT_ENABLE_INTA BIT(0) 44 #define ASPEED_PCIE_RC_INT_ENABLE_INTB BIT(1) 45 #define ASPEED_PCIE_RC_INT_ENABLE_INTC BIT(2) 46 #define ASPEED_PCIE_RC_INT_ENABLE_INTD BIT(3) 47 #define ASPEED_PCIE_RC_INT_ENABLE_RX BIT(4) 48 #define ASPEED_PCIE_RC_INT_STATUS 0x08 49 #define ASPEED_PCIE_RC_INT_STATUS_INTA BIT(0) 50 #define ASPEED_PCIE_RC_INT_STATUS_INTB BIT(1) 51 #define ASPEED_PCIE_RC_INT_STATUS_INTC BIT(2) 52 #define ASPEED_PCIE_RC_INT_STATUS_INTD BIT(3) 53 #define ASPEED_PCIE_RC_INT_STATUS_INTX_MASK 0xf 54 #define ASPEED_PCIE_RC_INT_STATUS_RX BIT(4) 55 56 #define ASPEED_PCIE_RC_RX_DATA 0x0C 57 #define ASPEED_PCIE_RC_RX_DW0 0x10 58 #define ASPEED_PCIE_RC_RX_DW1 0x14 59 #define ASPEED_PCIE_RC_RX_DW2 0x18 60 #define ASPEED_PCIE_RC_RX_DW3 0x1C 61 #define ASPEED_PCIE_RC_MSI_ENABLE0 0x20 62 #define ASPEED_PCIE_RC_MSI_ENABLE1 0x24 63 #define ASPEED_PCIE_RC_MSI_STATUS0 0x28 64 #define ASPEED_PCIE_RC_MSI_STATUS1 0x2C 65 #define ASPEED_PCIE_RC_TX_TAG 0x3C 66 67 static void aspeed_pcie_rc_update_irq(AspeedPCIERc *s) 68 { 69 bool intx = !!(s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] & 70 s->regs[TO_REG(ASPEED_PCIE_RC_INT_ENABLE)]); 71 bool msi0 = !!(s->regs[TO_REG(ASPEED_PCIE_RC_MSI_STATUS0)] & 72 s->regs[TO_REG(ASPEED_PCIE_RC_MSI_ENABLE0)]); 73 bool msi1 = !!(s->regs[TO_REG(ASPEED_PCIE_RC_MSI_STATUS1)] & 74 s->regs[TO_REG(ASPEED_PCIE_RC_MSI_ENABLE1)]); 75 bool level = intx || msi0 || msi1; 76 77 qemu_set_irq(s->irq, level); 78 } 79 80 static uint64_t aspeed_pcie_rc_read(void *opaque, hwaddr addr, 81 unsigned int size) 82 { 83 AspeedPCIERc *s = ASPEED_PCIE_RC(opaque); 84 uint64_t val = 0; 85 86 switch (addr) { 87 case ASPEED_PCIE_RC_CTRL: 88 case ASPEED_PCIE_RC_INT_ENABLE: 89 case ASPEED_PCIE_RC_INT_STATUS: 90 case ASPEED_PCIE_RC_RX_DATA: 91 case ASPEED_PCIE_RC_RX_DW0: 92 case ASPEED_PCIE_RC_RX_DW1: 93 case ASPEED_PCIE_RC_RX_DW2: 94 case ASPEED_PCIE_RC_RX_DW3: 95 case ASPEED_PCIE_RC_MSI_ENABLE0: 96 case ASPEED_PCIE_RC_MSI_ENABLE1: 97 case ASPEED_PCIE_RC_MSI_STATUS0: 98 case ASPEED_PCIE_RC_MSI_STATUS1: 99 case ASPEED_PCIE_RC_TX_TAG: 100 val = s->regs[TO_REG(addr)]; 101 break; 102 103 default: 104 qemu_log_mask(LOG_GUEST_ERROR, 105 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 106 __func__, addr); 107 break; 108 } 109 110 trace_aspeed_pcie_rc_read(addr, val); 111 return val; 112 } 113 114 static void aspeed_pcie_rc_write(void *opaque, hwaddr addr, uint64_t data, 115 unsigned int size) 116 { 117 AspeedPCIERc *s = ASPEED_PCIE_RC(opaque); 118 119 trace_aspeed_pcie_rc_write(addr, data); 120 121 switch (addr) { 122 case ASPEED_PCIE_RC_CTRL: /* TODO: unlock/lock RX */ 123 case ASPEED_PCIE_RC_INT_ENABLE: 124 case ASPEED_PCIE_RC_MSI_ENABLE0: 125 case ASPEED_PCIE_RC_MSI_ENABLE1: 126 case ASPEED_PCIE_RC_TX_TAG: 127 s->regs[TO_REG(addr)] = data; 128 break; 129 case ASPEED_PCIE_RC_MSI_STATUS0: 130 case ASPEED_PCIE_RC_MSI_STATUS1: 131 s->regs[TO_REG(addr)] &= ~data; 132 break; 133 case ASPEED_PCIE_RC_INT_STATUS: /* preserve INTx status*/ 134 s->regs[TO_REG(addr)] &= ~data | ASPEED_PCIE_RC_INT_STATUS_INTX_MASK; 135 break; 136 default: 137 qemu_log_mask(LOG_GUEST_ERROR, 138 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 139 __func__, addr); 140 break; 141 } 142 } 143 144 static const MemoryRegionOps aspeed_pcie_rc_ops = { 145 .read = aspeed_pcie_rc_read, 146 .write = aspeed_pcie_rc_write, 147 .endianness = DEVICE_LITTLE_ENDIAN, 148 .valid = { 149 .min_access_size = 1, 150 .max_access_size = 4, 151 }, 152 }; 153 154 static void aspeed_pcie_rc_set_irq(void *opaque, int irq, int level) 155 { 156 AspeedPCIERc *s = (AspeedPCIERc *) opaque; 157 158 assert(irq < PCI_NUM_PINS); 159 160 if (level) { 161 s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] |= BIT(irq); 162 } else { 163 s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] &= ~BIT(irq); 164 } 165 166 aspeed_pcie_rc_update_irq(s); 167 } 168 169 static int aspeed_pcie_rc_map_irq(PCIDevice *pci_dev, int irq_num) 170 { 171 return irq_num % PCI_NUM_PINS; 172 } 173 174 static void aspeed_pcie_rc_realize(DeviceState *dev, Error **errp) 175 { 176 PCIHostState *pci = PCI_HOST_BRIDGE(dev); 177 AspeedPCIERc *s = ASPEED_PCIE_RC(dev); 178 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 179 PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev); 180 181 memory_region_init_io(&s->reg_rc_mmio, OBJECT(s), &aspeed_pcie_rc_ops, s, 182 TYPE_ASPEED_PCIE_RC ".regs", 0x40); 183 184 /* PCI configuration space */ 185 pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX / 2); 186 sysbus_init_mmio(sbd, &pex->mmio); 187 188 /* MMIO and IO region */ 189 memory_region_init(&s->mmio, OBJECT(s), "mmio", UINT64_MAX); 190 memory_region_init(&s->io, OBJECT(s), "io", 0x10000); 191 192 memory_region_init_io(&s->mmio_window, OBJECT(s), &unassigned_io_ops, 193 OBJECT(s), "mmio_window", UINT64_MAX); 194 memory_region_init_io(&s->io_window, OBJECT(s), &unassigned_io_ops, 195 OBJECT(s), "ioport_window", 64 * 1024); 196 197 memory_region_add_subregion(&s->mmio_window, 0, &s->mmio); 198 memory_region_add_subregion(&s->io_window, 0, &s->io); 199 sysbus_init_mmio(sbd, &s->mmio_window); 200 sysbus_init_mmio(sbd, &s->io_window); 201 202 sysbus_init_irq(sbd, &s->irq); 203 204 pci->bus = pci_register_root_bus(dev, dev->id, aspeed_pcie_rc_set_irq, 205 aspeed_pcie_rc_map_irq, s, &s->mmio, 206 &s->io, 0, 4, TYPE_PCIE_BUS); 207 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; 208 209 qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal); 210 } 211 212 static void aspeed_pcie_rc_reset(DeviceState *dev) 213 { 214 AspeedPCIERc *s = ASPEED_PCIE_RC(dev); 215 216 memset(s->regs, 0, sizeof(s->regs)); 217 } 218 219 static const char *aspeed_pcie_rc_root_bus_path(PCIHostState *host_bridge, 220 PCIBus *rootbus) 221 { 222 AspeedPCIERc *s = ASPEED_PCIE_RC(host_bridge); 223 224 snprintf(s->name, sizeof(s->name), "0000:%02x", s->bus_nr); 225 return s->name; 226 } 227 228 static void aspeed_pcie_rc_init(Object *obj) 229 { 230 AspeedPCIERc *s = ASPEED_PCIE_RC(obj); 231 AspeedPCIERoot *root = &s->root; 232 233 object_initialize_child(obj, "root", root, TYPE_ASPEED_PCIE_ROOT); 234 qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); 235 qdev_prop_set_bit(DEVICE(root), "multifunction", false); 236 } 237 238 static Property aspeed_pcie_rc_props[] = { 239 DEFINE_PROP_UINT32("bus-nr", AspeedPCIERc, bus_nr, 0), 240 DEFINE_PROP_END_OF_LIST(), 241 }; 242 243 static void aspeed_pcie_rc_class_init(ObjectClass *klass, void *data) 244 { 245 DeviceClass *dc = DEVICE_CLASS(klass); 246 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); 247 248 hc->root_bus_path = aspeed_pcie_rc_root_bus_path; 249 device_class_set_legacy_reset(dc, aspeed_pcie_rc_reset); 250 dc->realize = aspeed_pcie_rc_realize; 251 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 252 dc->fw_name = "pci"; 253 device_class_set_props(dc, aspeed_pcie_rc_props); 254 255 msi_nonbroken = true; 256 } 257 258 static const TypeInfo aspeed_pcie_rc_info = { 259 .name = TYPE_ASPEED_PCIE_RC, 260 .parent = TYPE_PCIE_HOST_BRIDGE, 261 .instance_size = sizeof(AspeedPCIERc), 262 .instance_init = aspeed_pcie_rc_init, 263 .class_init = aspeed_pcie_rc_class_init, 264 }; 265 266 static void aspeed_pcie_root_class_init(ObjectClass *klass, void *data) 267 { 268 DeviceClass *dc = DEVICE_CLASS(klass); 269 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 270 271 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 272 dc->desc = "Aspeed PCIe Host Bridge"; 273 274 k->vendor_id = PCI_VENDOR_ID_ASPEED; 275 k->device_id = PCI_DEVICE_ID_AST2600_RC; 276 k->revision = 0; 277 k->class_id = PCI_CLASS_BRIDGE_HOST; 278 279 /* */ 280 dc->user_creatable = false; 281 } 282 283 static const TypeInfo aspeed_pcie_root_info = { 284 .name = TYPE_ASPEED_PCIE_ROOT, 285 .parent = TYPE_PCI_DEVICE, 286 .instance_size = sizeof(AspeedPCIERoot), 287 .class_init = aspeed_pcie_root_class_init, 288 .interfaces = (InterfaceInfo[]) { 289 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 290 { } 291 }, 292 }; 293 294 /* 295 * AHB to PCIe bridge (PCIECFG) 296 */ 297 298 #define ASPEED_PCIE_CFG_CTRL 0x00 299 #define ASPEED_PCIE_CFG_CTRL_ENABLE BIT(0) 300 #define ASPEED_PCIE_CFG_CTRL_CLEAR_RX BIT(4) 301 #define ASPEED_PCIE_CFG_EN_IRQ 0x04 302 #define ASPEED_PCIE_CFG_TX_CLEAR 0x08 303 #define ASPEED_PCIE_CFG_RX_DATA 0x0C 304 #define ASPEED_PCIE_CFG_TX_DW0 0x10 305 #define ASPEED_PCIE_CFG_TX_DW1 0x14 306 #define ASPEED_PCIE_CFG_TX_DW2 0x18 307 #define ASPEED_PCIE_CFG_TX_DW3 0x1C 308 #define ASPEED_PCIE_CFG_TX_DATA 0x20 309 #define ASPEED_PCIE_CFG_TX_STATUS 0x24 310 #define ASPEED_PCIE_CFG_TX_STATUS_IDLE BIT(31) 311 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_RX_DONE BIT(27) 312 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_RX_DONE BIT(26) 313 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_TX_DONE BIT(25) 314 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_TX_DONE BIT(24) 315 #define ASPEED_PCIE_CFG_TX_STATUS_TRIG BIT(0) 316 #define ASPEED_PCIE_CFG_MSI0 0x58 317 #define ASPEED_PCIE_CFG_MSI1 0x5C 318 #define ASPEED_PCIE_CFG_REG60 0x60 319 #define ASPEED_PCIE_CFG_REG64 0x64 320 #define ASPEED_PCIE_CFG_REG68 0x68 321 322 #define ASPEED_PCIE_CFG_RC_MAX_MSI 64 323 324 static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr, 325 unsigned int size) 326 { 327 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque); 328 uint64_t val = 0; 329 330 switch (addr) { 331 case ASPEED_PCIE_CFG_CTRL: 332 case ASPEED_PCIE_CFG_EN_IRQ: 333 case ASPEED_PCIE_CFG_TX_CLEAR: 334 case ASPEED_PCIE_CFG_RX_DATA: 335 case ASPEED_PCIE_CFG_TX_DW0: 336 case ASPEED_PCIE_CFG_TX_DW1: 337 case ASPEED_PCIE_CFG_TX_DW2: 338 case ASPEED_PCIE_CFG_TX_DW3: 339 case ASPEED_PCIE_CFG_TX_STATUS: 340 case ASPEED_PCIE_CFG_REG60: 341 case ASPEED_PCIE_CFG_REG64: 342 case ASPEED_PCIE_CFG_REG68: 343 val = s->regs[TO_REG(addr)]; 344 break; 345 case ASPEED_PCIE_CFG_MSI0: 346 case ASPEED_PCIE_CFG_MSI1: 347 printf("%s: 0x%" HWADDR_PRIx "\n", __func__, addr); 348 val = s->regs[TO_REG(addr)]; 349 break; 350 default: 351 qemu_log_mask(LOG_GUEST_ERROR, 352 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 353 __func__, addr); 354 break; 355 } 356 357 trace_aspeed_pcie_cfg_read(addr, val); 358 return val; 359 } 360 361 #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ 362 #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ 363 #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */ 364 #define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */ 365 366 #define PCIE_CFG_FMTTYPE_MASK(dw0) (((dw0) >> 24) & 0xff) 367 #define PCIE_CFG_BYTE_EN(dw1) ((dw1) & 0xf) 368 369 #define PCIE_MMCFG_ADDR(bus, devfn, offset) \ 370 ((((bus) & PCIE_MMCFG_BUS_MASK) << PCIE_MMCFG_BUS_BIT) | \ 371 (((devfn) & PCIE_MMCFG_DEVFN_MASK) << PCIE_MMCFG_DEVFN_BIT) | \ 372 ((offset) & PCIE_MMCFG_CONFOFFSET_MASK)) 373 374 /* TODO : find a better way to deduce len/addr/val from byte enable */ 375 static void aspeed_pcie_cfg_translate_write(AspeedPCIECfg *s, uint32_t *addr, 376 uint64_t *val, int *len) 377 { 378 uint8_t byte_en = PCIE_CFG_BYTE_EN(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW1)]); 379 380 *len = ctpop8(byte_en); 381 382 switch (byte_en) { 383 case 0x1: 384 case 0x3: 385 case 0xf: 386 break; 387 case 0x4: 388 *addr += 2; 389 *val = (*val >> (2 * 8)) & MAKE_64BIT_MASK(0, *len * 8); 390 break; 391 case 0x2: 392 case 0xc: 393 *addr += *len; 394 *val = (*val >> (*len * 8)) & MAKE_64BIT_MASK(0, *len * 8); 395 break; 396 default: 397 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid byte enable: %d\n", 398 __func__, byte_en); 399 g_assert_not_reached(); 400 } 401 } 402 403 static void aspeed_pcie_cfg_readwrite(AspeedPCIECfg *s) 404 { 405 bool is_write = !!(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)] & (1ul << 30)); 406 uint32_t cfg_addr = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW2)]; 407 uint8_t bus = (cfg_addr >> 24) & 0xff; 408 uint8_t devfn = (cfg_addr >> 16) & 0xff; 409 uint32_t offset = cfg_addr & 0xffc; 410 uint8_t rc_index = !!(bus & 0x80); 411 AspeedPCIERc *rc = &s->rcs[rc_index]; 412 413 uint64_t val = ~0; 414 int len; 415 416 PCIHostState *pci = PCI_HOST_BRIDGE(rc); 417 PCIDevice *pdev; 418 419 /* HACK: rework host bridge */ 420 if (bus == 0x80) { 421 bus = 0; 422 } 423 424 pdev = pci_find_device(pci->bus, bus, devfn); 425 if (!pdev) { 426 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = ~0; 427 goto out; 428 } 429 430 switch (PCIE_CFG_FMTTYPE_MASK(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)])) { 431 case TLP_FMTTYPE_CFGWR0: 432 case TLP_FMTTYPE_CFGWR1: 433 val = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DATA)]; 434 aspeed_pcie_cfg_translate_write(s, &offset, &val, &len); 435 436 pci_host_config_write_common(pdev, offset, pci_config_size(pdev), 437 val, len); 438 break; 439 440 case TLP_FMTTYPE_CFGRD0: 441 case TLP_FMTTYPE_CFGRD1: 442 val = pci_host_config_read_common(pdev, offset, 443 pci_config_size(pdev), 4); 444 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = val; 445 break; 446 default: 447 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CFG type. DW0=0x%x\n", 448 __func__, s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)]); 449 } 450 451 out: 452 rc->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] |= 453 ASPEED_PCIE_RC_INT_STATUS_RX; 454 455 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |= BIT(24 + rc_index); 456 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |= 457 ASPEED_PCIE_CFG_TX_STATUS_IDLE; 458 459 trace_aspeed_pcie_cfg_rw(is_write ? "write" : "read", bus, devfn, 460 cfg_addr, val); 461 } 462 463 static void aspeed_pcie_cfg_msi_notify(AspeedPCIECfg *s, hwaddr addr, 464 uint64_t data) 465 { 466 bool rc_index = !!(addr == ASPEED_PCIE_CFG_MSI1); 467 AspeedPCIERc *rc = &s->rcs[rc_index]; 468 int reg; 469 470 trace_aspeed_pcie_cfg_msi_notify(addr, data); 471 472 /* Written data is the HW IRQ number */ 473 if (data >= ASPEED_PCIE_CFG_RC_MAX_MSI) { 474 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid MSI vector %"PRIx64"\n", 475 __func__, data); 476 return; 477 } 478 479 /* TODO: what is ASPEED_PCIE_RC_CTRL_RX_MSI_SELECT ? */ 480 if (!(rc->regs[TO_REG(ASPEED_PCIE_RC_CTRL)] & 481 ASPEED_PCIE_RC_CTRL_RX_MSI)) { 482 qemu_log_mask(LOG_GUEST_ERROR, "%s: MSI are not enabled\n", __func__); 483 return; 484 } 485 486 reg = data < 32 ? ASPEED_PCIE_RC_MSI_STATUS0 : ASPEED_PCIE_RC_MSI_STATUS1; 487 488 rc->regs[TO_REG(reg)] |= BIT(data % 32); 489 aspeed_pcie_rc_update_irq(rc); 490 } 491 492 static void aspeed_pcie_cfg_write(void *opaque, hwaddr addr, uint64_t data, 493 unsigned int size) 494 { 495 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque); 496 497 trace_aspeed_pcie_cfg_write(addr, data); 498 499 /* TODO: test ASPEED_PCIE_CFG_CTRL_ENABLE */ 500 501 switch (addr) { 502 case ASPEED_PCIE_CFG_EN_IRQ: 503 case ASPEED_PCIE_CFG_TX_DW0: 504 case ASPEED_PCIE_CFG_TX_DW1: 505 case ASPEED_PCIE_CFG_TX_DW2: 506 case ASPEED_PCIE_CFG_TX_DW3: 507 case ASPEED_PCIE_CFG_TX_DATA: 508 case ASPEED_PCIE_CFG_REG60: 509 case ASPEED_PCIE_CFG_REG64: 510 case ASPEED_PCIE_CFG_REG68: 511 s->regs[TO_REG(addr)] = data; 512 break; 513 case ASPEED_PCIE_CFG_MSI0: 514 case ASPEED_PCIE_CFG_MSI1: 515 aspeed_pcie_cfg_msi_notify(s, addr, data); 516 break; 517 case ASPEED_PCIE_CFG_CTRL: 518 if (data & ASPEED_PCIE_CFG_CTRL_CLEAR_RX) { 519 s->regs[TO_REG(ASPEED_PCIE_CFG_RX_DATA)] = ~0; 520 } 521 break; 522 523 case ASPEED_PCIE_CFG_TX_CLEAR: 524 if (data == 0x1) { 525 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] &= 526 ~ASPEED_PCIE_CFG_TX_STATUS_IDLE; 527 } 528 break; 529 case ASPEED_PCIE_CFG_TX_STATUS: 530 if (data & ASPEED_PCIE_CFG_TX_STATUS_TRIG) { 531 aspeed_pcie_cfg_readwrite(s); 532 } 533 break; 534 default: 535 qemu_log_mask(LOG_GUEST_ERROR, 536 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 537 __func__, addr); 538 break; 539 } 540 } 541 542 static const MemoryRegionOps aspeed_pcie_cfg_ops = { 543 .read = aspeed_pcie_cfg_read, 544 .write = aspeed_pcie_cfg_write, 545 .endianness = DEVICE_LITTLE_ENDIAN, 546 .valid = { 547 .min_access_size = 1, 548 .max_access_size = 4, 549 }, 550 }; 551 552 static void aspeed_pcie_cfg_reset(DeviceState *dev) 553 { 554 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev); 555 556 memset(s->regs, 0, sizeof(s->regs)); 557 } 558 559 static void aspeed_pcie_cfg_instance_init(Object *obj) 560 { 561 AspeedPCIECfg *s = ASPEED_PCIE_CFG(obj); 562 int i; 563 564 for (i = 0; i < ARRAY_SIZE(s->rcs); i++) { 565 object_initialize_child(obj, "rcs[*]", &s->rcs[i], 566 TYPE_ASPEED_PCIE_RC); 567 } 568 } 569 570 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp) 571 { 572 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev); 573 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 574 int nr_rcs = ARRAY_SIZE(s->rcs); 575 int i; 576 577 memory_region_init(&s->reg_mmio_container, OBJECT(s), 578 TYPE_ASPEED_PCIE_CFG ".container", 0x100); 579 sysbus_init_mmio(sbd, &s->reg_mmio_container); 580 581 memory_region_init_io(&s->reg_cfg_mmio, OBJECT(s), &aspeed_pcie_cfg_ops, s, 582 TYPE_ASPEED_PCIE_CFG ".regs", 0x80); 583 memory_region_add_subregion(&s->reg_mmio_container, 0x0, &s->reg_cfg_mmio); 584 585 for (i = 0; i < nr_rcs; i++) { 586 object_property_set_int(OBJECT(&s->rcs[i]), "bus-nr", 587 i * PCI_BUS_MAX / nr_rcs, &error_abort); 588 if (!sysbus_realize(SYS_BUS_DEVICE(&s->rcs[i]), errp)) { 589 return; 590 } 591 592 /* RC registers */ 593 memory_region_add_subregion(&s->reg_mmio_container, 0x80 + i * 0x40, 594 &s->rcs[i].reg_rc_mmio); 595 } 596 } 597 598 static Property aspeed_pcie_cfg_props[] = { 599 DEFINE_PROP_END_OF_LIST(), 600 }; 601 602 static void aspeed_pcie_cfg_class_init(ObjectClass *klass, void *data) 603 { 604 DeviceClass *dc = DEVICE_CLASS(klass); 605 606 dc->realize = aspeed_pcie_cfg_realize; 607 device_class_set_legacy_reset(dc, aspeed_pcie_cfg_reset); 608 device_class_set_props(dc, aspeed_pcie_cfg_props); 609 } 610 611 static const TypeInfo aspeed_pcie_cfg_info = { 612 .name = TYPE_ASPEED_PCIE_CFG, 613 .parent = TYPE_SYS_BUS_DEVICE, 614 .instance_size = sizeof(AspeedPCIECfg), 615 .instance_init = aspeed_pcie_cfg_instance_init, 616 .class_init = aspeed_pcie_cfg_class_init, 617 }; 618 619 620 /* 621 * PHY 622 */ 623 624 #define ASPEED_PCIE_PHY_DEVID 0x00 625 #define ASPEED_PCIE_PHY_CLASS_CODE 0x04 626 #define ASPEED_PCIE_PHY_CLASS_CODE_A3 0x6 627 #define ASPEED_PCIE_PHY_DATALINK 0x10 628 #define ASPEED_PCIE_PHY_HOTPLUG 0x14 629 #define ASPEED_PCIE_PHY_CTRL1 0x30 630 #define ASPEED_PCIE_PHY_CTRL1_ROOTPORT (BIT(5) | BIT(4)) 631 #define ASPEED_PCIE_PHY_CTRL1_ENABLE BIT(1) 632 #define ASPEED_PCIE_PHY_PROTECT 0x7C 633 #define ASPEED_PCIE_PHY_LINK 0xC0 634 #define ASPEED_PCIE_PHY_LINK_STATUS BIT(5) 635 #define ASPEED_PCIE_PHY_BDF 0xC4 636 #define ASPEED_PCIE_PHY_LINK_STS 0xD0 637 638 static uint64_t aspeed_pcie_phy_read(void *opaque, hwaddr addr, 639 unsigned int size) 640 { 641 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque); 642 uint64_t val = 0; 643 644 switch (addr) { 645 case ASPEED_PCIE_PHY_DEVID: 646 case ASPEED_PCIE_PHY_CLASS_CODE: 647 case ASPEED_PCIE_PHY_DATALINK: 648 case ASPEED_PCIE_PHY_CTRL1: 649 case ASPEED_PCIE_PHY_PROTECT: 650 case ASPEED_PCIE_PHY_LINK: 651 case ASPEED_PCIE_PHY_BDF: 652 case ASPEED_PCIE_PHY_LINK_STS: 653 val = s->regs[TO_REG(addr)]; 654 break; 655 default: 656 qemu_log_mask(LOG_GUEST_ERROR, 657 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 658 __func__, addr); 659 break; 660 } 661 662 trace_aspeed_pcie_phy_read(addr, val); 663 return val; 664 } 665 666 static void aspeed_pcie_phy_write(void *opaque, hwaddr addr, uint64_t data, 667 unsigned int size) 668 { 669 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque); 670 671 trace_aspeed_pcie_phy_write(addr, data); 672 673 /* TODO: test protect */ 674 675 switch (addr) { 676 case ASPEED_PCIE_PHY_PROTECT: 677 data &= 0xff; 678 s->regs[TO_REG(addr)] = !!(data == 0xA8); 679 break; 680 681 case ASPEED_PCIE_PHY_DEVID: 682 case ASPEED_PCIE_PHY_CLASS_CODE: 683 case ASPEED_PCIE_PHY_DATALINK: 684 case ASPEED_PCIE_PHY_CTRL1: /* 0x30 == root port, else bridge */ 685 s->regs[TO_REG(addr)] = data; 686 break; 687 default: 688 qemu_log_mask(LOG_GUEST_ERROR, 689 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 690 __func__, addr); 691 break; 692 } 693 } 694 695 static const MemoryRegionOps aspeed_pcie_phy_ops = { 696 .read = aspeed_pcie_phy_read, 697 .write = aspeed_pcie_phy_write, 698 .endianness = DEVICE_LITTLE_ENDIAN, 699 .valid = { 700 .min_access_size = 1, 701 .max_access_size = 4, 702 }, 703 }; 704 705 static void aspeed_pcie_phy_reset(DeviceState *dev) 706 { 707 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev); 708 709 memset(s->regs, 0, sizeof(s->regs)); 710 711 s->regs[TO_REG(ASPEED_PCIE_PHY_DEVID)] = 712 (PCI_DEVICE_ID_AST2600_RC << 16) | PCI_VENDOR_ID_ASPEED; 713 s->regs[TO_REG(ASPEED_PCIE_PHY_CLASS_CODE)] = 714 0x06040000 | ASPEED_PCIE_PHY_CLASS_CODE_A3; 715 s->regs[TO_REG(ASPEED_PCIE_PHY_DATALINK)] = 0xD7040022; 716 s->regs[TO_REG(ASPEED_PCIE_PHY_LINK)] = ASPEED_PCIE_PHY_LINK_STATUS; 717 s->regs[TO_REG(ASPEED_PCIE_PHY_BDF)] = 0x0; /* TODO: BUS+DEV */ 718 } 719 720 static void aspeed_pcie_phy_realize(DeviceState *dev, Error **errp) 721 { 722 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev); 723 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 724 725 memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_pcie_phy_ops, s, 726 TYPE_ASPEED_PCIE_PHY, 0x200); 727 sysbus_init_mmio(sbd, &s->mmio); 728 } 729 730 static Property aspeed_pcie_phy_props[] = { 731 DEFINE_PROP_END_OF_LIST(), 732 }; 733 734 static void aspeed_pcie_phy_class_init(ObjectClass *klass, void *data) 735 { 736 DeviceClass *dc = DEVICE_CLASS(klass); 737 738 dc->realize = aspeed_pcie_phy_realize; 739 device_class_set_legacy_reset(dc, aspeed_pcie_phy_reset); 740 device_class_set_props(dc, aspeed_pcie_phy_props); 741 } 742 743 static const TypeInfo aspeed_pcie_phy_info = { 744 .name = TYPE_ASPEED_PCIE_PHY, 745 .parent = TYPE_SYS_BUS_DEVICE, 746 .instance_size = sizeof(AspeedPCIEPhy), 747 .class_init = aspeed_pcie_phy_class_init, 748 }; 749 750 static void aspeed_pcie_register(void) 751 { 752 type_register_static(&aspeed_pcie_root_info); 753 type_register_static(&aspeed_pcie_rc_info); 754 type_register_static(&aspeed_pcie_phy_info); 755 type_register_static(&aspeed_pcie_cfg_info); 756 } 757 758 type_init(aspeed_pcie_register) 759