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