1/* $Id: io.c,v 1.1.1.1 2007/08/03 18:52:15 Exp $ 2 * 3 * linux/arch/sh/kernel/io_se.c 4 * 5 * Copyright (C) 2000 Kazumoto Kojima 6 * 7 * I/O routine for Hitachi SolutionEngine. 8 * 9 */ 10 11#include <linux/kernel.h> 12#include <linux/types.h> 13#include <asm/io.h> 14#include <asm/se.h> 15 16/* SH pcmcia io window base, start and end. */ 17int sh_pcic_io_wbase = 0xb8400000; 18int sh_pcic_io_start; 19int sh_pcic_io_stop; 20int sh_pcic_io_type; 21int sh_pcic_io_dummy; 22 23/* MS7750 requires special versions of in*, out* routines, since 24 PC-like io ports are located at upper half byte of 16-bit word which 25 can be accessed only with 16-bit wide. */ 26 27static inline volatile __u16 * 28port2adr(unsigned int port) 29{ 30 if (port & 0xff000000) 31 return ( volatile __u16 *) port; 32 if (port >= 0x2000) 33 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); 34 else if (port >= 0x1000) 35 return (volatile __u16 *) (PA_83902 + (port << 1)); 36 else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) 37 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1)); 38 else 39 return (volatile __u16 *) (PA_SUPERIO + (port << 1)); 40} 41 42static inline int 43shifted_port(unsigned long port) 44{ 45 /* For IDE registers, value is not shifted */ 46 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) 47 return 0; 48 else 49 return 1; 50} 51 52unsigned char se_inb(unsigned long port) 53{ 54 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) 55 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 56 else if (shifted_port(port)) 57 return (*port2adr(port) >> 8); 58 else 59 return (*port2adr(port))&0xff; 60} 61 62unsigned char se_inb_p(unsigned long port) 63{ 64 unsigned long v; 65 66 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) 67 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 68 else if (shifted_port(port)) 69 v = (*port2adr(port) >> 8); 70 else 71 v = (*port2adr(port))&0xff; 72 ctrl_delay(); 73 return v; 74} 75 76unsigned short se_inw(unsigned long port) 77{ 78 if (port >= 0x2000 || 79 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) 80 return *port2adr(port); 81 else 82 maybebadio(port); 83 return 0; 84} 85 86unsigned int se_inl(unsigned long port) 87{ 88 maybebadio(port); 89 return 0; 90} 91 92void se_outb(unsigned char value, unsigned long port) 93{ 94 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) 95 *(__u8 *)(sh_pcic_io_wbase + port) = value; 96 else if (shifted_port(port)) 97 *(port2adr(port)) = value << 8; 98 else 99 *(port2adr(port)) = value; 100} 101 102void se_outb_p(unsigned char value, unsigned long port) 103{ 104 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) 105 *(__u8 *)(sh_pcic_io_wbase + port) = value; 106 else if (shifted_port(port)) 107 *(port2adr(port)) = value << 8; 108 else 109 *(port2adr(port)) = value; 110 ctrl_delay(); 111} 112 113void se_outw(unsigned short value, unsigned long port) 114{ 115 if (port >= 0x2000 || 116 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) 117 *port2adr(port) = value; 118 else 119 maybebadio(port); 120} 121 122void se_outl(unsigned int value, unsigned long port) 123{ 124 maybebadio(port); 125} 126 127void se_insb(unsigned long port, void *addr, unsigned long count) 128{ 129 volatile __u16 *p = port2adr(port); 130 __u8 *ap = addr; 131 132 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { 133 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 134 while (count--) 135 *ap++ = *bp; 136 } else if (shifted_port(port)) { 137 while (count--) 138 *ap++ = *p >> 8; 139 } else { 140 while (count--) 141 *ap++ = *p; 142 } 143} 144 145void se_insw(unsigned long port, void *addr, unsigned long count) 146{ 147 volatile __u16 *p = port2adr(port); 148 __u16 *ap = addr; 149 while (count--) 150 *ap++ = *p; 151} 152 153void se_insl(unsigned long port, void *addr, unsigned long count) 154{ 155 maybebadio(port); 156} 157 158void se_outsb(unsigned long port, const void *addr, unsigned long count) 159{ 160 volatile __u16 *p = port2adr(port); 161 const __u8 *ap = addr; 162 163 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { 164 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 165 while (count--) 166 *bp = *ap++; 167 } else if (shifted_port(port)) { 168 while (count--) 169 *p = *ap++ << 8; 170 } else { 171 while (count--) 172 *p = *ap++; 173 } 174} 175 176void se_outsw(unsigned long port, const void *addr, unsigned long count) 177{ 178 volatile __u16 *p = port2adr(port); 179 const __u16 *ap = addr; 180 while (count--) 181 *p = *ap++; 182} 183 184void se_outsl(unsigned long port, const void *addr, unsigned long count) 185{ 186 maybebadio(port); 187} 188