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