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