root / hw / versatile_pci.c @ deb54399
History | View | Annotate | Download (3.7 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 "hw.h" |
11 |
#include "pci.h" |
12 |
#include "primecell.h" |
13 |
|
14 |
static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr) |
15 |
{ |
16 |
return addr & 0xffffff; |
17 |
} |
18 |
|
19 |
static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr, |
20 |
uint32_t val) |
21 |
{ |
22 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
|
23 |
} |
24 |
|
25 |
static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr, |
26 |
uint32_t val) |
27 |
{ |
28 |
#ifdef TARGET_WORDS_BIGENDIAN
|
29 |
val = bswap16(val); |
30 |
#endif
|
31 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
|
32 |
} |
33 |
|
34 |
static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr, |
35 |
uint32_t val) |
36 |
{ |
37 |
#ifdef TARGET_WORDS_BIGENDIAN
|
38 |
val = bswap32(val); |
39 |
#endif
|
40 |
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
|
41 |
} |
42 |
|
43 |
static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr) |
44 |
{ |
45 |
uint32_t val; |
46 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
|
47 |
return val;
|
48 |
} |
49 |
|
50 |
static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr) |
51 |
{ |
52 |
uint32_t val; |
53 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
|
54 |
#ifdef TARGET_WORDS_BIGENDIAN
|
55 |
val = bswap16(val); |
56 |
#endif
|
57 |
return val;
|
58 |
} |
59 |
|
60 |
static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr) |
61 |
{ |
62 |
uint32_t val; |
63 |
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
|
64 |
#ifdef TARGET_WORDS_BIGENDIAN
|
65 |
val = bswap32(val); |
66 |
#endif
|
67 |
return val;
|
68 |
} |
69 |
|
70 |
static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
|
71 |
&pci_vpb_config_writeb, |
72 |
&pci_vpb_config_writew, |
73 |
&pci_vpb_config_writel, |
74 |
}; |
75 |
|
76 |
static CPUReadMemoryFunc *pci_vpb_config_read[] = {
|
77 |
&pci_vpb_config_readb, |
78 |
&pci_vpb_config_readw, |
79 |
&pci_vpb_config_readl, |
80 |
}; |
81 |
|
82 |
static int pci_vpb_irq; |
83 |
|
84 |
static int pci_vpb_map_irq(PCIDevice *d, int irq_num) |
85 |
{ |
86 |
return irq_num;
|
87 |
} |
88 |
|
89 |
static void pci_vpb_set_irq(qemu_irq *pic, int irq_num, int level) |
90 |
{ |
91 |
qemu_set_irq(pic[pci_vpb_irq + irq_num], level); |
92 |
} |
93 |
|
94 |
PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview) |
95 |
{ |
96 |
PCIBus *s; |
97 |
PCIDevice *d; |
98 |
int mem_config;
|
99 |
uint32_t base; |
100 |
const char * name; |
101 |
|
102 |
pci_vpb_irq = irq; |
103 |
if (realview) {
|
104 |
base = 0x60000000;
|
105 |
name = "RealView EB PCI Controller";
|
106 |
} else {
|
107 |
base = 0x40000000;
|
108 |
name = "Versatile/PB PCI Controller";
|
109 |
} |
110 |
s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4); |
111 |
/* ??? Register memory space. */
|
112 |
|
113 |
mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
|
114 |
pci_vpb_config_write, s); |
115 |
/* Selfconfig area. */
|
116 |
cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config); |
117 |
/* Normal config area. */
|
118 |
cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config); |
119 |
|
120 |
d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL); |
121 |
|
122 |
if (realview) {
|
123 |
/* IO memory area. */
|
124 |
isa_mmio_init(base + 0x03000000, 0x00100000); |
125 |
} |
126 |
|
127 |
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX); |
128 |
/* Both boards have the same device ID. Oh well. */
|
129 |
pci_config_set_device_id(d->config, 0x0300); // device_id |
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 |
} |