aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-avr32/io.h
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-02-12 10:28:56 -0500
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-04-27 07:44:14 -0400
commite3e7d8d4ea37b8372ee417452d03171c5dc55125 (patch)
tree247a899f472e5cf1a3f7467dda88a017bee134a6 /include/asm-avr32/io.h
parent92b728c147adb8c690b520304f4c9ee3eee43c21 (diff)
[AVR32] Make I/O access macros work with external devices
Fix the I/O access macros so that they work with externally connected devices accessed in little-endian mode over any bus width: * Use a set of macros to define I/O port- and memory operations borrowed from MIPS. * Allow subarchitecture to specify address- and data-mangling * Implement at32ap-specific port mangling (with build-time configurable bus width. Only one bus width at a time supported for now.) * Rewrite iowriteN and friends to use write[bwl] and friends (not the __raw counterparts.) This has been tested using pata_pcmcia to access a CompactFlash card connected to the EBI (16-bit bus width.) Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'include/asm-avr32/io.h')
-rw-r--r--include/asm-avr32/io.h335
1 files changed, 183 insertions, 152 deletions
diff --git a/include/asm-avr32/io.h b/include/asm-avr32/io.h
index c08e81048393..27b1523d42e0 100644
--- a/include/asm-avr32/io.h
+++ b/include/asm-avr32/io.h
@@ -1,13 +1,15 @@
1#ifndef __ASM_AVR32_IO_H 1#ifndef __ASM_AVR32_IO_H
2#define __ASM_AVR32_IO_H 2#define __ASM_AVR32_IO_H
3 3
4#include <linux/kernel.h>
4#include <linux/string.h> 5#include <linux/string.h>
5 6#include <linux/types.h>
6#ifdef __KERNEL__
7 7
8#include <asm/addrspace.h> 8#include <asm/addrspace.h>
9#include <asm/byteorder.h> 9#include <asm/byteorder.h>
10 10
11#include <asm/arch/io.h>
12
11/* virt_to_phys will only work when address is in P1 or P2 */ 13/* virt_to_phys will only work when address is in P1 or P2 */
12static __inline__ unsigned long virt_to_phys(volatile void *address) 14static __inline__ unsigned long virt_to_phys(volatile void *address)
13{ 15{
@@ -36,204 +38,235 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
36extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); 38extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
37extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); 39extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
38 40
39static inline void writeb(unsigned char b, volatile void __iomem *addr) 41static inline void __raw_writeb(u8 v, volatile void __iomem *addr)
40{ 42{
41 *(volatile unsigned char __force *)addr = b; 43 *(volatile u8 __force *)addr = v;
42} 44}
43static inline void writew(unsigned short b, volatile void __iomem *addr) 45static inline void __raw_writew(u16 v, volatile void __iomem *addr)
44{ 46{
45 *(volatile unsigned short __force *)addr = b; 47 *(volatile u16 __force *)addr = v;
46} 48}
47static inline void writel(unsigned int b, volatile void __iomem *addr) 49static inline void __raw_writel(u32 v, volatile void __iomem *addr)
48{ 50{
49 *(volatile unsigned int __force *)addr = b; 51 *(volatile u32 __force *)addr = v;
50} 52}
51#define __raw_writeb writeb
52#define __raw_writew writew
53#define __raw_writel writel
54 53
55static inline unsigned char readb(const volatile void __iomem *addr) 54static inline u8 __raw_readb(const volatile void __iomem *addr)
56{ 55{
57 return *(const volatile unsigned char __force *)addr; 56 return *(const volatile u8 __force *)addr;
58} 57}
59static inline unsigned short readw(const volatile void __iomem *addr) 58static inline u16 __raw_readw(const volatile void __iomem *addr)
60{ 59{
61 return *(const volatile unsigned short __force *)addr; 60 return *(const volatile u16 __force *)addr;
62} 61}
63static inline unsigned int readl(const volatile void __iomem *addr) 62static inline u32 __raw_readl(const volatile void __iomem *addr)
64{ 63{
65 return *(const volatile unsigned int __force *)addr; 64 return *(const volatile u32 __force *)addr;
65}
66
67/* Convert I/O port address to virtual address */
68#ifndef __io
69# define __io(p) ((void *)phys_to_uncached(p))
70#endif
71
72/*
73 * Not really sure about the best way to slow down I/O on
74 * AVR32. Defining it as a no-op until we have an actual test case.
75 */
76#define SLOW_DOWN_IO do { } while (0)
77
78#define __BUILD_MEMORY_SINGLE(pfx, bwl, type) \
79static inline void \
80pfx##write##bwl(type val, volatile void __iomem *addr) \
81{ \
82 volatile type *__addr; \
83 type __val; \
84 \
85 __addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr)); \
86 __val = pfx##ioswab##bwl(__addr, val); \
87 \
88 BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
89 \
90 *__addr = __val; \
91} \
92 \
93static inline type pfx##read##bwl(const volatile void __iomem *addr) \
94{ \
95 volatile type *__addr; \
96 type __val; \
97 \
98 __addr = (void *)__swizzle_addr_##bwl((unsigned long)(addr)); \
99 \
100 BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
101 \
102 __val = *__addr; \
103 return pfx##ioswab##bwl(__addr, __val); \
104}
105
106#define __BUILD_IOPORT_SINGLE(pfx, bwl, type, p, slow) \
107static inline void pfx##out##bwl##p(type val, unsigned long port) \
108{ \
109 volatile type *__addr; \
110 type __val; \
111 \
112 __addr = __io(__swizzle_addr_##bwl(port)); \
113 __val = pfx##ioswab##bwl(__addr, val); \
114 \
115 BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
116 \
117 *__addr = __val; \
118 slow; \
119} \
120 \
121static inline type pfx##in##bwl##p(unsigned long port) \
122{ \
123 volatile type *__addr; \
124 type __val; \
125 \
126 __addr = __io(__swizzle_addr_##bwl(port)); \
127 \
128 BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
129 \
130 __val = *__addr; \
131 slow; \
132 \
133 return pfx##ioswab##bwl(__addr, __val); \
66} 134}
67#define __raw_readb readb
68#define __raw_readw readw
69#define __raw_readl readl
70 135
71#define writesb(p, d, l) __raw_writesb((unsigned int)p, d, l) 136#define __BUILD_MEMORY_PFX(bus, bwl, type) \
72#define writesw(p, d, l) __raw_writesw((unsigned int)p, d, l) 137 __BUILD_MEMORY_SINGLE(bus, bwl, type)
73#define writesl(p, d, l) __raw_writesl((unsigned int)p, d, l) 138
139#define BUILDIO_MEM(bwl, type) \
140 __BUILD_MEMORY_PFX(, bwl, type) \
141 __BUILD_MEMORY_PFX(__mem_, bwl, type)
142
143#define __BUILD_IOPORT_PFX(bus, bwl, type) \
144 __BUILD_IOPORT_SINGLE(bus, bwl, type, ,) \
145 __BUILD_IOPORT_SINGLE(bus, bwl, type, _p, SLOW_DOWN_IO)
146
147#define BUILDIO_IOPORT(bwl, type) \
148 __BUILD_IOPORT_PFX(, bwl, type) \
149 __BUILD_IOPORT_PFX(__mem_, bwl, type)
150
151BUILDIO_MEM(b, u8)
152BUILDIO_MEM(w, u16)
153BUILDIO_MEM(l, u32)
154
155BUILDIO_IOPORT(b, u8)
156BUILDIO_IOPORT(w, u16)
157BUILDIO_IOPORT(l, u32)
158
159#define readb_relaxed readb
160#define readw_relaxed readw
161#define readl_relaxed readl
162
163#define __BUILD_MEMORY_STRING(bwl, type) \
164static inline void writes##bwl(volatile void __iomem *addr, \
165 const void *data, unsigned int count) \
166{ \
167 const type *__data = data; \
168 \
169 while (count--) \
170 __mem_write##bwl(*__data++, addr); \
171} \
172 \
173static inline void reads##bwl(const volatile void __iomem *addr, \
174 void *data, unsigned int count) \
175{ \
176 type *__data = data; \
177 \
178 while (count--) \
179 *__data++ = __mem_read##bwl(addr); \
180}
181
182#define __BUILD_IOPORT_STRING(bwl, type) \
183static inline void outs##bwl(unsigned long port, const void *data, \
184 unsigned int count) \
185{ \
186 const type *__data = data; \
187 \
188 while (count--) \
189 __mem_out##bwl(*__data++, port); \
190} \
191 \
192static inline void ins##bwl(unsigned long port, void *data, \
193 unsigned int count) \
194{ \
195 type *__data = data; \
196 \
197 while (count--) \
198 *__data++ = __mem_in##bwl(port); \
199}
74 200
75#define readsb(p, d, l) __raw_readsb((unsigned int)p, d, l) 201#define BUILDSTRING(bwl, type) \
76#define readsw(p, d, l) __raw_readsw((unsigned int)p, d, l) 202 __BUILD_MEMORY_STRING(bwl, type) \
77#define readsl(p, d, l) __raw_readsl((unsigned int)p, d, l) 203 __BUILD_IOPORT_STRING(bwl, type)
78 204
205BUILDSTRING(b, u8)
206BUILDSTRING(w, u16)
207BUILDSTRING(l, u32)
79 208
80/* 209/*
81 * io{read,write}{8,16,32} macros in both le (for PCI style consumers) and native be 210 * io{read,write}{8,16,32} macros in both le (for PCI style consumers) and native be
82 */ 211 */
83#ifndef ioread8 212#ifndef ioread8
84 213
85#define ioread8(p) ({ unsigned int __v = __raw_readb(p); __v; }) 214#define ioread8(p) ((unsigned int)readb(p))
86 215
87#define ioread16(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; }) 216#define ioread16(p) ((unsigned int)readw(p))
88#define ioread16be(p) ({ unsigned int __v = be16_to_cpu(__raw_readw(p)); __v; }) 217#define ioread16be(p) ((unsigned int)__raw_readw(p))
89 218
90#define ioread32(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; }) 219#define ioread32(p) ((unsigned int)readl(p))
91#define ioread32be(p) ({ unsigned int __v = be32_to_cpu(__raw_readl(p)); __v; }) 220#define ioread32be(p) ((unsigned int)__raw_readl(p))
92 221
93#define iowrite8(v,p) __raw_writeb(v, p) 222#define iowrite8(v,p) writeb(v, p)
94 223
95#define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p) 224#define iowrite16(v,p) writew(v, p)
96#define iowrite16be(v,p) __raw_writew(cpu_to_be16(v), p) 225#define iowrite16be(v,p) __raw_writew(v, p)
97 226
98#define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p) 227#define iowrite32(v,p) writel(v, p)
99#define iowrite32be(v,p) __raw_writel(cpu_to_be32(v), p) 228#define iowrite32be(v,p) __raw_writel(v, p)
100 229
101#define ioread8_rep(p,d,c) __raw_readsb(p,d,c) 230#define ioread8_rep(p,d,c) readsb(p,d,c)
102#define ioread16_rep(p,d,c) __raw_readsw(p,d,c) 231#define ioread16_rep(p,d,c) readsw(p,d,c)
103#define ioread32_rep(p,d,c) __raw_readsl(p,d,c) 232#define ioread32_rep(p,d,c) readsl(p,d,c)
104 233
105#define iowrite8_rep(p,s,c) __raw_writesb(p,s,c) 234#define iowrite8_rep(p,s,c) writesb(p,s,c)
106#define iowrite16_rep(p,s,c) __raw_writesw(p,s,c) 235#define iowrite16_rep(p,s,c) writesw(p,s,c)
107#define iowrite32_rep(p,s,c) __raw_writesl(p,s,c) 236#define iowrite32_rep(p,s,c) writesl(p,s,c)
108 237
109#endif 238#endif
110 239
111
112/*
113 * These two are only here because ALSA _thinks_ it needs them...
114 */
115static inline void memcpy_fromio(void * to, const volatile void __iomem *from, 240static inline void memcpy_fromio(void * to, const volatile void __iomem *from,
116 unsigned long count) 241 unsigned long count)
117{ 242{
118 char *p = to; 243 char *p = to;
119 while (count) { 244 volatile const char __iomem *addr = from;
120 count--; 245
121 *p = readb(from); 246 while (count--)
122 p++; 247 *p++ = readb(addr++);
123 from++;
124 }
125} 248}
126 249
127static inline void memcpy_toio(volatile void __iomem *to, const void * from, 250static inline void memcpy_toio(volatile void __iomem *to, const void * from,
128 unsigned long count) 251 unsigned long count)
129{ 252{
130 const char *p = from; 253 const char *p = from;
131 while (count) { 254 volatile char __iomem *addr = to;
132 count--; 255
133 writeb(*p, to); 256 while (count--)
134 p++; 257 writeb(*p++, addr++);
135 to++;
136 }
137} 258}
138 259
139static inline void memset_io(volatile void __iomem *addr, unsigned char val, 260static inline void memset_io(volatile void __iomem *addr, unsigned char val,
140 unsigned long count) 261 unsigned long count)
141{ 262{
142 memset((void __force *)addr, val, count); 263 volatile char __iomem *p = addr;
143}
144
145/*
146 * Bad read/write accesses...
147 */
148extern void __readwrite_bug(const char *fn);
149
150#define IO_SPACE_LIMIT 0xffffffff
151
152/* Convert I/O port address to virtual address */
153#define __io(p) ((void __iomem *)phys_to_uncached(p))
154
155/*
156 * IO port access primitives
157 * -------------------------
158 *
159 * The AVR32 doesn't have special IO access instructions; all IO is memory
160 * mapped. Note that these are defined to perform little endian accesses
161 * only. Their primary purpose is to access PCI and ISA peripherals.
162 *
163 * Note that for a big endian machine, this implies that the following
164 * big endian mode connectivity is in place.
165 *
166 * The machine specific io.h include defines __io to translate an "IO"
167 * address to a memory address.
168 *
169 * Note that we prevent GCC re-ordering or caching values in expressions
170 * by introducing sequence points into the in*() definitions. Note that
171 * __raw_* do not guarantee this behaviour.
172 *
173 * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
174 */
175#define outb(v, p) __raw_writeb(v, __io(p))
176#define outw(v, p) __raw_writew(cpu_to_le16(v), __io(p))
177#define outl(v, p) __raw_writel(cpu_to_le32(v), __io(p))
178
179#define inb(p) __raw_readb(__io(p))
180#define inw(p) le16_to_cpu(__raw_readw(__io(p)))
181#define inl(p) le32_to_cpu(__raw_readl(__io(p)))
182
183static inline void __outsb(unsigned long port, void *addr, unsigned int count)
184{
185 while (count--) {
186 outb(*(u8 *)addr, port);
187 addr++;
188 }
189}
190 264
191static inline void __insb(unsigned long port, void *addr, unsigned int count) 265 while (count--)
192{ 266 writeb(val, p++);
193 while (count--) {
194 *(u8 *)addr = inb(port);
195 addr++;
196 }
197} 267}
198 268
199static inline void __outsw(unsigned long port, void *addr, unsigned int count) 269#define IO_SPACE_LIMIT 0xffffffff
200{
201 while (count--) {
202 outw(*(u16 *)addr, port);
203 addr += 2;
204 }
205}
206
207static inline void __insw(unsigned long port, void *addr, unsigned int count)
208{
209 while (count--) {
210 *(u16 *)addr = inw(port);
211 addr += 2;
212 }
213}
214
215static inline void __outsl(unsigned long port, void *addr, unsigned int count)
216{
217 while (count--) {
218 outl(*(u32 *)addr, port);
219 addr += 4;
220 }
221}
222
223static inline void __insl(unsigned long port, void *addr, unsigned int count)
224{
225 while (count--) {
226 *(u32 *)addr = inl(port);
227 addr += 4;
228 }
229}
230
231#define outsb(port, addr, count) __outsb(port, addr, count)
232#define insb(port, addr, count) __insb(port, addr, count)
233#define outsw(port, addr, count) __outsw(port, addr, count)
234#define insw(port, addr, count) __insw(port, addr, count)
235#define outsl(port, addr, count) __outsl(port, addr, count)
236#define insl(port, addr, count) __insl(port, addr, count)
237 270
238extern void __iomem *__ioremap(unsigned long offset, size_t size, 271extern void __iomem *__ioremap(unsigned long offset, size_t size,
239 unsigned long flags); 272 unsigned long flags);
@@ -292,6 +325,4 @@ extern void __iounmap(void __iomem *addr);
292 */ 325 */
293#define xlate_dev_kmem_ptr(p) p 326#define xlate_dev_kmem_ptr(p) p
294 327
295#endif /* __KERNEL__ */
296
297#endif /* __ASM_AVR32_IO_H */ 328#endif /* __ASM_AVR32_IO_H */