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