1/* 2 * linux/arch/m32r/platforms/m32104ut/io.c 3 * 4 * Typical I/O routines for M32104UT board. 5 * 6 * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata, 7 * Hitoshi Yamamoto, Mamoru Sakugawa, 8 * Naoto Sugai, Hayato Fujiwara 9 */ 10 11#include <asm/m32r.h> 12#include <asm/page.h> 13#include <asm/io.h> 14#include <asm/byteorder.h> 15 16#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) 17#include <linux/types.h> 18 19#define M32R_PCC_IOMAP_SIZE 0x1000 20 21#define M32R_PCC_IOSTART0 0x1000 22#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1) 23 24extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int); 25extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int); 26extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); 27extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); 28#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ 29 30#define PORT2ADDR(port) _port2addr(port) 31 32static inline void *_port2addr(unsigned long port) 33{ 34 return (void *)(port | NONCACHE_OFFSET); 35} 36 37#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) 38static inline void *__port2addr_ata(unsigned long port) 39{ 40 static int dummy_reg; 41 42 switch (port) { 43 case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); 44 case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); 45 case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); 46 case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); 47 case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); 48 case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); 49 case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); 50 case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); 51 case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); 52 default: return (void *)&dummy_reg; 53 } 54} 55#endif 56 57/* 58 * M32104T-LAN is located in the extended bus space 59 * from 0x01000000 to 0x01ffffff on physical address. 60 * The base address of LAN controller(LAN91C111) is 0x300. 61 */ 62#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) 63#define LAN_IOEND (0x320 | NONCACHE_OFFSET) 64static inline void *_port2addr_ne(unsigned long port) 65{ 66 return (void *)(port + NONCACHE_OFFSET + 0x01000000); 67} 68 69static inline void delay(void) 70{ 71 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); 72} 73 74/* 75 * NIC I/O function 76 */ 77 78#define PORT2ADDR_NE(port) _port2addr_ne(port) 79 80static inline unsigned char _ne_inb(void *portp) 81{ 82 return *(volatile unsigned char *)portp; 83} 84 85static inline unsigned short _ne_inw(void *portp) 86{ 87 return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); 88} 89 90static inline void _ne_insb(void *portp, void *addr, unsigned long count) 91{ 92 unsigned char *buf = (unsigned char *)addr; 93 94 while (count--) 95 *buf++ = _ne_inb(portp); 96} 97 98static inline void _ne_outb(unsigned char b, void *portp) 99{ 100 *(volatile unsigned char *)portp = b; 101} 102 103static inline void _ne_outw(unsigned short w, void *portp) 104{ 105 *(volatile unsigned short *)portp = cpu_to_le16(w); 106} 107 108unsigned char _inb(unsigned long port) 109{ 110 if (port >= LAN_IOSTART && port < LAN_IOEND) 111 return _ne_inb(PORT2ADDR_NE(port)); 112 113 return *(volatile unsigned char *)PORT2ADDR(port); 114} 115 116unsigned short _inw(unsigned long port) 117{ 118 if (port >= LAN_IOSTART && port < LAN_IOEND) 119 return _ne_inw(PORT2ADDR_NE(port)); 120 121 return *(volatile unsigned short *)PORT2ADDR(port); 122} 123 124unsigned long _inl(unsigned long port) 125{ 126 return *(volatile unsigned long *)PORT2ADDR(port); 127} 128 129unsigned char _inb_p(unsigned long port) 130{ 131 unsigned char v = _inb(port); 132 delay(); 133 return (v); 134} 135 136unsigned short _inw_p(unsigned long port) 137{ 138 unsigned short v = _inw(port); 139 delay(); 140 return (v); 141} 142 143unsigned long _inl_p(unsigned long port) 144{ 145 unsigned long v = _inl(port); 146 delay(); 147 return (v); 148} 149 150void _outb(unsigned char b, unsigned long port) 151{ 152 if (port >= LAN_IOSTART && port < LAN_IOEND) 153 _ne_outb(b, PORT2ADDR_NE(port)); 154 else 155 *(volatile unsigned char *)PORT2ADDR(port) = b; 156} 157 158void _outw(unsigned short w, unsigned long port) 159{ 160 if (port >= LAN_IOSTART && port < LAN_IOEND) 161 _ne_outw(w, PORT2ADDR_NE(port)); 162 else 163 *(volatile unsigned short *)PORT2ADDR(port) = w; 164} 165 166void _outl(unsigned long l, unsigned long port) 167{ 168 *(volatile unsigned long *)PORT2ADDR(port) = l; 169} 170 171void _outb_p(unsigned char b, unsigned long port) 172{ 173 _outb(b, port); 174 delay(); 175} 176 177void _outw_p(unsigned short w, unsigned long port) 178{ 179 _outw(w, port); 180 delay(); 181} 182 183void _outl_p(unsigned long l, unsigned long port) 184{ 185 _outl(l, port); 186 delay(); 187} 188 189void _insb(unsigned int port, void *addr, unsigned long count) 190{ 191 if (port >= LAN_IOSTART && port < LAN_IOEND) 192 _ne_insb(PORT2ADDR_NE(port), addr, count); 193 else { 194 unsigned char *buf = addr; 195 unsigned char *portp = PORT2ADDR(port); 196 while (count--) 197 *buf++ = *(volatile unsigned char *)portp; 198 } 199} 200 201void _insw(unsigned int port, void *addr, unsigned long count) 202{ 203 unsigned short *buf = addr; 204 unsigned short *portp; 205 206 if (port >= LAN_IOSTART && port < LAN_IOEND) { 207 /* 208 * This portion is only used by smc91111.c to read data 209 * from the DATA_REG. Do not swap the data. 210 */ 211 portp = PORT2ADDR_NE(port); 212 while (count--) 213 *buf++ = *(volatile unsigned short *)portp; 214#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) 215 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { 216 pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), 217 count, 1); 218#endif 219#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) 220 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { 221 portp = __port2addr_ata(port); 222 while (count--) 223 *buf++ = *(volatile unsigned short *)portp; 224#endif 225 } else { 226 portp = PORT2ADDR(port); 227 while (count--) 228 *buf++ = *(volatile unsigned short *)portp; 229 } 230} 231 232void _insl(unsigned int port, void *addr, unsigned long count) 233{ 234 unsigned long *buf = addr; 235 unsigned long *portp; 236 237 portp = PORT2ADDR(port); 238 while (count--) 239 *buf++ = *(volatile unsigned long *)portp; 240} 241 242void _outsb(unsigned int port, const void *addr, unsigned long count) 243{ 244 const unsigned char *buf = addr; 245 unsigned char *portp; 246 247 if (port >= LAN_IOSTART && port < LAN_IOEND) { 248 portp = PORT2ADDR_NE(port); 249 while (count--) 250 _ne_outb(*buf++, portp); 251 } else { 252 portp = PORT2ADDR(port); 253 while (count--) 254 *(volatile unsigned char *)portp = *buf++; 255 } 256} 257 258void _outsw(unsigned int port, const void *addr, unsigned long count) 259{ 260 const unsigned short *buf = addr; 261 unsigned short *portp; 262 263 if (port >= LAN_IOSTART && port < LAN_IOEND) { 264 /* 265 * This portion is only used by smc91111.c to write data 266 * into the DATA_REG. Do not swap the data. 267 */ 268 portp = PORT2ADDR_NE(port); 269 while (count--) 270 *(volatile unsigned short *)portp = *buf++; 271#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) 272 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { 273 portp = __port2addr_ata(port); 274 while (count--) 275 *(volatile unsigned short *)portp = *buf++; 276#endif 277#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) 278 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { 279 pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), 280 count, 1); 281#endif 282 } else { 283 portp = PORT2ADDR(port); 284 while (count--) 285 *(volatile unsigned short *)portp = *buf++; 286 } 287} 288 289void _outsl(unsigned int port, const void *addr, unsigned long count) 290{ 291 const unsigned long *buf = addr; 292 unsigned char *portp; 293 294 portp = PORT2ADDR(port); 295 while (count--) 296 *(volatile unsigned long *)portp = *buf++; 297} 298