diff options
Diffstat (limited to 'include/asm-arm/arch-ixp4xx/io.h')
-rw-r--r-- | include/asm-arm/arch-ixp4xx/io.h | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h new file mode 100644 index 000000000000..c27b9d3079a7 --- /dev/null +++ b/include/asm-arm/arch-ixp4xx/io.h | |||
@@ -0,0 +1,388 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-ixp4xx/io.h | ||
3 | * | ||
4 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
5 | * | ||
6 | * Copyright (C) 2002-2004 MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARM_ARCH_IO_H | ||
14 | #define __ASM_ARM_ARCH_IO_H | ||
15 | |||
16 | #include <asm/hardware.h> | ||
17 | |||
18 | #define IO_SPACE_LIMIT 0xffff0000 | ||
19 | |||
20 | #define BIT(x) ((1)<<(x)) | ||
21 | |||
22 | |||
23 | extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data); | ||
24 | extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); | ||
25 | |||
26 | |||
27 | /* | ||
28 | * IXP4xx provides two methods of accessing PCI memory space: | ||
29 | * | ||
30 | * 1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB). | ||
31 | * To access PCI via this space, we simply ioremap() the BAR | ||
32 | * into the kernel and we can use the standard read[bwl]/write[bwl] | ||
33 | * macros. This is the preffered method due to speed but it | ||
34 | * limits the system to just 64MB of PCI memory. This can be | ||
35 | * problamatic if using video cards and other memory-heavy | ||
36 | * targets. | ||
37 | * | ||
38 | * 2) If > 64MB of memory space is required, the IXP4xx can be configured | ||
39 | * to use indirect registers to access PCI (as we do below for I/O | ||
40 | * transactions). This allows for up to 128MB (0x48000000 to 0x4fffffff) | ||
41 | * of memory on the bus. The disadvantadge of this is that every | ||
42 | * PCI access requires three local register accesses plus a spinlock, | ||
43 | * but in some cases the performance hit is acceptable. In addition, | ||
44 | * you cannot mmap() PCI devices in this case. | ||
45 | * | ||
46 | */ | ||
47 | #ifndef CONFIG_IXP4XX_INDIRECT_PCI | ||
48 | |||
49 | #define __mem_pci(a) (a) | ||
50 | |||
51 | #else | ||
52 | |||
53 | #include <linux/mm.h> | ||
54 | |||
55 | /* | ||
56 | * In the case of using indirect PCI, we simply return the actual PCI | ||
57 | * address and our read/write implementation use that to drive the | ||
58 | * access registers. If something outside of PCI is ioremap'd, we | ||
59 | * fallback to the default. | ||
60 | */ | ||
61 | static inline void __iomem * | ||
62 | __ixp4xx_ioremap(unsigned long addr, size_t size, unsigned long flags, unsigned long align) | ||
63 | { | ||
64 | extern void __iomem * __ioremap(unsigned long, size_t, unsigned long, unsigned long); | ||
65 | if((addr < 0x48000000) || (addr > 0x4fffffff)) | ||
66 | return __ioremap(addr, size, flags, align); | ||
67 | |||
68 | return (void *)addr; | ||
69 | } | ||
70 | |||
71 | static inline void | ||
72 | __ixp4xx_iounmap(void __iomem *addr) | ||
73 | { | ||
74 | extern void __iounmap(void __iomem *addr); | ||
75 | |||
76 | if ((u32)addr >= VMALLOC_START) | ||
77 | __iounmap(addr); | ||
78 | } | ||
79 | |||
80 | #define __arch_ioremap(a, s, f, x) __ixp4xx_ioremap(a, s, f, x) | ||
81 | #define __arch_iounmap(a) __ixp4xx_iounmap(a) | ||
82 | |||
83 | #define writeb(p, v) __ixp4xx_writeb(p, v) | ||
84 | #define writew(p, v) __ixp4xx_writew(p, v) | ||
85 | #define writel(p, v) __ixp4xx_writel(p, v) | ||
86 | |||
87 | #define writesb(p, v, l) __ixp4xx_writesb(p, v, l) | ||
88 | #define writesw(p, v, l) __ixp4xx_writesw(p, v, l) | ||
89 | #define writesl(p, v, l) __ixp4xx_writesl(p, v, l) | ||
90 | |||
91 | #define readb(p) __ixp4xx_readb(p) | ||
92 | #define readw(p) __ixp4xx_readw(p) | ||
93 | #define readl(p) __ixp4xx_readl(p) | ||
94 | |||
95 | #define readsb(p, v, l) __ixp4xx_readsb(p, v, l) | ||
96 | #define readsw(p, v, l) __ixp4xx_readsw(p, v, l) | ||
97 | #define readsl(p, v, l) __ixp4xx_readsl(p, v, l) | ||
98 | |||
99 | static inline void | ||
100 | __ixp4xx_writeb(u8 value, u32 addr) | ||
101 | { | ||
102 | u32 n, byte_enables, data; | ||
103 | |||
104 | if (addr >= VMALLOC_START) { | ||
105 | __raw_writeb(value, addr); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | n = addr % 4; | ||
110 | byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL; | ||
111 | data = value << (8*n); | ||
112 | ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data); | ||
113 | } | ||
114 | |||
115 | static inline void | ||
116 | __ixp4xx_writesb(u32 bus_addr, u8 *vaddr, int count) | ||
117 | { | ||
118 | while (count--) | ||
119 | writeb(*vaddr++, bus_addr); | ||
120 | } | ||
121 | |||
122 | static inline void | ||
123 | __ixp4xx_writew(u16 value, u32 addr) | ||
124 | { | ||
125 | u32 n, byte_enables, data; | ||
126 | |||
127 | if (addr >= VMALLOC_START) { | ||
128 | __raw_writew(value, addr); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | n = addr % 4; | ||
133 | byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL; | ||
134 | data = value << (8*n); | ||
135 | ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data); | ||
136 | } | ||
137 | |||
138 | static inline void | ||
139 | __ixp4xx_writesw(u32 bus_addr, u16 *vaddr, int count) | ||
140 | { | ||
141 | while (count--) | ||
142 | writew(*vaddr++, bus_addr); | ||
143 | } | ||
144 | |||
145 | static inline void | ||
146 | __ixp4xx_writel(u32 value, u32 addr) | ||
147 | { | ||
148 | if (addr >= VMALLOC_START) { | ||
149 | __raw_writel(value, addr); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | ixp4xx_pci_write(addr, NP_CMD_MEMWRITE, value); | ||
154 | } | ||
155 | |||
156 | static inline void | ||
157 | __ixp4xx_writesl(u32 bus_addr, u32 *vaddr, int count) | ||
158 | { | ||
159 | while (count--) | ||
160 | writel(*vaddr++, bus_addr); | ||
161 | } | ||
162 | |||
163 | static inline unsigned char | ||
164 | __ixp4xx_readb(u32 addr) | ||
165 | { | ||
166 | u32 n, byte_enables, data; | ||
167 | |||
168 | if (addr >= VMALLOC_START) | ||
169 | return __raw_readb(addr); | ||
170 | |||
171 | n = addr % 4; | ||
172 | byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL; | ||
173 | if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_MEMREAD, &data)) | ||
174 | return 0xff; | ||
175 | |||
176 | return data >> (8*n); | ||
177 | } | ||
178 | |||
179 | static inline void | ||
180 | __ixp4xx_readsb(u32 bus_addr, u8 *vaddr, u32 count) | ||
181 | { | ||
182 | while (count--) | ||
183 | *vaddr++ = readb(bus_addr); | ||
184 | } | ||
185 | |||
186 | static inline unsigned short | ||
187 | __ixp4xx_readw(u32 addr) | ||
188 | { | ||
189 | u32 n, byte_enables, data; | ||
190 | |||
191 | if (addr >= VMALLOC_START) | ||
192 | return __raw_readw(addr); | ||
193 | |||
194 | n = addr % 4; | ||
195 | byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL; | ||
196 | if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_MEMREAD, &data)) | ||
197 | return 0xffff; | ||
198 | |||
199 | return data>>(8*n); | ||
200 | } | ||
201 | |||
202 | static inline void | ||
203 | __ixp4xx_readsw(u32 bus_addr, u16 *vaddr, u32 count) | ||
204 | { | ||
205 | while (count--) | ||
206 | *vaddr++ = readw(bus_addr); | ||
207 | } | ||
208 | |||
209 | static inline unsigned long | ||
210 | __ixp4xx_readl(u32 addr) | ||
211 | { | ||
212 | u32 data; | ||
213 | |||
214 | if (addr >= VMALLOC_START) | ||
215 | return __raw_readl(addr); | ||
216 | |||
217 | if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data)) | ||
218 | return 0xffffffff; | ||
219 | |||
220 | return data; | ||
221 | } | ||
222 | |||
223 | static inline void | ||
224 | __ixp4xx_readsl(u32 bus_addr, u32 *vaddr, u32 count) | ||
225 | { | ||
226 | while (count--) | ||
227 | *vaddr++ = readl(bus_addr); | ||
228 | } | ||
229 | |||
230 | |||
231 | /* | ||
232 | * We can use the built-in functions b/c they end up calling writeb/readb | ||
233 | */ | ||
234 | #define memset_io(c,v,l) _memset_io((c),(v),(l)) | ||
235 | #define memcpy_fromio(a,c,l) _memcpy_fromio((a),(c),(l)) | ||
236 | #define memcpy_toio(c,a,l) _memcpy_toio((c),(a),(l)) | ||
237 | |||
238 | #define eth_io_copy_and_sum(s,c,l,b) \ | ||
239 | eth_copy_and_sum((s),__mem_pci(c),(l),(b)) | ||
240 | |||
241 | static inline int | ||
242 | check_signature(unsigned long bus_addr, const unsigned char *signature, | ||
243 | int length) | ||
244 | { | ||
245 | int retval = 0; | ||
246 | do { | ||
247 | if (readb(bus_addr) != *signature) | ||
248 | goto out; | ||
249 | bus_addr++; | ||
250 | signature++; | ||
251 | length--; | ||
252 | } while (length); | ||
253 | retval = 1; | ||
254 | out: | ||
255 | return retval; | ||
256 | } | ||
257 | |||
258 | #endif | ||
259 | |||
260 | /* | ||
261 | * IXP4xx does not have a transparent cpu -> PCI I/O translation | ||
262 | * window. Instead, it has a set of registers that must be tweaked | ||
263 | * with the proper byte lanes, command types, and address for the | ||
264 | * transaction. This means that we need to override the default | ||
265 | * I/O functions. | ||
266 | */ | ||
267 | #define outb(p, v) __ixp4xx_outb(p, v) | ||
268 | #define outw(p, v) __ixp4xx_outw(p, v) | ||
269 | #define outl(p, v) __ixp4xx_outl(p, v) | ||
270 | |||
271 | #define outsb(p, v, l) __ixp4xx_outsb(p, v, l) | ||
272 | #define outsw(p, v, l) __ixp4xx_outsw(p, v, l) | ||
273 | #define outsl(p, v, l) __ixp4xx_outsl(p, v, l) | ||
274 | |||
275 | #define inb(p) __ixp4xx_inb(p) | ||
276 | #define inw(p) __ixp4xx_inw(p) | ||
277 | #define inl(p) __ixp4xx_inl(p) | ||
278 | |||
279 | #define insb(p, v, l) __ixp4xx_insb(p, v, l) | ||
280 | #define insw(p, v, l) __ixp4xx_insw(p, v, l) | ||
281 | #define insl(p, v, l) __ixp4xx_insl(p, v, l) | ||
282 | |||
283 | |||
284 | static inline void | ||
285 | __ixp4xx_outb(u8 value, u32 addr) | ||
286 | { | ||
287 | u32 n, byte_enables, data; | ||
288 | n = addr % 4; | ||
289 | byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL; | ||
290 | data = value << (8*n); | ||
291 | ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data); | ||
292 | } | ||
293 | |||
294 | static inline void | ||
295 | __ixp4xx_outsb(u32 io_addr, const u8 *vaddr, u32 count) | ||
296 | { | ||
297 | while (count--) | ||
298 | outb(*vaddr++, io_addr); | ||
299 | } | ||
300 | |||
301 | static inline void | ||
302 | __ixp4xx_outw(u16 value, u32 addr) | ||
303 | { | ||
304 | u32 n, byte_enables, data; | ||
305 | n = addr % 4; | ||
306 | byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL; | ||
307 | data = value << (8*n); | ||
308 | ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data); | ||
309 | } | ||
310 | |||
311 | static inline void | ||
312 | __ixp4xx_outsw(u32 io_addr, const u16 *vaddr, u32 count) | ||
313 | { | ||
314 | while (count--) | ||
315 | outw(cpu_to_le16(*vaddr++), io_addr); | ||
316 | } | ||
317 | |||
318 | static inline void | ||
319 | __ixp4xx_outl(u32 value, u32 addr) | ||
320 | { | ||
321 | ixp4xx_pci_write(addr, NP_CMD_IOWRITE, value); | ||
322 | } | ||
323 | |||
324 | static inline void | ||
325 | __ixp4xx_outsl(u32 io_addr, const u32 *vaddr, u32 count) | ||
326 | { | ||
327 | while (count--) | ||
328 | outl(*vaddr++, io_addr); | ||
329 | } | ||
330 | |||
331 | static inline u8 | ||
332 | __ixp4xx_inb(u32 addr) | ||
333 | { | ||
334 | u32 n, byte_enables, data; | ||
335 | n = addr % 4; | ||
336 | byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL; | ||
337 | if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_IOREAD, &data)) | ||
338 | return 0xff; | ||
339 | |||
340 | return data >> (8*n); | ||
341 | } | ||
342 | |||
343 | static inline void | ||
344 | __ixp4xx_insb(u32 io_addr, u8 *vaddr, u32 count) | ||
345 | { | ||
346 | while (count--) | ||
347 | *vaddr++ = inb(io_addr); | ||
348 | } | ||
349 | |||
350 | static inline u16 | ||
351 | __ixp4xx_inw(u32 addr) | ||
352 | { | ||
353 | u32 n, byte_enables, data; | ||
354 | n = addr % 4; | ||
355 | byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL; | ||
356 | if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_IOREAD, &data)) | ||
357 | return 0xffff; | ||
358 | |||
359 | return data>>(8*n); | ||
360 | } | ||
361 | |||
362 | static inline void | ||
363 | __ixp4xx_insw(u32 io_addr, u16 *vaddr, u32 count) | ||
364 | { | ||
365 | while (count--) | ||
366 | *vaddr++ = le16_to_cpu(inw(io_addr)); | ||
367 | } | ||
368 | |||
369 | static inline u32 | ||
370 | __ixp4xx_inl(u32 addr) | ||
371 | { | ||
372 | u32 data; | ||
373 | if (ixp4xx_pci_read(addr, NP_CMD_IOREAD, &data)) | ||
374 | return 0xffffffff; | ||
375 | |||
376 | return data; | ||
377 | } | ||
378 | |||
379 | static inline void | ||
380 | __ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count) | ||
381 | { | ||
382 | while (count--) | ||
383 | *vaddr++ = inl(io_addr); | ||
384 | } | ||
385 | |||
386 | |||
387 | #endif // __ASM_ARM_ARCH_IO_H | ||
388 | |||