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 "hw/hw.h" 26 #include "hw/ppc/ppc.h" 27 #include "hw/ppc/ppc4xx.h" 28 #include "hw/pci/pci.h" 29 #include "hw/pci/pci_host.h" 30 #include "exec/address-spaces.h" 31 #include "trace.h" 32 33 struct PLBOutMap { 34 uint64_t la; 35 uint64_t pcia; 36 uint32_t sa; 37 MemoryRegion mr; 38 }; 39 40 struct PLBInMap { 41 uint64_t sa; 42 uint64_t la; 43 MemoryRegion mr; 44 }; 45 46 #define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" 47 #define PPC440_PCIX_HOST_BRIDGE(obj) \ 48 OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) 49 50 #define PPC440_PCIX_NR_POMS 3 51 #define PPC440_PCIX_NR_PIMS 3 52 53 typedef struct PPC440PCIXState { 54 PCIHostState parent_obj; 55 56 PCIDevice *dev; 57 struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; 58 struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; 59 uint32_t sts; 60 qemu_irq irq; 61 AddressSpace bm_as; 62 MemoryRegion bm; 63 64 MemoryRegion container; 65 MemoryRegion iomem; 66 MemoryRegion busmem; 67 } PPC440PCIXState; 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_read(addr, val); 172 switch (addr) { 173 case PCI_VENDOR_ID ... PCI_MAX_LAT: 174 stl_le_p(s->dev->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->dev->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_BRIDGE(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 /* All pins from each slot are tied to a single board IRQ. 418 * This may need further refactoring for other boards. */ 419 static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) 420 { 421 trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0); 422 return 0; 423 } 424 425 static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) 426 { 427 qemu_irq *pci_irq = opaque; 428 429 trace_ppc440_pcix_set_irq(irq_num); 430 if (irq_num < 0) { 431 error_report("%s: PCI irq %d", __func__, irq_num); 432 return; 433 } 434 qemu_set_irq(*pci_irq, level); 435 } 436 437 static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) 438 { 439 PPC440PCIXState *s = opaque; 440 441 return &s->bm_as; 442 } 443 444 /* The default pci_host_data_{read,write} functions in pci/pci_host.c 445 * deny access to registers without bit 31 set but our clients want 446 * this to work so we have to override these here */ 447 static void pci_host_data_write(void *opaque, hwaddr addr, 448 uint64_t val, unsigned len) 449 { 450 PCIHostState *s = opaque; 451 pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); 452 } 453 454 static uint64_t pci_host_data_read(void *opaque, 455 hwaddr addr, unsigned len) 456 { 457 PCIHostState *s = opaque; 458 uint32_t val; 459 val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); 460 return val; 461 } 462 463 const MemoryRegionOps ppc440_pcix_host_data_ops = { 464 .read = pci_host_data_read, 465 .write = pci_host_data_write, 466 .endianness = DEVICE_LITTLE_ENDIAN, 467 }; 468 469 static void ppc440_pcix_realize(DeviceState *dev, Error **errp) 470 { 471 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 472 PPC440PCIXState *s; 473 PCIHostState *h; 474 475 h = PCI_HOST_BRIDGE(dev); 476 s = PPC440_PCIX_HOST_BRIDGE(dev); 477 478 sysbus_init_irq(sbd, &s->irq); 479 memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); 480 h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, 481 ppc440_pcix_map_irq, &s->irq, &s->busmem, 482 get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); 483 484 s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); 485 486 memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); 487 memory_region_add_subregion(&s->bm, 0x0, &s->busmem); 488 address_space_init(&s->bm_as, &s->bm, "pci-bm"); 489 pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s); 490 491 memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); 492 memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, 493 h, "pci-conf-idx", 4); 494 memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops, 495 h, "pci-conf-data", 4); 496 memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, 497 "pci.reg", PPC440_REG_SIZE); 498 memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); 499 memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); 500 memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); 501 sysbus_init_mmio(sbd, &s->container); 502 } 503 504 static void ppc440_pcix_class_init(ObjectClass *klass, void *data) 505 { 506 DeviceClass *dc = DEVICE_CLASS(klass); 507 508 dc->realize = ppc440_pcix_realize; 509 dc->reset = ppc440_pcix_reset; 510 } 511 512 static const TypeInfo ppc440_pcix_info = { 513 .name = TYPE_PPC440_PCIX_HOST_BRIDGE, 514 .parent = TYPE_PCI_HOST_BRIDGE, 515 .instance_size = sizeof(PPC440PCIXState), 516 .class_init = ppc440_pcix_class_init, 517 }; 518 519 static void ppc440_pcix_register_types(void) 520 { 521 type_register_static(&ppc440_pcix_info); 522 } 523 524 type_init(ppc440_pcix_register_types) 525