OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [arm/] [mach-ebsa110/] [io.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 
27
#include <asm/io.h>
28
#include <asm/page.h>
29
 
30
static u32 __isamem_convert_addr(void *addr)
31
{
32
        u32 ret, a = (u32) addr;
33
 
34
        /*
35
         * The PCMCIA controller is wired up as follows:
36
         *        +---------+---------+---------+---------+---------+---------+
37
         * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1     |         |         |
38
         *        | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
39
         *        +---------+---------+---------+---------+---------+---------+
40
         *  CPU   | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1   |         |         |
41
         *        | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
42
         *        +---------+---------+---------+---------+---------+---------+
43
         *
44
         * This means that we can access PCMCIA regions as follows:
45
         *      0x*10000 -> 0x*1ffff
46
         *      0x*70000 -> 0x*7ffff
47
         *      0x*90000 -> 0x*9ffff
48
         *      0x*f0000 -> 0x*fffff
49
         */
50
        ret  = (a & 0xf803fe) << 1;
51
        ret |= (a & 0x03fc00) << 2;
52
 
53
        ret += 0xe8000000;
54
 
55
        if ((a & 0x20000) == (a & 0x40000) >> 1)
56
                return ret;
57
 
58
        BUG();
59
        return 0;
60
}
61
 
62
/*
63
 * read[bwl] and write[bwl]
64
 */
65
u8 __readb(void *addr)
66
{
67
        u32 ret, a = __isamem_convert_addr(addr);
68
 
69
        if ((int)addr & 1)
70
                ret = __arch_getl(a);
71
        else
72
                ret = __arch_getb(a);
73
        return ret;
74
}
75
 
76
u16 __readw(void *addr)
77
{
78
        u32 a = __isamem_convert_addr(addr);
79
 
80
        if ((int)addr & 1)
81
                BUG();
82
 
83
        return __arch_getw(a);
84
}
85
 
86
u32 __readl(void *addr)
87
{
88
        u32 ret, a = __isamem_convert_addr(addr);
89
 
90
        if ((int)addr & 3)
91
                BUG();
92
 
93
        ret = __arch_getw(a);
94
        ret |= __arch_getw(a + 4) << 16;
95
        return ret;
96
}
97
 
98
EXPORT_SYMBOL(__readb);
99
EXPORT_SYMBOL(__readw);
100
EXPORT_SYMBOL(__readl);
101
 
102
void __writeb(u8 val, void *addr)
103
{
104
        u32 a = __isamem_convert_addr(addr);
105
 
106
        if ((int)addr & 1)
107
                __arch_putl(val, a);
108
        else
109
                __arch_putb(val, a);
110
}
111
 
112
void __writew(u16 val, void *addr)
113
{
114
        u32 a = __isamem_convert_addr(addr);
115
 
116
        if ((int)addr & 1)
117
                BUG();
118
 
119
        __arch_putw(val, a);
120
}
121
 
122
void __writel(u32 val, void *addr)
123
{
124
        u32 a = __isamem_convert_addr(addr);
125
 
126
        if ((int)addr & 3)
127
                BUG();
128
 
129
        __arch_putw(val, a);
130
        __arch_putw(val >> 16, a + 4);
131
}
132
 
133
EXPORT_SYMBOL(__writeb);
134
EXPORT_SYMBOL(__writew);
135
EXPORT_SYMBOL(__writel);
136
 
137
#define SUPERIO_PORT(p) \
138
        (((p) >> 3) == (0x3f8 >> 3) || \
139
         ((p) >> 3) == (0x2f8 >> 3) || \
140
         ((p) >> 3) == (0x378 >> 3))
141
 
142
/*
143
 * We're addressing an 8 or 16-bit peripheral which tranfers
144
 * odd addresses on the low ISA byte lane.
145
 */
146
u8 __inb8(unsigned int port)
147
{
148
        u32 ret;
149
 
150
        /*
151
         * The SuperIO registers use sane addressing techniques...
152
         */
153
        if (SUPERIO_PORT(port))
154
                ret = __arch_getb(ISAIO_BASE + (port << 2));
155
        else {
156
                u32 a = ISAIO_BASE + ((port & ~1) << 1);
157
 
158
                /*
159
                 * Shame nothing else does
160
                 */
161
                if (port & 1)
162
                        ret = __arch_getl(a);
163
                else
164
                        ret = __arch_getb(a);
165
        }
166
        return ret;
167
}
168
 
169
/*
170
 * We're addressing a 16-bit peripheral which transfers odd
171
 * addresses on the high ISA byte lane.
172
 */
173
u8 __inb16(unsigned int port)
174
{
175
        u32 ret;
176
 
177
        /*
178
         * The SuperIO registers use sane addressing techniques...
179
         */
180
        if (SUPERIO_PORT(port))
181
                ret = __arch_getb(ISAIO_BASE + (port << 2));
182
        else {
183
                u32 a = ISAIO_BASE + ((port & ~1) << 1);
184
 
185
                /*
186
                 * Shame nothing else does
187
                 */
188
                ret = __arch_getb(a + (port & 1));
189
        }
190
        return ret;
191
}
192
 
193
u16 __inw(unsigned int port)
194
{
195
        u32 ret;
196
 
197
        /*
198
         * The SuperIO registers use sane addressing techniques...
199
         */
200
        if (SUPERIO_PORT(port) || port & 1)
201
                ret = __arch_getw(ISAIO_BASE + (port << 2));
202
        else {
203
                u32 a = ISAIO_BASE + (port << 1);
204
 
205
                /*
206
                 * Shame nothing else does
207
                 */
208
                if (port & 1)
209
                        BUG();
210
 
211
                ret = __arch_getw(a);
212
        }
213
        return ret;
214
}
215
 
216
/*
217
 * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
218
 */
219
u32 __inl(unsigned int port)
220
{
221
        u32 a;
222
 
223
        if (SUPERIO_PORT(port) || port & 3)
224
                BUG();
225
 
226
        a = ISAIO_BASE + (port << 1);
227
 
228
        return __arch_getw(a) | __arch_getw(a + 4) << 16;
229
}
230
 
231
EXPORT_SYMBOL(__inb8);
232
EXPORT_SYMBOL(__inb16);
233
EXPORT_SYMBOL(__inw);
234
EXPORT_SYMBOL(__inl);
235
 
236
void __outb8(u8 val, unsigned int port)
237
{
238
        /*
239
         * The SuperIO registers use sane addressing techniques...
240
         */
241
        if (SUPERIO_PORT(port))
242
                __arch_putb(val, ISAIO_BASE + (port << 2));
243
        else {
244
                u32 a = ISAIO_BASE + ((port & ~1) << 1);
245
 
246
                /*
247
                 * Shame nothing else does
248
                 */
249
                if (port & 1)
250
                        __arch_putl(val, a);
251
                else
252
                        __arch_putb(val, a);
253
        }
254
}
255
 
256
void __outb16(u8 val, unsigned int port)
257
{
258
        /*
259
         * The SuperIO registers use sane addressing techniques...
260
         */
261
        if (SUPERIO_PORT(port))
262
                __arch_putb(val, ISAIO_BASE + (port << 2));
263
        else {
264
                u32 a = ISAIO_BASE + ((port & ~1) << 1);
265
 
266
                /*
267
                 * Shame nothing else does
268
                 */
269
                __arch_putb(val, a + (port & 1));
270
        }
271
}
272
 
273
void __outw(u16 val, unsigned int port)
274
{
275
        u32 off;
276
 
277
        /*
278
         * The SuperIO registers use sane addressing techniques...
279
         */
280
        if (SUPERIO_PORT(port))
281
                off = port << 2;
282
        else {
283
                off = port << 1;
284
                if (port & 1)
285
                        BUG();
286
 
287
        }
288
        __arch_putw(val, ISAIO_BASE + off);
289
}
290
 
291
void __outl(u32 val, unsigned int port)
292
{
293
        BUG();
294
}
295
 
296
EXPORT_SYMBOL(__outb8);
297
EXPORT_SYMBOL(__outb16);
298
EXPORT_SYMBOL(__outw);
299
EXPORT_SYMBOL(__outl);
300
 
301
extern void __arch_writesb(unsigned long virt, const void *from, int len);
302
extern void __arch_writesw(unsigned long virt, const void *from, int len);
303
extern void __arch_writesl(unsigned long virt, const void *from, int len);
304
extern void __arch_readsb(unsigned long virt, void *from, int len);
305
extern void __arch_readsw(unsigned long virt, void *from, int len);
306
extern void __arch_readsl(unsigned long virt, void *from, int len);
307
 
308
void outsb(unsigned int port, const void *from, int len)
309
{
310
        u32 off;
311
 
312
        if (SUPERIO_PORT(port))
313
                off = port << 2;
314
        else {
315
                off = (port & ~1) << 1;
316
                if (port & 1)
317
                        BUG();
318
        }
319
 
320
        __raw_writesb(ISAIO_BASE + off, from, len);
321
}
322
 
323
void insb(unsigned int port, void *from, int len)
324
{
325
        u32 off;
326
 
327
        if (SUPERIO_PORT(port))
328
                off = port << 2;
329
        else {
330
                off = (port & ~1) << 1;
331
                if (port & 1)
332
                        BUG();
333
        }
334
 
335
        __raw_readsb(ISAIO_BASE + off, from, len);
336
}
337
 
338
EXPORT_SYMBOL(outsb);
339
EXPORT_SYMBOL(insb);
340
 
341
void outsw(unsigned int port, const void *from, int len)
342
{
343
        u32 off;
344
 
345
        if (SUPERIO_PORT(port))
346
                off = port << 2;
347
        else {
348
                off = (port & ~1) << 1;
349
                if (port & 1)
350
                        BUG();
351
        }
352
 
353
        __raw_writesw(ISAIO_BASE + off, from, len);
354
}
355
 
356
void insw(unsigned int port, void *from, int len)
357
{
358
        u32 off;
359
 
360
        if (SUPERIO_PORT(port))
361
                off = port << 2;
362
        else {
363
                off = (port & ~1) << 1;
364
                if (port & 1)
365
                        BUG();
366
        }
367
 
368
        __raw_readsw(ISAIO_BASE + off, from, len);
369
}
370
 
371
EXPORT_SYMBOL(outsw);
372
EXPORT_SYMBOL(insw);
373
 
374
/*
375
 * We implement these as 16-bit insw/outsw, mainly for
376
 * 3c589 cards.
377
 */
378
void outsl(unsigned int port, const void *from, int len)
379
{
380
        u32 off = port << 1;
381
 
382
        if (SUPERIO_PORT(port) || port & 3)
383
                BUG();
384
 
385
        __raw_writesw(ISAIO_BASE + off, from, len << 1);
386
}
387
 
388
void insl(unsigned int port, void *from, int len)
389
{
390
        u32 off = port << 1;
391
 
392
        if (SUPERIO_PORT(port) || port & 3)
393
                BUG();
394
 
395
        __raw_readsw(ISAIO_BASE + off, from, len << 1);
396
}
397
 
398
EXPORT_SYMBOL(outsl);
399
EXPORT_SYMBOL(insl);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.