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" 26dd0f356dSBALATON Zoltan #include "qemu/units.h" 2764552b6bSMarkus Armbruster #include "hw/irq.h" 284d641f36SPhilippe Mathieu-Daudé #include "hw/pci-host/ppc4xx.h" 29edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h" 307ccc89b5SBALATON Zoltan #include "hw/pci/pci_host.h" 317ccc89b5SBALATON Zoltan #include "trace.h" 32db1015e9SEduardo Habkost #include "qom/object.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 475efa7545SBALATON Zoltan OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST) 487ccc89b5SBALATON Zoltan 497ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_POMS 3 507ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_PIMS 3 517ccc89b5SBALATON Zoltan 52db1015e9SEduardo Habkost struct PPC440PCIXState { 537ccc89b5SBALATON Zoltan PCIHostState parent_obj; 547ccc89b5SBALATON Zoltan 556e4acebaSBALATON Zoltan uint8_t config[PCI_CONFIG_SPACE_SIZE]; 567ccc89b5SBALATON Zoltan struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; 577ccc89b5SBALATON Zoltan struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; 587ccc89b5SBALATON Zoltan uint32_t sts; 596484ab3dSBALATON Zoltan qemu_irq irq; 607ccc89b5SBALATON Zoltan AddressSpace bm_as; 617ccc89b5SBALATON Zoltan MemoryRegion bm; 627ccc89b5SBALATON Zoltan 637ccc89b5SBALATON Zoltan MemoryRegion container; 647ccc89b5SBALATON Zoltan MemoryRegion iomem; 657ccc89b5SBALATON Zoltan MemoryRegion busmem; 6697784278SBALATON Zoltan MemoryRegion regs; 67db1015e9SEduardo Habkost }; 687ccc89b5SBALATON Zoltan 697ccc89b5SBALATON Zoltan #define PPC440_REG_BASE 0x80000 707ccc89b5SBALATON Zoltan #define PPC440_REG_SIZE 0xff 717ccc89b5SBALATON Zoltan 727ccc89b5SBALATON Zoltan #define PCIC0_CFGADDR 0x0 737ccc89b5SBALATON Zoltan #define PCIC0_CFGDATA 0x4 747ccc89b5SBALATON Zoltan 757ccc89b5SBALATON Zoltan #define PCIX0_POM0LAL 0x68 767ccc89b5SBALATON Zoltan #define PCIX0_POM0LAH 0x6c 777ccc89b5SBALATON Zoltan #define PCIX0_POM0SA 0x70 787ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAL 0x74 797ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAH 0x78 807ccc89b5SBALATON Zoltan #define PCIX0_POM1LAL 0x7c 817ccc89b5SBALATON Zoltan #define PCIX0_POM1LAH 0x80 827ccc89b5SBALATON Zoltan #define PCIX0_POM1SA 0x84 837ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAL 0x88 847ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAH 0x8c 857ccc89b5SBALATON Zoltan #define PCIX0_POM2SA 0x90 867ccc89b5SBALATON Zoltan 877ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAL 0x98 887ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAL 0x9c 897ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAH 0xa0 907ccc89b5SBALATON Zoltan #define PCIX0_PIM1SA 0xa4 917ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAL 0xa8 927ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAH 0xac 937ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAL 0xb0 947ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAL 0xb4 957ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAH 0xb8 967ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAH 0xf8 977ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAH 0xfc 987ccc89b5SBALATON Zoltan 997ccc89b5SBALATON Zoltan #define PCIX0_STS 0xe0 1007ccc89b5SBALATON Zoltan 1017ccc89b5SBALATON Zoltan #define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) 1027ccc89b5SBALATON Zoltan 1037ccc89b5SBALATON Zoltan static void ppc440_pcix_clear_region(MemoryRegion *parent, 1047ccc89b5SBALATON Zoltan MemoryRegion *mem) 1057ccc89b5SBALATON Zoltan { 1067ccc89b5SBALATON Zoltan if (memory_region_is_mapped(mem)) { 1077ccc89b5SBALATON Zoltan memory_region_del_subregion(parent, mem); 1087ccc89b5SBALATON Zoltan object_unparent(OBJECT(mem)); 1097ccc89b5SBALATON Zoltan } 1107ccc89b5SBALATON Zoltan } 1117ccc89b5SBALATON Zoltan 1127ccc89b5SBALATON Zoltan /* DMA mapping */ 1137ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) 1147ccc89b5SBALATON Zoltan { 1157ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pim[idx].mr; 1167ccc89b5SBALATON Zoltan char *name; 1177ccc89b5SBALATON Zoltan uint64_t size; 1187ccc89b5SBALATON Zoltan 1197ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 1207ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, mem); 1217ccc89b5SBALATON Zoltan 1227ccc89b5SBALATON Zoltan if (!(s->pim[idx].sa & 1)) { 1237ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 1247ccc89b5SBALATON Zoltan return; 1257ccc89b5SBALATON Zoltan } 1267ccc89b5SBALATON Zoltan 1277ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Inbound Window %d", idx); 1287ccc89b5SBALATON Zoltan size = ~(s->pim[idx].sa & ~7ULL) + 1; 1297ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), 1307ccc89b5SBALATON Zoltan s->pim[idx].la, size); 1317ccc89b5SBALATON Zoltan memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); 1327ccc89b5SBALATON Zoltan g_free(name); 1337ccc89b5SBALATON Zoltan 1347ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la); 1357ccc89b5SBALATON Zoltan } 1367ccc89b5SBALATON Zoltan 1377ccc89b5SBALATON Zoltan /* BAR mapping */ 1387ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) 1397ccc89b5SBALATON Zoltan { 1407ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pom[idx].mr; 1417ccc89b5SBALATON Zoltan MemoryRegion *address_space_mem = get_system_memory(); 1427ccc89b5SBALATON Zoltan char *name; 1437ccc89b5SBALATON Zoltan uint32_t size; 1447ccc89b5SBALATON Zoltan 1457ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 1467ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(address_space_mem, mem); 1477ccc89b5SBALATON Zoltan 1487ccc89b5SBALATON Zoltan if (!(s->pom[idx].sa & 1)) { 1497ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 1507ccc89b5SBALATON Zoltan return; 1517ccc89b5SBALATON Zoltan } 1527ccc89b5SBALATON Zoltan 1537ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Outbound Window %d", idx); 1547ccc89b5SBALATON Zoltan size = ~(s->pom[idx].sa & 0xfffffffe) + 1; 1557ccc89b5SBALATON Zoltan if (!size) { 1567ccc89b5SBALATON Zoltan size = 0xffffffff; 1577ccc89b5SBALATON Zoltan } 1587ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, 1597ccc89b5SBALATON Zoltan s->pom[idx].pcia, size); 1607ccc89b5SBALATON Zoltan memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); 1617ccc89b5SBALATON Zoltan g_free(name); 1627ccc89b5SBALATON Zoltan 1637ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia); 1647ccc89b5SBALATON Zoltan } 1657ccc89b5SBALATON Zoltan 1667ccc89b5SBALATON Zoltan static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, 1677ccc89b5SBALATON Zoltan uint64_t val, unsigned size) 1687ccc89b5SBALATON Zoltan { 1697ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 1707ccc89b5SBALATON Zoltan 1712d4c816aSBALATON Zoltan via trace_ppc440_pcix_reg_write(addr, val, size); 1727ccc89b5SBALATON Zoltan switch (addr) { 1737ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 1746e4acebaSBALATON Zoltan stl_le_p(s->config + addr, val); 1757ccc89b5SBALATON Zoltan break; 1767ccc89b5SBALATON Zoltan 1777ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 1787ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffff00000000ULL; 1797ccc89b5SBALATON Zoltan s->pom[0].la |= val; 1807ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1817ccc89b5SBALATON Zoltan break; 1827ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 1837ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffffULL; 1847ccc89b5SBALATON Zoltan s->pom[0].la |= val << 32; 1857ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1867ccc89b5SBALATON Zoltan break; 1877ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 1887ccc89b5SBALATON Zoltan s->pom[0].sa = val; 1897ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1907ccc89b5SBALATON Zoltan break; 1917ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 1927ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffff00000000ULL; 1937ccc89b5SBALATON Zoltan s->pom[0].pcia |= val; 1947ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 1957ccc89b5SBALATON Zoltan break; 1967ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 1977ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffffULL; 1987ccc89b5SBALATON Zoltan s->pom[0].pcia |= val << 32; 1997ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 2007ccc89b5SBALATON Zoltan break; 2017ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 2027ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffff00000000ULL; 2037ccc89b5SBALATON Zoltan s->pom[1].la |= val; 2047ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2057ccc89b5SBALATON Zoltan break; 2067ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 2077ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffffULL; 2087ccc89b5SBALATON Zoltan s->pom[1].la |= val << 32; 2097ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2107ccc89b5SBALATON Zoltan break; 2117ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 2127ccc89b5SBALATON Zoltan s->pom[1].sa = val; 2137ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2147ccc89b5SBALATON Zoltan break; 2157ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 2167ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffff00000000ULL; 2177ccc89b5SBALATON Zoltan s->pom[1].pcia |= val; 2187ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2197ccc89b5SBALATON Zoltan break; 2207ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 2217ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffffULL; 2227ccc89b5SBALATON Zoltan s->pom[1].pcia |= val << 32; 2237ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 2247ccc89b5SBALATON Zoltan break; 2257ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 2267ccc89b5SBALATON Zoltan s->pom[2].sa = val; 2277ccc89b5SBALATON Zoltan break; 2287ccc89b5SBALATON Zoltan 2297ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 2307ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffff00000000ULL; 2317ccc89b5SBALATON Zoltan s->pim[0].sa |= val; 2327ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2337ccc89b5SBALATON Zoltan break; 2347ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 2357ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffff00000000ULL; 2367ccc89b5SBALATON Zoltan s->pim[0].la |= val; 2377ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2387ccc89b5SBALATON Zoltan break; 2397ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 2407ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffffULL; 2417ccc89b5SBALATON Zoltan s->pim[0].la |= val << 32; 2427ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2437ccc89b5SBALATON Zoltan break; 2447ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 2457ccc89b5SBALATON Zoltan s->pim[1].sa = val; 2467ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2477ccc89b5SBALATON Zoltan break; 2487ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 2497ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffff00000000ULL; 2507ccc89b5SBALATON Zoltan s->pim[1].la |= val; 2517ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2527ccc89b5SBALATON Zoltan break; 2537ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 2547ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffffULL; 2557ccc89b5SBALATON Zoltan s->pim[1].la |= val << 32; 2567ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 2577ccc89b5SBALATON Zoltan break; 2587ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 2597ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffff00000000ULL; 26068143189SBALATON Zoltan s->pim[2].sa |= val; 2617ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2627ccc89b5SBALATON Zoltan break; 2637ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 2647ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffff00000000ULL; 2657ccc89b5SBALATON Zoltan s->pim[2].la |= val; 2667ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2677ccc89b5SBALATON Zoltan break; 2687ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 2697ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffffULL; 2707ccc89b5SBALATON Zoltan s->pim[2].la |= val << 32; 2717ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2727ccc89b5SBALATON Zoltan break; 2737ccc89b5SBALATON Zoltan 2747ccc89b5SBALATON Zoltan case PCIX0_STS: 2757ccc89b5SBALATON Zoltan s->sts = val; 2767ccc89b5SBALATON Zoltan break; 2777ccc89b5SBALATON Zoltan 2787ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 2797ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffffULL; 2807ccc89b5SBALATON Zoltan s->pim[0].sa |= val << 32; 2817ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 2827ccc89b5SBALATON Zoltan break; 2837ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 2847ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffffULL; 2857ccc89b5SBALATON Zoltan s->pim[2].sa |= val << 32; 2867ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 2877ccc89b5SBALATON Zoltan break; 2887ccc89b5SBALATON Zoltan 2897ccc89b5SBALATON Zoltan default: 29021a5a442SBALATON Zoltan qemu_log_mask(LOG_UNIMP, 29121a5a442SBALATON Zoltan "%s: unhandled PCI internal register 0x%"HWADDR_PRIx"\n", 29221a5a442SBALATON Zoltan __func__, addr); 2937ccc89b5SBALATON Zoltan break; 2947ccc89b5SBALATON Zoltan } 2957ccc89b5SBALATON Zoltan } 2967ccc89b5SBALATON Zoltan 2977ccc89b5SBALATON Zoltan static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, 2987ccc89b5SBALATON Zoltan unsigned size) 2997ccc89b5SBALATON Zoltan { 3007ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 3017ccc89b5SBALATON Zoltan uint32_t val; 3027ccc89b5SBALATON Zoltan 3037ccc89b5SBALATON Zoltan switch (addr) { 3047ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 3056e4acebaSBALATON Zoltan val = ldl_le_p(s->config + addr); 3067ccc89b5SBALATON Zoltan break; 3077ccc89b5SBALATON Zoltan 3087ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 3097ccc89b5SBALATON Zoltan val = s->pom[0].la; 3107ccc89b5SBALATON Zoltan break; 3117ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 3127ccc89b5SBALATON Zoltan val = s->pom[0].la >> 32; 3137ccc89b5SBALATON Zoltan break; 3147ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 3157ccc89b5SBALATON Zoltan val = s->pom[0].sa; 3167ccc89b5SBALATON Zoltan break; 3177ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 3187ccc89b5SBALATON Zoltan val = s->pom[0].pcia; 3197ccc89b5SBALATON Zoltan break; 3207ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 3217ccc89b5SBALATON Zoltan val = s->pom[0].pcia >> 32; 3227ccc89b5SBALATON Zoltan break; 3237ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 3247ccc89b5SBALATON Zoltan val = s->pom[1].la; 3257ccc89b5SBALATON Zoltan break; 3267ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 3277ccc89b5SBALATON Zoltan val = s->pom[1].la >> 32; 3287ccc89b5SBALATON Zoltan break; 3297ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 3307ccc89b5SBALATON Zoltan val = s->pom[1].sa; 3317ccc89b5SBALATON Zoltan break; 3327ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 3337ccc89b5SBALATON Zoltan val = s->pom[1].pcia; 3347ccc89b5SBALATON Zoltan break; 3357ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 3367ccc89b5SBALATON Zoltan val = s->pom[1].pcia >> 32; 3377ccc89b5SBALATON Zoltan break; 3387ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 3397ccc89b5SBALATON Zoltan val = s->pom[2].sa; 3407ccc89b5SBALATON Zoltan break; 3417ccc89b5SBALATON Zoltan 3427ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 3437ccc89b5SBALATON Zoltan val = s->pim[0].sa; 3447ccc89b5SBALATON Zoltan break; 3457ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 3467ccc89b5SBALATON Zoltan val = s->pim[0].la; 3477ccc89b5SBALATON Zoltan break; 3487ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 3497ccc89b5SBALATON Zoltan val = s->pim[0].la >> 32; 3507ccc89b5SBALATON Zoltan break; 3517ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 3527ccc89b5SBALATON Zoltan val = s->pim[1].sa; 3537ccc89b5SBALATON Zoltan break; 3547ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 3557ccc89b5SBALATON Zoltan val = s->pim[1].la; 3567ccc89b5SBALATON Zoltan break; 3577ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 3587ccc89b5SBALATON Zoltan val = s->pim[1].la >> 32; 3597ccc89b5SBALATON Zoltan break; 3607ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 3617ccc89b5SBALATON Zoltan val = s->pim[2].sa; 3627ccc89b5SBALATON Zoltan break; 3637ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 3647ccc89b5SBALATON Zoltan val = s->pim[2].la; 3657ccc89b5SBALATON Zoltan break; 3667ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 3677ccc89b5SBALATON Zoltan val = s->pim[2].la >> 32; 3687ccc89b5SBALATON Zoltan break; 3697ccc89b5SBALATON Zoltan 3707ccc89b5SBALATON Zoltan case PCIX0_STS: 3717ccc89b5SBALATON Zoltan val = s->sts; 3727ccc89b5SBALATON Zoltan break; 3737ccc89b5SBALATON Zoltan 3747ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 3757ccc89b5SBALATON Zoltan val = s->pim[0].sa >> 32; 3767ccc89b5SBALATON Zoltan break; 3777ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 3787ccc89b5SBALATON Zoltan val = s->pim[2].sa >> 32; 3797ccc89b5SBALATON Zoltan break; 3807ccc89b5SBALATON Zoltan 3817ccc89b5SBALATON Zoltan default: 38221a5a442SBALATON Zoltan qemu_log_mask(LOG_UNIMP, 38321a5a442SBALATON Zoltan "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n", 38421a5a442SBALATON Zoltan __func__, addr); 3857ccc89b5SBALATON Zoltan val = 0; 3867ccc89b5SBALATON Zoltan } 3877ccc89b5SBALATON Zoltan 3887ccc89b5SBALATON Zoltan trace_ppc440_pcix_reg_read(addr, val); 3897ccc89b5SBALATON Zoltan return val; 3907ccc89b5SBALATON Zoltan } 3917ccc89b5SBALATON Zoltan 3927ccc89b5SBALATON Zoltan static const MemoryRegionOps pci_reg_ops = { 3937ccc89b5SBALATON Zoltan .read = ppc440_pcix_reg_read4, 3947ccc89b5SBALATON Zoltan .write = ppc440_pcix_reg_write4, 3957ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 3967ccc89b5SBALATON Zoltan }; 3977ccc89b5SBALATON Zoltan 3987ccc89b5SBALATON Zoltan static void ppc440_pcix_reset(DeviceState *dev) 3997ccc89b5SBALATON Zoltan { 4005efa7545SBALATON Zoltan struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev); 4017ccc89b5SBALATON Zoltan int i; 4027ccc89b5SBALATON Zoltan 4037ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { 4047ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr); 4057ccc89b5SBALATON Zoltan } 4067ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 4077ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr); 4087ccc89b5SBALATON Zoltan } 4097ccc89b5SBALATON Zoltan memset(s->pom, 0, sizeof(s->pom)); 4107ccc89b5SBALATON Zoltan memset(s->pim, 0, sizeof(s->pim)); 4117ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 4127ccc89b5SBALATON Zoltan s->pim[i].sa = 0xffffffff00000000ULL; 4137ccc89b5SBALATON Zoltan } 4147ccc89b5SBALATON Zoltan s->sts = 0; 4157ccc89b5SBALATON Zoltan } 4167ccc89b5SBALATON Zoltan 4172a9cf495SBALATON Zoltan via /* 4182a9cf495SBALATON Zoltan via * All four IRQ[ABCD] pins from all slots are tied to a single board 4192a9cf495SBALATON Zoltan via * IRQ, so our mapping function here maps everything to IRQ 0. 4202a9cf495SBALATON Zoltan via * The code in pci_change_irq_level() tracks the number of times 4212a9cf495SBALATON Zoltan via * the mapped IRQ is asserted and deasserted, so if multiple devices 4222a9cf495SBALATON Zoltan via * assert an IRQ at the same time the behaviour is correct. 4232a9cf495SBALATON Zoltan via * 4242a9cf495SBALATON Zoltan via * This may need further refactoring for boards that use multiple IRQ lines. 4252a9cf495SBALATON Zoltan via */ 4267ccc89b5SBALATON Zoltan static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) 4277ccc89b5SBALATON Zoltan { 4286484ab3dSBALATON Zoltan trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0); 4296484ab3dSBALATON Zoltan return 0; 4307ccc89b5SBALATON Zoltan } 4317ccc89b5SBALATON Zoltan 4327ccc89b5SBALATON Zoltan static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) 4337ccc89b5SBALATON Zoltan { 4346484ab3dSBALATON Zoltan qemu_irq *pci_irq = opaque; 4357ccc89b5SBALATON Zoltan 4367ccc89b5SBALATON Zoltan trace_ppc440_pcix_set_irq(irq_num); 4377ccc89b5SBALATON Zoltan if (irq_num < 0) { 4387ccc89b5SBALATON Zoltan error_report("%s: PCI irq %d", __func__, irq_num); 4397ccc89b5SBALATON Zoltan return; 4407ccc89b5SBALATON Zoltan } 4416484ab3dSBALATON Zoltan qemu_set_irq(*pci_irq, level); 4427ccc89b5SBALATON Zoltan } 4437ccc89b5SBALATON Zoltan 4447ccc89b5SBALATON Zoltan static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) 4457ccc89b5SBALATON Zoltan { 4467ccc89b5SBALATON Zoltan PPC440PCIXState *s = opaque; 4477ccc89b5SBALATON Zoltan 4487ccc89b5SBALATON Zoltan return &s->bm_as; 4497ccc89b5SBALATON Zoltan } 4507ccc89b5SBALATON Zoltan 451ba7d12ebSYi Liu static const PCIIOMMUOps ppc440_iommu_ops = { 452ba7d12ebSYi Liu .get_address_space = ppc440_pcix_set_iommu, 453ba7d12ebSYi Liu }; 454ba7d12ebSYi Liu 4555cbd51a5SBALATON Zoltan via /* 4565cbd51a5SBALATON Zoltan via * Some guests on sam460ex write all kinds of garbage here such as 4575cbd51a5SBALATON Zoltan via * missing enable bit and low bits set and still expect this to work 4585cbd51a5SBALATON Zoltan via * (apparently it does on real hardware because these boot there) so 4595cbd51a5SBALATON Zoltan via * we have to override these ops here and fix it up 4605cbd51a5SBALATON Zoltan via */ 4615cbd51a5SBALATON Zoltan via static void pci_host_config_write(void *opaque, hwaddr addr, 4627ccc89b5SBALATON Zoltan uint64_t val, unsigned len) 4637ccc89b5SBALATON Zoltan { 4647ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 4655cbd51a5SBALATON Zoltan via 4665cbd51a5SBALATON Zoltan via if (addr != 0 || len != 4) { 4675cbd51a5SBALATON Zoltan via return; 4685cbd51a5SBALATON Zoltan via } 4695cbd51a5SBALATON Zoltan via s->config_reg = (val & 0xfffffffcULL) | (1UL << 31); 4707ccc89b5SBALATON Zoltan } 4717ccc89b5SBALATON Zoltan 4725cbd51a5SBALATON Zoltan via static uint64_t pci_host_config_read(void *opaque, hwaddr addr, 4735cbd51a5SBALATON Zoltan via unsigned len) 4747ccc89b5SBALATON Zoltan { 4757ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 4765cbd51a5SBALATON Zoltan via uint32_t val = s->config_reg; 4775cbd51a5SBALATON Zoltan via 4787ccc89b5SBALATON Zoltan return val; 4797ccc89b5SBALATON Zoltan } 4807ccc89b5SBALATON Zoltan 4815cbd51a5SBALATON Zoltan via const MemoryRegionOps ppc440_pcix_host_conf_ops = { 4825cbd51a5SBALATON Zoltan via .read = pci_host_config_read, 4835cbd51a5SBALATON Zoltan via .write = pci_host_config_write, 4847ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 4857ccc89b5SBALATON Zoltan }; 4867ccc89b5SBALATON Zoltan 4877b0f4ec9SCédric Le Goater static void ppc440_pcix_realize(DeviceState *dev, Error **errp) 4887ccc89b5SBALATON Zoltan { 4897b0f4ec9SCédric Le Goater SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 4907ccc89b5SBALATON Zoltan PPC440PCIXState *s; 4917ccc89b5SBALATON Zoltan PCIHostState *h; 4927ccc89b5SBALATON Zoltan 4937ccc89b5SBALATON Zoltan h = PCI_HOST_BRIDGE(dev); 4945efa7545SBALATON Zoltan s = PPC440_PCIX_HOST(dev); 4957ccc89b5SBALATON Zoltan 4967b0f4ec9SCédric Le Goater sysbus_init_irq(sbd, &s->irq); 497dd0f356dSBALATON Zoltan memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX); 498dd0f356dSBALATON Zoltan memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB); 4997b0f4ec9SCédric Le Goater h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, 500dd0f356dSBALATON Zoltan ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem, 5016e4acebaSBALATON Zoltan PCI_DEVFN(1, 0), 1, TYPE_PCI_BUS); 5027ccc89b5SBALATON Zoltan 5037ccc89b5SBALATON Zoltan memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); 5047ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->bm, 0x0, &s->busmem); 5057ccc89b5SBALATON Zoltan address_space_init(&s->bm_as, &s->bm, "pci-bm"); 506ba7d12ebSYi Liu pci_setup_iommu(h->bus, &ppc440_iommu_ops, s); 5077ccc89b5SBALATON Zoltan 5087ccc89b5SBALATON Zoltan memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); 5095cbd51a5SBALATON Zoltan via memory_region_init_io(&h->conf_mem, OBJECT(s), &ppc440_pcix_host_conf_ops, 5107ccc89b5SBALATON Zoltan h, "pci-conf-idx", 4); 5115cbd51a5SBALATON Zoltan via memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, 5127ccc89b5SBALATON Zoltan h, "pci-conf-data", 4); 51397784278SBALATON Zoltan memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg", 51497784278SBALATON Zoltan PPC440_REG_SIZE); 5157ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); 5167ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); 51797784278SBALATON Zoltan memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs); 5187b0f4ec9SCédric Le Goater sysbus_init_mmio(sbd, &s->container); 519dd0f356dSBALATON Zoltan sysbus_init_mmio(sbd, &s->iomem); 5207ccc89b5SBALATON Zoltan } 5217ccc89b5SBALATON Zoltan 5227ccc89b5SBALATON Zoltan static void ppc440_pcix_class_init(ObjectClass *klass, void *data) 5237ccc89b5SBALATON Zoltan { 5247ccc89b5SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 5257ccc89b5SBALATON Zoltan 5267b0f4ec9SCédric Le Goater dc->realize = ppc440_pcix_realize; 527*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, ppc440_pcix_reset); 5287ccc89b5SBALATON Zoltan } 5297ccc89b5SBALATON Zoltan 5307ccc89b5SBALATON Zoltan static const TypeInfo ppc440_pcix_info = { 5315efa7545SBALATON Zoltan .name = TYPE_PPC440_PCIX_HOST, 5327ccc89b5SBALATON Zoltan .parent = TYPE_PCI_HOST_BRIDGE, 5337ccc89b5SBALATON Zoltan .instance_size = sizeof(PPC440PCIXState), 5347ccc89b5SBALATON Zoltan .class_init = ppc440_pcix_class_init, 5357ccc89b5SBALATON Zoltan }; 5367ccc89b5SBALATON Zoltan 5377ccc89b5SBALATON Zoltan static void ppc440_pcix_register_types(void) 5387ccc89b5SBALATON Zoltan { 5397ccc89b5SBALATON Zoltan type_register_static(&ppc440_pcix_info); 5407ccc89b5SBALATON Zoltan } 5417ccc89b5SBALATON Zoltan 5427ccc89b5SBALATON Zoltan type_init(ppc440_pcix_register_types) 543