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