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