diff options
Diffstat (limited to 'arch/sh/kernel/io_generic.c')
-rw-r--r-- | arch/sh/kernel/io_generic.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c new file mode 100644 index 000000000000..a911b0149d1f --- /dev/null +++ b/arch/sh/kernel/io_generic.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* $Id: io_generic.c,v 1.2 2003/05/04 19:29:53 lethal Exp $ | ||
2 | * | ||
3 | * linux/arch/sh/kernel/io_generic.c | ||
4 | * | ||
5 | * Copyright (C) 2000 Niibe Yutaka | ||
6 | * | ||
7 | * Generic I/O routine. These can be used where a machine specific version | ||
8 | * is not required. | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | #include <asm/machvec.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | #if defined(CONFIG_CPU_SH3) | ||
21 | /* I'm not sure SH7709 has this kind of bug */ | ||
22 | #define SH3_PCMCIA_BUG_WORKAROUND 1 | ||
23 | #define DUMMY_READ_AREA6 0xba000000 | ||
24 | #endif | ||
25 | |||
26 | #define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) | ||
27 | |||
28 | unsigned long generic_io_base; | ||
29 | |||
30 | static inline void delay(void) | ||
31 | { | ||
32 | ctrl_inw(0xa0000000); | ||
33 | } | ||
34 | |||
35 | unsigned char generic_inb(unsigned long port) | ||
36 | { | ||
37 | return *(volatile unsigned char*)PORT2ADDR(port); | ||
38 | } | ||
39 | |||
40 | unsigned short generic_inw(unsigned long port) | ||
41 | { | ||
42 | return *(volatile unsigned short*)PORT2ADDR(port); | ||
43 | } | ||
44 | |||
45 | unsigned int generic_inl(unsigned long port) | ||
46 | { | ||
47 | return *(volatile unsigned long*)PORT2ADDR(port); | ||
48 | } | ||
49 | |||
50 | unsigned char generic_inb_p(unsigned long port) | ||
51 | { | ||
52 | unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); | ||
53 | |||
54 | delay(); | ||
55 | return v; | ||
56 | } | ||
57 | |||
58 | unsigned short generic_inw_p(unsigned long port) | ||
59 | { | ||
60 | unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); | ||
61 | |||
62 | delay(); | ||
63 | return v; | ||
64 | } | ||
65 | |||
66 | unsigned int generic_inl_p(unsigned long port) | ||
67 | { | ||
68 | unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); | ||
69 | |||
70 | delay(); | ||
71 | return v; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * insb/w/l all read a series of bytes/words/longs from a fixed port | ||
76 | * address. However as the port address doesn't change we only need to | ||
77 | * convert the port address to real address once. | ||
78 | */ | ||
79 | |||
80 | void generic_insb(unsigned long port, void *buffer, unsigned long count) | ||
81 | { | ||
82 | volatile unsigned char *port_addr; | ||
83 | unsigned char *buf=buffer; | ||
84 | |||
85 | port_addr = (volatile unsigned char *)PORT2ADDR(port); | ||
86 | |||
87 | while(count--) | ||
88 | *buf++ = *port_addr; | ||
89 | } | ||
90 | |||
91 | void generic_insw(unsigned long port, void *buffer, unsigned long count) | ||
92 | { | ||
93 | volatile unsigned short *port_addr; | ||
94 | unsigned short *buf=buffer; | ||
95 | |||
96 | port_addr = (volatile unsigned short *)PORT2ADDR(port); | ||
97 | |||
98 | while(count--) | ||
99 | *buf++ = *port_addr; | ||
100 | #ifdef SH3_PCMCIA_BUG_WORKAROUND | ||
101 | ctrl_inb (DUMMY_READ_AREA6); | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | void generic_insl(unsigned long port, void *buffer, unsigned long count) | ||
106 | { | ||
107 | volatile unsigned long *port_addr; | ||
108 | unsigned long *buf=buffer; | ||
109 | |||
110 | port_addr = (volatile unsigned long *)PORT2ADDR(port); | ||
111 | |||
112 | while(count--) | ||
113 | *buf++ = *port_addr; | ||
114 | #ifdef SH3_PCMCIA_BUG_WORKAROUND | ||
115 | ctrl_inb (DUMMY_READ_AREA6); | ||
116 | #endif | ||
117 | } | ||
118 | |||
119 | void generic_outb(unsigned char b, unsigned long port) | ||
120 | { | ||
121 | *(volatile unsigned char*)PORT2ADDR(port) = b; | ||
122 | } | ||
123 | |||
124 | void generic_outw(unsigned short b, unsigned long port) | ||
125 | { | ||
126 | *(volatile unsigned short*)PORT2ADDR(port) = b; | ||
127 | } | ||
128 | |||
129 | void generic_outl(unsigned int b, unsigned long port) | ||
130 | { | ||
131 | *(volatile unsigned long*)PORT2ADDR(port) = b; | ||
132 | } | ||
133 | |||
134 | void generic_outb_p(unsigned char b, unsigned long port) | ||
135 | { | ||
136 | *(volatile unsigned char*)PORT2ADDR(port) = b; | ||
137 | delay(); | ||
138 | } | ||
139 | |||
140 | void generic_outw_p(unsigned short b, unsigned long port) | ||
141 | { | ||
142 | *(volatile unsigned short*)PORT2ADDR(port) = b; | ||
143 | delay(); | ||
144 | } | ||
145 | |||
146 | void generic_outl_p(unsigned int b, unsigned long port) | ||
147 | { | ||
148 | *(volatile unsigned long*)PORT2ADDR(port) = b; | ||
149 | delay(); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * outsb/w/l all write a series of bytes/words/longs to a fixed port | ||
154 | * address. However as the port address doesn't change we only need to | ||
155 | * convert the port address to real address once. | ||
156 | */ | ||
157 | |||
158 | void generic_outsb(unsigned long port, const void *buffer, unsigned long count) | ||
159 | { | ||
160 | volatile unsigned char *port_addr; | ||
161 | const unsigned char *buf=buffer; | ||
162 | |||
163 | port_addr = (volatile unsigned char *)PORT2ADDR(port); | ||
164 | |||
165 | while(count--) | ||
166 | *port_addr = *buf++; | ||
167 | } | ||
168 | |||
169 | void generic_outsw(unsigned long port, const void *buffer, unsigned long count) | ||
170 | { | ||
171 | volatile unsigned short *port_addr; | ||
172 | const unsigned short *buf=buffer; | ||
173 | |||
174 | port_addr = (volatile unsigned short *)PORT2ADDR(port); | ||
175 | |||
176 | while(count--) | ||
177 | *port_addr = *buf++; | ||
178 | |||
179 | #ifdef SH3_PCMCIA_BUG_WORKAROUND | ||
180 | ctrl_inb (DUMMY_READ_AREA6); | ||
181 | #endif | ||
182 | } | ||
183 | |||
184 | void generic_outsl(unsigned long port, const void *buffer, unsigned long count) | ||
185 | { | ||
186 | volatile unsigned long *port_addr; | ||
187 | const unsigned long *buf=buffer; | ||
188 | |||
189 | port_addr = (volatile unsigned long *)PORT2ADDR(port); | ||
190 | |||
191 | while(count--) | ||
192 | *port_addr = *buf++; | ||
193 | |||
194 | #ifdef SH3_PCMCIA_BUG_WORKAROUND | ||
195 | ctrl_inb (DUMMY_READ_AREA6); | ||
196 | #endif | ||
197 | } | ||
198 | |||
199 | unsigned char generic_readb(unsigned long addr) | ||
200 | { | ||
201 | return *(volatile unsigned char*)addr; | ||
202 | } | ||
203 | |||
204 | unsigned short generic_readw(unsigned long addr) | ||
205 | { | ||
206 | return *(volatile unsigned short*)addr; | ||
207 | } | ||
208 | |||
209 | unsigned int generic_readl(unsigned long addr) | ||
210 | { | ||
211 | return *(volatile unsigned long*)addr; | ||
212 | } | ||
213 | |||
214 | void generic_writeb(unsigned char b, unsigned long addr) | ||
215 | { | ||
216 | *(volatile unsigned char*)addr = b; | ||
217 | } | ||
218 | |||
219 | void generic_writew(unsigned short b, unsigned long addr) | ||
220 | { | ||
221 | *(volatile unsigned short*)addr = b; | ||
222 | } | ||
223 | |||
224 | void generic_writel(unsigned int b, unsigned long addr) | ||
225 | { | ||
226 | *(volatile unsigned long*)addr = b; | ||
227 | } | ||
228 | |||
229 | void * generic_ioremap(unsigned long offset, unsigned long size) | ||
230 | { | ||
231 | return (void *) P2SEGADDR(offset); | ||
232 | } | ||
233 | EXPORT_SYMBOL(generic_ioremap); | ||
234 | |||
235 | void generic_iounmap(void *addr) | ||
236 | { | ||
237 | } | ||
238 | EXPORT_SYMBOL(generic_iounmap); | ||
239 | |||
240 | unsigned long generic_isa_port2addr(unsigned long offset) | ||
241 | { | ||
242 | return offset + generic_io_base; | ||
243 | } | ||