Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[linux-2.6] / arch / m32r / kernel / io_usrv.c
1 /*
2  *  linux/arch/m32r/kernel/io_usrv.c
3  *
4  *  Typical I/O routines for uServer board.
5  *
6  *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
7  *                           Hitoshi Yamamoto, Takeo Takahashi
8  *
9  *  This file is subject to the terms and conditions of the GNU General
10  *  Public License.  See the file "COPYING" in the main directory of this
11  *  archive for more details.
12  *
13  */
14
15 #include <asm/m32r.h>
16 #include <asm/page.h>
17 #include <asm/io.h>
18
19 #include <linux/types.h>
20 #include "../drivers/m32r_cfc.h"
21
22 extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
23 extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
24 extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
25 extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
26 #define CFC_IOSTART     CFC_IOPORT_BASE
27 #define CFC_IOEND       (CFC_IOSTART + (M32R_PCC_MAPSIZE * M32R_MAX_PCC) - 1)
28
29 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
30 #define UART0_REGSTART          0x04c20000
31 #define UART1_REGSTART          0x04c20100
32 #define UART_IOMAP_SIZE         8
33 #define UART0_IOSTART           0x3f8
34 #define UART0_IOEND             (UART0_IOSTART + UART_IOMAP_SIZE - 1)
35 #define UART1_IOSTART           0x2f8
36 #define UART1_IOEND             (UART1_IOSTART + UART_IOMAP_SIZE - 1)
37 #endif  /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
38
39 #define PORT2ADDR(port) _port2addr(port)
40
41 static inline void *_port2addr(unsigned long port)
42 {
43 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
44         if (port >= UART0_IOSTART && port <= UART0_IOEND)
45                 port = ((port - UART0_IOSTART) << 1) + UART0_REGSTART;
46         else if (port >= UART1_IOSTART && port <= UART1_IOEND)
47                 port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART;
48 #endif  /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
49         return (void *)(port | (NONCACHE_OFFSET));
50 }
51
52 static inline void delay(void)
53 {
54         __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
55 }
56
57 unsigned char _inb(unsigned long port)
58 {
59         if (port >= CFC_IOSTART && port <= CFC_IOEND) {
60                 unsigned char b;
61                 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
62                 return b;
63         } else
64                 return *(volatile unsigned char *)PORT2ADDR(port);
65 }
66
67 unsigned short _inw(unsigned long port)
68 {
69         if (port >= CFC_IOSTART && port <= CFC_IOEND) {
70                 unsigned short w;
71                 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
72                 return w;
73         } else
74                 return *(volatile unsigned short *)PORT2ADDR(port);
75 }
76
77 unsigned long _inl(unsigned long port)
78 {
79         if (port >= CFC_IOSTART && port <= CFC_IOEND) {
80                 unsigned long l;
81                 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
82                 return l;
83         } else
84                 return *(volatile unsigned long *)PORT2ADDR(port);
85 }
86
87 unsigned char _inb_p(unsigned long port)
88 {
89         unsigned char v = _inb(port);
90         delay();
91         return v;
92 }
93
94 unsigned short _inw_p(unsigned long port)
95 {
96         unsigned short v = _inw(port);
97         delay();
98         return v;
99 }
100
101 unsigned long _inl_p(unsigned long port)
102 {
103         unsigned long v = _inl(port);
104         delay();
105         return v;
106 }
107
108 void _outb(unsigned char b, unsigned long port)
109 {
110         if (port >= CFC_IOSTART && port <= CFC_IOEND)
111                 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
112         else
113                 *(volatile unsigned char *)PORT2ADDR(port) = b;
114 }
115
116 void _outw(unsigned short w, unsigned long port)
117 {
118         if (port >= CFC_IOSTART && port <= CFC_IOEND)
119                 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
120         else
121                 *(volatile unsigned short *)PORT2ADDR(port) = w;
122 }
123
124 void _outl(unsigned long l, unsigned long port)
125 {
126         if (port >= CFC_IOSTART && port <= CFC_IOEND)
127                 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
128         else
129                 *(volatile unsigned long *)PORT2ADDR(port) = l;
130 }
131
132 void _outb_p(unsigned char b, unsigned long port)
133 {
134         _outb(b, port);
135         delay();
136 }
137
138 void _outw_p(unsigned short w, unsigned long port)
139 {
140         _outw(w, port);
141         delay();
142 }
143
144 void _outl_p(unsigned long l, unsigned long port)
145 {
146         _outl(l, port);
147         delay();
148 }
149
150 void _insb(unsigned int port, void * addr, unsigned long count)
151 {
152         if (port >= CFC_IOSTART && port <= CFC_IOEND)
153                 pcc_ioread_byte(0, port, addr, sizeof(unsigned char), count, 1);
154         else {
155                 unsigned char *buf = addr;
156                 unsigned char *portp = PORT2ADDR(port);
157                 while (count--)
158                         *buf++ = *(volatile unsigned char *)portp;
159         }
160 }
161
162 void _insw(unsigned int port, void * addr, unsigned long count)
163 {
164         unsigned short *buf = addr;
165         unsigned short *portp;
166
167         if (port >= CFC_IOSTART && port <= CFC_IOEND)
168                 pcc_ioread_word(0, port, addr, sizeof(unsigned short), count,
169                         1);
170         else {
171                 portp = PORT2ADDR(port);
172                 while (count--)
173                         *buf++ = *(volatile unsigned short *)portp;
174         }
175 }
176
177 void _insl(unsigned int port, void * addr, unsigned long count)
178 {
179         unsigned long *buf = addr;
180         unsigned long *portp;
181
182         portp = PORT2ADDR(port);
183         while (count--)
184                 *buf++ = *(volatile unsigned long *)portp;
185 }
186
187 void _outsb(unsigned int port, const void * addr, unsigned long count)
188 {
189         const unsigned char *buf = addr;
190         unsigned char *portp;
191
192         if (port >= CFC_IOSTART && port <= CFC_IOEND)
193                 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
194                         count, 1);
195         else {
196                 portp = PORT2ADDR(port);
197                 while (count--)
198                         *(volatile unsigned char *)portp = *buf++;
199         }
200 }
201
202 void _outsw(unsigned int port, const void * addr, unsigned long count)
203 {
204         const unsigned short *buf = addr;
205         unsigned short *portp;
206
207         if (port >= CFC_IOSTART && port <= CFC_IOEND)
208                 pcc_iowrite_word(0, port, (void *)addr, sizeof(unsigned short),
209                         count, 1);
210         else {
211                 portp = PORT2ADDR(port);
212                 while (count--)
213                         *(volatile unsigned short *)portp = *buf++;
214         }
215 }
216
217 void _outsl(unsigned int port, const void * addr, unsigned long count)
218 {
219         const unsigned long *buf = addr;
220         unsigned char *portp;
221
222         portp = PORT2ADDR(port);
223         while (count--)
224                 *(volatile unsigned long *)portp = *buf++;
225 }