sh: Board updates for I/O routine rework.
[linux-2.6.git] / arch / sh / boards / se / 770x / io.c
1 /* $Id: io.c,v 1.6 2006/01/04 17:53:54 lethal Exp $
2  *
3  * linux/arch/sh/kernel/io_se.c
4  *
5  * Copyright (C) 2000  Kazumoto Kojima
6  *
7  * I/O routine for Hitachi SolutionEngine.
8  *
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <asm/io.h>
14 #include <asm/se.h>
15
16 /* SH pcmcia io window base, start and end.  */
17 int sh_pcic_io_wbase = 0xb8400000;
18 int sh_pcic_io_start;
19 int sh_pcic_io_stop;
20 int sh_pcic_io_type;
21 int sh_pcic_io_dummy;
22
23 static inline void delay(void)
24 {
25         ctrl_inw(0xa0000000);
26 }
27
28 /* MS7750 requires special versions of in*, out* routines, since
29    PC-like io ports are located at upper half byte of 16-bit word which
30    can be accessed only with 16-bit wide.  */
31
32 static inline volatile __u16 *
33 port2adr(unsigned int port)
34 {
35         if (port >= 0x2000)
36                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
37         else if (port >= 0x1000)
38                 return (volatile __u16 *) (PA_83902 + (port << 1));
39         else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
40                 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
41         else
42                 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
43 }
44
45 static inline int
46 shifted_port(unsigned long port)
47 {
48         /* For IDE registers, value is not shifted */
49         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
50                 return 0;
51         else
52                 return 1;
53 }
54
55 unsigned char se_inb(unsigned long port)
56 {
57         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
58                 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
59         else if (shifted_port(port))
60                 return (*port2adr(port) >> 8); 
61         else
62                 return (*port2adr(port))&0xff; 
63 }
64
65 unsigned char se_inb_p(unsigned long port)
66 {
67         unsigned long v;
68
69         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
70                 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
71         else if (shifted_port(port))
72                 v = (*port2adr(port) >> 8); 
73         else
74                 v = (*port2adr(port))&0xff; 
75         delay();
76         return v;
77 }
78
79 unsigned short se_inw(unsigned long port)
80 {
81         if (port >= 0x2000 ||
82             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
83                 return *port2adr(port);
84         else
85                 maybebadio(port);
86         return 0;
87 }
88
89 unsigned int se_inl(unsigned long port)
90 {
91         maybebadio(port);
92         return 0;
93 }
94
95 void se_outb(unsigned char value, unsigned long port)
96 {
97         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
98                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
99         else if (shifted_port(port))
100                 *(port2adr(port)) = value << 8;
101         else
102                 *(port2adr(port)) = value;
103 }
104
105 void se_outb_p(unsigned char value, unsigned long port)
106 {
107         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
108                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
109         else if (shifted_port(port))
110                 *(port2adr(port)) = value << 8;
111         else
112                 *(port2adr(port)) = value;
113         delay();
114 }
115
116 void se_outw(unsigned short value, unsigned long port)
117 {
118         if (port >= 0x2000 ||
119             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
120                 *port2adr(port) = value;
121         else
122                 maybebadio(port);
123 }
124
125 void se_outl(unsigned int value, unsigned long port)
126 {
127         maybebadio(port);
128 }
129
130 void se_insb(unsigned long port, void *addr, unsigned long count)
131 {
132         volatile __u16 *p = port2adr(port);
133         __u8 *ap = addr;
134
135         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
136                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
137                 while (count--)
138                         *ap++ = *bp;
139         } else if (shifted_port(port)) {
140                 while (count--)
141                         *ap++ = *p >> 8;
142         } else {
143                 while (count--)
144                         *ap++ = *p;
145         }
146 }
147
148 void se_insw(unsigned long port, void *addr, unsigned long count)
149 {
150         volatile __u16 *p = port2adr(port);
151         __u16 *ap = addr;
152         while (count--)
153                 *ap++ = *p;
154 }
155
156 void se_insl(unsigned long port, void *addr, unsigned long count)
157 {
158         maybebadio(port);
159 }
160
161 void se_outsb(unsigned long port, const void *addr, unsigned long count)
162 {
163         volatile __u16 *p = port2adr(port);
164         const __u8 *ap = addr;
165
166         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
167                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
168                 while (count--)
169                         *bp = *ap++;
170         } else if (shifted_port(port)) {
171                 while (count--)
172                         *p = *ap++ << 8;
173         } else {
174                 while (count--)
175                         *p = *ap++;
176         }
177 }
178
179 void se_outsw(unsigned long port, const void *addr, unsigned long count)
180 {
181         volatile __u16 *p = port2adr(port);
182         const __u16 *ap = addr;
183         while (count--)
184                 *p = *ap++;
185 }
186
187 void se_outsl(unsigned long port, const void *addr, unsigned long count)
188 {
189         maybebadio(port);
190 }