blob: da6c5f5c1f82b5fe2aa2c4f1a63664609d685e89 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Hirokazu Takata23680862005-06-21 17:16:10 -07002 * linux/arch/m32r/kernel/io_opsput.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Typical I/O routines for OPSPUT board.
5 *
Hirokazu Takata23680862005-06-21 17:16:10 -07006 * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Takeo Takahashi
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <asm/m32r.h>
15#include <asm/page.h>
16#include <asm/io.h>
17#include <asm/byteorder.h>
18
19#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
20#include <linux/types.h>
21
22#define M32R_PCC_IOMAP_SIZE 0x1000
23
24#define M32R_PCC_IOSTART0 0x1000
25#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
26
27extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
28extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
29extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
30extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
31#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
32
33#define PORT2ADDR(port) _port2addr(port)
34#define PORT2ADDR_USB(port) _port2addr_usb(port)
35
36static inline void *_port2addr(unsigned long port)
37{
Hirokazu Takata46ea1782006-01-06 00:18:43 -080038 return (void *)(port | NONCACHE_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039}
40
41/*
42 * OPSPUT-LAN is located in the extended bus space
43 * from 0x10000000 to 0x13ffffff on physical address.
44 * The base address of LAN controller(LAN91C111) is 0x300.
45 */
Hirokazu Takata46ea1782006-01-06 00:18:43 -080046#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
47#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048static inline void *_port2addr_ne(unsigned long port)
49{
Hirokazu Takataf3ac9fb2005-10-30 15:00:06 -080050 return (void *)(port + 0x10000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051}
52static inline void *_port2addr_usb(unsigned long port)
53{
54 return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
55}
56
57static inline void delay(void)
58{
59 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
60}
61
62/*
63 * NIC I/O function
64 */
65
66#define PORT2ADDR_NE(port) _port2addr_ne(port)
67
68static inline unsigned char _ne_inb(void *portp)
69{
70 return *(volatile unsigned char *)portp;
71}
72
73static inline unsigned short _ne_inw(void *portp)
74{
75 return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
76}
77
78static inline void _ne_insb(void *portp, void *addr, unsigned long count)
79{
80 unsigned char *buf = (unsigned char *)addr;
81
82 while (count--)
83 *buf++ = _ne_inb(portp);
84}
85
86static inline void _ne_outb(unsigned char b, void *portp)
87{
88 *(volatile unsigned char *)portp = b;
89}
90
91static inline void _ne_outw(unsigned short w, void *portp)
92{
93 *(volatile unsigned short *)portp = cpu_to_le16(w);
94}
95
96unsigned char _inb(unsigned long port)
97{
98 if (port >= LAN_IOSTART && port < LAN_IOEND)
99 return _ne_inb(PORT2ADDR_NE(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
101 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
102 unsigned char b;
103 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
104 return b;
105 } else
106#endif
107
108 return *(volatile unsigned char *)PORT2ADDR(port);
109}
110
111unsigned short _inw(unsigned long port)
112{
113 if (port >= LAN_IOSTART && port < LAN_IOEND)
114 return _ne_inw(PORT2ADDR_NE(port));
115#if defined(CONFIG_USB)
116 else if(port >= 0x340 && port < 0x3a0)
117 return *(volatile unsigned short *)PORT2ADDR_USB(port);
118#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
120 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
121 unsigned short w;
122 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
123 return w;
124 } else
125#endif
126 return *(volatile unsigned short *)PORT2ADDR(port);
127}
128
129unsigned long _inl(unsigned long port)
130{
131#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
132 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
133 unsigned long l;
134 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
135 return l;
136 } else
137#endif
138 return *(volatile unsigned long *)PORT2ADDR(port);
139}
140
141unsigned char _inb_p(unsigned long port)
142{
Hirokazu Takata23680862005-06-21 17:16:10 -0700143 unsigned char v = _inb(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 delay();
145 return (v);
146}
147
148unsigned short _inw_p(unsigned long port)
149{
Hirokazu Takata23680862005-06-21 17:16:10 -0700150 unsigned short v = _inw(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 delay();
152 return (v);
153}
154
155unsigned long _inl_p(unsigned long port)
156{
Hirokazu Takata23680862005-06-21 17:16:10 -0700157 unsigned long v = _inl(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 delay();
159 return (v);
160}
161
162void _outb(unsigned char b, unsigned long port)
163{
164 if (port >= LAN_IOSTART && port < LAN_IOEND)
165 _ne_outb(b, PORT2ADDR_NE(port));
166 else
167#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
168 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
169 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
170 } else
171#endif
172 *(volatile unsigned char *)PORT2ADDR(port) = b;
173}
174
175void _outw(unsigned short w, unsigned long port)
176{
177 if (port >= LAN_IOSTART && port < LAN_IOEND)
178 _ne_outw(w, PORT2ADDR_NE(port));
179 else
180#if defined(CONFIG_USB)
181 if(port >= 0x340 && port < 0x3a0)
182 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
183 else
184#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
186 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
187 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
188 } else
189#endif
190 *(volatile unsigned short *)PORT2ADDR(port) = w;
191}
192
193void _outl(unsigned long l, unsigned long port)
194{
195#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
196 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
197 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
198 } else
199#endif
200 *(volatile unsigned long *)PORT2ADDR(port) = l;
201}
202
203void _outb_p(unsigned char b, unsigned long port)
204{
Hirokazu Takata23680862005-06-21 17:16:10 -0700205 _outb(b, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 delay();
207}
208
209void _outw_p(unsigned short w, unsigned long port)
210{
Hirokazu Takata23680862005-06-21 17:16:10 -0700211 _outw(w, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 delay();
213}
214
215void _outl_p(unsigned long l, unsigned long port)
216{
Hirokazu Takata23680862005-06-21 17:16:10 -0700217 _outl(l, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 delay();
219}
220
221void _insb(unsigned int port, void *addr, unsigned long count)
222{
223 if (port >= LAN_IOSTART && port < LAN_IOEND)
224 _ne_insb(PORT2ADDR_NE(port), addr, count);
225#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
226 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
227 pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
228 count, 1);
229 }
230#endif
231 else {
232 unsigned char *buf = addr;
233 unsigned char *portp = PORT2ADDR(port);
234 while (count--)
235 *buf++ = *(volatile unsigned char *)portp;
236 }
237}
238
239void _insw(unsigned int port, void *addr, unsigned long count)
240{
241 unsigned short *buf = addr;
242 unsigned short *portp;
243
244 if (port >= LAN_IOSTART && port < LAN_IOEND) {
245 /*
246 * This portion is only used by smc91111.c to read data
247 * from the DATA_REG. Do not swap the data.
248 */
249 portp = PORT2ADDR_NE(port);
250 while (count--)
251 *buf++ = *(volatile unsigned short *)portp;
252#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
253 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
254 pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
255 count, 1);
256#endif
257 } else {
258 portp = PORT2ADDR(port);
259 while (count--)
260 *buf++ = *(volatile unsigned short *)portp;
261 }
262}
263
264void _insl(unsigned int port, void *addr, unsigned long count)
265{
266 unsigned long *buf = addr;
267 unsigned long *portp;
268
269 portp = PORT2ADDR(port);
270 while (count--)
271 *buf++ = *(volatile unsigned long *)portp;
272}
273
274void _outsb(unsigned int port, const void *addr, unsigned long count)
275{
276 const unsigned char *buf = addr;
277 unsigned char *portp;
278
279 if (port >= LAN_IOSTART && port < LAN_IOEND) {
280 portp = PORT2ADDR_NE(port);
281 while (count--)
282 _ne_outb(*buf++, portp);
283#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
284 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
285 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
286 count, 1);
287#endif
288 } else {
289 portp = PORT2ADDR(port);
290 while (count--)
291 *(volatile unsigned char *)portp = *buf++;
292 }
293}
294
295void _outsw(unsigned int port, const void *addr, unsigned long count)
296{
297 const unsigned short *buf = addr;
298 unsigned short *portp;
299
300 if (port >= LAN_IOSTART && port < LAN_IOEND) {
301 /*
302 * This portion is only used by smc91111.c to write data
303 * into the DATA_REG. Do not swap the data.
304 */
305 portp = PORT2ADDR_NE(port);
306 while (count--)
307 *(volatile unsigned short *)portp = *buf++;
308#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
309 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
310 pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
311 count, 1);
312#endif
313 } else {
314 portp = PORT2ADDR(port);
315 while (count--)
316 *(volatile unsigned short *)portp = *buf++;
317 }
318}
319
320void _outsl(unsigned int port, const void *addr, unsigned long count)
321{
322 const unsigned long *buf = addr;
323 unsigned char *portp;
324
325 portp = PORT2ADDR(port);
326 while (count--)
327 *(volatile unsigned long *)portp = *buf++;
328}