Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
io.c
Go to the documentation of this file.
1 /*
2  * linux/arch/m32r/platforms/opsput/io.c
3  *
4  * Typical I/O routines for OPSPUT 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 #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 
27 extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
28 extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
29 extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
30 extern 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 
36 static inline void *_port2addr(unsigned long port)
37 {
38  return (void *)(port | NONCACHE_OFFSET);
39 }
40 
41 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
42 static inline void *__port2addr_ata(unsigned long port)
43 {
44  static int dummy_reg;
45 
46  switch (port) {
47  case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
48  case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
49  case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
50  case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
51  case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
52  case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
53  case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
54  case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
55  case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
56  default: return (void *)&dummy_reg;
57  }
58 }
59 #endif
60 
61 /*
62  * OPSPUT-LAN is located in the extended bus space
63  * from 0x10000000 to 0x13ffffff on physical address.
64  * The base address of LAN controller(LAN91C111) is 0x300.
65  */
66 #define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
67 #define LAN_IOEND (0x320 | NONCACHE_OFFSET)
68 static inline void *_port2addr_ne(unsigned long port)
69 {
70  return (void *)(port + 0x10000000);
71 }
72 static inline void *_port2addr_usb(unsigned long port)
73 {
74  return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
75 }
76 
77 static inline void delay(void)
78 {
79  __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
80 }
81 
82 /*
83  * NIC I/O function
84  */
85 
86 #define PORT2ADDR_NE(port) _port2addr_ne(port)
87 
88 static inline unsigned char _ne_inb(void *portp)
89 {
90  return *(volatile unsigned char *)portp;
91 }
92 
93 static inline unsigned short _ne_inw(void *portp)
94 {
95  return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
96 }
97 
98 static inline void _ne_insb(void *portp, void *addr, unsigned long count)
99 {
100  unsigned char *buf = (unsigned char *)addr;
101 
102  while (count--)
103  *buf++ = _ne_inb(portp);
104 }
105 
106 static inline void _ne_outb(unsigned char b, void *portp)
107 {
108  *(volatile unsigned char *)portp = b;
109 }
110 
111 static inline void _ne_outw(unsigned short w, void *portp)
112 {
113  *(volatile unsigned short *)portp = cpu_to_le16(w);
114 }
115 
116 unsigned char _inb(unsigned long port)
117 {
118  if (port >= LAN_IOSTART && port < LAN_IOEND)
119  return _ne_inb(PORT2ADDR_NE(port));
120 
121 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
122  else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
123  return *(volatile unsigned char *)__port2addr_ata(port);
124  }
125 #endif
126 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
127  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
128  unsigned char b;
129  pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
130  return b;
131  } else
132 #endif
133 
134  return *(volatile unsigned char *)PORT2ADDR(port);
135 }
136 
137 unsigned short _inw(unsigned long port)
138 {
139  if (port >= LAN_IOSTART && port < LAN_IOEND)
140  return _ne_inw(PORT2ADDR_NE(port));
141 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
142  else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
143  return *(volatile unsigned short *)__port2addr_ata(port);
144  }
145 #endif
146 #if defined(CONFIG_USB)
147  else if(port >= 0x340 && port < 0x3a0)
148  return *(volatile unsigned short *)PORT2ADDR_USB(port);
149 #endif
150 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
151  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
152  unsigned short w;
153  pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
154  return w;
155  } else
156 #endif
157  return *(volatile unsigned short *)PORT2ADDR(port);
158 }
159 
160 unsigned long _inl(unsigned long port)
161 {
162 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
163  if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
164  unsigned long l;
165  pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
166  return l;
167  } else
168 #endif
169  return *(volatile unsigned long *)PORT2ADDR(port);
170 }
171 
172 unsigned char _inb_p(unsigned long port)
173 {
174  unsigned char v = _inb(port);
175  delay();
176  return (v);
177 }
178 
179 unsigned short _inw_p(unsigned long port)
180 {
181  unsigned short v = _inw(port);
182  delay();
183  return (v);
184 }
185 
186 unsigned long _inl_p(unsigned long port)
187 {
188  unsigned long v = _inl(port);
189  delay();
190  return (v);
191 }
192 
193 void _outb(unsigned char b, unsigned long port)
194 {
195  if (port >= LAN_IOSTART && port < LAN_IOEND)
196  _ne_outb(b, PORT2ADDR_NE(port));
197  else
198 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
199  if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
200  *(volatile unsigned char *)__port2addr_ata(port) = b;
201  } else
202 #endif
203 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
204  if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
205  pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
206  } else
207 #endif
208  *(volatile unsigned char *)PORT2ADDR(port) = b;
209 }
210 
211 void _outw(unsigned short w, unsigned long port)
212 {
213  if (port >= LAN_IOSTART && port < LAN_IOEND)
214  _ne_outw(w, PORT2ADDR_NE(port));
215  else
216 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
217  if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
218  *(volatile unsigned short *)__port2addr_ata(port) = w;
219  } else
220 #endif
221 #if defined(CONFIG_USB)
222  if(port >= 0x340 && port < 0x3a0)
223  *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
224  else
225 #endif
226 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
227  if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
228  pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
229  } else
230 #endif
231  *(volatile unsigned short *)PORT2ADDR(port) = w;
232 }
233 
234 void _outl(unsigned long l, unsigned long port)
235 {
236 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
237  if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
238  pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
239  } else
240 #endif
241  *(volatile unsigned long *)PORT2ADDR(port) = l;
242 }
243 
244 void _outb_p(unsigned char b, unsigned long port)
245 {
246  _outb(b, port);
247  delay();
248 }
249 
250 void _outw_p(unsigned short w, unsigned long port)
251 {
252  _outw(w, port);
253  delay();
254 }
255 
256 void _outl_p(unsigned long l, unsigned long port)
257 {
258  _outl(l, port);
259  delay();
260 }
261 
262 void _insb(unsigned int port, void *addr, unsigned long count)
263 {
264  if (port >= LAN_IOSTART && port < LAN_IOEND)
265  _ne_insb(PORT2ADDR_NE(port), addr, count);
266 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
267  else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
268  unsigned char *buf = addr;
269  unsigned char *portp = __port2addr_ata(port);
270  while (count--)
271  *buf++ = *(volatile unsigned char *)portp;
272  }
273 #endif
274 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
275  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
276  pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
277  count, 1);
278  }
279 #endif
280  else {
281  unsigned char *buf = addr;
282  unsigned char *portp = PORT2ADDR(port);
283  while (count--)
284  *buf++ = *(volatile unsigned char *)portp;
285  }
286 }
287 
288 void _insw(unsigned int port, void *addr, unsigned long count)
289 {
290  unsigned short *buf = addr;
291  unsigned short *portp;
292 
293  if (port >= LAN_IOSTART && port < LAN_IOEND) {
294  /*
295  * This portion is only used by smc91111.c to read data
296  * from the DATA_REG. Do not swap the data.
297  */
298  portp = PORT2ADDR_NE(port);
299  while (count--)
300  *buf++ = *(volatile unsigned short *)portp;
301 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
302  } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
303  pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
304  count, 1);
305 #endif
306 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
307  } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
308  portp = __port2addr_ata(port);
309  while (count--)
310  *buf++ = *(volatile unsigned short *)portp;
311 #endif
312  } else {
313  portp = PORT2ADDR(port);
314  while (count--)
315  *buf++ = *(volatile unsigned short *)portp;
316  }
317 }
318 
319 void _insl(unsigned int port, void *addr, unsigned long count)
320 {
321  unsigned long *buf = addr;
322  unsigned long *portp;
323 
324  portp = PORT2ADDR(port);
325  while (count--)
326  *buf++ = *(volatile unsigned long *)portp;
327 }
328 
329 void _outsb(unsigned int port, const void *addr, unsigned long count)
330 {
331  const unsigned char *buf = addr;
332  unsigned char *portp;
333 
334  if (port >= LAN_IOSTART && port < LAN_IOEND) {
335  portp = PORT2ADDR_NE(port);
336  while (count--)
337  _ne_outb(*buf++, portp);
338 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
339  } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
340  portp = __port2addr_ata(port);
341  while (count--)
342  *(volatile unsigned char *)portp = *buf++;
343 #endif
344 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
345  } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
346  pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
347  count, 1);
348 #endif
349  } else {
350  portp = PORT2ADDR(port);
351  while (count--)
352  *(volatile unsigned char *)portp = *buf++;
353  }
354 }
355 
356 void _outsw(unsigned int port, const void *addr, unsigned long count)
357 {
358  const unsigned short *buf = addr;
359  unsigned short *portp;
360 
361  if (port >= LAN_IOSTART && port < LAN_IOEND) {
362  /*
363  * This portion is only used by smc91111.c to write data
364  * into the DATA_REG. Do not swap the data.
365  */
366  portp = PORT2ADDR_NE(port);
367  while (count--)
368  *(volatile unsigned short *)portp = *buf++;
369 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
370  } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
371  portp = __port2addr_ata(port);
372  while (count--)
373  *(volatile unsigned short *)portp = *buf++;
374 #endif
375 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
376  } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
377  pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
378  count, 1);
379 #endif
380  } else {
381  portp = PORT2ADDR(port);
382  while (count--)
383  *(volatile unsigned short *)portp = *buf++;
384  }
385 }
386 
387 void _outsl(unsigned int port, const void *addr, unsigned long count)
388 {
389  const unsigned long *buf = addr;
390  unsigned char *portp;
391 
392  portp = PORT2ADDR(port);
393  while (count--)
394  *(volatile unsigned long *)portp = *buf++;
395 }