blob: ac1c396d477de375a271efeaf810c71945d2cc6f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Hirokazu Takata3264f972007-08-01 21:09:31 +09002 * linux/arch/m32r/platforms/mappi/io.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Typical I/O routines for Mappi board.
5 *
Hirokazu Takata23680862005-06-21 17:16:10 -07006 * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <asm/m32r.h>
11#include <asm/page.h>
12#include <asm/io.h>
13#include <asm/byteorder.h>
14
15#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
16#include <linux/types.h>
17
18#define M32R_PCC_IOMAP_SIZE 0x1000
19
20#define M32R_PCC_IOSTART0 0x1000
21#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
22#define M32R_PCC_IOSTART1 0x2000
23#define M32R_PCC_IOEND1 (M32R_PCC_IOSTART1 + M32R_PCC_IOMAP_SIZE - 1)
24
25extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int);
26extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
27#endif /* CONFIG_PCMCIA && CONFIG_M32R_PCC */
28
29#define PORT2ADDR(port) _port2addr(port)
30
31static inline void *_port2addr(unsigned long port)
32{
Hirokazu Takata46ea1782006-01-06 00:18:43 -080033 return (void *)(port | NONCACHE_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -070034}
35
36static inline void *_port2addr_ne(unsigned long port)
37{
38 return (void *)((port<<1) + NONCACHE_OFFSET + 0x0C000000);
39}
40
41static inline void delay(void)
42{
43 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
44}
45
46/*
47 * NIC I/O function
48 */
49
50#define PORT2ADDR_NE(port) _port2addr_ne(port)
51
52static inline unsigned char _ne_inb(void *portp)
53{
54 return (unsigned char) *(volatile unsigned short *)portp;
55}
56
57static inline unsigned short _ne_inw(void *portp)
58{
59 unsigned short tmp;
60
61 tmp = *(volatile unsigned short *)portp;
62 return le16_to_cpu(tmp);
63}
64
65static inline void _ne_outb(unsigned char b, void *portp)
66{
67 *(volatile unsigned short *)portp = (unsigned short)b;
68}
69
70static inline void _ne_outw(unsigned short w, void *portp)
71{
72 *(volatile unsigned short *)portp = cpu_to_le16(w);
73}
74
75unsigned char _inb(unsigned long port)
76{
77 if (port >= 0x300 && port < 0x320)
78 return _ne_inb(PORT2ADDR_NE(port));
79 else
80#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
81 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
82 unsigned char b;
83 pcc_ioread(0, port, &b, sizeof(b), 1, 0);
84 return b;
85 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
86 unsigned char b;
87 pcc_ioread(1, port, &b, sizeof(b), 1, 0);
88 return b;
89 } else
90#endif
91
92 return *(volatile unsigned char *)PORT2ADDR(port);
93}
94
95unsigned short _inw(unsigned long port)
96{
97 if (port >= 0x300 && port < 0x320)
98 return _ne_inw(PORT2ADDR_NE(port));
99 else
100#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
101 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
102 unsigned short w;
103 pcc_ioread(0, port, &w, sizeof(w), 1, 0);
104 return w;
105 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
106 unsigned short w;
107 pcc_ioread(1, port, &w, sizeof(w), 1, 0);
108 return w;
109 } else
110#endif
111 return *(volatile unsigned short *)PORT2ADDR(port);
112}
113
114unsigned long _inl(unsigned long port)
115{
116#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
117 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
118 unsigned long l;
119 pcc_ioread(0, port, &l, sizeof(l), 1, 0);
120 return l;
121 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
122 unsigned short l;
123 pcc_ioread(1, port, &l, sizeof(l), 1, 0);
124 return l;
125 } else
126#endif
127 return *(volatile unsigned long *)PORT2ADDR(port);
128}
129
130unsigned char _inb_p(unsigned long port)
131{
Hirokazu Takata23680862005-06-21 17:16:10 -0700132 unsigned char v = _inb(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 delay();
134 return (v);
135}
136
137unsigned short _inw_p(unsigned long port)
138{
Hirokazu Takata23680862005-06-21 17:16:10 -0700139 unsigned short v = _inw(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 delay();
141 return (v);
142}
143
144unsigned long _inl_p(unsigned long port)
145{
Hirokazu Takata23680862005-06-21 17:16:10 -0700146 unsigned long v = _inl(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 delay();
148 return (v);
149}
150
151void _outb(unsigned char b, unsigned long port)
152{
153 if (port >= 0x300 && port < 0x320)
154 _ne_outb(b, PORT2ADDR_NE(port));
155 else
156#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
157 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
158 pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
159 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
160 pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
161 } else
162#endif
163 *(volatile unsigned char *)PORT2ADDR(port) = b;
164}
165
166void _outw(unsigned short w, unsigned long port)
167{
168 if (port >= 0x300 && port < 0x320)
169 _ne_outw(w, PORT2ADDR_NE(port));
170 else
171#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
172 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
173 pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
174 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
175 pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
176 } else
177#endif
178 *(volatile unsigned short *)PORT2ADDR(port) = w;
179}
180
181void _outl(unsigned long l, unsigned long port)
182{
183#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
184 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
185 pcc_iowrite(0, port, &l, sizeof(l), 1, 0);
186 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
187 pcc_iowrite(1, port, &l, sizeof(l), 1, 0);
188 } else
189#endif
190 *(volatile unsigned long *)PORT2ADDR(port) = l;
191}
192
193void _outb_p(unsigned char b, unsigned long port)
194{
Hirokazu Takata23680862005-06-21 17:16:10 -0700195 _outb(b, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 delay();
197}
198
199void _outw_p(unsigned short w, unsigned long port)
200{
Hirokazu Takata23680862005-06-21 17:16:10 -0700201 _outw(w, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 delay();
203}
204
205void _outl_p(unsigned long l, unsigned long port)
206{
Hirokazu Takata23680862005-06-21 17:16:10 -0700207 _outl(l, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 delay();
209}
210
211void _insb(unsigned int port, void *addr, unsigned long count)
212{
213 unsigned short *buf = addr;
214 unsigned short *portp;
215
216 if (port >= 0x300 && port < 0x320){
217 portp = PORT2ADDR_NE(port);
218 while (count--)
219 *buf++ = *(volatile unsigned char *)portp;
220#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
221 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
222 pcc_ioread(0, port, (void *)addr, sizeof(unsigned char),
223 count, 1);
224 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
225 pcc_ioread(1, port, (void *)addr, sizeof(unsigned char),
226 count, 1);
227#endif
228 } else {
229 portp = PORT2ADDR(port);
230 while (count--)
231 *buf++ = *(volatile unsigned char *)portp;
232 }
233}
234
235void _insw(unsigned int port, void *addr, unsigned long count)
236{
237 unsigned short *buf = addr;
238 unsigned short *portp;
239
240 if (port >= 0x300 && port < 0x320) {
241 portp = PORT2ADDR_NE(port);
242 while (count--)
243 *buf++ = _ne_inw(portp);
244#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
245 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
246 pcc_ioread(0, port, (void *)addr, sizeof(unsigned short),
247 count, 1);
248 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
249 pcc_ioread(1, port, (void *)addr, sizeof(unsigned short),
250 count, 1);
251#endif
252 } else {
253 portp = PORT2ADDR(port);
254 while (count--)
255 *buf++ = *(volatile unsigned short *)portp;
256 }
257}
258
259void _insl(unsigned int port, void *addr, unsigned long count)
260{
261 unsigned long *buf = addr;
262 unsigned long *portp;
263
264 portp = PORT2ADDR(port);
265 while (count--)
266 *buf++ = *(volatile unsigned long *)portp;
267}
268
269void _outsb(unsigned int port, const void *addr, unsigned long count)
270{
271 const unsigned char *buf = addr;
272 unsigned char *portp;
273
274 if (port >= 0x300 && port < 0x320) {
275 portp = PORT2ADDR_NE(port);
276 while (count--)
277 _ne_outb(*buf++, portp);
278#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
279 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
280 pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char),
281 count, 1);
282 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
283 pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char),
284 count, 1);
285#endif
286 } else {
287 portp = PORT2ADDR(port);
288 while (count--)
289 *(volatile unsigned char *)portp = *buf++;
290 }
291}
292
293void _outsw(unsigned int port, const void *addr, unsigned long count)
294{
295 const unsigned short *buf = addr;
296 unsigned short *portp;
297
298 if (port >= 0x300 && port < 0x320) {
299 portp = PORT2ADDR_NE(port);
300 while (count--)
301 _ne_outw(*buf++, portp);
302#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
303 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
304 pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short),
305 count, 1);
306 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
307 pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short),
308 count, 1);
309#endif
310 } else {
311 portp = PORT2ADDR(port);
312 while (count--)
313 *(volatile unsigned short *)portp = *buf++;
314 }
315}
316
317void _outsl(unsigned int port, const void *addr, unsigned long count)
318{
319 const unsigned long *buf = addr;
320 unsigned char *portp;
321
322 portp = PORT2ADDR(port);
323 while (count--)
324 *(volatile unsigned long *)portp = *buf++;
325}