1 /* 2 * ARM Versatile/PB PCI host controller 3 * 4 * Copyright (c) 2006-2009 CodeSourcery. 5 * Written by Paul Brook 6 * 7 * This code is licensed under the LGPL. 8 */ 9 10 #include "hw/sysbus.h" 11 #include "hw/pci/pci.h" 12 #include "hw/pci/pci_host.h" 13 #include "exec/address-spaces.h" 14 15 typedef struct { 16 SysBusDevice busdev; 17 qemu_irq irq[4]; 18 int realview; 19 MemoryRegion mem_config; 20 MemoryRegion mem_config2; 21 MemoryRegion isa; 22 } PCIVPBState; 23 24 static inline uint32_t vpb_pci_config_addr(hwaddr addr) 25 { 26 return addr & 0xffffff; 27 } 28 29 static void pci_vpb_config_write(void *opaque, hwaddr addr, 30 uint64_t val, unsigned size) 31 { 32 pci_data_write(opaque, vpb_pci_config_addr(addr), val, size); 33 } 34 35 static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr, 36 unsigned size) 37 { 38 uint32_t val; 39 val = pci_data_read(opaque, vpb_pci_config_addr(addr), size); 40 return val; 41 } 42 43 static const MemoryRegionOps pci_vpb_config_ops = { 44 .read = pci_vpb_config_read, 45 .write = pci_vpb_config_write, 46 .endianness = DEVICE_NATIVE_ENDIAN, 47 }; 48 49 static int pci_vpb_map_irq(PCIDevice *d, int irq_num) 50 { 51 return irq_num; 52 } 53 54 static void pci_vpb_set_irq(void *opaque, int irq_num, int level) 55 { 56 qemu_irq *pic = opaque; 57 58 qemu_set_irq(pic[irq_num], level); 59 } 60 61 static int pci_vpb_init(SysBusDevice *dev) 62 { 63 PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev); 64 PCIBus *bus; 65 int i; 66 67 for (i = 0; i < 4; i++) { 68 sysbus_init_irq(dev, &s->irq[i]); 69 } 70 bus = pci_register_bus(&dev->qdev, "pci", 71 pci_vpb_set_irq, pci_vpb_map_irq, s->irq, 72 get_system_memory(), get_system_io(), 73 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); 74 75 /* ??? Register memory space. */ 76 77 /* Our memory regions are: 78 * 0 : PCI self config window 79 * 1 : PCI config window 80 * 2 : PCI IO window (realview_pci only) 81 */ 82 memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus, 83 "pci-vpb-selfconfig", 0x1000000); 84 sysbus_init_mmio(dev, &s->mem_config); 85 memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus, 86 "pci-vpb-config", 0x1000000); 87 sysbus_init_mmio(dev, &s->mem_config2); 88 if (s->realview) { 89 isa_mmio_setup(&s->isa, 0x0100000); 90 sysbus_init_mmio(dev, &s->isa); 91 } 92 93 pci_create_simple(bus, -1, "versatile_pci_host"); 94 return 0; 95 } 96 97 static int pci_realview_init(SysBusDevice *dev) 98 { 99 PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev); 100 s->realview = 1; 101 return pci_vpb_init(dev); 102 } 103 104 static int versatile_pci_host_init(PCIDevice *d) 105 { 106 pci_set_word(d->config + PCI_STATUS, 107 PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); 108 pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10); 109 return 0; 110 } 111 112 static void versatile_pci_host_class_init(ObjectClass *klass, void *data) 113 { 114 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 115 116 k->init = versatile_pci_host_init; 117 k->vendor_id = PCI_VENDOR_ID_XILINX; 118 k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30; 119 k->class_id = PCI_CLASS_PROCESSOR_CO; 120 } 121 122 static const TypeInfo versatile_pci_host_info = { 123 .name = "versatile_pci_host", 124 .parent = TYPE_PCI_DEVICE, 125 .instance_size = sizeof(PCIDevice), 126 .class_init = versatile_pci_host_class_init, 127 }; 128 129 static void pci_vpb_class_init(ObjectClass *klass, void *data) 130 { 131 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); 132 133 sdc->init = pci_vpb_init; 134 } 135 136 static const TypeInfo pci_vpb_info = { 137 .name = "versatile_pci", 138 .parent = TYPE_SYS_BUS_DEVICE, 139 .instance_size = sizeof(PCIVPBState), 140 .class_init = pci_vpb_class_init, 141 }; 142 143 static void pci_realview_class_init(ObjectClass *klass, void *data) 144 { 145 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); 146 147 sdc->init = pci_realview_init; 148 } 149 150 static const TypeInfo pci_realview_info = { 151 .name = "realview_pci", 152 .parent = TYPE_SYS_BUS_DEVICE, 153 .instance_size = sizeof(PCIVPBState), 154 .class_init = pci_realview_class_init, 155 }; 156 157 static void versatile_pci_register_types(void) 158 { 159 type_register_static(&pci_vpb_info); 160 type_register_static(&pci_realview_info); 161 type_register_static(&versatile_pci_host_info); 162 } 163 164 type_init(versatile_pci_register_types) 165