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