1/* 2 * arch/sh/boards/se/7343/io.c 3 * 4 * I/O routine for SH-Mobile3AS 7343 SolutionEngine. 5 * 6 */ 7#include <linux/kernel.h> 8#include <asm/io.h> 9#include <asm/mach/se7343.h> 10 11#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a) 12 13struct iop { 14 unsigned long start, end; 15 unsigned long base; 16 struct iop *(*check) (struct iop * p, unsigned long port); 17 unsigned char (*inb) (struct iop * p, unsigned long port); 18 unsigned short (*inw) (struct iop * p, unsigned long port); 19 void (*outb) (struct iop * p, unsigned char value, unsigned long port); 20 void (*outw) (struct iop * p, unsigned short value, unsigned long port); 21}; 22 23struct iop * 24simple_check(struct iop *p, unsigned long port) 25{ 26 static int count; 27 28 if (count < 100) 29 count++; 30 31 port &= 0xFFFF; 32 33 if ((p->start <= port) && (port <= p->end)) 34 return p; 35 else 36 badio(check, port); 37} 38 39struct iop * 40ide_check(struct iop *p, unsigned long port) 41{ 42 if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7)) 43 return p; 44 return NULL; 45} 46 47unsigned char 48simple_inb(struct iop *p, unsigned long port) 49{ 50 return *(unsigned char *) (p->base + port); 51} 52 53unsigned short 54simple_inw(struct iop *p, unsigned long port) 55{ 56 return *(unsigned short *) (p->base + port); 57} 58 59void 60simple_outb(struct iop *p, unsigned char value, unsigned long port) 61{ 62 *(unsigned char *) (p->base + port) = value; 63} 64 65void 66simple_outw(struct iop *p, unsigned short value, unsigned long port) 67{ 68 *(unsigned short *) (p->base + port) = value; 69} 70 71unsigned char 72pcc_inb(struct iop *p, unsigned long port) 73{ 74 unsigned long addr = p->base + port + 0x40000; 75 unsigned long v; 76 77 if (port & 1) 78 addr += 0x00400000; 79 v = *(volatile unsigned char *) addr; 80 return v; 81} 82 83void 84pcc_outb(struct iop *p, unsigned char value, unsigned long port) 85{ 86 unsigned long addr = p->base + port + 0x40000; 87 88 if (port & 1) 89 addr += 0x00400000; 90 *(volatile unsigned char *) addr = value; 91} 92 93unsigned char 94bad_inb(struct iop *p, unsigned long port) 95{ 96 badio(inb, port); 97} 98 99void 100bad_outb(struct iop *p, unsigned char value, unsigned long port) 101{ 102 badio(inw, port); 103} 104 105#ifdef CONFIG_SMC91X 106/* MSTLANEX01 LAN at 0xb400:0000 */ 107static struct iop laniop = { 108 .start = 0x00, 109 .end = 0x0F, 110 .base = 0x04000000, 111 .check = simple_check, 112 .inb = simple_inb, 113 .inw = simple_inw, 114 .outb = simple_outb, 115 .outw = simple_outw, 116}; 117#endif 118 119#ifdef CONFIG_NE2000 120/* NE2000 pc card NIC */ 121static struct iop neiop = { 122 .start = 0x280, 123 .end = 0x29f, 124 .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */ 125 .check = simple_check, 126 .inb = pcc_inb, 127 .inw = simple_inw, 128 .outb = pcc_outb, 129 .outw = simple_outw, 130}; 131#endif 132 133#ifdef CONFIG_IDE 134/* CF in CF slot */ 135static struct iop cfiop = { 136 .base = 0xb0600000, 137 .check = ide_check, 138 .inb = pcc_inb, 139 .inw = simple_inw, 140 .outb = pcc_outb, 141 .outw = simple_outw, 142}; 143#endif 144 145static __inline__ struct iop * 146port2iop(unsigned long port) 147{ 148 if (0) ; 149#if defined(CONFIG_SMC91X) 150 else if (laniop.check(&laniop, port)) 151 return &laniop; 152#endif 153#if defined(CONFIG_NE2000) 154 else if (neiop.check(&neiop, port)) 155 return &neiop; 156#endif 157#if defined(CONFIG_IDE) 158 else if (cfiop.check(&cfiop, port)) 159 return &cfiop; 160#endif 161 else 162 return NULL; 163} 164 165static inline void 166delay(void) 167{ 168 ctrl_inw(0xac000000); 169 ctrl_inw(0xac000000); 170} 171 172unsigned char 173sh7343se_inb(unsigned long port) 174{ 175 struct iop *p = port2iop(port); 176 return (p->inb) (p, port); 177} 178 179unsigned char 180sh7343se_inb_p(unsigned long port) 181{ 182 unsigned char v = sh7343se_inb(port); 183 delay(); 184 return v; 185} 186 187unsigned short 188sh7343se_inw(unsigned long port) 189{ 190 struct iop *p = port2iop(port); 191 return (p->inw) (p, port); 192} 193 194unsigned int 195sh7343se_inl(unsigned long port) 196{ 197 badio(inl, port); 198} 199 200void 201sh7343se_outb(unsigned char value, unsigned long port) 202{ 203 struct iop *p = port2iop(port); 204 (p->outb) (p, value, port); 205} 206 207void 208sh7343se_outb_p(unsigned char value, unsigned long port) 209{ 210 sh7343se_outb(value, port); 211 delay(); 212} 213 214void 215sh7343se_outw(unsigned short value, unsigned long port) 216{ 217 struct iop *p = port2iop(port); 218 (p->outw) (p, value, port); 219} 220 221void 222sh7343se_outl(unsigned int value, unsigned long port) 223{ 224 badio(outl, port); 225} 226 227void 228sh7343se_insb(unsigned long port, void *addr, unsigned long count) 229{ 230 unsigned char *a = addr; 231 struct iop *p = port2iop(port); 232 while (count--) 233 *a++ = (p->inb) (p, port); 234} 235 236void 237sh7343se_insw(unsigned long port, void *addr, unsigned long count) 238{ 239 unsigned short *a = addr; 240 struct iop *p = port2iop(port); 241 while (count--) 242 *a++ = (p->inw) (p, port); 243} 244 245void 246sh7343se_insl(unsigned long port, void *addr, unsigned long count) 247{ 248 badio(insl, port); 249} 250 251void 252sh7343se_outsb(unsigned long port, const void *addr, unsigned long count) 253{ 254 unsigned char *a = (unsigned char *) addr; 255 struct iop *p = port2iop(port); 256 while (count--) 257 (p->outb) (p, *a++, port); 258} 259 260void 261sh7343se_outsw(unsigned long port, const void *addr, unsigned long count) 262{ 263 unsigned short *a = (unsigned short *) addr; 264 struct iop *p = port2iop(port); 265 while (count--) 266 (p->outw) (p, *a++, port); 267} 268 269void 270sh7343se_outsl(unsigned long port, const void *addr, unsigned long count) 271{ 272 badio(outsw, port); 273} 274