Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-ebsa110/io.c
10817 views
1
/*
2
* linux/arch/arm/mach-ebsa110/isamem.c
3
*
4
* Copyright (C) 2001 Russell King
5
*
6
* Perform "ISA" memory and IO accesses. The EBSA110 has some "peculiarities"
7
* in the way it handles accesses to odd IO ports on 16-bit devices. These
8
* devices have their D0-D15 lines connected to the processors D0-D15 lines.
9
* Since they expect all byte IO operations to be performed on D0-D7, and the
10
* StrongARM expects to transfer the byte to these odd addresses on D8-D15,
11
* we must use a trick to get the required behaviour.
12
*
13
* The trick employed here is to use long word stores to odd address -1. The
14
* glue logic picks this up as a "trick" access, and asserts the LSB of the
15
* peripherals address bus, thereby accessing the odd IO port. Meanwhile, the
16
* StrongARM transfers its data on D0-D7 as expected.
17
*
18
* Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller
19
* wiring was screwed in such a way that it had limited memory space access.
20
* Luckily, the work-around for this is not too horrible. See
21
* __isamem_convert_addr for the details.
22
*/
23
#include <linux/module.h>
24
#include <linux/kernel.h>
25
#include <linux/types.h>
26
#include <linux/io.h>
27
28
#include <mach/hardware.h>
29
#include <asm/page.h>
30
31
static void __iomem *__isamem_convert_addr(const volatile void __iomem *addr)
32
{
33
u32 ret, a = (u32 __force) addr;
34
35
/*
36
* The PCMCIA controller is wired up as follows:
37
* +---------+---------+---------+---------+---------+---------+
38
* PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1 | | |
39
* | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
40
* +---------+---------+---------+---------+---------+---------+
41
* CPU | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1 | | |
42
* | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
43
* +---------+---------+---------+---------+---------+---------+
44
*
45
* This means that we can access PCMCIA regions as follows:
46
* 0x*10000 -> 0x*1ffff
47
* 0x*70000 -> 0x*7ffff
48
* 0x*90000 -> 0x*9ffff
49
* 0x*f0000 -> 0x*fffff
50
*/
51
ret = (a & 0xf803fe) << 1;
52
ret |= (a & 0x03fc00) << 2;
53
54
ret += 0xe8000000;
55
56
if ((a & 0x20000) == (a & 0x40000) >> 1)
57
return (void __iomem *)ret;
58
59
BUG();
60
return NULL;
61
}
62
63
/*
64
* read[bwl] and write[bwl]
65
*/
66
u8 __readb(const volatile void __iomem *addr)
67
{
68
void __iomem *a = __isamem_convert_addr(addr);
69
u32 ret;
70
71
if ((unsigned long)addr & 1)
72
ret = __raw_readl(a);
73
else
74
ret = __raw_readb(a);
75
return ret;
76
}
77
78
u16 __readw(const volatile void __iomem *addr)
79
{
80
void __iomem *a = __isamem_convert_addr(addr);
81
82
if ((unsigned long)addr & 1)
83
BUG();
84
85
return __raw_readw(a);
86
}
87
88
u32 __readl(const volatile void __iomem *addr)
89
{
90
void __iomem *a = __isamem_convert_addr(addr);
91
u32 ret;
92
93
if ((unsigned long)addr & 3)
94
BUG();
95
96
ret = __raw_readw(a);
97
ret |= __raw_readw(a + 4) << 16;
98
return ret;
99
}
100
101
EXPORT_SYMBOL(__readb);
102
EXPORT_SYMBOL(__readw);
103
EXPORT_SYMBOL(__readl);
104
105
void readsw(const void __iomem *addr, void *data, int len)
106
{
107
void __iomem *a = __isamem_convert_addr(addr);
108
109
BUG_ON((unsigned long)addr & 1);
110
111
__raw_readsw(a, data, len);
112
}
113
EXPORT_SYMBOL(readsw);
114
115
void readsl(const void __iomem *addr, void *data, int len)
116
{
117
void __iomem *a = __isamem_convert_addr(addr);
118
119
BUG_ON((unsigned long)addr & 3);
120
121
__raw_readsl(a, data, len);
122
}
123
EXPORT_SYMBOL(readsl);
124
125
void __writeb(u8 val, void __iomem *addr)
126
{
127
void __iomem *a = __isamem_convert_addr(addr);
128
129
if ((unsigned long)addr & 1)
130
__raw_writel(val, a);
131
else
132
__raw_writeb(val, a);
133
}
134
135
void __writew(u16 val, void __iomem *addr)
136
{
137
void __iomem *a = __isamem_convert_addr(addr);
138
139
if ((unsigned long)addr & 1)
140
BUG();
141
142
__raw_writew(val, a);
143
}
144
145
void __writel(u32 val, void __iomem *addr)
146
{
147
void __iomem *a = __isamem_convert_addr(addr);
148
149
if ((unsigned long)addr & 3)
150
BUG();
151
152
__raw_writew(val, a);
153
__raw_writew(val >> 16, a + 4);
154
}
155
156
EXPORT_SYMBOL(__writeb);
157
EXPORT_SYMBOL(__writew);
158
EXPORT_SYMBOL(__writel);
159
160
void writesw(void __iomem *addr, const void *data, int len)
161
{
162
void __iomem *a = __isamem_convert_addr(addr);
163
164
BUG_ON((unsigned long)addr & 1);
165
166
__raw_writesw(a, data, len);
167
}
168
EXPORT_SYMBOL(writesw);
169
170
void writesl(void __iomem *addr, const void *data, int len)
171
{
172
void __iomem *a = __isamem_convert_addr(addr);
173
174
BUG_ON((unsigned long)addr & 3);
175
176
__raw_writesl(a, data, len);
177
}
178
EXPORT_SYMBOL(writesl);
179
180
#define SUPERIO_PORT(p) \
181
(((p) >> 3) == (0x3f8 >> 3) || \
182
((p) >> 3) == (0x2f8 >> 3) || \
183
((p) >> 3) == (0x378 >> 3))
184
185
/*
186
* We're addressing an 8 or 16-bit peripheral which tranfers
187
* odd addresses on the low ISA byte lane.
188
*/
189
u8 __inb8(unsigned int port)
190
{
191
u32 ret;
192
193
/*
194
* The SuperIO registers use sane addressing techniques...
195
*/
196
if (SUPERIO_PORT(port))
197
ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
198
else {
199
void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
200
201
/*
202
* Shame nothing else does
203
*/
204
if (port & 1)
205
ret = __raw_readl(a);
206
else
207
ret = __raw_readb(a);
208
}
209
return ret;
210
}
211
212
/*
213
* We're addressing a 16-bit peripheral which transfers odd
214
* addresses on the high ISA byte lane.
215
*/
216
u8 __inb16(unsigned int port)
217
{
218
unsigned int offset;
219
220
/*
221
* The SuperIO registers use sane addressing techniques...
222
*/
223
if (SUPERIO_PORT(port))
224
offset = port << 2;
225
else
226
offset = (port & ~1) << 1 | (port & 1);
227
228
return __raw_readb((void __iomem *)ISAIO_BASE + offset);
229
}
230
231
u16 __inw(unsigned int port)
232
{
233
unsigned int offset;
234
235
/*
236
* The SuperIO registers use sane addressing techniques...
237
*/
238
if (SUPERIO_PORT(port))
239
offset = port << 2;
240
else {
241
offset = port << 1;
242
BUG_ON(port & 1);
243
}
244
return __raw_readw((void __iomem *)ISAIO_BASE + offset);
245
}
246
247
/*
248
* Fake a 32-bit read with two 16-bit reads. Needed for 3c589.
249
*/
250
u32 __inl(unsigned int port)
251
{
252
void __iomem *a;
253
254
if (SUPERIO_PORT(port) || port & 3)
255
BUG();
256
257
a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
258
259
return __raw_readw(a) | __raw_readw(a + 4) << 16;
260
}
261
262
EXPORT_SYMBOL(__inb8);
263
EXPORT_SYMBOL(__inb16);
264
EXPORT_SYMBOL(__inw);
265
EXPORT_SYMBOL(__inl);
266
267
void __outb8(u8 val, unsigned int port)
268
{
269
/*
270
* The SuperIO registers use sane addressing techniques...
271
*/
272
if (SUPERIO_PORT(port))
273
__raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
274
else {
275
void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
276
277
/*
278
* Shame nothing else does
279
*/
280
if (port & 1)
281
__raw_writel(val, a);
282
else
283
__raw_writeb(val, a);
284
}
285
}
286
287
void __outb16(u8 val, unsigned int port)
288
{
289
unsigned int offset;
290
291
/*
292
* The SuperIO registers use sane addressing techniques...
293
*/
294
if (SUPERIO_PORT(port))
295
offset = port << 2;
296
else
297
offset = (port & ~1) << 1 | (port & 1);
298
299
__raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
300
}
301
302
void __outw(u16 val, unsigned int port)
303
{
304
unsigned int offset;
305
306
/*
307
* The SuperIO registers use sane addressing techniques...
308
*/
309
if (SUPERIO_PORT(port))
310
offset = port << 2;
311
else {
312
offset = port << 1;
313
BUG_ON(port & 1);
314
}
315
__raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
316
}
317
318
void __outl(u32 val, unsigned int port)
319
{
320
BUG();
321
}
322
323
EXPORT_SYMBOL(__outb8);
324
EXPORT_SYMBOL(__outb16);
325
EXPORT_SYMBOL(__outw);
326
EXPORT_SYMBOL(__outl);
327
328
void outsb(unsigned int port, const void *from, int len)
329
{
330
u32 off;
331
332
if (SUPERIO_PORT(port))
333
off = port << 2;
334
else {
335
off = (port & ~1) << 1;
336
if (port & 1)
337
BUG();
338
}
339
340
__raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
341
}
342
343
void insb(unsigned int port, void *from, int len)
344
{
345
u32 off;
346
347
if (SUPERIO_PORT(port))
348
off = port << 2;
349
else {
350
off = (port & ~1) << 1;
351
if (port & 1)
352
BUG();
353
}
354
355
__raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
356
}
357
358
EXPORT_SYMBOL(outsb);
359
EXPORT_SYMBOL(insb);
360
361
void outsw(unsigned int port, const void *from, int len)
362
{
363
u32 off;
364
365
if (SUPERIO_PORT(port))
366
off = port << 2;
367
else {
368
off = (port & ~1) << 1;
369
if (port & 1)
370
BUG();
371
}
372
373
__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
374
}
375
376
void insw(unsigned int port, void *from, int len)
377
{
378
u32 off;
379
380
if (SUPERIO_PORT(port))
381
off = port << 2;
382
else {
383
off = (port & ~1) << 1;
384
if (port & 1)
385
BUG();
386
}
387
388
__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
389
}
390
391
EXPORT_SYMBOL(outsw);
392
EXPORT_SYMBOL(insw);
393
394
/*
395
* We implement these as 16-bit insw/outsw, mainly for
396
* 3c589 cards.
397
*/
398
void outsl(unsigned int port, const void *from, int len)
399
{
400
u32 off = port << 1;
401
402
if (SUPERIO_PORT(port) || port & 3)
403
BUG();
404
405
__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
406
}
407
408
void insl(unsigned int port, void *from, int len)
409
{
410
u32 off = port << 1;
411
412
if (SUPERIO_PORT(port) || port & 3)
413
BUG();
414
415
__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
416
}
417
418
EXPORT_SYMBOL(outsl);
419
EXPORT_SYMBOL(insl);
420
421