Commit | Line | Data |
---|---|---|
94c0fa52 | 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> | |
94c0fa52 | 20 | #include <asm/landisk/iodata_landisk.h> |
21 | #include <asm/addrspace.h> | |
d7cdc9e8 | 22 | #include <asm/io.h> |
94c0fa52 | 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 | ||
94c0fa52 | 45 | static inline void delay(void) |
46 | { | |
47 | ctrl_inw(0xa0000000); | |
48 | } | |
49 | ||
50 | static inline unsigned long port2adr(unsigned int port) | |
51 | { | |
52 | if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) | |
53 | if (port == 0x3f6) | |
54 | return ((unsigned long)area5_io_base + 0x2c); | |
55 | else | |
56 | return ((unsigned long)area5_io_base + PA_PIDE_OFFSET + | |
57 | ((port - 0x1f0) << 1)); | |
58 | else if ((0x170 <= port && port < 0x178) || port == 0x376) | |
59 | if (port == 0x376) | |
60 | return ((unsigned long)area6_io_base + 0x2c); | |
61 | else | |
62 | return ((unsigned long)area6_io_base + PA_SIDE_OFFSET + | |
63 | ((port - 0x170) << 1)); | |
64 | else | |
d7cdc9e8 | 65 | maybebadio((unsigned long)port); |
94c0fa52 | 66 | |
67 | return port; | |
68 | } | |
69 | ||
70 | /* In case someone configures the kernel w/o PCI support: in that */ | |
71 | /* scenario, don't ever bother to check for PCI-window addresses */ | |
72 | ||
73 | /* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ | |
74 | #if defined(CONFIG_PCI) | |
75 | #define CHECK_SH7751_PCIIO(port) \ | |
76 | ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) | |
77 | #else | |
78 | #define CHECK_SH_7751_PCIIO(port) (0) | |
79 | #endif | |
80 | ||
81 | /* | |
82 | * General outline: remap really low stuff [eventually] to SuperIO, | |
83 | * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) | |
84 | * is mapped through the PCI IO window. Stuff with high bits (PXSEG) | |
85 | * should be way beyond the window, and is used w/o translation for | |
86 | * compatibility. | |
87 | */ | |
d7cdc9e8 | 88 | u8 landisk_inb(unsigned long port) |
94c0fa52 | 89 | { |
90 | if (PXSEG(port)) | |
d7cdc9e8 | 91 | return ctrl_inb(port); |
94c0fa52 | 92 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 PM |
93 | return ctrl_inb(PCI_IOMAP(port)); |
94 | ||
95 | return ctrl_inw(port2adr(port)) & 0xff; | |
94c0fa52 | 96 | } |
97 | ||
d7cdc9e8 | 98 | u8 landisk_inb_p(unsigned long port) |
94c0fa52 | 99 | { |
d7cdc9e8 | 100 | u8 v; |
94c0fa52 | 101 | |
102 | if (PXSEG(port)) | |
d7cdc9e8 | 103 | v = ctrl_inb(port); |
94c0fa52 | 104 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 105 | v = ctrl_inb(PCI_IOMAP(port)); |
94c0fa52 | 106 | else |
d7cdc9e8 PM |
107 | v = ctrl_inw(port2adr(port)) & 0xff; |
108 | ||
94c0fa52 | 109 | delay(); |
110 | ||
111 | return v; | |
112 | } | |
113 | ||
d7cdc9e8 | 114 | u16 landisk_inw(unsigned long port) |
94c0fa52 | 115 | { |
116 | if (PXSEG(port)) | |
d7cdc9e8 | 117 | return ctrl_inw(port); |
94c0fa52 | 118 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 119 | return ctrl_inw(PCI_IOMAP(port)); |
94c0fa52 | 120 | else |
d7cdc9e8 | 121 | maybebadio(port); |
94c0fa52 | 122 | |
123 | return 0; | |
124 | } | |
125 | ||
d7cdc9e8 | 126 | u32 landisk_inl(unsigned long port) |
94c0fa52 | 127 | { |
128 | if (PXSEG(port)) | |
d7cdc9e8 | 129 | return ctrl_inl(port); |
94c0fa52 | 130 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 131 | return ctrl_inl(PCI_IOMAP(port)); |
94c0fa52 | 132 | else |
d7cdc9e8 | 133 | maybebadio(port); |
94c0fa52 | 134 | |
135 | return 0; | |
136 | } | |
137 | ||
d7cdc9e8 | 138 | void landisk_outb(u8 value, unsigned long port) |
94c0fa52 | 139 | { |
94c0fa52 | 140 | if (PXSEG(port)) |
d7cdc9e8 | 141 | ctrl_outb(value, port); |
94c0fa52 | 142 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 143 | ctrl_outb(value, PCI_IOMAP(port)); |
94c0fa52 | 144 | else |
d7cdc9e8 | 145 | ctrl_outw(value, port2adr(port)); |
94c0fa52 | 146 | } |
147 | ||
d7cdc9e8 | 148 | void landisk_outb_p(u8 value, unsigned long port) |
94c0fa52 | 149 | { |
150 | if (PXSEG(port)) | |
d7cdc9e8 | 151 | ctrl_outb(value, port); |
94c0fa52 | 152 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 153 | ctrl_outb(value, PCI_IOMAP(port)); |
94c0fa52 | 154 | else |
d7cdc9e8 | 155 | ctrl_outw(value, port2adr(port)); |
94c0fa52 | 156 | delay(); |
157 | } | |
158 | ||
d7cdc9e8 | 159 | void landisk_outw(u16 value, unsigned long port) |
94c0fa52 | 160 | { |
161 | if (PXSEG(port)) | |
d7cdc9e8 | 162 | ctrl_outw(value, port); |
94c0fa52 | 163 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 164 | ctrl_outw(value, PCI_IOMAP(port)); |
94c0fa52 | 165 | else |
d7cdc9e8 | 166 | maybebadio(port); |
94c0fa52 | 167 | } |
168 | ||
d7cdc9e8 | 169 | void landisk_outl(u32 value, unsigned long port) |
94c0fa52 | 170 | { |
171 | if (PXSEG(port)) | |
d7cdc9e8 | 172 | ctrl_outl(value, port); |
94c0fa52 | 173 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 174 | ctrl_outl(value, PCI_IOMAP(port)); |
94c0fa52 | 175 | else |
d7cdc9e8 | 176 | maybebadio(port); |
94c0fa52 | 177 | } |
178 | ||
d7cdc9e8 | 179 | void landisk_insb(unsigned long port, void *dst, unsigned long count) |
94c0fa52 | 180 | { |
d7cdc9e8 PM |
181 | volatile u16 *p; |
182 | u8 *buf = dst; | |
94c0fa52 | 183 | |
d7cdc9e8 PM |
184 | if (PXSEG(port)) { |
185 | while (count--) | |
186 | *buf++ = *(volatile u8 *)port; | |
187 | } else if (CHECK_SH7751_PCIIO(port)) { | |
188 | volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port); | |
94c0fa52 | 189 | |
d7cdc9e8 PM |
190 | while (count--) |
191 | *buf++ = *bp; | |
192 | } else { | |
193 | p = (volatile u16 *)port2adr(port); | |
194 | while (count--) | |
195 | *buf++ = *p & 0xff; | |
94c0fa52 | 196 | } |
197 | } | |
198 | ||
d7cdc9e8 | 199 | void landisk_insw(unsigned long port, void *dst, unsigned long count) |
94c0fa52 | 200 | { |
d7cdc9e8 PM |
201 | volatile u16 *p; |
202 | u16 *buf = dst; | |
94c0fa52 | 203 | |
204 | if (PXSEG(port)) | |
d7cdc9e8 | 205 | p = (volatile u16 *)port; |
94c0fa52 | 206 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 207 | p = (volatile u16 *)PCI_IOMAP(port); |
94c0fa52 | 208 | else |
d7cdc9e8 | 209 | p = (volatile u16 *)port2adr(port); |
94c0fa52 | 210 | while (count--) |
d7cdc9e8 | 211 | *buf++ = *p; |
94c0fa52 | 212 | } |
213 | ||
d7cdc9e8 | 214 | void landisk_insl(unsigned long port, void *dst, unsigned long count) |
94c0fa52 | 215 | { |
d7cdc9e8 PM |
216 | u32 *buf = dst; |
217 | ||
94c0fa52 | 218 | if (CHECK_SH7751_PCIIO(port)) { |
d7cdc9e8 | 219 | volatile u32 *p = (volatile u32 *)PCI_IOMAP(port); |
94c0fa52 | 220 | |
d7cdc9e8 PM |
221 | while (count--) |
222 | *buf++ = *p; | |
94c0fa52 | 223 | } else |
d7cdc9e8 | 224 | maybebadio(port); |
94c0fa52 | 225 | } |
226 | ||
d7cdc9e8 | 227 | void landisk_outsb(unsigned long port, const void *src, unsigned long count) |
94c0fa52 | 228 | { |
d7cdc9e8 PM |
229 | volatile u16 *p; |
230 | const u8 *buf = src; | |
231 | ||
94c0fa52 | 232 | if (PXSEG(port)) |
d7cdc9e8 PM |
233 | while (count--) |
234 | ctrl_outb(*buf++, port); | |
94c0fa52 | 235 | else if (CHECK_SH7751_PCIIO(port)) { |
d7cdc9e8 | 236 | volatile u8 *bp = (volatile u8 *)PCI_IOMAP(port); |
94c0fa52 | 237 | |
d7cdc9e8 PM |
238 | while (count--) |
239 | *bp = *buf++; | |
94c0fa52 | 240 | } else { |
d7cdc9e8 PM |
241 | p = (volatile u16 *)port2adr(port); |
242 | while (count--) | |
243 | *p = *buf++; | |
94c0fa52 | 244 | } |
245 | } | |
246 | ||
d7cdc9e8 | 247 | void landisk_outsw(unsigned long port, const void *src, unsigned long count) |
94c0fa52 | 248 | { |
d7cdc9e8 PM |
249 | volatile u16 *p; |
250 | const u16 *buf = src; | |
94c0fa52 | 251 | |
252 | if (PXSEG(port)) | |
d7cdc9e8 | 253 | p = (volatile u16 *)port; |
94c0fa52 | 254 | else if (CHECK_SH7751_PCIIO(port)) |
d7cdc9e8 | 255 | p = (volatile u16 *)PCI_IOMAP(port); |
94c0fa52 | 256 | else |
d7cdc9e8 | 257 | p = (volatile u16 *)port2adr(port); |
94c0fa52 | 258 | |
d7cdc9e8 PM |
259 | while (count--) |
260 | *p = *buf++; | |
94c0fa52 | 261 | } |
262 | ||
d7cdc9e8 | 263 | void landisk_outsl(unsigned long port, const void *src, unsigned long count) |
94c0fa52 | 264 | { |
d7cdc9e8 | 265 | const u32 *buf = src; |
94c0fa52 | 266 | |
d7cdc9e8 PM |
267 | if (CHECK_SH7751_PCIIO(port)) { |
268 | volatile u32 *p = (volatile u32 *)PCI_IOMAP(port); | |
94c0fa52 | 269 | |
d7cdc9e8 PM |
270 | while (count--) |
271 | *p = *buf++; | |
272 | } else | |
273 | maybebadio(port); | |
94c0fa52 | 274 | } |
275 | ||
d7cdc9e8 | 276 | void __iomem *landisk_ioport_map(unsigned long port, unsigned int size) |
94c0fa52 | 277 | { |
d7cdc9e8 PM |
278 | if (PXSEG(port)) |
279 | return (void __iomem *)port; | |
280 | else if (CHECK_SH7751_PCIIO(port)) | |
281 | return (void __iomem *)PCI_IOMAP(port); | |
94c0fa52 | 282 | |
d7cdc9e8 | 283 | return (void __iomem *)port2adr(port); |
94c0fa52 | 284 | } |