1 /* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
3 * linux/arch/sh/kernel/io_se.c
5 * Copyright (C) 2000 Kazumoto Kojima
7 * I/O routine for Hitachi SolutionEngine.
11 #include <linux/kernel.h>
12 #include <linux/types.h>
14 #include <asm/se/se.h>
16 /* SH pcmcia io window base, start and end. */
17 int sh_pcic_io_wbase = 0xb8400000;
23 static inline void delay(void)
28 /* MS7750 requires special versions of in*, out* routines, since
29 PC-like io ports are located at upper half byte of 16-bit word which
30 can be accessed only with 16-bit wide. */
32 static inline volatile __u16 *
33 port2adr(unsigned int port)
36 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
37 else if (port >= 0x1000)
38 return (volatile __u16 *) (PA_83902 + (port << 1));
39 else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
40 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
42 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
46 shifted_port(unsigned long port)
48 /* For IDE registers, value is not shifted */
49 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
55 #define maybebadio(name,port) \
56 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
57 #name, (port), (__u32) __builtin_return_address(0))
59 unsigned char se_inb(unsigned long port)
61 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
62 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
63 else if (shifted_port(port))
64 return (*port2adr(port) >> 8);
66 return (*port2adr(port))&0xff;
69 unsigned char se_inb_p(unsigned long port)
73 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
74 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
75 else if (shifted_port(port))
76 v = (*port2adr(port) >> 8);
78 v = (*port2adr(port))&0xff;
83 unsigned short se_inw(unsigned long port)
86 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
87 return *port2adr(port);
89 maybebadio(inw, port);
93 unsigned int se_inl(unsigned long port)
95 maybebadio(inl, port);
99 void se_outb(unsigned char value, unsigned long port)
101 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
102 *(__u8 *)(sh_pcic_io_wbase + port) = value;
103 else if (shifted_port(port))
104 *(port2adr(port)) = value << 8;
106 *(port2adr(port)) = value;
109 void se_outb_p(unsigned char value, unsigned long port)
111 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
112 *(__u8 *)(sh_pcic_io_wbase + port) = value;
113 else if (shifted_port(port))
114 *(port2adr(port)) = value << 8;
116 *(port2adr(port)) = value;
120 void se_outw(unsigned short value, unsigned long port)
122 if (port >= 0x2000 ||
123 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
124 *port2adr(port) = value;
126 maybebadio(outw, port);
129 void se_outl(unsigned int value, unsigned long port)
131 maybebadio(outl, port);
134 void se_insb(unsigned long port, void *addr, unsigned long count)
136 volatile __u16 *p = port2adr(port);
139 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
140 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
143 } else if (shifted_port(port)) {
152 void se_insw(unsigned long port, void *addr, unsigned long count)
154 volatile __u16 *p = port2adr(port);
160 void se_insl(unsigned long port, void *addr, unsigned long count)
162 maybebadio(insl, port);
165 void se_outsb(unsigned long port, const void *addr, unsigned long count)
167 volatile __u16 *p = port2adr(port);
168 const __u8 *ap = addr;
170 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
171 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
174 } else if (shifted_port(port)) {
183 void se_outsw(unsigned long port, const void *addr, unsigned long count)
185 volatile __u16 *p = port2adr(port);
186 const __u16 *ap = addr;
191 void se_outsl(unsigned long port, const void *addr, unsigned long count)
193 maybebadio(outsw, port);
196 /* Map ISA bus address to the real address. Only for PCMCIA. */
198 /* ISA page descriptor. */
199 static __u32 sh_isa_memmap[256];
202 sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
206 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
210 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
212 printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
213 start, length, offset, idx, sh_isa_memmap[idx]);
219 se_isa_port2addr(unsigned long offset)
223 idx = (offset >> 12) & 0xff;
225 return sh_isa_memmap[idx] + offset;