Merge branch 'master' into upstream
[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 >= 0x2000)
31                 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
32         else if (port >= 0x1000)
33                 return (volatile __u16 *) (PA_83902 + (port << 1));
34         else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
35                 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
36         else
37                 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
38 }
39
40 static inline int
41 shifted_port(unsigned long port)
42 {
43         /* For IDE registers, value is not shifted */
44         if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
45                 return 0;
46         else
47                 return 1;
48 }
49
50 unsigned char se_inb(unsigned long port)
51 {
52         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
53                 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
54         else if (shifted_port(port))
55                 return (*port2adr(port) >> 8); 
56         else
57                 return (*port2adr(port))&0xff; 
58 }
59
60 unsigned char se_inb_p(unsigned long port)
61 {
62         unsigned long v;
63
64         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
65                 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
66         else if (shifted_port(port))
67                 v = (*port2adr(port) >> 8); 
68         else
69                 v = (*port2adr(port))&0xff; 
70         ctrl_delay();
71         return v;
72 }
73
74 unsigned short se_inw(unsigned long port)
75 {
76         if (port >= 0x2000 ||
77             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
78                 return *port2adr(port);
79         else
80                 maybebadio(port);
81         return 0;
82 }
83
84 unsigned int se_inl(unsigned long port)
85 {
86         maybebadio(port);
87         return 0;
88 }
89
90 void se_outb(unsigned char value, unsigned long port)
91 {
92         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
93                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
94         else if (shifted_port(port))
95                 *(port2adr(port)) = value << 8;
96         else
97                 *(port2adr(port)) = value;
98 }
99
100 void se_outb_p(unsigned char value, unsigned long port)
101 {
102         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
103                 *(__u8 *)(sh_pcic_io_wbase + port) = value; 
104         else if (shifted_port(port))
105                 *(port2adr(port)) = value << 8;
106         else
107                 *(port2adr(port)) = value;
108         ctrl_delay();
109 }
110
111 void se_outw(unsigned short value, unsigned long port)
112 {
113         if (port >= 0x2000 ||
114             (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
115                 *port2adr(port) = value;
116         else
117                 maybebadio(port);
118 }
119
120 void se_outl(unsigned int value, unsigned long port)
121 {
122         maybebadio(port);
123 }
124
125 void se_insb(unsigned long port, void *addr, unsigned long count)
126 {
127         volatile __u16 *p = port2adr(port);
128         __u8 *ap = addr;
129
130         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
131                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
132                 while (count--)
133                         *ap++ = *bp;
134         } else if (shifted_port(port)) {
135                 while (count--)
136                         *ap++ = *p >> 8;
137         } else {
138                 while (count--)
139                         *ap++ = *p;
140         }
141 }
142
143 void se_insw(unsigned long port, void *addr, unsigned long count)
144 {
145         volatile __u16 *p = port2adr(port);
146         __u16 *ap = addr;
147         while (count--)
148                 *ap++ = *p;
149 }
150
151 void se_insl(unsigned long port, void *addr, unsigned long count)
152 {
153         maybebadio(port);
154 }
155
156 void se_outsb(unsigned long port, const void *addr, unsigned long count)
157 {
158         volatile __u16 *p = port2adr(port);
159         const __u8 *ap = addr;
160
161         if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
162                 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
163                 while (count--)
164                         *bp = *ap++;
165         } else if (shifted_port(port)) {
166                 while (count--)
167                         *p = *ap++ << 8;
168         } else {
169                 while (count--)
170                         *p = *ap++;
171         }
172 }
173
174 void se_outsw(unsigned long port, const void *addr, unsigned long count)
175 {
176         volatile __u16 *p = port2adr(port);
177         const __u16 *ap = addr;
178         while (count--)
179                 *p = *ap++;
180 }
181
182 void se_outsl(unsigned long port, const void *addr, unsigned long count)
183 {
184         maybebadio(port);
185 }