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