Pull battery into release branch
[linux-2.6] / arch / sh / boards / se / 770x / io.c
1 /* $Id: io.c,v 1.7 2006/02/05 21:55:29 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 /* MS7750 requires special versions of in*, out* routines, since
24    PC-like io ports are located at upper half byte of 16-bit word which
25    can be accessed only with 16-bit wide.  */
26
27 static inline volatile __u16 *
28 port2adr(unsigned int port)
29 {
30         if (port & 0xff000000)
31                 return ( volatile __u16 *) port;
32         if (port >= 0x2000)
33                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
34         else if (port >= 0x1000)
35                 return (volatile __u16 *) (PA_83902 + (port << 1));
36         else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
37                 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
38         else
39                 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
40 }
41
42 static inline int
43 shifted_port(unsigned long port)
44 {
45         /* For IDE registers, value is not shifted */
46         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
47                 return 0;
48         else
49                 return 1;
50 }
51
52 unsigned char se_inb(unsigned long port)
53 {
54         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
55                 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
56         else if (shifted_port(port))
57                 return (*port2adr(port) >> 8); 
58         else
59                 return (*port2adr(port))&0xff; 
60 }
61
62 unsigned char se_inb_p(unsigned long port)
63 {
64         unsigned long v;
65
66         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
67                 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
68         else if (shifted_port(port))
69                 v = (*port2adr(port) >> 8); 
70         else
71                 v = (*port2adr(port))&0xff; 
72         ctrl_delay();
73         return v;
74 }
75
76 unsigned short se_inw(unsigned long port)
77 {
78         if (port >= 0x2000 ||
79             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
80                 return *port2adr(port);
81         else
82                 maybebadio(port);
83         return 0;
84 }
85
86 unsigned int se_inl(unsigned long port)
87 {
88         maybebadio(port);
89         return 0;
90 }
91
92 void se_outb(unsigned char value, unsigned long port)
93 {
94         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
95                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
96         else if (shifted_port(port))
97                 *(port2adr(port)) = value << 8;
98         else
99                 *(port2adr(port)) = value;
100 }
101
102 void se_outb_p(unsigned char value, unsigned long port)
103 {
104         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
105                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
106         else if (shifted_port(port))
107                 *(port2adr(port)) = value << 8;
108         else
109                 *(port2adr(port)) = value;
110         ctrl_delay();
111 }
112
113 void se_outw(unsigned short value, unsigned long port)
114 {
115         if (port >= 0x2000 ||
116             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
117                 *port2adr(port) = value;
118         else
119                 maybebadio(port);
120 }
121
122 void se_outl(unsigned int value, unsigned long port)
123 {
124         maybebadio(port);
125 }
126
127 void se_insb(unsigned long port, void *addr, unsigned long count)
128 {
129         volatile __u16 *p = port2adr(port);
130         __u8 *ap = addr;
131
132         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
133                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
134                 while (count--)
135                         *ap++ = *bp;
136         } else if (shifted_port(port)) {
137                 while (count--)
138                         *ap++ = *p >> 8;
139         } else {
140                 while (count--)
141                         *ap++ = *p;
142         }
143 }
144
145 void se_insw(unsigned long port, void *addr, unsigned long count)
146 {
147         volatile __u16 *p = port2adr(port);
148         __u16 *ap = addr;
149         while (count--)
150                 *ap++ = *p;
151 }
152
153 void se_insl(unsigned long port, void *addr, unsigned long count)
154 {
155         maybebadio(port);
156 }
157
158 void se_outsb(unsigned long port, const void *addr, unsigned long count)
159 {
160         volatile __u16 *p = port2adr(port);
161         const __u8 *ap = addr;
162
163         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
164                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
165                 while (count--)
166                         *bp = *ap++;
167         } else if (shifted_port(port)) {
168                 while (count--)
169                         *p = *ap++ << 8;
170         } else {
171                 while (count--)
172                         *p = *ap++;
173         }
174 }
175
176 void se_outsw(unsigned long port, const void *addr, unsigned long count)
177 {
178         volatile __u16 *p = port2adr(port);
179         const __u16 *ap = addr;
180         while (count--)
181                 *p = *ap++;
182 }
183
184 void se_outsl(unsigned long port, const void *addr, unsigned long count)
185 {
186         maybebadio(port);
187 }