f73ca3f0f5a1dd77f429e95b76373da2908a5962
[linux-2.6.git] / arch / sh / boards / renesas / r7780rp / io.c
1 /*
2  * linux/arch/sh/kernel/io_r7780rp.c
3  *
4  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
5  * Based largely on io_se.c.
6  *
7  * I/O routine for Renesas Solutions Highlander R7780RP-1
8  *
9  * Initial version only to support LAN access; some
10  * placeholder code from io_r7780rp.c left in with the
11  * expectation of later SuperIO and PCMCIA access.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <asm/r7780rp/r7780rp.h>
17 #include <asm/addrspace.h>
18 #include <asm/io.h>
19
20 #include <linux/module.h>
21 #include <linux/pci.h>
22 #include "../../../drivers/pci/pci-sh7780.h"
23
24 /*
25  * The 7780 R7780RP-1 uses the built-in PCI controller (PCIC)
26  * of the 7780 processor, and has a SuperIO accessible via the PCI.
27  * The board also includes a PCMCIA controller on its memory bus,
28  * like the other Solution Engine boards.
29  */
30
31 #define SH7780_PCIIOBR_MASK     0xFFFC0000      /* IO Space Mask */
32 #define PCIIOBR         (volatile long *)PCI_REG(SH7780_PCIIOBR)
33 #define PCIMBR          (volatile long *)PCI_REG(SH7780_PCIMBR)
34 #define PCI_IO_AREA     SH7780_PCI_IO_BASE
35 #define PCI_MEM_AREA    SH7780_PCI_CONFIG_BASE
36
37 #define PCI_IOMAP(adr)  (PCI_IO_AREA + (adr & ~SH7780_PCIIOBR_MASK))
38
39 static inline void delay(void)
40 {
41         ctrl_inw(0xa0000000);
42 }
43
44 static inline unsigned long port2adr(unsigned int port)
45 {
46         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
47                 if (port == 0x3f6)
48                         return (PA_AREA5_IO + 0x80c);
49                 else
50                         return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
51         else
52                 maybebadio((unsigned long)port);
53
54         return port;
55 }
56
57 static inline unsigned long port88796l(unsigned int port, int flag)
58 {
59         unsigned long addr;
60
61         if (flag)
62                 addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
63         else
64                 addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
65
66         return addr;
67 }
68
69 /* The 7780 R7780RP-1 seems to have everything hooked */
70 /* up pretty normally (nothing on high-bytes only...) so this */
71 /* shouldn't be needed */
72 static inline int shifted_port(unsigned long port)
73 {
74         /* For IDE registers, value is not shifted */
75         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
76                 return 0;
77         else
78                 return 1;
79 }
80
81 /* In case someone configures the kernel w/o PCI support: in that */
82 /* scenario, don't ever bother to check for PCI-window addresses */
83
84 /* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
85 #if defined(CONFIG_PCI)
86 #define CHECK_SH7780_PCIIO(port) \
87   ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7780_PCI_IO_SIZE)))
88 #else
89 #define CHECK_SH7780_PCIIO(port) (0)
90 #endif
91
92 #if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
93 #define CHECK_AX88796L_PORT(port) \
94   ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
95 #else
96 #define CHECK_AX88796L_PORT(port) (0)
97 #endif
98
99 /*
100  * General outline: remap really low stuff [eventually] to SuperIO,
101  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
102  * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
103  * should be way beyond the window, and is used  w/o translation for
104  * compatibility.
105  */
106 u8 r7780rp_inb(unsigned long port)
107 {
108         if (CHECK_AX88796L_PORT(port))
109                 return ctrl_inw(port88796l(port, 0)) & 0xff;
110         else if (PXSEG(port))
111                 return ctrl_inb(port);
112         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
113                 return ctrl_inb(PCI_IOMAP(port));
114
115         return ctrl_inw(port2adr(port)) & 0xff;
116 }
117
118 u8 r7780rp_inb_p(unsigned long port)
119 {
120         u8 v;
121
122         if (CHECK_AX88796L_PORT(port))
123                 v = ctrl_inw(port88796l(port, 0)) & 0xff;
124         else if (PXSEG(port))
125                 v = ctrl_inb(port);
126         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
127                 v = ctrl_inb(PCI_IOMAP(port));
128         else
129                 v = ctrl_inw(port2adr(port)) & 0xff;
130
131         delay();
132
133         return v;
134 }
135
136 u16 r7780rp_inw(unsigned long port)
137 {
138         if (CHECK_AX88796L_PORT(port))
139                 maybebadio(port);
140         else if (PXSEG(port))
141                 return ctrl_inw(port);
142         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
143                 return ctrl_inw(PCI_IOMAP(port));
144         else
145                 maybebadio(port);
146
147         return 0;
148 }
149
150 u32 r7780rp_inl(unsigned long port)
151 {
152         if (CHECK_AX88796L_PORT(port))
153                 maybebadio(port);
154         else if (PXSEG(port))
155                 return ctrl_inl(port);
156         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
157                 return ctrl_inl(PCI_IOMAP(port));
158         else
159                 maybebadio(port);
160
161         return 0;
162 }
163
164 void r7780rp_outb(u8 value, unsigned long port)
165 {
166         if (CHECK_AX88796L_PORT(port))
167                 ctrl_outw(value, port88796l(port, 0));
168         else if (PXSEG(port))
169                 ctrl_outb(value, port);
170         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
171                 ctrl_outb(value, PCI_IOMAP(port));
172         else
173                 ctrl_outw(value, port2adr(port));
174 }
175
176 void r7780rp_outb_p(u8 value, unsigned long port)
177 {
178         if (CHECK_AX88796L_PORT(port))
179                 ctrl_outw(value, port88796l(port, 0));
180         else if (PXSEG(port))
181                 ctrl_outb(value, port);
182         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
183                 ctrl_outb(value, PCI_IOMAP(port));
184         else
185                 ctrl_outw(value, port2adr(port));
186
187         delay();
188 }
189
190 void r7780rp_outw(u16 value, unsigned long port)
191 {
192         if (CHECK_AX88796L_PORT(port))
193                 maybebadio(port);
194         else if (PXSEG(port))
195                 ctrl_outw(value, port);
196         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
197                 ctrl_outw(value, PCI_IOMAP(port));
198         else
199                 maybebadio(port);
200 }
201
202 void r7780rp_outl(u32 value, unsigned long port)
203 {
204         if (CHECK_AX88796L_PORT(port))
205                 maybebadio(port);
206         else if (PXSEG(port))
207                 ctrl_outl(value, port);
208         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
209                 ctrl_outl(value, PCI_IOMAP(port));
210         else
211                 maybebadio(port);
212 }
213
214 void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
215 {
216         volatile u16 *p;
217         u8 *buf = dst;
218
219         if (CHECK_AX88796L_PORT(port)) {
220                 p = (volatile u16 *)port88796l(port, 0);
221                 while (count--)
222                         *buf++ = *p & 0xff;
223         } else if (PXSEG(port)) {
224                 while (count--)
225                         *buf++ = *(volatile u8 *)port;
226         } else if (CHECK_SH7780_PCIIO(port) || shifted_port(port)) {
227                 volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port);
228
229                 while (count--)
230                         *buf++ = *bp;
231         } else {
232                 p = (volatile u16 *)port2adr(port);
233                 while (count--)
234                         *buf++ = *p & 0xff;
235         }
236 }
237
238 void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
239 {
240         volatile u16 *p;
241         u16 *buf = dst;
242
243         if (CHECK_AX88796L_PORT(port))
244                 p = (volatile u16 *)port88796l(port, 1);
245         else if (PXSEG(port))
246                 p = (volatile u16 *)port;
247         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
248                 p = (volatile u16 *)PCI_IOMAP(port);
249         else
250                 p = (volatile u16 *)port2adr(port);
251
252         while (count--)
253                 *buf++ = *p;
254 }
255
256 void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
257 {
258         u32 *buf = dst;
259
260         if (CHECK_AX88796L_PORT(port))
261                 maybebadio(port);
262         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port)) {
263                 volatile u32 *p = (volatile u32 *)PCI_IOMAP(port);
264
265                 while (count--)
266                         *buf++ = *p;
267         } else
268                 maybebadio(port);
269 }
270
271 void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
272 {
273         volatile u16 *p;
274         const u8 *buf = src;
275
276         if (CHECK_AX88796L_PORT(port)) {
277                 p = (volatile u16 *)port88796l(port, 0);
278                 while (count--)
279                         *p = *buf++;
280         } else if (PXSEG(port))
281                 while (count--)
282                         ctrl_outb(*buf++, port);
283         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port)) {
284                 volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port);
285
286                 while (count--)
287                         *bp = *buf++;
288         } else {
289                 p = (volatile u16 *)port2adr(port);
290                 while (count--)
291                         *p = *buf++;
292         }
293 }
294
295 void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
296 {
297         volatile u16 *p;
298         const u16 *buf = src;
299
300         if (CHECK_AX88796L_PORT(port))
301                 p = (volatile u16 *)port88796l(port, 1);
302         else if (PXSEG(port))
303                 p = (volatile u16 *)port;
304         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
305                 p = (volatile u16 *)PCI_IOMAP(port);
306         else
307                 p = (volatile u16 *)port2adr(port);
308
309         while (count--)
310                 *p = *buf++;
311 }
312
313 void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
314 {
315         const u32 *buf = src;
316
317         if (CHECK_AX88796L_PORT(port))
318                 maybebadio(port);
319         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port)) {
320                 volatile u32 *p = (volatile u32 *)PCI_IOMAP(port);
321
322                 while (count--)
323                         *p = *buf++;
324         } else
325                 maybebadio(port);
326 }
327
328 void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
329 {
330         if (CHECK_AX88796L_PORT(port))
331                 return (void __iomem *)port88796l(port, size > 1);
332         else if (PXSEG(port))
333                 return (void __iomem *)port;
334         else if (CHECK_SH7780_PCIIO(port) || shifted_port(port))
335                 return (void __iomem *)PCI_IOMAP(port);
336
337         return (void __iomem *)port2adr(port);
338 }