1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/pci.h>
29#include <linux/init.h>
30#include <asm/olpc.h>
31#include <asm/geode.h>
32#include <asm/pci_x86.h>
33
34
35
36
37
38
39
40
41
42
43
44
45static const uint32_t lxnb_hdr[] = {
46 0x0, 0x0, 0x0, 0x0,
47 0x0, 0x0, 0x0, 0x0,
48
49 0x281022, 0x2200005, 0x6000021, 0x80f808,
50 0x0, 0x0, 0x0, 0x0,
51 0x0, 0x0, 0x0, 0x28100b,
52 0x0, 0x0, 0x0, 0x0,
53 0x0, 0x0, 0x0, 0x0,
54 0x0, 0x0, 0x0, 0x0,
55 0x0, 0x0, 0x0, 0x0,
56};
57
58static const uint32_t gxnb_hdr[] = {
59 0xfffffffd, 0x0, 0x0, 0x0,
60 0x0, 0x0, 0x0, 0x0,
61
62 0x28100b, 0x2200005, 0x6000021, 0x80f808,
63 0xac1d, 0x0, 0x0, 0x0,
64 0x0, 0x0, 0x0, 0x28100b,
65 0x0, 0x0, 0x0, 0x0,
66 0x0, 0x0, 0x0, 0x0,
67 0x0, 0x0, 0x0, 0x0,
68 0x0, 0x0, 0x0, 0x0,
69};
70
71static const uint32_t lxfb_hdr[] = {
72 0xff000008, 0xffffc000, 0xffffc000, 0xffffc000,
73 0xffffc000, 0x0, 0x0, 0x0,
74
75 0x20811022, 0x2200003, 0x3000000, 0x0,
76 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000,
77 0xfe00c000, 0x0, 0x0, 0x30100b,
78 0x0, 0x0, 0x0, 0x10e,
79 0x0, 0x0, 0x0, 0x0,
80 0x3d0, 0x3c0, 0xa0000, 0x0,
81 0x0, 0x0, 0x0, 0x0,
82};
83
84static const uint32_t gxfb_hdr[] = {
85 0xff800008, 0xffffc000, 0xffffc000, 0xffffc000,
86 0x0, 0x0, 0x0, 0x0,
87
88 0x30100b, 0x2200003, 0x3000000, 0x0,
89 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000,
90 0x0, 0x0, 0x0, 0x30100b,
91 0x0, 0x0, 0x0, 0x0,
92 0x0, 0x0, 0x0, 0x0,
93 0x3d0, 0x3c0, 0xa0000, 0x0,
94 0x0, 0x0, 0x0, 0x0,
95};
96
97static const uint32_t aes_hdr[] = {
98 0xffffc000, 0x0, 0x0, 0x0,
99 0x0, 0x0, 0x0, 0x0,
100
101 0x20821022, 0x2a00006, 0x10100000, 0x8,
102 0xfe010000, 0x0, 0x0, 0x0,
103 0x0, 0x0, 0x0, 0x20821022,
104 0x0, 0x0, 0x0, 0x0,
105 0x0, 0x0, 0x0, 0x0,
106 0x0, 0x0, 0x0, 0x0,
107 0x0, 0x0, 0x0, 0x0,
108};
109
110
111static const uint32_t isa_hdr[] = {
112 0xfffffff9, 0xffffff01, 0xffffffc1, 0xffffffe1,
113 0xffffff81, 0xffffffc1, 0x0, 0x0,
114
115 0x20901022, 0x2a00049, 0x6010003, 0x802000,
116 0x18b1, 0x1001, 0x1801, 0x1881,
117 0x1401, 0x1841, 0x0, 0x20901022,
118 0x0, 0x0, 0x0, 0x0,
119 0x0, 0x0, 0x0, 0x0,
120 0x0, 0x0, 0x0, 0xaa5b,
121 0x0, 0x0, 0x0, 0x0,
122};
123
124static const uint32_t ac97_hdr[] = {
125 0xffffff81, 0x0, 0x0, 0x0,
126 0x0, 0x0, 0x0, 0x0,
127
128 0x20931022, 0x2a00041, 0x4010001, 0x0,
129 0x1481, 0x0, 0x0, 0x0,
130 0x0, 0x0, 0x0, 0x20931022,
131 0x0, 0x0, 0x0, 0x205,
132 0x0, 0x0, 0x0, 0x0,
133 0x0, 0x0, 0x0, 0x0,
134 0x0, 0x0, 0x0, 0x0,
135};
136
137static const uint32_t ohci_hdr[] = {
138 0xfffff000, 0x0, 0x0, 0x0,
139 0x0, 0x0, 0x0, 0x0,
140
141 0x20941022, 0x2300006, 0xc031002, 0x0,
142 0xfe01a000, 0x0, 0x0, 0x0,
143 0x0, 0x0, 0x0, 0x20941022,
144 0x0, 0x40, 0x0, 0x40a,
145 0xc8020001, 0x0, 0x0, 0x0,
146
147 0x0, 0x0, 0x0, 0x0,
148 0x0, 0x0, 0x0, 0x0,
149};
150
151static const uint32_t ehci_hdr[] = {
152 0xfffff000, 0x0, 0x0, 0x0,
153 0x0, 0x0, 0x0, 0x0,
154
155 0x20951022, 0x2300006, 0xc032002, 0x0,
156 0xfe01b000, 0x0, 0x0, 0x0,
157 0x0, 0x0, 0x0, 0x20951022,
158 0x0, 0x40, 0x0, 0x40a,
159 0xc8020001, 0x0, 0x0, 0x0,
160
161#if 0
162 0x1, 0x40080000, 0x0, 0x0,
163#endif
164 0x01000001, 0x0, 0x0, 0x0,
165 0x2020, 0x0, 0x0, 0x0,
166
167};
168
169static uint32_t ff_loc = ~0;
170static uint32_t zero_loc;
171static int bar_probing;
172static int is_lx;
173
174#define NB_SLOT 0x1
175#define SB_SLOT 0xf
176
177static int is_simulated(unsigned int bus, unsigned int devfn)
178{
179 return (!bus && ((PCI_SLOT(devfn) == NB_SLOT) ||
180 (PCI_SLOT(devfn) == SB_SLOT)));
181}
182
183static uint32_t *hdr_addr(const uint32_t *hdr, int reg)
184{
185 uint32_t addr;
186
187
188
189
190
191
192
193
194
195
196
197
198 addr = (uint32_t)hdr + reg + (bar_probing ? -0x10 : 0x20);
199
200 bar_probing = 0;
201 return (uint32_t *)addr;
202}
203
204static int pci_olpc_read(unsigned int seg, unsigned int bus,
205 unsigned int devfn, int reg, int len, uint32_t *value)
206{
207 uint32_t *addr;
208
209 WARN_ON(seg);
210
211
212 if (!is_simulated(bus, devfn))
213 return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
214
215
216
217
218
219 if (reg >= 0x70)
220 addr = &zero_loc;
221 else {
222 switch (devfn) {
223 case 0x8:
224 addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg);
225 break;
226 case 0x9:
227 addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg);
228 break;
229 case 0xa:
230 addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc;
231 break;
232 case 0x78:
233 addr = hdr_addr(isa_hdr, reg);
234 break;
235 case 0x7b:
236 addr = hdr_addr(ac97_hdr, reg);
237 break;
238 case 0x7c:
239 addr = hdr_addr(ohci_hdr, reg);
240 break;
241 case 0x7d:
242 addr = hdr_addr(ehci_hdr, reg);
243 break;
244 default:
245 addr = &ff_loc;
246 break;
247 }
248 }
249 switch (len) {
250 case 1:
251 *value = *(uint8_t *)addr;
252 break;
253 case 2:
254 *value = *(uint16_t *)addr;
255 break;
256 case 4:
257 *value = *addr;
258 break;
259 default:
260 BUG();
261 }
262
263 return 0;
264}
265
266static int pci_olpc_write(unsigned int seg, unsigned int bus,
267 unsigned int devfn, int reg, int len, uint32_t value)
268{
269 WARN_ON(seg);
270
271
272 if (!is_simulated(bus, devfn))
273 return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
274
275
276
277
278
279
280
281
282
283
284
285 if ((reg >= 0x10) && (reg < 0x2c)) {
286
287 if (value == ~0)
288 bar_probing = 1;
289 } else {
290
291
292
293
294 if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) &&
295 (reg != PCI_LATENCY_TIMER) &&
296 (reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44))
297 printk(KERN_WARNING "OLPC PCI: Config write to devfn"
298 " %x reg %x value %x\n", devfn, reg, value);
299 }
300
301 return 0;
302}
303
304static const struct pci_raw_ops pci_olpc_conf = {
305 .read = pci_olpc_read,
306 .write = pci_olpc_write,
307};
308
309int __init pci_olpc_init(void)
310{
311 printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n");
312 raw_pci_ops = &pci_olpc_conf;
313 is_lx = is_geode_lx();
314 return 0;
315}
316