1*7ccc89b5SBALATON Zoltan /* 2*7ccc89b5SBALATON Zoltan * Emulation of the ibm,plb-pcix PCI controller 3*7ccc89b5SBALATON Zoltan * This is found in some 440 SoCs e.g. the 460EX. 4*7ccc89b5SBALATON Zoltan * 5*7ccc89b5SBALATON Zoltan * Copyright (c) 2016-2018 BALATON Zoltan 6*7ccc89b5SBALATON Zoltan * 7*7ccc89b5SBALATON Zoltan * Derived from ppc4xx_pci.c and pci-host/ppce500.c 8*7ccc89b5SBALATON Zoltan * 9*7ccc89b5SBALATON Zoltan * This program is free software; you can redistribute it and/or modify 10*7ccc89b5SBALATON Zoltan * it under the terms of the GNU General Public License, version 2, as 11*7ccc89b5SBALATON Zoltan * published by the Free Software Foundation. 12*7ccc89b5SBALATON Zoltan * 13*7ccc89b5SBALATON Zoltan * This program is distributed in the hope that it will be useful, 14*7ccc89b5SBALATON Zoltan * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*7ccc89b5SBALATON Zoltan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*7ccc89b5SBALATON Zoltan * GNU General Public License for more details. 17*7ccc89b5SBALATON Zoltan * 18*7ccc89b5SBALATON Zoltan * You should have received a copy of the GNU General Public License 19*7ccc89b5SBALATON Zoltan * along with this program; if not, see <http://www.gnu.org/licenses/>. 20*7ccc89b5SBALATON Zoltan */ 21*7ccc89b5SBALATON Zoltan 22*7ccc89b5SBALATON Zoltan #include "qemu/osdep.h" 23*7ccc89b5SBALATON Zoltan #include "qemu/error-report.h" 24*7ccc89b5SBALATON Zoltan #include "hw/hw.h" 25*7ccc89b5SBALATON Zoltan #include "hw/ppc/ppc.h" 26*7ccc89b5SBALATON Zoltan #include "hw/ppc/ppc4xx.h" 27*7ccc89b5SBALATON Zoltan #include "hw/pci/pci.h" 28*7ccc89b5SBALATON Zoltan #include "hw/pci/pci_host.h" 29*7ccc89b5SBALATON Zoltan #include "exec/address-spaces.h" 30*7ccc89b5SBALATON Zoltan #include "trace.h" 31*7ccc89b5SBALATON Zoltan 32*7ccc89b5SBALATON Zoltan struct PLBOutMap { 33*7ccc89b5SBALATON Zoltan uint64_t la; 34*7ccc89b5SBALATON Zoltan uint64_t pcia; 35*7ccc89b5SBALATON Zoltan uint32_t sa; 36*7ccc89b5SBALATON Zoltan MemoryRegion mr; 37*7ccc89b5SBALATON Zoltan }; 38*7ccc89b5SBALATON Zoltan 39*7ccc89b5SBALATON Zoltan struct PLBInMap { 40*7ccc89b5SBALATON Zoltan uint64_t sa; 41*7ccc89b5SBALATON Zoltan uint64_t la; 42*7ccc89b5SBALATON Zoltan MemoryRegion mr; 43*7ccc89b5SBALATON Zoltan }; 44*7ccc89b5SBALATON Zoltan 45*7ccc89b5SBALATON Zoltan #define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" 46*7ccc89b5SBALATON Zoltan #define PPC440_PCIX_HOST_BRIDGE(obj) \ 47*7ccc89b5SBALATON Zoltan OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) 48*7ccc89b5SBALATON Zoltan 49*7ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_POMS 3 50*7ccc89b5SBALATON Zoltan #define PPC440_PCIX_NR_PIMS 3 51*7ccc89b5SBALATON Zoltan 52*7ccc89b5SBALATON Zoltan typedef struct PPC440PCIXState { 53*7ccc89b5SBALATON Zoltan PCIHostState parent_obj; 54*7ccc89b5SBALATON Zoltan 55*7ccc89b5SBALATON Zoltan PCIDevice *dev; 56*7ccc89b5SBALATON Zoltan struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; 57*7ccc89b5SBALATON Zoltan struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; 58*7ccc89b5SBALATON Zoltan uint32_t sts; 59*7ccc89b5SBALATON Zoltan qemu_irq irq[PCI_NUM_PINS]; 60*7ccc89b5SBALATON Zoltan AddressSpace bm_as; 61*7ccc89b5SBALATON Zoltan MemoryRegion bm; 62*7ccc89b5SBALATON Zoltan 63*7ccc89b5SBALATON Zoltan MemoryRegion container; 64*7ccc89b5SBALATON Zoltan MemoryRegion iomem; 65*7ccc89b5SBALATON Zoltan MemoryRegion busmem; 66*7ccc89b5SBALATON Zoltan } PPC440PCIXState; 67*7ccc89b5SBALATON Zoltan 68*7ccc89b5SBALATON Zoltan #define PPC440_REG_BASE 0x80000 69*7ccc89b5SBALATON Zoltan #define PPC440_REG_SIZE 0xff 70*7ccc89b5SBALATON Zoltan 71*7ccc89b5SBALATON Zoltan #define PCIC0_CFGADDR 0x0 72*7ccc89b5SBALATON Zoltan #define PCIC0_CFGDATA 0x4 73*7ccc89b5SBALATON Zoltan 74*7ccc89b5SBALATON Zoltan #define PCIX0_POM0LAL 0x68 75*7ccc89b5SBALATON Zoltan #define PCIX0_POM0LAH 0x6c 76*7ccc89b5SBALATON Zoltan #define PCIX0_POM0SA 0x70 77*7ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAL 0x74 78*7ccc89b5SBALATON Zoltan #define PCIX0_POM0PCIAH 0x78 79*7ccc89b5SBALATON Zoltan #define PCIX0_POM1LAL 0x7c 80*7ccc89b5SBALATON Zoltan #define PCIX0_POM1LAH 0x80 81*7ccc89b5SBALATON Zoltan #define PCIX0_POM1SA 0x84 82*7ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAL 0x88 83*7ccc89b5SBALATON Zoltan #define PCIX0_POM1PCIAH 0x8c 84*7ccc89b5SBALATON Zoltan #define PCIX0_POM2SA 0x90 85*7ccc89b5SBALATON Zoltan 86*7ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAL 0x98 87*7ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAL 0x9c 88*7ccc89b5SBALATON Zoltan #define PCIX0_PIM0LAH 0xa0 89*7ccc89b5SBALATON Zoltan #define PCIX0_PIM1SA 0xa4 90*7ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAL 0xa8 91*7ccc89b5SBALATON Zoltan #define PCIX0_PIM1LAH 0xac 92*7ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAL 0xb0 93*7ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAL 0xb4 94*7ccc89b5SBALATON Zoltan #define PCIX0_PIM2LAH 0xb8 95*7ccc89b5SBALATON Zoltan #define PCIX0_PIM0SAH 0xf8 96*7ccc89b5SBALATON Zoltan #define PCIX0_PIM2SAH 0xfc 97*7ccc89b5SBALATON Zoltan 98*7ccc89b5SBALATON Zoltan #define PCIX0_STS 0xe0 99*7ccc89b5SBALATON Zoltan 100*7ccc89b5SBALATON Zoltan #define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) 101*7ccc89b5SBALATON Zoltan 102*7ccc89b5SBALATON Zoltan static void ppc440_pcix_clear_region(MemoryRegion *parent, 103*7ccc89b5SBALATON Zoltan MemoryRegion *mem) 104*7ccc89b5SBALATON Zoltan { 105*7ccc89b5SBALATON Zoltan if (memory_region_is_mapped(mem)) { 106*7ccc89b5SBALATON Zoltan memory_region_del_subregion(parent, mem); 107*7ccc89b5SBALATON Zoltan object_unparent(OBJECT(mem)); 108*7ccc89b5SBALATON Zoltan } 109*7ccc89b5SBALATON Zoltan } 110*7ccc89b5SBALATON Zoltan 111*7ccc89b5SBALATON Zoltan /* DMA mapping */ 112*7ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) 113*7ccc89b5SBALATON Zoltan { 114*7ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pim[idx].mr; 115*7ccc89b5SBALATON Zoltan char *name; 116*7ccc89b5SBALATON Zoltan uint64_t size; 117*7ccc89b5SBALATON Zoltan 118*7ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 119*7ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, mem); 120*7ccc89b5SBALATON Zoltan 121*7ccc89b5SBALATON Zoltan if (!(s->pim[idx].sa & 1)) { 122*7ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 123*7ccc89b5SBALATON Zoltan return; 124*7ccc89b5SBALATON Zoltan } 125*7ccc89b5SBALATON Zoltan 126*7ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Inbound Window %d", idx); 127*7ccc89b5SBALATON Zoltan size = ~(s->pim[idx].sa & ~7ULL) + 1; 128*7ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), 129*7ccc89b5SBALATON Zoltan s->pim[idx].la, size); 130*7ccc89b5SBALATON Zoltan memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); 131*7ccc89b5SBALATON Zoltan g_free(name); 132*7ccc89b5SBALATON Zoltan 133*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pim(idx, size, s->pim[idx].la); 134*7ccc89b5SBALATON Zoltan } 135*7ccc89b5SBALATON Zoltan 136*7ccc89b5SBALATON Zoltan /* BAR mapping */ 137*7ccc89b5SBALATON Zoltan static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) 138*7ccc89b5SBALATON Zoltan { 139*7ccc89b5SBALATON Zoltan MemoryRegion *mem = &s->pom[idx].mr; 140*7ccc89b5SBALATON Zoltan MemoryRegion *address_space_mem = get_system_memory(); 141*7ccc89b5SBALATON Zoltan char *name; 142*7ccc89b5SBALATON Zoltan uint32_t size; 143*7ccc89b5SBALATON Zoltan 144*7ccc89b5SBALATON Zoltan /* Before we modify anything, unmap and destroy the region */ 145*7ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(address_space_mem, mem); 146*7ccc89b5SBALATON Zoltan 147*7ccc89b5SBALATON Zoltan if (!(s->pom[idx].sa & 1)) { 148*7ccc89b5SBALATON Zoltan /* Not enabled, nothing to do */ 149*7ccc89b5SBALATON Zoltan return; 150*7ccc89b5SBALATON Zoltan } 151*7ccc89b5SBALATON Zoltan 152*7ccc89b5SBALATON Zoltan name = g_strdup_printf("PCI Outbound Window %d", idx); 153*7ccc89b5SBALATON Zoltan size = ~(s->pom[idx].sa & 0xfffffffe) + 1; 154*7ccc89b5SBALATON Zoltan if (!size) { 155*7ccc89b5SBALATON Zoltan size = 0xffffffff; 156*7ccc89b5SBALATON Zoltan } 157*7ccc89b5SBALATON Zoltan memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, 158*7ccc89b5SBALATON Zoltan s->pom[idx].pcia, size); 159*7ccc89b5SBALATON Zoltan memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); 160*7ccc89b5SBALATON Zoltan g_free(name); 161*7ccc89b5SBALATON Zoltan 162*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_update_pom(idx, size, s->pom[idx].la, s->pom[idx].pcia); 163*7ccc89b5SBALATON Zoltan } 164*7ccc89b5SBALATON Zoltan 165*7ccc89b5SBALATON Zoltan static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, 166*7ccc89b5SBALATON Zoltan uint64_t val, unsigned size) 167*7ccc89b5SBALATON Zoltan { 168*7ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 169*7ccc89b5SBALATON Zoltan 170*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_reg_read(addr, val); 171*7ccc89b5SBALATON Zoltan switch (addr) { 172*7ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 173*7ccc89b5SBALATON Zoltan stl_le_p(s->dev->config + addr, val); 174*7ccc89b5SBALATON Zoltan break; 175*7ccc89b5SBALATON Zoltan 176*7ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 177*7ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffff00000000ULL; 178*7ccc89b5SBALATON Zoltan s->pom[0].la |= val; 179*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 180*7ccc89b5SBALATON Zoltan break; 181*7ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 182*7ccc89b5SBALATON Zoltan s->pom[0].la &= 0xffffffffULL; 183*7ccc89b5SBALATON Zoltan s->pom[0].la |= val << 32; 184*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 185*7ccc89b5SBALATON Zoltan break; 186*7ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 187*7ccc89b5SBALATON Zoltan s->pom[0].sa = val; 188*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 189*7ccc89b5SBALATON Zoltan break; 190*7ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 191*7ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffff00000000ULL; 192*7ccc89b5SBALATON Zoltan s->pom[0].pcia |= val; 193*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 194*7ccc89b5SBALATON Zoltan break; 195*7ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 196*7ccc89b5SBALATON Zoltan s->pom[0].pcia &= 0xffffffffULL; 197*7ccc89b5SBALATON Zoltan s->pom[0].pcia |= val << 32; 198*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 0); 199*7ccc89b5SBALATON Zoltan break; 200*7ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 201*7ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffff00000000ULL; 202*7ccc89b5SBALATON Zoltan s->pom[1].la |= val; 203*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 204*7ccc89b5SBALATON Zoltan break; 205*7ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 206*7ccc89b5SBALATON Zoltan s->pom[1].la &= 0xffffffffULL; 207*7ccc89b5SBALATON Zoltan s->pom[1].la |= val << 32; 208*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 209*7ccc89b5SBALATON Zoltan break; 210*7ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 211*7ccc89b5SBALATON Zoltan s->pom[1].sa = val; 212*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 213*7ccc89b5SBALATON Zoltan break; 214*7ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 215*7ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffff00000000ULL; 216*7ccc89b5SBALATON Zoltan s->pom[1].pcia |= val; 217*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 218*7ccc89b5SBALATON Zoltan break; 219*7ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 220*7ccc89b5SBALATON Zoltan s->pom[1].pcia &= 0xffffffffULL; 221*7ccc89b5SBALATON Zoltan s->pom[1].pcia |= val << 32; 222*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pom(s, 1); 223*7ccc89b5SBALATON Zoltan break; 224*7ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 225*7ccc89b5SBALATON Zoltan s->pom[2].sa = val; 226*7ccc89b5SBALATON Zoltan break; 227*7ccc89b5SBALATON Zoltan 228*7ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 229*7ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffff00000000ULL; 230*7ccc89b5SBALATON Zoltan s->pim[0].sa |= val; 231*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 232*7ccc89b5SBALATON Zoltan break; 233*7ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 234*7ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffff00000000ULL; 235*7ccc89b5SBALATON Zoltan s->pim[0].la |= val; 236*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 237*7ccc89b5SBALATON Zoltan break; 238*7ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 239*7ccc89b5SBALATON Zoltan s->pim[0].la &= 0xffffffffULL; 240*7ccc89b5SBALATON Zoltan s->pim[0].la |= val << 32; 241*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 242*7ccc89b5SBALATON Zoltan break; 243*7ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 244*7ccc89b5SBALATON Zoltan s->pim[1].sa = val; 245*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 246*7ccc89b5SBALATON Zoltan break; 247*7ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 248*7ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffff00000000ULL; 249*7ccc89b5SBALATON Zoltan s->pim[1].la |= val; 250*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 251*7ccc89b5SBALATON Zoltan break; 252*7ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 253*7ccc89b5SBALATON Zoltan s->pim[1].la &= 0xffffffffULL; 254*7ccc89b5SBALATON Zoltan s->pim[1].la |= val << 32; 255*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 1); 256*7ccc89b5SBALATON Zoltan break; 257*7ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 258*7ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffff00000000ULL; 259*7ccc89b5SBALATON Zoltan s->pim[2].sa = val; 260*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 261*7ccc89b5SBALATON Zoltan break; 262*7ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 263*7ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffff00000000ULL; 264*7ccc89b5SBALATON Zoltan s->pim[2].la |= val; 265*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 266*7ccc89b5SBALATON Zoltan break; 267*7ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 268*7ccc89b5SBALATON Zoltan s->pim[2].la &= 0xffffffffULL; 269*7ccc89b5SBALATON Zoltan s->pim[2].la |= val << 32; 270*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 271*7ccc89b5SBALATON Zoltan break; 272*7ccc89b5SBALATON Zoltan 273*7ccc89b5SBALATON Zoltan case PCIX0_STS: 274*7ccc89b5SBALATON Zoltan s->sts = val; 275*7ccc89b5SBALATON Zoltan break; 276*7ccc89b5SBALATON Zoltan 277*7ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 278*7ccc89b5SBALATON Zoltan s->pim[0].sa &= 0xffffffffULL; 279*7ccc89b5SBALATON Zoltan s->pim[0].sa |= val << 32; 280*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 0); 281*7ccc89b5SBALATON Zoltan break; 282*7ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 283*7ccc89b5SBALATON Zoltan s->pim[2].sa &= 0xffffffffULL; 284*7ccc89b5SBALATON Zoltan s->pim[2].sa |= val << 32; 285*7ccc89b5SBALATON Zoltan ppc440_pcix_update_pim(s, 2); 286*7ccc89b5SBALATON Zoltan break; 287*7ccc89b5SBALATON Zoltan 288*7ccc89b5SBALATON Zoltan default: 289*7ccc89b5SBALATON Zoltan error_report("%s: unhandled PCI internal register 0x%lx", __func__, 290*7ccc89b5SBALATON Zoltan (unsigned long)addr); 291*7ccc89b5SBALATON Zoltan break; 292*7ccc89b5SBALATON Zoltan } 293*7ccc89b5SBALATON Zoltan } 294*7ccc89b5SBALATON Zoltan 295*7ccc89b5SBALATON Zoltan static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, 296*7ccc89b5SBALATON Zoltan unsigned size) 297*7ccc89b5SBALATON Zoltan { 298*7ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = opaque; 299*7ccc89b5SBALATON Zoltan uint32_t val; 300*7ccc89b5SBALATON Zoltan 301*7ccc89b5SBALATON Zoltan switch (addr) { 302*7ccc89b5SBALATON Zoltan case PCI_VENDOR_ID ... PCI_MAX_LAT: 303*7ccc89b5SBALATON Zoltan val = ldl_le_p(s->dev->config + addr); 304*7ccc89b5SBALATON Zoltan break; 305*7ccc89b5SBALATON Zoltan 306*7ccc89b5SBALATON Zoltan case PCIX0_POM0LAL: 307*7ccc89b5SBALATON Zoltan val = s->pom[0].la; 308*7ccc89b5SBALATON Zoltan break; 309*7ccc89b5SBALATON Zoltan case PCIX0_POM0LAH: 310*7ccc89b5SBALATON Zoltan val = s->pom[0].la >> 32; 311*7ccc89b5SBALATON Zoltan break; 312*7ccc89b5SBALATON Zoltan case PCIX0_POM0SA: 313*7ccc89b5SBALATON Zoltan val = s->pom[0].sa; 314*7ccc89b5SBALATON Zoltan break; 315*7ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAL: 316*7ccc89b5SBALATON Zoltan val = s->pom[0].pcia; 317*7ccc89b5SBALATON Zoltan break; 318*7ccc89b5SBALATON Zoltan case PCIX0_POM0PCIAH: 319*7ccc89b5SBALATON Zoltan val = s->pom[0].pcia >> 32; 320*7ccc89b5SBALATON Zoltan break; 321*7ccc89b5SBALATON Zoltan case PCIX0_POM1LAL: 322*7ccc89b5SBALATON Zoltan val = s->pom[1].la; 323*7ccc89b5SBALATON Zoltan break; 324*7ccc89b5SBALATON Zoltan case PCIX0_POM1LAH: 325*7ccc89b5SBALATON Zoltan val = s->pom[1].la >> 32; 326*7ccc89b5SBALATON Zoltan break; 327*7ccc89b5SBALATON Zoltan case PCIX0_POM1SA: 328*7ccc89b5SBALATON Zoltan val = s->pom[1].sa; 329*7ccc89b5SBALATON Zoltan break; 330*7ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAL: 331*7ccc89b5SBALATON Zoltan val = s->pom[1].pcia; 332*7ccc89b5SBALATON Zoltan break; 333*7ccc89b5SBALATON Zoltan case PCIX0_POM1PCIAH: 334*7ccc89b5SBALATON Zoltan val = s->pom[1].pcia >> 32; 335*7ccc89b5SBALATON Zoltan break; 336*7ccc89b5SBALATON Zoltan case PCIX0_POM2SA: 337*7ccc89b5SBALATON Zoltan val = s->pom[2].sa; 338*7ccc89b5SBALATON Zoltan break; 339*7ccc89b5SBALATON Zoltan 340*7ccc89b5SBALATON Zoltan case PCIX0_PIM0SAL: 341*7ccc89b5SBALATON Zoltan val = s->pim[0].sa; 342*7ccc89b5SBALATON Zoltan break; 343*7ccc89b5SBALATON Zoltan case PCIX0_PIM0LAL: 344*7ccc89b5SBALATON Zoltan val = s->pim[0].la; 345*7ccc89b5SBALATON Zoltan break; 346*7ccc89b5SBALATON Zoltan case PCIX0_PIM0LAH: 347*7ccc89b5SBALATON Zoltan val = s->pim[0].la >> 32; 348*7ccc89b5SBALATON Zoltan break; 349*7ccc89b5SBALATON Zoltan case PCIX0_PIM1SA: 350*7ccc89b5SBALATON Zoltan val = s->pim[1].sa; 351*7ccc89b5SBALATON Zoltan break; 352*7ccc89b5SBALATON Zoltan case PCIX0_PIM1LAL: 353*7ccc89b5SBALATON Zoltan val = s->pim[1].la; 354*7ccc89b5SBALATON Zoltan break; 355*7ccc89b5SBALATON Zoltan case PCIX0_PIM1LAH: 356*7ccc89b5SBALATON Zoltan val = s->pim[1].la >> 32; 357*7ccc89b5SBALATON Zoltan break; 358*7ccc89b5SBALATON Zoltan case PCIX0_PIM2SAL: 359*7ccc89b5SBALATON Zoltan val = s->pim[2].sa; 360*7ccc89b5SBALATON Zoltan break; 361*7ccc89b5SBALATON Zoltan case PCIX0_PIM2LAL: 362*7ccc89b5SBALATON Zoltan val = s->pim[2].la; 363*7ccc89b5SBALATON Zoltan break; 364*7ccc89b5SBALATON Zoltan case PCIX0_PIM2LAH: 365*7ccc89b5SBALATON Zoltan val = s->pim[2].la >> 32; 366*7ccc89b5SBALATON Zoltan break; 367*7ccc89b5SBALATON Zoltan 368*7ccc89b5SBALATON Zoltan case PCIX0_STS: 369*7ccc89b5SBALATON Zoltan val = s->sts; 370*7ccc89b5SBALATON Zoltan break; 371*7ccc89b5SBALATON Zoltan 372*7ccc89b5SBALATON Zoltan case PCIX0_PIM0SAH: 373*7ccc89b5SBALATON Zoltan val = s->pim[0].sa >> 32; 374*7ccc89b5SBALATON Zoltan break; 375*7ccc89b5SBALATON Zoltan case PCIX0_PIM2SAH: 376*7ccc89b5SBALATON Zoltan val = s->pim[2].sa >> 32; 377*7ccc89b5SBALATON Zoltan break; 378*7ccc89b5SBALATON Zoltan 379*7ccc89b5SBALATON Zoltan default: 380*7ccc89b5SBALATON Zoltan error_report("%s: invalid PCI internal register 0x%lx", __func__, 381*7ccc89b5SBALATON Zoltan (unsigned long)addr); 382*7ccc89b5SBALATON Zoltan val = 0; 383*7ccc89b5SBALATON Zoltan } 384*7ccc89b5SBALATON Zoltan 385*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_reg_read(addr, val); 386*7ccc89b5SBALATON Zoltan return val; 387*7ccc89b5SBALATON Zoltan } 388*7ccc89b5SBALATON Zoltan 389*7ccc89b5SBALATON Zoltan static const MemoryRegionOps pci_reg_ops = { 390*7ccc89b5SBALATON Zoltan .read = ppc440_pcix_reg_read4, 391*7ccc89b5SBALATON Zoltan .write = ppc440_pcix_reg_write4, 392*7ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 393*7ccc89b5SBALATON Zoltan }; 394*7ccc89b5SBALATON Zoltan 395*7ccc89b5SBALATON Zoltan static void ppc440_pcix_reset(DeviceState *dev) 396*7ccc89b5SBALATON Zoltan { 397*7ccc89b5SBALATON Zoltan struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev); 398*7ccc89b5SBALATON Zoltan int i; 399*7ccc89b5SBALATON Zoltan 400*7ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { 401*7ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(get_system_memory(), &s->pom[i].mr); 402*7ccc89b5SBALATON Zoltan } 403*7ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 404*7ccc89b5SBALATON Zoltan ppc440_pcix_clear_region(&s->bm, &s->pim[i].mr); 405*7ccc89b5SBALATON Zoltan } 406*7ccc89b5SBALATON Zoltan memset(s->pom, 0, sizeof(s->pom)); 407*7ccc89b5SBALATON Zoltan memset(s->pim, 0, sizeof(s->pim)); 408*7ccc89b5SBALATON Zoltan for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) { 409*7ccc89b5SBALATON Zoltan s->pim[i].sa = 0xffffffff00000000ULL; 410*7ccc89b5SBALATON Zoltan } 411*7ccc89b5SBALATON Zoltan s->sts = 0; 412*7ccc89b5SBALATON Zoltan } 413*7ccc89b5SBALATON Zoltan 414*7ccc89b5SBALATON Zoltan /* All pins from each slot are tied to a single board IRQ. 415*7ccc89b5SBALATON Zoltan * This may need further refactoring for other boards. */ 416*7ccc89b5SBALATON Zoltan static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) 417*7ccc89b5SBALATON Zoltan { 418*7ccc89b5SBALATON Zoltan int slot = pci_dev->devfn >> 3; 419*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, slot); 420*7ccc89b5SBALATON Zoltan return slot - 1; 421*7ccc89b5SBALATON Zoltan } 422*7ccc89b5SBALATON Zoltan 423*7ccc89b5SBALATON Zoltan static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) 424*7ccc89b5SBALATON Zoltan { 425*7ccc89b5SBALATON Zoltan qemu_irq *pci_irqs = opaque; 426*7ccc89b5SBALATON Zoltan 427*7ccc89b5SBALATON Zoltan trace_ppc440_pcix_set_irq(irq_num); 428*7ccc89b5SBALATON Zoltan if (irq_num < 0) { 429*7ccc89b5SBALATON Zoltan error_report("%s: PCI irq %d", __func__, irq_num); 430*7ccc89b5SBALATON Zoltan return; 431*7ccc89b5SBALATON Zoltan } 432*7ccc89b5SBALATON Zoltan qemu_set_irq(pci_irqs[irq_num], level); 433*7ccc89b5SBALATON Zoltan } 434*7ccc89b5SBALATON Zoltan 435*7ccc89b5SBALATON Zoltan static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn) 436*7ccc89b5SBALATON Zoltan { 437*7ccc89b5SBALATON Zoltan PPC440PCIXState *s = opaque; 438*7ccc89b5SBALATON Zoltan 439*7ccc89b5SBALATON Zoltan return &s->bm_as; 440*7ccc89b5SBALATON Zoltan } 441*7ccc89b5SBALATON Zoltan 442*7ccc89b5SBALATON Zoltan /* The default pci_host_data_{read,write} functions in pci/pci_host.c 443*7ccc89b5SBALATON Zoltan * deny access to registers without bit 31 set but our clients want 444*7ccc89b5SBALATON Zoltan * this to work so we have to override these here */ 445*7ccc89b5SBALATON Zoltan static void pci_host_data_write(void *opaque, hwaddr addr, 446*7ccc89b5SBALATON Zoltan uint64_t val, unsigned len) 447*7ccc89b5SBALATON Zoltan { 448*7ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 449*7ccc89b5SBALATON Zoltan pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); 450*7ccc89b5SBALATON Zoltan } 451*7ccc89b5SBALATON Zoltan 452*7ccc89b5SBALATON Zoltan static uint64_t pci_host_data_read(void *opaque, 453*7ccc89b5SBALATON Zoltan hwaddr addr, unsigned len) 454*7ccc89b5SBALATON Zoltan { 455*7ccc89b5SBALATON Zoltan PCIHostState *s = opaque; 456*7ccc89b5SBALATON Zoltan uint32_t val; 457*7ccc89b5SBALATON Zoltan val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); 458*7ccc89b5SBALATON Zoltan return val; 459*7ccc89b5SBALATON Zoltan } 460*7ccc89b5SBALATON Zoltan 461*7ccc89b5SBALATON Zoltan const MemoryRegionOps ppc440_pcix_host_data_ops = { 462*7ccc89b5SBALATON Zoltan .read = pci_host_data_read, 463*7ccc89b5SBALATON Zoltan .write = pci_host_data_write, 464*7ccc89b5SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 465*7ccc89b5SBALATON Zoltan }; 466*7ccc89b5SBALATON Zoltan 467*7ccc89b5SBALATON Zoltan static int ppc440_pcix_initfn(SysBusDevice *dev) 468*7ccc89b5SBALATON Zoltan { 469*7ccc89b5SBALATON Zoltan PPC440PCIXState *s; 470*7ccc89b5SBALATON Zoltan PCIHostState *h; 471*7ccc89b5SBALATON Zoltan int i; 472*7ccc89b5SBALATON Zoltan 473*7ccc89b5SBALATON Zoltan h = PCI_HOST_BRIDGE(dev); 474*7ccc89b5SBALATON Zoltan s = PPC440_PCIX_HOST_BRIDGE(dev); 475*7ccc89b5SBALATON Zoltan 476*7ccc89b5SBALATON Zoltan for (i = 0; i < ARRAY_SIZE(s->irq); i++) { 477*7ccc89b5SBALATON Zoltan sysbus_init_irq(dev, &s->irq[i]); 478*7ccc89b5SBALATON Zoltan } 479*7ccc89b5SBALATON Zoltan 480*7ccc89b5SBALATON Zoltan memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); 481*7ccc89b5SBALATON Zoltan h->bus = pci_register_root_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq, 482*7ccc89b5SBALATON Zoltan ppc440_pcix_map_irq, s->irq, &s->busmem, 483*7ccc89b5SBALATON Zoltan get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS); 484*7ccc89b5SBALATON Zoltan 485*7ccc89b5SBALATON Zoltan s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); 486*7ccc89b5SBALATON Zoltan 487*7ccc89b5SBALATON Zoltan memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); 488*7ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->bm, 0x0, &s->busmem); 489*7ccc89b5SBALATON Zoltan address_space_init(&s->bm_as, &s->bm, "pci-bm"); 490*7ccc89b5SBALATON Zoltan pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s); 491*7ccc89b5SBALATON Zoltan 492*7ccc89b5SBALATON Zoltan memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); 493*7ccc89b5SBALATON Zoltan memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, 494*7ccc89b5SBALATON Zoltan h, "pci-conf-idx", 4); 495*7ccc89b5SBALATON Zoltan memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops, 496*7ccc89b5SBALATON Zoltan h, "pci-conf-data", 4); 497*7ccc89b5SBALATON Zoltan memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, 498*7ccc89b5SBALATON Zoltan "pci.reg", PPC440_REG_SIZE); 499*7ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); 500*7ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); 501*7ccc89b5SBALATON Zoltan memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); 502*7ccc89b5SBALATON Zoltan sysbus_init_mmio(dev, &s->container); 503*7ccc89b5SBALATON Zoltan 504*7ccc89b5SBALATON Zoltan return 0; 505*7ccc89b5SBALATON Zoltan } 506*7ccc89b5SBALATON Zoltan 507*7ccc89b5SBALATON Zoltan static void ppc440_pcix_class_init(ObjectClass *klass, void *data) 508*7ccc89b5SBALATON Zoltan { 509*7ccc89b5SBALATON Zoltan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 510*7ccc89b5SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 511*7ccc89b5SBALATON Zoltan 512*7ccc89b5SBALATON Zoltan k->init = ppc440_pcix_initfn; 513*7ccc89b5SBALATON Zoltan dc->reset = ppc440_pcix_reset; 514*7ccc89b5SBALATON Zoltan } 515*7ccc89b5SBALATON Zoltan 516*7ccc89b5SBALATON Zoltan static const TypeInfo ppc440_pcix_info = { 517*7ccc89b5SBALATON Zoltan .name = TYPE_PPC440_PCIX_HOST_BRIDGE, 518*7ccc89b5SBALATON Zoltan .parent = TYPE_PCI_HOST_BRIDGE, 519*7ccc89b5SBALATON Zoltan .instance_size = sizeof(PPC440PCIXState), 520*7ccc89b5SBALATON Zoltan .class_init = ppc440_pcix_class_init, 521*7ccc89b5SBALATON Zoltan }; 522*7ccc89b5SBALATON Zoltan 523*7ccc89b5SBALATON Zoltan static void ppc440_pcix_register_types(void) 524*7ccc89b5SBALATON Zoltan { 525*7ccc89b5SBALATON Zoltan type_register_static(&ppc440_pcix_info); 526*7ccc89b5SBALATON Zoltan } 527*7ccc89b5SBALATON Zoltan 528*7ccc89b5SBALATON Zoltan type_init(ppc440_pcix_register_types) 529