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