17ccc89b5SBALATON Zoltan /* 27ccc89b5SBALATON Zoltan * Emulation of the ibm,plb-pcix PCI controller 37ccc89b5SBALATON Zoltan * This is found in some 440 SoCs e.g. the 460EX. 47ccc89b5SBALATON Zoltan * 57ccc89b5SBALATON Zoltan * Copyright (c) 2016-2018 BALATON Zoltan 67ccc89b5SBALATON Zoltan * 77ccc89b5SBALATON Zoltan * Derived from ppc4xx_pci.c and pci-host/ppce500.c 87ccc89b5SBALATON Zoltan * 97ccc89b5SBALATON Zoltan * This program is free software; you can redistribute it and/or modify 107ccc89b5SBALATON Zoltan * it under the terms of the GNU General Public License, version 2, as 117ccc89b5SBALATON Zoltan * published by the Free Software Foundation. 127ccc89b5SBALATON Zoltan * 137ccc89b5SBALATON Zoltan * This program is distributed in the hope that it will be useful, 147ccc89b5SBALATON Zoltan * but WITHOUT ANY WARRANTY; without even the implied warranty of 157ccc89b5SBALATON Zoltan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 167ccc89b5SBALATON Zoltan * GNU General Public License for more details. 177ccc89b5SBALATON Zoltan * 187ccc89b5SBALATON Zoltan * You should have received a copy of the GNU General Public License 197ccc89b5SBALATON Zoltan * along with this program; if not, see <http://www.gnu.org/licenses/>. 207ccc89b5SBALATON Zoltan */ 217ccc89b5SBALATON Zoltan 227ccc89b5SBALATON Zoltan #include "qemu/osdep.h" 237ccc89b5SBALATON Zoltan #include "qemu/error-report.h" 2421a5a442SBALATON Zoltan #include "qemu/log.h" 250b8fa32fSMarkus Armbruster #include "qemu/module.h" 2664552b6bSMarkus Armbruster #include "hw/irq.h" 277ccc89b5SBALATON Zoltan #include "hw/ppc/ppc.h" 287ccc89b5SBALATON Zoltan #include "hw/ppc/ppc4xx.h" 297ccc89b5SBALATON Zoltan #include "hw/pci/pci.h" 307ccc89b5SBALATON Zoltan #include "hw/pci/pci_host.h" 317ccc89b5SBALATON Zoltan #include "exec/address-spaces.h" 327ccc89b5SBALATON Zoltan #include "trace.h" 33*db1015e9SEduardo Habkost #include "qom/object.h" 347ccc89b5SBALATON Zoltan 357ccc89b5SBALATON Zoltan struct PLBOutMap { 367ccc89b5SBALATON Zoltan uint64_t la; 377ccc89b5SBALATON Zoltan uint64_t pcia; 387ccc89b5SBALATON Zoltan uint32_t sa; 397ccc89b5SBALATON Zoltan MemoryRegion mr; 407ccc89b5SBALATON Zoltan }; 417ccc89b5SBALATON Zoltan 427ccc89b5SBALATON Zoltan struct PLBInMap { 437ccc89b5SBALATON Zoltan uint64_t sa; 447ccc89b5SBALATON Zoltan uint64_t la; 457ccc89b5SBALATON Zoltan MemoryRegion mr; 467ccc89b5SBALATON Zoltan }; 477ccc89b5SBALATON Zoltan 487ccc89b5SBALATON Zoltan #define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" 49*db1015e9SEduardo Habkost typedef struct PPC440PCIXState PPC440PCIXState; 507ccc89b5SBALATON Zoltan #define PPC440_PCIX_HOST_BRIDGE(obj) \ 517ccc89b5SBALATON Zoltan OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) 527ccc89b5SBALATON Zoltan 537ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_POMS 3 547ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_PIMS 3 557ccc89b5SBALATON Zoltan 56*db1015e9SEduardo Habkost struct PPC440PCIXState { 577ccc89b5SBALATON Zoltan PCIHostState parent_obj; 587ccc89b5SBALATON Zoltan 597ccc89b5SBALATON Zoltan PCIDevice *dev; 607ccc89b5SBALATON Zoltan struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; 617ccc89b5SBALATON Zoltan struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; 627ccc89b5SBALATON Zoltan uint32_t sts; 636484ab3dSBALATON Zoltan qemu_irq irq; 647ccc89b5SBALATON Zoltan AddressSpace bm_as; 657ccc89b5SBALATON Zoltan MemoryRegion bm; 667ccc89b5SBALATON Zoltan 677ccc89b5SBALATON Zoltan MemoryRegion container; 687ccc89b5SBALATON Zoltan MemoryRegion iomem; 697ccc89b5SBALATON Zoltan MemoryRegion busmem; 70*db1015e9SEduardo Habkost }; 717ccc89b5SBALATON Zoltan 727ccc89b5SBALATON Zoltan #define PPC440_REG_BASE 0x80000 737ccc89b5SBALATON Zoltan #define PPC440_REG_SIZE 0xff 747ccc89b5SBALATON Zoltan 757ccc89b5SBALATON Zoltan #define PCIC0_CFGADDR 0x0 767ccc89b5SBALATON Zoltan #define PCIC0_CFGDATA 0x4 777ccc89b5SBALATON Zoltan 787ccc89b5SBALATON Zoltan #define PCIX0_POM0LAL 0x68 797ccc89b5SBALATON Zoltan #define PCIX0_POM0LAH 0x6c 807ccc89b5SBALATON Zoltan #define PCIX0_POM0SA 0x70 817ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAL 0x74 827ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAH 0x78 837ccc89b5SBALATON Zoltan #define PCIX0_POM1LAL 0x7c 847ccc89b5SBALATON Zoltan #define PCIX0_POM1LAH 0x80 857ccc89b5SBALATON Zoltan #define PCIX0_POM1SA 0x84 867ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAL 0x88 877ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAH 0x8c 887ccc89b5SBALATON Zoltan #define PCIX0_POM2SA 0x90 897ccc89b5SBALATON Zoltan 907ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAL 0x98 917ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAL 0x9c 927ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAH 0xa0 937ccc89b5SBALATON Zoltan #define PCIX0_PIM1SA 0xa4 947ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAL 0xa8 957ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAH 0xac 967ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAL 0xb0 977ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAL 0xb4 987ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAH 0xb8 997ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAH 0xf8 1007ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAH 0xfc 1017ccc89b5SBALATON Zoltan 1027ccc89b5SBALATON Zoltan #define PCIX0_STS 0xe0 1037ccc89b5SBALATON Zoltan 1047ccc89b5SBALATON Zoltan #define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) 1057ccc89b5SBALATON Zoltan 1067ccc89b5SBALATON Zoltan static void ppc440_pcix_clear_region(MemoryRegion *parent, 1077ccc89b5SBALATON Zoltan MemoryRegion *mem) 1087ccc89b5SBALATON Zoltan { 1097ccc89b5SBALATON Zoltan if (memory_region_is_mapped(mem)) { 1107ccc89b5SBALATON Zoltan memory_region_del_subregion(parent, mem); 1117ccc89b5SBALATON Zoltan object_unparent(OBJECT(mem)); 1127ccc89b5SBALATON Zoltan } 1137ccc89b5SBALATON Zoltan } 1147ccc89b5SBALATON Zoltan 1157ccc89b5SBALATON Zoltan /* DMA mapping */ 1167ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) 1177ccc89b5SBALATON Zoltan { 1187ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pim[idx].mr; 1197ccc89b5SBALATON Zoltan char *name; 1207ccc89b5SBALATON Zoltan uint64_t size; 1217ccc89b5SBALATON Zoltan 1227ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 1237ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, mem); 1247ccc89b5SBALATON Zoltan 1257ccc89b5SBALATON Zoltan if (!(s->pim[idx].sa & 1)) { 1267ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 1277ccc89b5SBALATON Zoltan return; 1287ccc89b5SBALATON Zoltan } 1297ccc89b5SBALATON Zoltan 1307ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Inbound Window %d", idx); 1317ccc89b5SBALATON Zoltan size = ~(s->pim[idx].sa & ~7ULL) + 1; 1327ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), 1337ccc89b5SBALATON Zoltan s->pim[idx].la, size); 1347ccc89b5SBALATON Zoltan memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); 1357ccc89b5SBALATON Zoltan g_free(name); 1367ccc89b5SBALATON Zoltan 1377ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la); 1387ccc89b5SBALATON Zoltan } 1397ccc89b5SBALATON Zoltan 1407ccc89b5SBALATON Zoltan /* BAR mapping */ 1417ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) 1427ccc89b5SBALATON Zoltan { 1437ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pom[idx].mr; 1447ccc89b5SBALATON Zoltan MemoryRegion *address_space_mem = get_system_memory(); 1457ccc89b5SBALATON Zoltan char *name; 1467ccc89b5SBALATON Zoltan uint32_t size; 1477ccc89b5SBALATON Zoltan 1487ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 1497ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(address_space_mem, mem); 1507ccc89b5SBALATON Zoltan 1517ccc89b5SBALATON Zoltan if (!(s->pom[idx].sa & 1)) { 1527ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 1537ccc89b5SBALATON Zoltan return; 1547ccc89b5SBALATON Zoltan } 1557ccc89b5SBALATON Zoltan 1567ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Outbound Window %d", idx); 1577ccc89b5SBALATON Zoltan size = ~(s->pom[idx].sa & 0xfffffffe) + 1; 1587ccc89b5SBALATON Zoltan if (!size) { 1597ccc89b5SBALATON Zoltan size = 0xffffffff; 1607ccc89b5SBALATON Zoltan } 1617ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, 1627ccc89b5SBALATON Zoltan s->pom[idx].pcia, size); 1637ccc89b5SBALATON Zoltan memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); 1647ccc89b5SBALATON Zoltan g_free(name); 1657ccc89b5SBALATON Zoltan 1667ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia); 1677ccc89b5SBALATON Zoltan } 1687ccc89b5SBALATON Zoltan 1697ccc89b5SBALATON Zoltan static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, 1707ccc89b5SBALATON Zoltan uint64_t val, unsigned size) 1717ccc89b5SBALATON Zoltan { 1727ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 1737ccc89b5SBALATON Zoltan 1747ccc89b5SBALATON Zoltan trace_ppc440_pcix_reg_read(addr, val); 1757ccc89b5SBALATON Zoltan switch (addr) { 1767ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 1777ccc89b5SBALATON Zoltan stl_le_p(s->dev->config + addr, val); 1787ccc89b5SBALATON Zoltan break; 1797ccc89b5SBALATON Zoltan 1807ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 1817ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffff00000000ULL; 1827ccc89b5SBALATON Zoltan s->pom[0].la |= val; 1837ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1847ccc89b5SBALATON Zoltan break; 1857ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 1867ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffffULL; 1877ccc89b5SBALATON Zoltan s->pom[0].la |= val << 32; 1887ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1897ccc89b5SBALATON Zoltan break; 1907ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 1917ccc89b5SBALATON Zoltan s->pom[0].sa = val; 1927ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1937ccc89b5SBALATON Zoltan break; 1947ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 1957ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffff00000000ULL; 1967ccc89b5SBALATON Zoltan s->pom[0].pcia |= val; 1977ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1987ccc89b5SBALATON Zoltan break; 1997ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 2007ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffffULL; 2017ccc89b5SBALATON Zoltan s->pom[0].pcia |= val << 32; 2027ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 2037ccc89b5SBALATON Zoltan break; 2047ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 2057ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffff00000000ULL; 2067ccc89b5SBALATON Zoltan s->pom[1].la |= val; 2077ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2087ccc89b5SBALATON Zoltan break; 2097ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 2107ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffffULL; 2117ccc89b5SBALATON Zoltan s->pom[1].la |= val << 32; 2127ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2137ccc89b5SBALATON Zoltan break; 2147ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 2157ccc89b5SBALATON Zoltan s->pom[1].sa = val; 2167ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2177ccc89b5SBALATON Zoltan break; 2187ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 2197ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffff00000000ULL; 2207ccc89b5SBALATON Zoltan s->pom[1].pcia |= val; 2217ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2227ccc89b5SBALATON Zoltan break; 2237ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 2247ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffffULL; 2257ccc89b5SBALATON Zoltan s->pom[1].pcia |= val << 32; 2267ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2277ccc89b5SBALATON Zoltan break; 2287ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 2297ccc89b5SBALATON Zoltan s->pom[2].sa = val; 2307ccc89b5SBALATON Zoltan break; 2317ccc89b5SBALATON Zoltan 2327ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 2337ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffff00000000ULL; 2347ccc89b5SBALATON Zoltan s->pim[0].sa |= val; 2357ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2367ccc89b5SBALATON Zoltan break; 2377ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 2387ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffff00000000ULL; 2397ccc89b5SBALATON Zoltan s->pim[0].la |= val; 2407ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2417ccc89b5SBALATON Zoltan break; 2427ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 2437ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffffULL; 2447ccc89b5SBALATON Zoltan s->pim[0].la |= val << 32; 2457ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2467ccc89b5SBALATON Zoltan break; 2477ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 2487ccc89b5SBALATON Zoltan s->pim[1].sa = val; 2497ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2507ccc89b5SBALATON Zoltan break; 2517ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 2527ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffff00000000ULL; 2537ccc89b5SBALATON Zoltan s->pim[1].la |= val; 2547ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2557ccc89b5SBALATON Zoltan break; 2567ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 2577ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffffULL; 2587ccc89b5SBALATON Zoltan s->pim[1].la |= val << 32; 2597ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2607ccc89b5SBALATON Zoltan break; 2617ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 2627ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffff00000000ULL; 26368143189SBALATON Zoltan s->pim[2].sa |= val; 2647ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2657ccc89b5SBALATON Zoltan break; 2667ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 2677ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffff00000000ULL; 2687ccc89b5SBALATON Zoltan s->pim[2].la |= val; 2697ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2707ccc89b5SBALATON Zoltan break; 2717ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 2727ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffffULL; 2737ccc89b5SBALATON Zoltan s->pim[2].la |= val << 32; 2747ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2757ccc89b5SBALATON Zoltan break; 2767ccc89b5SBALATON Zoltan 2777ccc89b5SBALATON Zoltan case PCIX0_STS: 2787ccc89b5SBALATON Zoltan s->sts = val; 2797ccc89b5SBALATON Zoltan break; 2807ccc89b5SBALATON Zoltan 2817ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 2827ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffffULL; 2837ccc89b5SBALATON Zoltan s->pim[0].sa |= val << 32; 2847ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2857ccc89b5SBALATON Zoltan break; 2867ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 2877ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffffULL; 2887ccc89b5SBALATON Zoltan s->pim[2].sa |= val << 32; 2897ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2907ccc89b5SBALATON Zoltan break; 2917ccc89b5SBALATON Zoltan 2927ccc89b5SBALATON Zoltan default: 29321a5a442SBALATON Zoltan qemu_log_mask(LOG_UNIMP, 29421a5a442SBALATON Zoltan "%s: unhandled PCI internal register 0x%"HWADDR_PRIx"\n", 29521a5a442SBALATON Zoltan __func__, addr); 2967ccc89b5SBALATON Zoltan break; 2977ccc89b5SBALATON Zoltan } 2987ccc89b5SBALATON Zoltan } 2997ccc89b5SBALATON Zoltan 3007ccc89b5SBALATON Zoltan static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, 3017ccc89b5SBALATON Zoltan unsigned size) 3027ccc89b5SBALATON Zoltan { 3037ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 3047ccc89b5SBALATON Zoltan uint32_t val; 3057ccc89b5SBALATON Zoltan 3067ccc89b5SBALATON Zoltan switch (addr) { 3077ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 3087ccc89b5SBALATON Zoltan val = ldl_le_p(s->dev->config + addr); 3097ccc89b5SBALATON Zoltan break; 3107ccc89b5SBALATON Zoltan 3117ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 3127ccc89b5SBALATON Zoltan val = s->pom[0].la; 3137ccc89b5SBALATON Zoltan break; 3147ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 3157ccc89b5SBALATON Zoltan val = s->pom[0].la >> 32; 3167ccc89b5SBALATON Zoltan break; 3177ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 3187ccc89b5SBALATON Zoltan val = s->pom[0].sa; 3197ccc89b5SBALATON Zoltan break; 3207ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 3217ccc89b5SBALATON Zoltan val = s->pom[0].pcia; 3227ccc89b5SBALATON Zoltan break; 3237ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 3247ccc89b5SBALATON Zoltan val = s->pom[0].pcia >> 32; 3257ccc89b5SBALATON Zoltan break; 3267ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 3277ccc89b5SBALATON Zoltan val = s->pom[1].la; 3287ccc89b5SBALATON Zoltan break; 3297ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 3307ccc89b5SBALATON Zoltan val = s->pom[1].la >> 32; 3317ccc89b5SBALATON Zoltan break; 3327ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 3337ccc89b5SBALATON Zoltan val = s->pom[1].sa; 3347ccc89b5SBALATON Zoltan break; 3357ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 3367ccc89b5SBALATON Zoltan val = s->pom[1].pcia; 3377ccc89b5SBALATON Zoltan break; 3387ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 3397ccc89b5SBALATON Zoltan val = s->pom[1].pcia >> 32; 3407ccc89b5SBALATON Zoltan break; 3417ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 3427ccc89b5SBALATON Zoltan val = s->pom[2].sa; 3437ccc89b5SBALATON Zoltan break; 3447ccc89b5SBALATON Zoltan 3457ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 3467ccc89b5SBALATON Zoltan val = s->pim[0].sa; 3477ccc89b5SBALATON Zoltan break; 3487ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 3497ccc89b5SBALATON Zoltan val = s->pim[0].la; 3507ccc89b5SBALATON Zoltan break; 3517ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 3527ccc89b5SBALATON Zoltan val = s->pim[0].la >> 32; 3537ccc89b5SBALATON Zoltan break; 3547ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 3557ccc89b5SBALATON Zoltan val = s->pim[1].sa; 3567ccc89b5SBALATON Zoltan break; 3577ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 3587ccc89b5SBALATON Zoltan val = s->pim[1].la; 3597ccc89b5SBALATON Zoltan break; 3607ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 3617ccc89b5SBALATON Zoltan val = s->pim[1].la >> 32; 3627ccc89b5SBALATON Zoltan break; 3637ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 3647ccc89b5SBALATON Zoltan val = s->pim[2].sa; 3657ccc89b5SBALATON Zoltan break; 3667ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 3677ccc89b5SBALATON Zoltan val = s->pim[2].la; 3687ccc89b5SBALATON Zoltan break; 3697ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 3707ccc89b5SBALATON Zoltan val = s->pim[2].la >> 32; 3717ccc89b5SBALATON Zoltan break; 3727ccc89b5SBALATON Zoltan 3737ccc89b5SBALATON Zoltan case PCIX0_STS: 3747ccc89b5SBALATON Zoltan val = s->sts; 3757ccc89b5SBALATON Zoltan break; 3767ccc89b5SBALATON Zoltan 3777ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 3787ccc89b5SBALATON Zoltan val = s->pim[0].sa >> 32; 3797ccc89b5SBALATON Zoltan break; 3807ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 3817ccc89b5SBALATON Zoltan val = s->pim[2].sa >> 32; 3827ccc89b5SBALATON Zoltan break; 3837ccc89b5SBALATON Zoltan 3847ccc89b5SBALATON Zoltan default: 38521a5a442SBALATON Zoltan qemu_log_mask(LOG_UNIMP, 38621a5a442SBALATON Zoltan "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n", 38721a5a442SBALATON Zoltan __func__, addr); 3887ccc89b5SBALATON Zoltan val = 0; 3897ccc89b5SBALATON Zoltan } 3907ccc89b5SBALATON Zoltan 3917ccc89b5SBALATON Zoltan trace_ppc440_pcix_reg_read(addr, val); 3927ccc89b5SBALATON Zoltan return val; 3937ccc89b5SBALATON Zoltan } 3947ccc89b5SBALATON Zoltan 3957ccc89b5SBALATON Zoltan static const MemoryRegionOps pci_reg_ops = { 3967ccc89b5SBALATON Zoltan .read = ppc440_pcix_reg_read4, 3977ccc89b5SBALATON Zoltan .write = ppc440_pcix_reg_write4, 3987ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 3997ccc89b5SBALATON Zoltan }; 4007ccc89b5SBALATON Zoltan 4017ccc89b5SBALATON Zoltan static void ppc440_pcix_reset(DeviceState *dev) 4027ccc89b5SBALATON Zoltan { 4037ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev); 4047ccc89b5SBALATON Zoltan int i; 4057ccc89b5SBALATON Zoltan 4067ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { 4077ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr); 4087ccc89b5SBALATON Zoltan } 4097ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 4107ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr); 4117ccc89b5SBALATON Zoltan } 4127ccc89b5SBALATON Zoltan memset(s->pom, 0, sizeof(s->pom)); 4137ccc89b5SBALATON Zoltan memset(s->pim, 0, sizeof(s->pim)); 4147ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 4157ccc89b5SBALATON Zoltan s->pim[i].sa = 0xffffffff00000000ULL; 4167ccc89b5SBALATON Zoltan } 4177ccc89b5SBALATON Zoltan s->sts = 0; 4187ccc89b5SBALATON Zoltan } 4197ccc89b5SBALATON Zoltan 4207ccc89b5SBALATON Zoltan /* All pins from each slot are tied to a single board IRQ. 4217ccc89b5SBALATON Zoltan * This may need further refactoring for other boards. */ 4227ccc89b5SBALATON Zoltan static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) 4237ccc89b5SBALATON Zoltan { 4246484ab3dSBALATON Zoltan trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0); 4256484ab3dSBALATON Zoltan return 0; 4267ccc89b5SBALATON Zoltan } 4277ccc89b5SBALATON Zoltan 4287ccc89b5SBALATON Zoltan static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) 4297ccc89b5SBALATON Zoltan { 4306484ab3dSBALATON Zoltan qemu_irq *pci_irq = opaque; 4317ccc89b5SBALATON Zoltan 4327ccc89b5SBALATON Zoltan trace_ppc440_pcix_set_irq(irq_num); 4337ccc89b5SBALATON Zoltan if (irq_num < 0) { 4347ccc89b5SBALATON Zoltan error_report("%s: PCI irq %d", __func__, irq_num); 4357ccc89b5SBALATON Zoltan return; 4367ccc89b5SBALATON Zoltan } 4376484ab3dSBALATON Zoltan qemu_set_irq(*pci_irq, level); 4387ccc89b5SBALATON Zoltan } 4397ccc89b5SBALATON Zoltan 4407ccc89b5SBALATON Zoltan static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) 4417ccc89b5SBALATON Zoltan { 4427ccc89b5SBALATON Zoltan PPC440PCIXState *s = opaque; 4437ccc89b5SBALATON Zoltan 4447ccc89b5SBALATON Zoltan return &s->bm_as; 4457ccc89b5SBALATON Zoltan } 4467ccc89b5SBALATON Zoltan 4477ccc89b5SBALATON Zoltan /* The default pci_host_data_{read,write} functions in pci/pci_host.c 4487ccc89b5SBALATON Zoltan * deny access to registers without bit 31 set but our clients want 4497ccc89b5SBALATON Zoltan * this to work so we have to override these here */ 4507ccc89b5SBALATON Zoltan static void pci_host_data_write(void *opaque, hwaddr addr, 4517ccc89b5SBALATON Zoltan uint64_t val, unsigned len) 4527ccc89b5SBALATON Zoltan { 4537ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 4547ccc89b5SBALATON Zoltan pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); 4557ccc89b5SBALATON Zoltan } 4567ccc89b5SBALATON Zoltan 4577ccc89b5SBALATON Zoltan static uint64_t pci_host_data_read(void *opaque, 4587ccc89b5SBALATON Zoltan hwaddr addr, unsigned len) 4597ccc89b5SBALATON Zoltan { 4607ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 4617ccc89b5SBALATON Zoltan uint32_t val; 4627ccc89b5SBALATON Zoltan val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); 4637ccc89b5SBALATON Zoltan return val; 4647ccc89b5SBALATON Zoltan } 4657ccc89b5SBALATON Zoltan 4667ccc89b5SBALATON Zoltan const MemoryRegionOps ppc440_pcix_host_data_ops = { 4677ccc89b5SBALATON Zoltan .read = pci_host_data_read, 4687ccc89b5SBALATON Zoltan .write = pci_host_data_write, 4697ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 4707ccc89b5SBALATON Zoltan }; 4717ccc89b5SBALATON Zoltan 4727b0f4ec9SCédric Le Goater static void ppc440_pcix_realize(DeviceState *dev, Error **errp) 4737ccc89b5SBALATON Zoltan { 4747b0f4ec9SCédric Le Goater SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 4757ccc89b5SBALATON Zoltan PPC440PCIXState *s; 4767ccc89b5SBALATON Zoltan PCIHostState *h; 4777ccc89b5SBALATON Zoltan 4787ccc89b5SBALATON Zoltan h = PCI_HOST_BRIDGE(dev); 4797ccc89b5SBALATON Zoltan s = PPC440_PCIX_HOST_BRIDGE(dev); 4807ccc89b5SBALATON Zoltan 4817b0f4ec9SCédric Le Goater sysbus_init_irq(sbd, &s->irq); 4827ccc89b5SBALATON Zoltan memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); 4837b0f4ec9SCédric Le Goater h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, 4846484ab3dSBALATON Zoltan ppc440_pcix_map_irq, &s->irq, &s->busmem, 4856484ab3dSBALATON Zoltan get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); 4867ccc89b5SBALATON Zoltan 4877ccc89b5SBALATON Zoltan s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); 4887ccc89b5SBALATON Zoltan 4897ccc89b5SBALATON Zoltan memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); 4907ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->bm, 0x0, &s->busmem); 4917ccc89b5SBALATON Zoltan address_space_init(&s->bm_as, &s->bm, "pci-bm"); 4927ccc89b5SBALATON Zoltan pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s); 4937ccc89b5SBALATON Zoltan 4947ccc89b5SBALATON Zoltan memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); 4957ccc89b5SBALATON Zoltan memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, 4967ccc89b5SBALATON Zoltan h, "pci-conf-idx", 4); 4977ccc89b5SBALATON Zoltan memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops, 4987ccc89b5SBALATON Zoltan h, "pci-conf-data", 4); 4997ccc89b5SBALATON Zoltan memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, 5007ccc89b5SBALATON Zoltan "pci.reg", PPC440_REG_SIZE); 5017ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); 5027ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); 5037ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); 5047b0f4ec9SCédric Le Goater sysbus_init_mmio(sbd, &s->container); 5057ccc89b5SBALATON Zoltan } 5067ccc89b5SBALATON Zoltan 5077ccc89b5SBALATON Zoltan static void ppc440_pcix_class_init(ObjectClass *klass, void *data) 5087ccc89b5SBALATON Zoltan { 5097ccc89b5SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 5107ccc89b5SBALATON Zoltan 5117b0f4ec9SCédric Le Goater dc->realize = ppc440_pcix_realize; 5127ccc89b5SBALATON Zoltan dc->reset = ppc440_pcix_reset; 5137ccc89b5SBALATON Zoltan } 5147ccc89b5SBALATON Zoltan 5157ccc89b5SBALATON Zoltan static const TypeInfo ppc440_pcix_info = { 5167ccc89b5SBALATON Zoltan .name = TYPE_PPC440_PCIX_HOST_BRIDGE, 5177ccc89b5SBALATON Zoltan .parent = TYPE_PCI_HOST_BRIDGE, 5187ccc89b5SBALATON Zoltan .instance_size = sizeof(PPC440PCIXState), 5197ccc89b5SBALATON Zoltan .class_init = ppc440_pcix_class_init, 5207ccc89b5SBALATON Zoltan }; 5217ccc89b5SBALATON Zoltan 5227ccc89b5SBALATON Zoltan static void ppc440_pcix_register_types(void) 5237ccc89b5SBALATON Zoltan { 5247ccc89b5SBALATON Zoltan type_register_static(&ppc440_pcix_info); 5257ccc89b5SBALATON Zoltan } 5267ccc89b5SBALATON Zoltan 5277ccc89b5SBALATON Zoltan type_init(ppc440_pcix_register_types) 528