]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - arch/sh/boards/se/7343/io.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[linux-2.6.git] / arch / sh / boards / se / 7343 / io.c
1 /*
2  * arch/sh/boards/se/7343/io.c
3  *
4  * I/O routine for SH-Mobile3AS 7343 SolutionEngine.
5  *
6  */
7
8 #include <linux/config.h>
9 #include <linux/kernel.h>
10 #include <asm/io.h>
11 #include <asm/mach/se7343.h>
12
13 #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
14
15 struct iop {
16         unsigned long start, end;
17         unsigned long base;
18         struct iop *(*check) (struct iop * p, unsigned long port);
19         unsigned char (*inb) (struct iop * p, unsigned long port);
20         unsigned short (*inw) (struct iop * p, unsigned long port);
21         void (*outb) (struct iop * p, unsigned char value, unsigned long port);
22         void (*outw) (struct iop * p, unsigned short value, unsigned long port);
23 };
24
25 struct iop *
26 simple_check(struct iop *p, unsigned long port)
27 {
28         static int count;
29
30         if (count < 100)
31                 count++;
32
33         port &= 0xFFFF;
34
35         if ((p->start <= port) && (port <= p->end))
36                 return p;
37         else
38                 badio(check, port);
39 }
40
41 struct iop *
42 ide_check(struct iop *p, unsigned long port)
43 {
44         if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
45                 return p;
46         return NULL;
47 }
48
49 unsigned char
50 simple_inb(struct iop *p, unsigned long port)
51 {
52         return *(unsigned char *) (p->base + port);
53 }
54
55 unsigned short
56 simple_inw(struct iop *p, unsigned long port)
57 {
58         return *(unsigned short *) (p->base + port);
59 }
60
61 void
62 simple_outb(struct iop *p, unsigned char value, unsigned long port)
63 {
64         *(unsigned char *) (p->base + port) = value;
65 }
66
67 void
68 simple_outw(struct iop *p, unsigned short value, unsigned long port)
69 {
70         *(unsigned short *) (p->base + port) = value;
71 }
72
73 unsigned char
74 pcc_inb(struct iop *p, unsigned long port)
75 {
76         unsigned long addr = p->base + port + 0x40000;
77         unsigned long v;
78
79         if (port & 1)
80                 addr += 0x00400000;
81         v = *(volatile unsigned char *) addr;
82         return v;
83 }
84
85 void
86 pcc_outb(struct iop *p, unsigned char value, unsigned long port)
87 {
88         unsigned long addr = p->base + port + 0x40000;
89
90         if (port & 1)
91                 addr += 0x00400000;
92         *(volatile unsigned char *) addr = value;
93 }
94
95 unsigned char
96 bad_inb(struct iop *p, unsigned long port)
97 {
98         badio(inb, port);
99 }
100
101 void
102 bad_outb(struct iop *p, unsigned char value, unsigned long port)
103 {
104         badio(inw, port);
105 }
106
107 #ifdef CONFIG_SMC91X
108 /* MSTLANEX01 LAN at 0xb400:0000 */
109 static struct iop laniop = {
110         .start = 0x00,
111         .end = 0x0F,
112         .base = 0x04000000,
113         .check = simple_check,
114         .inb = simple_inb,
115         .inw = simple_inw,
116         .outb = simple_outb,
117         .outw = simple_outw,
118 };
119 #endif
120
121 #ifdef CONFIG_NE2000
122 /* NE2000 pc card NIC */
123 static struct iop neiop = {
124         .start = 0x280,
125         .end = 0x29f,
126         .base = 0xb0600000 + 0x80,      /* soft 0x280 -> hard 0x300 */
127         .check = simple_check,
128         .inb = pcc_inb,
129         .inw = simple_inw,
130         .outb = pcc_outb,
131         .outw = simple_outw,
132 };
133 #endif
134
135 #ifdef CONFIG_IDE
136 /* CF in CF slot */
137 static struct iop cfiop = {
138         .base = 0xb0600000,
139         .check = ide_check,
140         .inb = pcc_inb,
141         .inw = simple_inw,
142         .outb = pcc_outb,
143         .outw = simple_outw,
144 };
145 #endif
146
147 static __inline__ struct iop *
148 port2iop(unsigned long port)
149 {
150         if (0) ;
151 #if defined(CONFIG_SMC91X)
152         else if (laniop.check(&laniop, port))
153                 return &laniop;
154 #endif
155 #if defined(CONFIG_NE2000)
156         else if (neiop.check(&neiop, port))
157                 return &neiop;
158 #endif
159 #if defined(CONFIG_IDE)
160         else if (cfiop.check(&cfiop, port))
161                 return &cfiop;
162 #endif
163         else
164                 return NULL;
165 }
166
167 static inline void
168 delay(void)
169 {
170         ctrl_inw(0xac000000);
171         ctrl_inw(0xac000000);
172 }
173
174 unsigned char
175 sh7343se_inb(unsigned long port)
176 {
177         struct iop *p = port2iop(port);
178         return (p->inb) (p, port);
179 }
180
181 unsigned char
182 sh7343se_inb_p(unsigned long port)
183 {
184         unsigned char v = sh7343se_inb(port);
185         delay();
186         return v;
187 }
188
189 unsigned short
190 sh7343se_inw(unsigned long port)
191 {
192         struct iop *p = port2iop(port);
193         return (p->inw) (p, port);
194 }
195
196 unsigned int
197 sh7343se_inl(unsigned long port)
198 {
199         badio(inl, port);
200 }
201
202 void
203 sh7343se_outb(unsigned char value, unsigned long port)
204 {
205         struct iop *p = port2iop(port);
206         (p->outb) (p, value, port);
207 }
208
209 void
210 sh7343se_outb_p(unsigned char value, unsigned long port)
211 {
212         sh7343se_outb(value, port);
213         delay();
214 }
215
216 void
217 sh7343se_outw(unsigned short value, unsigned long port)
218 {
219         struct iop *p = port2iop(port);
220         (p->outw) (p, value, port);
221 }
222
223 void
224 sh7343se_outl(unsigned int value, unsigned long port)
225 {
226         badio(outl, port);
227 }
228
229 void
230 sh7343se_insb(unsigned long port, void *addr, unsigned long count)
231 {
232         unsigned char *a = addr;
233         struct iop *p = port2iop(port);
234         while (count--)
235                 *a++ = (p->inb) (p, port);
236 }
237
238 void
239 sh7343se_insw(unsigned long port, void *addr, unsigned long count)
240 {
241         unsigned short *a = addr;
242         struct iop *p = port2iop(port);
243         while (count--)
244                 *a++ = (p->inw) (p, port);
245 }
246
247 void
248 sh7343se_insl(unsigned long port, void *addr, unsigned long count)
249 {
250         badio(insl, port);
251 }
252
253 void
254 sh7343se_outsb(unsigned long port, const void *addr, unsigned long count)
255 {
256         unsigned char *a = (unsigned char *) addr;
257         struct iop *p = port2iop(port);
258         while (count--)
259                 (p->outb) (p, *a++, port);
260 }
261
262 void
263 sh7343se_outsw(unsigned long port, const void *addr, unsigned long count)
264 {
265         unsigned short *a = (unsigned short *) addr;
266         struct iop *p = port2iop(port);
267         while (count--)
268                 (p->outw) (p, *a++, port);
269 }
270
271 void
272 sh7343se_outsl(unsigned long port, const void *addr, unsigned long count)
273 {
274         badio(outsw, port);
275 }