1 /* 2 * Emulation of the ibm,plb-pcix PCI controller 3 * This is found in some 440 SoCs e.g. the 460EX. 4 * 5 * Copyright (c) 2016-2018 BALATON Zoltan 6 * 7 * Derived from ppc4xx_pci.c and pci-host/ppce500.c 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License, version 2, as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "qemu/error-report.h" 24 #include "qemu/log.h" 25 #include "qemu/module.h" 26 #include "qemu/units.h" 27 #include "hw/irq.h" 28 #include "hw/pci-host/ppc4xx.h" 29 #include "hw/pci/pci_device.h" 30 #include "hw/pci/pci_host.h" 31 #include "trace.h" 32 #include "qom/object.h" 33 34 struct PLBOutMap { 35 uint64_t la; 36 uint64_t pcia; 37 uint32_t sa; 38 MemoryRegion mr; 39 }; 40 41 struct PLBInMap { 42 uint64_t sa; 43 uint64_t la; 44 MemoryRegion mr; 45 }; 46 47 OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST) 48 49 #define PPC440_PCIX_NR_POMS 3 50 #define PPC440_PCIX_NR_PIMS 3 51 52 struct PPC440PCIXState { 53 PCIHostState parent_obj; 54 55 uint8_t config[PCI_CONFIG_SPACE_SIZE]; 56 struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; 57 struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; 58 uint32_t sts; 59 qemu_irq irq; 60 AddressSpace bm_as; 61 MemoryRegion bm; 62 63 MemoryRegion container; 64 MemoryRegion iomem; 65 MemoryRegion busmem; 66 MemoryRegion regs; 67 }; 68 69 #define PPC440_REG_BASE 0x80000 70 #define PPC440_REG_SIZE 0xff 71 72 #define PCIC0_CFGADDR 0x0 73 #define PCIC0_CFGDATA 0x4 74 75 #define PCIX0_POM0LAL 0x68 76 #define PCIX0_POM0LAH 0x6c 77 #define PCIX0_POM0SA 0x70 78 #define PCIX0_POM0PCIAL 0x74 79 #define PCIX0_POM0PCIAH 0x78 80 #define PCIX0_POM1LAL 0x7c 81 #define PCIX0_POM1LAH 0x80 82 #define PCIX0_POM1SA 0x84 83 #define PCIX0_POM1PCIAL 0x88 84 #define PCIX0_POM1PCIAH 0x8c 85 #define PCIX0_POM2SA 0x90 86 87 #define PCIX0_PIM0SAL 0x98 88 #define PCIX0_PIM0LAL 0x9c 89 #define PCIX0_PIM0LAH 0xa0 90 #define PCIX0_PIM1SA 0xa4 91 #define PCIX0_PIM1LAL 0xa8 92 #define PCIX0_PIM1LAH 0xac 93 #define PCIX0_PIM2SAL 0xb0 94 #define PCIX0_PIM2LAL 0xb4 95 #define PCIX0_PIM2LAH 0xb8 96 #define PCIX0_PIM0SAH 0xf8 97 #define PCIX0_PIM2SAH 0xfc 98 99 #define PCIX0_STS 0xe0 100 101 #define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) 102 103 static void ppc440_pcix_clear_region(MemoryRegion *parent, 104 MemoryRegion *mem) 105 { 106 if (memory_region_is_mapped(mem)) { 107 memory_region_del_subregion(parent, mem); 108 object_unparent(OBJECT(mem)); 109 } 110 } 111 112 /* DMA mapping */ 113 static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) 114 { 115 MemoryRegion *mem = &s->pim[idx].mr; 116 char *name; 117 uint64_t size; 118 119 /* Before we modify anything, unmap and destroy the region */ 120 ppc440_pcix_clear_region(&s->bm, mem); 121 122 if (!(s->pim[idx].sa & 1)) { 123 /* Not enabled, nothing to do */ 124 return; 125 } 126 127 name = g_strdup_printf("PCI Inbound Window %d", idx); 128 size = ~(s->pim[idx].sa & ~7ULL) + 1; 129 memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), 130 s->pim[idx].la, size); 131 memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); 132 g_free(name); 133 134 trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la); 135 } 136 137 /* BAR mapping */ 138 static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) 139 { 140 MemoryRegion *mem = &s->pom[idx].mr; 141 MemoryRegion *address_space_mem = get_system_memory(); 142 char *name; 143 uint32_t size; 144 145 /* Before we modify anything, unmap and destroy the region */ 146 ppc440_pcix_clear_region(address_space_mem, mem); 147 148 if (!(s->pom[idx].sa & 1)) { 149 /* Not enabled, nothing to do */ 150 return; 151 } 152 153 name = g_strdup_printf("PCI Outbound Window %d", idx); 154 size = ~(s->pom[idx].sa & 0xfffffffe) + 1; 155 if (!size) { 156 size = 0xffffffff; 157 } 158 memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, 159 s->pom[idx].pcia, size); 160 memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); 161 g_free(name); 162 163 trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia); 164 } 165 166 static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, 167 uint64_t val, unsigned size) 168 { 169 struct PPC440PCIXState *s = opaque; 170 171 trace_ppc440_pcix_reg_write(addr, val, size); 172 switch (addr) { 173 case PCI_VENDOR_ID ... PCI_MAX_LAT: 174 stl_le_p(s->config + addr, val); 175 break; 176 177 case PCIX0_POM0LAL: 178 s->pom[0].la &= 0xffffffff00000000ULL; 179 s->pom[0].la |= val; 180 ppc440_pcix_update_pom(s, 0); 181 break; 182 case PCIX0_POM0LAH: 183 s->pom[0].la &= 0xffffffffULL; 184 s->pom[0].la |= val << 32; 185 ppc440_pcix_update_pom(s, 0); 186 break; 187 case PCIX0_POM0SA: 188 s->pom[0].sa = val; 189 ppc440_pcix_update_pom(s, 0); 190 break; 191 case PCIX0_POM0PCIAL: 192 s->pom[0].pcia &= 0xffffffff00000000ULL; 193 s->pom[0].pcia |= val; 194 ppc440_pcix_update_pom(s, 0); 195 break; 196 case PCIX0_POM0PCIAH: 197 s->pom[0].pcia &= 0xffffffffULL; 198 s->pom[0].pcia |= val << 32; 199 ppc440_pcix_update_pom(s, 0); 200 break; 201 case PCIX0_POM1LAL: 202 s->pom[1].la &= 0xffffffff00000000ULL; 203 s->pom[1].la |= val; 204 ppc440_pcix_update_pom(s, 1); 205 break; 206 case PCIX0_POM1LAH: 207 s->pom[1].la &= 0xffffffffULL; 208 s->pom[1].la |= val << 32; 209 ppc440_pcix_update_pom(s, 1); 210 break; 211 case PCIX0_POM1SA: 212 s->pom[1].sa = val; 213 ppc440_pcix_update_pom(s, 1); 214 break; 215 case PCIX0_POM1PCIAL: 216 s->pom[1].pcia &= 0xffffffff00000000ULL; 217 s->pom[1].pcia |= val; 218 ppc440_pcix_update_pom(s, 1); 219 break; 220 case PCIX0_POM1PCIAH: 221 s->pom[1].pcia &= 0xffffffffULL; 222 s->pom[1].pcia |= val << 32; 223 ppc440_pcix_update_pom(s, 1); 224 break; 225 case PCIX0_POM2SA: 226 s->pom[2].sa = val; 227 break; 228 229 case PCIX0_PIM0SAL: 230 s->pim[0].sa &= 0xffffffff00000000ULL; 231 s->pim[0].sa |= val; 232 ppc440_pcix_update_pim(s, 0); 233 break; 234 case PCIX0_PIM0LAL: 235 s->pim[0].la &= 0xffffffff00000000ULL; 236 s->pim[0].la |= val; 237 ppc440_pcix_update_pim(s, 0); 238 break; 239 case PCIX0_PIM0LAH: 240 s->pim[0].la &= 0xffffffffULL; 241 s->pim[0].la |= val << 32; 242 ppc440_pcix_update_pim(s, 0); 243 break; 244 case PCIX0_PIM1SA: 245 s->pim[1].sa = val; 246 ppc440_pcix_update_pim(s, 1); 247 break; 248 case PCIX0_PIM1LAL: 249 s->pim[1].la &= 0xffffffff00000000ULL; 250 s->pim[1].la |= val; 251 ppc440_pcix_update_pim(s, 1); 252 break; 253 case PCIX0_PIM1LAH: 254 s->pim[1].la &= 0xffffffffULL; 255 s->pim[1].la |= val << 32; 256 ppc440_pcix_update_pim(s, 1); 257 break; 258 case PCIX0_PIM2SAL: 259 s->pim[2].sa &= 0xffffffff00000000ULL; 260 s->pim[2].sa |= val; 261 ppc440_pcix_update_pim(s, 2); 262 break; 263 case PCIX0_PIM2LAL: 264 s->pim[2].la &= 0xffffffff00000000ULL; 265 s->pim[2].la |= val; 266 ppc440_pcix_update_pim(s, 2); 267 break; 268 case PCIX0_PIM2LAH: 269 s->pim[2].la &= 0xffffffffULL; 270 s->pim[2].la |= val << 32; 271 ppc440_pcix_update_pim(s, 2); 272 break; 273 274 case PCIX0_STS: 275 s->sts = val; 276 break; 277 278 case PCIX0_PIM0SAH: 279 s->pim[0].sa &= 0xffffffffULL; 280 s->pim[0].sa |= val << 32; 281 ppc440_pcix_update_pim(s, 0); 282 break; 283 case PCIX0_PIM2SAH: 284 s->pim[2].sa &= 0xffffffffULL; 285 s->pim[2].sa |= val << 32; 286 ppc440_pcix_update_pim(s, 2); 287 break; 288 289 default: 290 qemu_log_mask(LOG_UNIMP, 291 "%s: unhandled PCI internal register 0x%"HWADDR_PRIx"\n", 292 __func__, addr); 293 break; 294 } 295 } 296 297 static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, 298 unsigned size) 299 { 300 struct PPC440PCIXState *s = opaque; 301 uint32_t val; 302 303 switch (addr) { 304 case PCI_VENDOR_ID ... PCI_MAX_LAT: 305 val = ldl_le_p(s->config + addr); 306 break; 307 308 case PCIX0_POM0LAL: 309 val = s->pom[0].la; 310 break; 311 case PCIX0_POM0LAH: 312 val = s->pom[0].la >> 32; 313 break; 314 case PCIX0_POM0SA: 315 val = s->pom[0].sa; 316 break; 317 case PCIX0_POM0PCIAL: 318 val = s->pom[0].pcia; 319 break; 320 case PCIX0_POM0PCIAH: 321 val = s->pom[0].pcia >> 32; 322 break; 323 case PCIX0_POM1LAL: 324 val = s->pom[1].la; 325 break; 326 case PCIX0_POM1LAH: 327 val = s->pom[1].la >> 32; 328 break; 329 case PCIX0_POM1SA: 330 val = s->pom[1].sa; 331 break; 332 case PCIX0_POM1PCIAL: 333 val = s->pom[1].pcia; 334 break; 335 case PCIX0_POM1PCIAH: 336 val = s->pom[1].pcia >> 32; 337 break; 338 case PCIX0_POM2SA: 339 val = s->pom[2].sa; 340 break; 341 342 case PCIX0_PIM0SAL: 343 val = s->pim[0].sa; 344 break; 345 case PCIX0_PIM0LAL: 346 val = s->pim[0].la; 347 break; 348 case PCIX0_PIM0LAH: 349 val = s->pim[0].la >> 32; 350 break; 351 case PCIX0_PIM1SA: 352 val = s->pim[1].sa; 353 break; 354 case PCIX0_PIM1LAL: 355 val = s->pim[1].la; 356 break; 357 case PCIX0_PIM1LAH: 358 val = s->pim[1].la >> 32; 359 break; 360 case PCIX0_PIM2SAL: 361 val = s->pim[2].sa; 362 break; 363 case PCIX0_PIM2LAL: 364 val = s->pim[2].la; 365 break; 366 case PCIX0_PIM2LAH: 367 val = s->pim[2].la >> 32; 368 break; 369 370 case PCIX0_STS: 371 val = s->sts; 372 break; 373 374 case PCIX0_PIM0SAH: 375 val = s->pim[0].sa >> 32; 376 break; 377 case PCIX0_PIM2SAH: 378 val = s->pim[2].sa >> 32; 379 break; 380 381 default: 382 qemu_log_mask(LOG_UNIMP, 383 "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n", 384 __func__, addr); 385 val = 0; 386 } 387 388 trace_ppc440_pcix_reg_read(addr, val); 389 return val; 390 } 391 392 static const MemoryRegionOps pci_reg_ops = { 393 .read = ppc440_pcix_reg_read4, 394 .write = ppc440_pcix_reg_write4, 395 .endianness = DEVICE_LITTLE_ENDIAN, 396 }; 397 398 static void ppc440_pcix_reset(DeviceState *dev) 399 { 400 struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev); 401 int i; 402 403 for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { 404 ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr); 405 } 406 for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 407 ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr); 408 } 409 memset(s->pom, 0, sizeof(s->pom)); 410 memset(s->pim, 0, sizeof(s->pim)); 411 for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 412 s->pim[i].sa = 0xffffffff00000000ULL; 413 } 414 s->sts = 0; 415 } 416 417 /* 418 * All four IRQ[ABCD] pins from all slots are tied to a single board 419 * IRQ, so our mapping function here maps everything to IRQ 0. 420 * The code in pci_change_irq_level() tracks the number of times 421 * the mapped IRQ is asserted and deasserted, so if multiple devices 422 * assert an IRQ at the same time the behaviour is correct. 423 * 424 * This may need further refactoring for boards that use multiple IRQ lines. 425 */ 426 static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) 427 { 428 trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0); 429 return 0; 430 } 431 432 static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) 433 { 434 qemu_irq *pci_irq = opaque; 435 436 trace_ppc440_pcix_set_irq(irq_num); 437 if (irq_num < 0) { 438 error_report("%s: PCI irq %d", __func__, irq_num); 439 return; 440 } 441 qemu_set_irq(*pci_irq, level); 442 } 443 444 static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) 445 { 446 PPC440PCIXState *s = opaque; 447 448 return &s->bm_as; 449 } 450 451 static const PCIIOMMUOps ppc440_iommu_ops = { 452 .get_address_space = ppc440_pcix_set_iommu, 453 }; 454 455 /* 456 * Some guests on sam460ex write all kinds of garbage here such as 457 * missing enable bit and low bits set and still expect this to work 458 * (apparently it does on real hardware because these boot there) so 459 * we have to override these ops here and fix it up 460 */ 461 static void pci_host_config_write(void *opaque, hwaddr addr, 462 uint64_t val, unsigned len) 463 { 464 PCIHostState *s = opaque; 465 466 if (addr != 0 || len != 4) { 467 return; 468 } 469 s->config_reg = (val & 0xfffffffcULL) | (1UL << 31); 470 } 471 472 static uint64_t pci_host_config_read(void *opaque, hwaddr addr, 473 unsigned len) 474 { 475 PCIHostState *s = opaque; 476 uint32_t val = s->config_reg; 477 478 return val; 479 } 480 481 const MemoryRegionOps ppc440_pcix_host_conf_ops = { 482 .read = pci_host_config_read, 483 .write = pci_host_config_write, 484 .endianness = DEVICE_LITTLE_ENDIAN, 485 }; 486 487 static void ppc440_pcix_realize(DeviceState *dev, Error **errp) 488 { 489 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 490 PPC440PCIXState *s; 491 PCIHostState *h; 492 493 h = PCI_HOST_BRIDGE(dev); 494 s = PPC440_PCIX_HOST(dev); 495 496 sysbus_init_irq(sbd, &s->irq); 497 memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX); 498 memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB); 499 h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, 500 ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem, 501 PCI_DEVFN(1, 0), 1, TYPE_PCI_BUS); 502 503 memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); 504 memory_region_add_subregion(&s->bm, 0x0, &s->busmem); 505 address_space_init(&s->bm_as, &s->bm, "pci-bm"); 506 pci_setup_iommu(h->bus, &ppc440_iommu_ops, s); 507 508 memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); 509 memory_region_init_io(&h->conf_mem, OBJECT(s), &ppc440_pcix_host_conf_ops, 510 h, "pci-conf-idx", 4); 511 memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, 512 h, "pci-conf-data", 4); 513 memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg", 514 PPC440_REG_SIZE); 515 memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); 516 memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); 517 memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs); 518 sysbus_init_mmio(sbd, &s->container); 519 sysbus_init_mmio(sbd, &s->iomem); 520 } 521 522 static void ppc440_pcix_class_init(ObjectClass *klass, void *data) 523 { 524 DeviceClass *dc = DEVICE_CLASS(klass); 525 526 dc->realize = ppc440_pcix_realize; 527 device_class_set_legacy_reset(dc, ppc440_pcix_reset); 528 } 529 530 static const TypeInfo ppc440_pcix_info = { 531 .name = TYPE_PPC440_PCIX_HOST, 532 .parent = TYPE_PCI_HOST_BRIDGE, 533 .instance_size = sizeof(PPC440PCIXState), 534 .class_init = ppc440_pcix_class_init, 535 }; 536 537 static void ppc440_pcix_register_types(void) 538 { 539 type_register_static(&ppc440_pcix_info); 540 } 541 542 type_init(ppc440_pcix_register_types) 543