diff options
Diffstat (limited to 'arch/sh/boards/se/7343/io.c')
-rw-r--r-- | arch/sh/boards/se/7343/io.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/arch/sh/boards/se/7343/io.c b/arch/sh/boards/se/7343/io.c new file mode 100644 index 000000000000..646661a146ad --- /dev/null +++ b/arch/sh/boards/se/7343/io.c | |||
@@ -0,0 +1,275 @@ | |||
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 | } | ||