diff options
Diffstat (limited to 'arch/sh/boards/renesas/hs7751rvoip/io.c')
-rw-r--r-- | arch/sh/boards/renesas/hs7751rvoip/io.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c new file mode 100644 index 000000000000..456753d2649c --- /dev/null +++ b/arch/sh/boards/renesas/hs7751rvoip/io.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /* | ||
2 | * linux/arch/sh/kernel/io_hs7751rvoip.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Ian da Silva, Jeremy Siegel | ||
5 | * Based largely on io_se.c. | ||
6 | * | ||
7 | * I/O routine for Renesas Technology sales HS7751RVoIP | ||
8 | * | ||
9 | * Initial version only to support LAN access; some | ||
10 | * placeholder code from io_hs7751rvoip.c left in with the | ||
11 | * expectation of later SuperIO and PCMCIA access. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/hs7751rvoip/hs7751rvoip.h> | ||
19 | #include <asm/addrspace.h> | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include "../../../drivers/pci/pci-sh7751.h" | ||
24 | |||
25 | extern void *area5_io8_base; /* Area 5 8bit I/O Base address */ | ||
26 | extern void *area6_io8_base; /* Area 6 8bit I/O Base address */ | ||
27 | extern void *area5_io16_base; /* Area 5 16bit I/O Base address */ | ||
28 | extern void *area6_io16_base; /* Area 6 16bit I/O Base address */ | ||
29 | |||
30 | /* | ||
31 | * The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC) | ||
32 | * of the 7751R processor, and has a SuperIO accessible via the PCI. | ||
33 | * The board also includes a PCMCIA controller on its memory bus, | ||
34 | * like the other Solution Engine boards. | ||
35 | */ | ||
36 | |||
37 | #define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) | ||
38 | #define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) | ||
39 | #define PCI_IO_AREA SH7751_PCI_IO_BASE | ||
40 | #define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE | ||
41 | |||
42 | #define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) | ||
43 | |||
44 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
45 | #define CODEC_IO_BASE 0x1000 | ||
46 | #endif | ||
47 | |||
48 | #define maybebadio(name,port) \ | ||
49 | printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ | ||
50 | #name, (port), (__u32) __builtin_return_address(0)) | ||
51 | |||
52 | static inline void delay(void) | ||
53 | { | ||
54 | ctrl_inw(0xa0000000); | ||
55 | } | ||
56 | |||
57 | static inline unsigned long port2adr(unsigned int port) | ||
58 | { | ||
59 | if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) | ||
60 | if (port == 0x3f6) | ||
61 | return ((unsigned long)area5_io16_base + 0x0c); | ||
62 | else | ||
63 | return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1)); | ||
64 | else | ||
65 | maybebadio(port2adr, (unsigned long)port); | ||
66 | return port; | ||
67 | } | ||
68 | |||
69 | /* The 7751R HS7751RVoIP seems to have everything hooked */ | ||
70 | /* up pretty normally (nothing on high-bytes only...) so this */ | ||
71 | /* shouldn't be needed */ | ||
72 | static inline int shifted_port(unsigned long port) | ||
73 | { | ||
74 | /* For IDE registers, value is not shifted */ | ||
75 | if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) | ||
76 | return 0; | ||
77 | else | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
82 | static inline int | ||
83 | codec_port(unsigned long port) | ||
84 | { | ||
85 | if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20)) | ||
86 | return 1; | ||
87 | else | ||
88 | return 0; | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | /* In case someone configures the kernel w/o PCI support: in that */ | ||
93 | /* scenario, don't ever bother to check for PCI-window addresses */ | ||
94 | |||
95 | /* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ | ||
96 | #if defined(CONFIG_PCI) | ||
97 | #define CHECK_SH7751_PCIIO(port) \ | ||
98 | ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) | ||
99 | #else | ||
100 | #define CHECK_SH7751_PCIIO(port) (0) | ||
101 | #endif | ||
102 | |||
103 | /* | ||
104 | * General outline: remap really low stuff [eventually] to SuperIO, | ||
105 | * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) | ||
106 | * is mapped through the PCI IO window. Stuff with high bits (PXSEG) | ||
107 | * should be way beyond the window, and is used w/o translation for | ||
108 | * compatibility. | ||
109 | */ | ||
110 | unsigned char hs7751rvoip_inb(unsigned long port) | ||
111 | { | ||
112 | if (PXSEG(port)) | ||
113 | return *(volatile unsigned char *)port; | ||
114 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
115 | else if (codec_port(port)) | ||
116 | return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)); | ||
117 | #endif | ||
118 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
119 | return *(volatile unsigned char *)PCI_IOMAP(port); | ||
120 | else | ||
121 | return (*(volatile unsigned short *)port2adr(port) & 0xff); | ||
122 | } | ||
123 | |||
124 | unsigned char hs7751rvoip_inb_p(unsigned long port) | ||
125 | { | ||
126 | unsigned char v; | ||
127 | |||
128 | if (PXSEG(port)) | ||
129 | v = *(volatile unsigned char *)port; | ||
130 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
131 | else if (codec_port(port)) | ||
132 | v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)); | ||
133 | #endif | ||
134 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
135 | v = *(volatile unsigned char *)PCI_IOMAP(port); | ||
136 | else | ||
137 | v = (*(volatile unsigned short *)port2adr(port) & 0xff); | ||
138 | delay(); | ||
139 | return v; | ||
140 | } | ||
141 | |||
142 | unsigned short hs7751rvoip_inw(unsigned long port) | ||
143 | { | ||
144 | if (PXSEG(port)) | ||
145 | return *(volatile unsigned short *)port; | ||
146 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
147 | return *(volatile unsigned short *)PCI_IOMAP(port); | ||
148 | else | ||
149 | maybebadio(inw, port); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | unsigned int hs7751rvoip_inl(unsigned long port) | ||
154 | { | ||
155 | if (PXSEG(port)) | ||
156 | return *(volatile unsigned long *)port; | ||
157 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
158 | return *(volatile unsigned long *)PCI_IOMAP(port); | ||
159 | else | ||
160 | maybebadio(inl, port); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void hs7751rvoip_outb(unsigned char value, unsigned long port) | ||
165 | { | ||
166 | |||
167 | if (PXSEG(port)) | ||
168 | *(volatile unsigned char *)port = value; | ||
169 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
170 | else if (codec_port(port)) | ||
171 | *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value; | ||
172 | #endif | ||
173 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
174 | *(unsigned char *)PCI_IOMAP(port) = value; | ||
175 | else | ||
176 | *(volatile unsigned short *)port2adr(port) = value; | ||
177 | } | ||
178 | |||
179 | void hs7751rvoip_outb_p(unsigned char value, unsigned long port) | ||
180 | { | ||
181 | if (PXSEG(port)) | ||
182 | *(volatile unsigned char *)port = value; | ||
183 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
184 | else if (codec_port(port)) | ||
185 | *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value; | ||
186 | #endif | ||
187 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
188 | *(unsigned char *)PCI_IOMAP(port) = value; | ||
189 | else | ||
190 | *(volatile unsigned short *)port2adr(port) = value; | ||
191 | delay(); | ||
192 | } | ||
193 | |||
194 | void hs7751rvoip_outw(unsigned short value, unsigned long port) | ||
195 | { | ||
196 | if (PXSEG(port)) | ||
197 | *(volatile unsigned short *)port = value; | ||
198 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
199 | *(unsigned short *)PCI_IOMAP(port) = value; | ||
200 | else | ||
201 | maybebadio(outw, port); | ||
202 | } | ||
203 | |||
204 | void hs7751rvoip_outl(unsigned int value, unsigned long port) | ||
205 | { | ||
206 | if (PXSEG(port)) | ||
207 | *(volatile unsigned long *)port = value; | ||
208 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
209 | *((unsigned long *)PCI_IOMAP(port)) = value; | ||
210 | else | ||
211 | maybebadio(outl, port); | ||
212 | } | ||
213 | |||
214 | void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count) | ||
215 | { | ||
216 | if (PXSEG(port)) | ||
217 | while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port; | ||
218 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
219 | else if (codec_port(port)) | ||
220 | while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)); | ||
221 | #endif | ||
222 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { | ||
223 | volatile __u8 *bp = (__u8 *)PCI_IOMAP(port); | ||
224 | |||
225 | while (count--) *((volatile unsigned char *) addr)++ = *bp; | ||
226 | } else { | ||
227 | volatile __u16 *p = (volatile unsigned short *)port2adr(port); | ||
228 | |||
229 | while (count--) *((unsigned char *) addr)++ = *p & 0xff; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count) | ||
234 | { | ||
235 | volatile __u16 *p; | ||
236 | |||
237 | if (PXSEG(port)) | ||
238 | p = (volatile unsigned short *)port; | ||
239 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
240 | p = (volatile unsigned short *)PCI_IOMAP(port); | ||
241 | else | ||
242 | p = (volatile unsigned short *)port2adr(port); | ||
243 | while (count--) *((__u16 *) addr)++ = *p; | ||
244 | } | ||
245 | |||
246 | void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count) | ||
247 | { | ||
248 | if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { | ||
249 | volatile __u32 *p = (__u32 *)PCI_IOMAP(port); | ||
250 | |||
251 | while (count--) *((__u32 *) addr)++ = *p; | ||
252 | } else | ||
253 | maybebadio(insl, port); | ||
254 | } | ||
255 | |||
256 | void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count) | ||
257 | { | ||
258 | if (PXSEG(port)) | ||
259 | while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++; | ||
260 | #if defined(CONFIG_HS7751RVOIP_CODEC) | ||
261 | else if (codec_port(port)) | ||
262 | while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++; | ||
263 | #endif | ||
264 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { | ||
265 | volatile __u8 *bp = (__u8 *)PCI_IOMAP(port); | ||
266 | |||
267 | while (count--) *bp = *((volatile unsigned char *) addr)++; | ||
268 | } else { | ||
269 | volatile __u16 *p = (volatile unsigned short *)port2adr(port); | ||
270 | |||
271 | while (count--) *p = *((unsigned char *) addr)++; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count) | ||
276 | { | ||
277 | volatile __u16 *p; | ||
278 | |||
279 | if (PXSEG(port)) | ||
280 | p = (volatile unsigned short *)port; | ||
281 | else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) | ||
282 | p = (volatile unsigned short *)PCI_IOMAP(port); | ||
283 | else | ||
284 | p = (volatile unsigned short *)port2adr(port); | ||
285 | while (count--) *p = *((__u16 *) addr)++; | ||
286 | } | ||
287 | |||
288 | void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count) | ||
289 | { | ||
290 | if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) { | ||
291 | volatile __u32 *p = (__u32 *)PCI_IOMAP(port); | ||
292 | |||
293 | while (count--) *p = *((__u32 *) addr)++; | ||
294 | } else | ||
295 | maybebadio(outsl, port); | ||
296 | } | ||
297 | |||
298 | void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size) | ||
299 | { | ||
300 | if (offset >= 0xfd000000) | ||
301 | return (void *)offset; | ||
302 | else | ||
303 | return (void *)P2SEGADDR(offset); | ||
304 | } | ||
305 | EXPORT_SYMBOL(hs7751rvoip_ioremap); | ||
306 | |||
307 | unsigned long hs7751rvoip_isa_port2addr(unsigned long offset) | ||
308 | { | ||
309 | return port2adr(offset); | ||
310 | } | ||