Linux 2.6.13-rc4
[linux-2.6/next.git] / arch / sh / boards / se / 770x / io.c
blob9a39ee963143fa4169bae4e9bb46abaabcf27a68
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.
9 */
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <asm/io.h>
14 #include <asm/se/se.h>
16 /* SH pcmcia io window base, start and end. */
17 int sh_pcic_io_wbase = 0xb8400000;
18 int sh_pcic_io_start;
19 int sh_pcic_io_stop;
20 int sh_pcic_io_type;
21 int sh_pcic_io_dummy;
23 static inline void delay(void)
25 ctrl_inw(0xa0000000);
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)
35 if (port >= 0x2000)
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));
41 else
42 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
45 static inline int
46 shifted_port(unsigned long port)
48 /* For IDE registers, value is not shifted */
49 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
50 return 0;
51 else
52 return 1;
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);
65 else
66 return (*port2adr(port))&0xff;
69 unsigned char se_inb_p(unsigned long port)
71 unsigned long v;
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);
77 else
78 v = (*port2adr(port))&0xff;
79 delay();
80 return v;
83 unsigned short se_inw(unsigned long port)
85 if (port >= 0x2000 ||
86 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
87 return *port2adr(port);
88 else
89 maybebadio(inw, port);
90 return 0;
93 unsigned int se_inl(unsigned long port)
95 maybebadio(inl, port);
96 return 0;
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;
105 else
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;
115 else
116 *(port2adr(port)) = value;
117 delay();
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;
125 else
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);
137 __u8 *ap = addr;
139 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
140 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
141 while (count--)
142 *ap++ = *bp;
143 } else if (shifted_port(port)) {
144 while (count--)
145 *ap++ = *p >> 8;
146 } else {
147 while (count--)
148 *ap++ = *p;
152 void se_insw(unsigned long port, void *addr, unsigned long count)
154 volatile __u16 *p = port2adr(port);
155 __u16 *ap = addr;
156 while (count--)
157 *ap++ = *p;
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);
172 while (count--)
173 *bp = *ap++;
174 } else if (shifted_port(port)) {
175 while (count--)
176 *p = *ap++ << 8;
177 } else {
178 while (count--)
179 *p = *ap++;
183 void se_outsw(unsigned long port, const void *addr, unsigned long count)
185 volatile __u16 *p = port2adr(port);
186 const __u16 *ap = addr;
187 while (count--)
188 *p = *ap++;
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];
201 static int
202 sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
204 int idx;
206 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
207 return -1;
209 idx = start >> 12;
210 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
211 #if 0
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]);
214 #endif
215 return 0;
218 unsigned long
219 se_isa_port2addr(unsigned long offset)
221 int idx;
223 idx = (offset >> 12) & 0xff;
224 offset &= 0xfff;
225 return sh_isa_memmap[idx] + offset;