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