1 |
1 |
/*
|
2 |
2 |
* ARM Versatile/PB PCI host controller
|
3 |
3 |
*
|
4 |
|
* Copyright (c) 2006 CodeSourcery.
|
|
4 |
* Copyright (c) 2006-2009 CodeSourcery.
|
5 |
5 |
* Written by Paul Brook
|
6 |
6 |
*
|
7 |
7 |
* This code is licenced under the LGPL.
|
8 |
8 |
*/
|
9 |
9 |
|
10 |
|
#include "hw.h"
|
|
10 |
#include "sysbus.h"
|
11 |
11 |
#include "pci.h"
|
12 |
|
#include "primecell.h"
|
|
12 |
|
|
13 |
typedef struct {
|
|
14 |
SysBusDevice busdev;
|
|
15 |
qemu_irq irq[4];
|
|
16 |
int realview;
|
|
17 |
int mem_config;
|
|
18 |
} PCIVPBState;
|
13 |
19 |
|
14 |
20 |
static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
|
15 |
21 |
{
|
... | ... | |
89 |
95 |
qemu_set_irq(pic[irq_num], level);
|
90 |
96 |
}
|
91 |
97 |
|
92 |
|
PCIBus *pci_vpb_init(qemu_irq *pic, int realview)
|
|
98 |
static void pci_vpb_map(SysBusDevice *dev, target_phys_addr_t base)
|
93 |
99 |
{
|
94 |
|
PCIBus *s;
|
95 |
|
PCIDevice *d;
|
96 |
|
int mem_config;
|
97 |
|
uint32_t base;
|
98 |
|
const char * name;
|
99 |
|
qemu_irq *irqs;
|
|
100 |
PCIVPBState *s = (PCIVPBState *)dev;
|
|
101 |
/* Selfconfig area. */
|
|
102 |
cpu_register_physical_memory(base + 0x01000000, 0x1000000, s->mem_config);
|
|
103 |
/* Normal config area. */
|
|
104 |
cpu_register_physical_memory(base + 0x02000000, 0x1000000, s->mem_config);
|
|
105 |
|
|
106 |
if (s->realview) {
|
|
107 |
/* IO memory area. */
|
|
108 |
isa_mmio_init(base + 0x03000000, 0x00100000);
|
|
109 |
}
|
|
110 |
}
|
|
111 |
|
|
112 |
static void pci_vpb_init(SysBusDevice *dev)
|
|
113 |
{
|
|
114 |
PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
|
|
115 |
PCIBus *bus;
|
100 |
116 |
int i;
|
101 |
117 |
|
102 |
|
irqs = qemu_mallocz(sizeof(qemu_irq) * 4);
|
103 |
118 |
for (i = 0; i < 4; i++) {
|
104 |
|
irqs[i] = pic[i];
|
105 |
|
}
|
106 |
|
if (realview) {
|
107 |
|
base = 0x60000000;
|
108 |
|
name = "RealView EB PCI Controller";
|
109 |
|
} else {
|
110 |
|
base = 0x40000000;
|
111 |
|
name = "Versatile/PB PCI Controller";
|
|
119 |
sysbus_init_irq(dev, &s->irq[i]);
|
112 |
120 |
}
|
113 |
|
s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, irqs, 11 << 3, 4);
|
|
121 |
bus = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
|
|
122 |
11 << 3, 4);
|
|
123 |
qdev_attach_child_bus(&dev->qdev, "pci", bus);
|
|
124 |
|
114 |
125 |
/* ??? Register memory space. */
|
115 |
126 |
|
116 |
|
mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
|
117 |
|
pci_vpb_config_write, s);
|
118 |
|
/* Selfconfig area. */
|
119 |
|
cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config);
|
120 |
|
/* Normal config area. */
|
121 |
|
cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config);
|
|
127 |
s->mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
|
|
128 |
pci_vpb_config_write, bus);
|
|
129 |
sysbus_init_mmio_cb(dev, 0x04000000, pci_vpb_map);
|
122 |
130 |
|
123 |
|
d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL);
|
|
131 |
pci_create_simple(bus, -1, "versatile_pci_host");
|
|
132 |
}
|
124 |
133 |
|
125 |
|
if (realview) {
|
126 |
|
/* IO memory area. */
|
127 |
|
isa_mmio_init(base + 0x03000000, 0x00100000);
|
128 |
|
}
|
|
134 |
static void pci_realview_init(SysBusDevice *dev)
|
|
135 |
{
|
|
136 |
PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
|
|
137 |
s->realview = 1;
|
|
138 |
pci_vpb_init(dev);
|
|
139 |
}
|
129 |
140 |
|
|
141 |
static void versatile_pci_host_init(PCIDevice *d)
|
|
142 |
{
|
130 |
143 |
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX);
|
131 |
144 |
/* Both boards have the same device ID. Oh well. */
|
132 |
145 |
pci_config_set_device_id(d->config, PCI_DEVICE_ID_XILINX_XC2VP30);
|
... | ... | |
138 |
151 |
d->config[0x09] = 0x00; // programming i/f
|
139 |
152 |
pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_CO);
|
140 |
153 |
d->config[0x0D] = 0x10; // latency_timer
|
|
154 |
}
|
141 |
155 |
|
142 |
|
return s;
|
|
156 |
static void versatile_pci_register_devices(void)
|
|
157 |
{
|
|
158 |
sysbus_register_dev("versatile_pci", sizeof(PCIVPBState), pci_vpb_init);
|
|
159 |
sysbus_register_dev("realview_pci", sizeof(PCIVPBState),
|
|
160 |
pci_realview_init);
|
|
161 |
pci_qdev_register("versatile_pci_host", sizeof(PCIDevice),
|
|
162 |
versatile_pci_host_init);
|
143 |
163 |
}
|
|
164 |
|
|
165 |
device_init(versatile_pci_register_devices)
|