root / hw / versatile_pci.c @ 92d88ecb
History | View | Annotate | Download (3.6 kB)
1 |
/*
|
---|---|
2 |
* ARM Versatile/PB PCI host controller
|
3 |
*
|
4 |
* Copyright (c) 2006 CodeSourcery.
|
5 |
* Written by Paul Brook
|
6 |
*
|
7 |
* This code is licenced under the LGPL.
|
8 |
*/
|
9 |
|
10 |
#include "vl.h" |
11 |
|
12 |
static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr) |
13 |
{ |
14 |
return addr & 0xffffff; |
15 |
} |
16 |
|
17 |
static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr, |
18 |
uint32_t val) |
19 |
{ |
20 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
|
21 |
} |
22 |
|
23 |
static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr, |
24 |
uint32_t val) |
25 |
{ |
26 |
#ifdef TARGET_WORDS_BIGENDIAN
|
27 |
val = bswap16(val); |
28 |
#endif
|
29 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
|
30 |
} |
31 |
|
32 |
static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr, |
33 |
uint32_t val) |
34 |
{ |
35 |
#ifdef TARGET_WORDS_BIGENDIAN
|
36 |
val = bswap32(val); |
37 |
#endif
|
38 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
|
39 |
} |
40 |
|
41 |
static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr) |
42 |
{ |
43 |
uint32_t val; |
44 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
|
45 |
return val;
|
46 |
} |
47 |
|
48 |
static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr) |
49 |
{ |
50 |
uint32_t val; |
51 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
|
52 |
#ifdef TARGET_WORDS_BIGENDIAN
|
53 |
val = bswap16(val); |
54 |
#endif
|
55 |
return val;
|
56 |
} |
57 |
|
58 |
static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr) |
59 |
{ |
60 |
uint32_t val; |
61 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
|
62 |
#ifdef TARGET_WORDS_BIGENDIAN
|
63 |
val = bswap32(val); |
64 |
#endif
|
65 |
return val;
|
66 |
} |
67 |
|
68 |
static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
|
69 |
&pci_vpb_config_writeb, |
70 |
&pci_vpb_config_writew, |
71 |
&pci_vpb_config_writel, |
72 |
}; |
73 |
|
74 |
static CPUReadMemoryFunc *pci_vpb_config_read[] = {
|
75 |
&pci_vpb_config_readb, |
76 |
&pci_vpb_config_readw, |
77 |
&pci_vpb_config_readl, |
78 |
}; |
79 |
|
80 |
static int pci_vpb_irq; |
81 |
|
82 |
static int pci_vpb_map_irq(PCIDevice *d, int irq_num) |
83 |
{ |
84 |
return irq_num;
|
85 |
} |
86 |
|
87 |
static void pci_vpb_set_irq(qemu_irq *pic, int irq_num, int level) |
88 |
{ |
89 |
qemu_set_irq(pic[pci_vpb_irq + irq_num], level); |
90 |
} |
91 |
|
92 |
PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview) |
93 |
{ |
94 |
PCIBus *s; |
95 |
PCIDevice *d; |
96 |
int mem_config;
|
97 |
uint32_t base; |
98 |
const char * name; |
99 |
|
100 |
pci_vpb_irq = irq; |
101 |
if (realview) {
|
102 |
base = 0x60000000;
|
103 |
name = "RealView EB PCI Controller";
|
104 |
} else {
|
105 |
base = 0x40000000;
|
106 |
name = "Versatile/PB PCI Controller";
|
107 |
} |
108 |
s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4); |
109 |
/* ??? Register memory space. */
|
110 |
|
111 |
mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
|
112 |
pci_vpb_config_write, s); |
113 |
/* Selfconfig area. */
|
114 |
cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config); |
115 |
/* Normal config area. */
|
116 |
cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config); |
117 |
|
118 |
d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL); |
119 |
|
120 |
if (realview) {
|
121 |
/* IO memory area. */
|
122 |
isa_mmio_init(base + 0x03000000, 0x00100000); |
123 |
} |
124 |
|
125 |
d->config[0x00] = 0xee; // vendor_id |
126 |
d->config[0x01] = 0x10; |
127 |
/* Both boards have the same device ID. Oh well. */
|
128 |
d->config[0x02] = 0x00; // device_id |
129 |
d->config[0x03] = 0x03; |
130 |
d->config[0x04] = 0x00; |
131 |
d->config[0x05] = 0x00; |
132 |
d->config[0x06] = 0x20; |
133 |
d->config[0x07] = 0x02; |
134 |
d->config[0x08] = 0x00; // revision |
135 |
d->config[0x09] = 0x00; // programming i/f |
136 |
d->config[0x0A] = 0x40; // class_sub = pci host |
137 |
d->config[0x0B] = 0x0b; // class_base = PCI_bridge |
138 |
d->config[0x0D] = 0x10; // latency_timer |
139 |
|
140 |
return s;
|
141 |
} |
142 |
|