Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / arch / sh / boards / overdrive / io.c
1 /* 
2  * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3  *
4  * May be copied or modified under the terms of the GNU General Public
5  * License.  See linux/COPYING for more information.                            
6  *
7  * This file contains the I/O routines for use on the overdrive board
8  *
9  */
10
11 #include <linux/types.h>
12 #include <linux/delay.h>
13 #include <asm/processor.h>
14 #include <asm/io.h>
15 #include <asm/addrspace.h>
16
17 #include <asm/overdrive/overdrive.h>
18
19 /*
20  * readX/writeX() are used to access memory mapped devices. On some
21  * architectures the memory mapped IO stuff needs to be accessed
22  * differently. On the SuperH architecture, we just read/write the
23  * memory location directly.
24  */
25
26 #define dprintk(x...)
27
28 /* Translates an IO address to where it is mapped in memory */
29
30 #define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
31
32 unsigned char od_inb(unsigned long port)
33 {
34 dprintk("od_inb(%x)\n", port);
35         return readb(io_addr(port)) & 0xff;
36 }
37
38
39 unsigned short od_inw(unsigned long port)
40 {
41 dprintk("od_inw(%x)\n", port);
42         return readw(io_addr(port)) & 0xffff;
43 }
44
45 unsigned int od_inl(unsigned long port)
46 {
47 dprintk("od_inl(%x)\n", port);
48         return readl(io_addr(port));
49 }
50
51 void od_outb(unsigned char value, unsigned long port)
52 {
53 dprintk("od_outb(%x, %x)\n", value, port);
54         writeb(value, io_addr(port));
55 }
56
57 void od_outw(unsigned short value, unsigned long port)
58 {
59 dprintk("od_outw(%x, %x)\n", value, port);
60         writew(value, io_addr(port));
61 }
62
63 void od_outl(unsigned int value, unsigned long port)
64 {
65 dprintk("od_outl(%x, %x)\n", value, port);
66         writel(value, io_addr(port));
67 }
68
69 /* This is horrible at the moment - needs more work to do something sensible */
70 #define IO_DELAY() udelay(10)
71
72 #define OUT_DELAY(x,type) \
73 void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
74
75 #define IN_DELAY(x,type) \
76 unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
77
78
79 OUT_DELAY(b,char)
80 OUT_DELAY(w,short)
81 OUT_DELAY(l,int)
82
83 IN_DELAY(b,char)
84 IN_DELAY(w,short)
85 IN_DELAY(l,int)
86
87
88 /*  Now for the string version of these functions */
89 void od_outsb(unsigned long port, const void *addr, unsigned long count)
90 {
91         int i;
92         unsigned char *p = (unsigned char *) addr;
93
94         for (i = 0; i < count; i++, p++) {
95                 outb(*p, port);
96         }
97 }
98
99
100 void od_insb(unsigned long port, void *addr, unsigned long count)
101 {
102         int i;
103         unsigned char *p = (unsigned char *) addr;
104
105         for (i = 0; i < count; i++, p++) {
106                 *p = inb(port);
107         }
108 }
109
110 /* For the 16 and 32 bit string functions, we have to worry about alignment.
111  * The SH does not do unaligned accesses, so we have to read as bytes and
112  * then write as a word or dword. 
113  * This can be optimised a lot more, especially in the case where the data
114  * is aligned
115  */
116
117 void od_outsw(unsigned long port, const void *addr, unsigned long count)
118 {
119         int i;
120         unsigned short tmp;
121         unsigned char *p = (unsigned char *) addr;
122
123         for (i = 0; i < count; i++, p += 2) {
124                 tmp = (*p) | ((*(p + 1)) << 8);
125                 outw(tmp, port);
126         }
127 }
128
129
130 void od_insw(unsigned long port, void *addr, unsigned long count)
131 {
132         int i;
133         unsigned short tmp;
134         unsigned char *p = (unsigned char *) addr;
135
136         for (i = 0; i < count; i++, p += 2) {
137                 tmp = inw(port);
138                 p[0] = tmp & 0xff;
139                 p[1] = (tmp >> 8) & 0xff;
140         }
141 }
142
143
144 void od_outsl(unsigned long port, const void *addr, unsigned long count)
145 {
146         int i;
147         unsigned tmp;
148         unsigned char *p = (unsigned char *) addr;
149
150         for (i = 0; i < count; i++, p += 4) {
151                 tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
152                       ((*(p + 3)) << 24);
153                 outl(tmp, port);
154         }
155 }
156
157
158 void od_insl(unsigned long port, void *addr, unsigned long count)
159 {
160         int i;
161         unsigned tmp;
162         unsigned char *p = (unsigned char *) addr;
163
164         for (i = 0; i < count; i++, p += 4) {
165                 tmp = inl(port);
166                 p[0] = tmp & 0xff;
167                 p[1] = (tmp >> 8) & 0xff;
168                 p[2] = (tmp >> 16) & 0xff;
169                 p[3] = (tmp >> 24) & 0xff;
170
171         }
172 }