Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _H8300_IO_H |
2 | #define _H8300_IO_H | |
3 | ||
4 | #ifdef __KERNEL__ | |
5 | ||
1da177e4 LT |
6 | #include <asm/virtconvert.h> |
7 | ||
8 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) | |
9 | #include <asm/regs306x.h> | |
10 | #elif defined(CONFIG_H8S2678) | |
11 | #include <asm/regs267x.h> | |
12 | #else | |
13 | #error UNKNOWN CPU TYPE | |
14 | #endif | |
15 | ||
16 | ||
17 | /* | |
18 | * These are for ISA/PCI shared memory _only_ and should never be used | |
19 | * on any other type of memory, including Zorro memory. They are meant to | |
20 | * access the bus in the bus byte order which is little-endian!. | |
21 | * | |
22 | * readX/writeX() are used to access memory mapped devices. On some | |
23 | * architectures the memory mapped IO stuff needs to be accessed | |
24 | * differently. On the m68k architecture, we just read/write the | |
25 | * memory location directly. | |
26 | */ | |
27 | /* ++roman: The assignments to temp. vars avoid that gcc sometimes generates | |
28 | * two accesses to memory, which may be undesireable for some devices. | |
29 | */ | |
30 | ||
31 | /* | |
32 | * swap functions are sometimes needed to interface little-endian hardware | |
33 | */ | |
34 | ||
35 | static inline unsigned short _swapw(volatile unsigned short v) | |
36 | { | |
37 | #ifndef H8300_IO_NOSWAP | |
38 | unsigned short r; | |
39 | __asm__("xor.b %w0,%x0\n\t" | |
40 | "xor.b %x0,%w0\n\t" | |
41 | "xor.b %w0,%x0" | |
42 | :"=r"(r) | |
43 | :"0"(v)); | |
44 | return r; | |
45 | #else | |
46 | return v; | |
47 | #endif | |
48 | } | |
49 | ||
50 | static inline unsigned long _swapl(volatile unsigned long v) | |
51 | { | |
52 | #ifndef H8300_IO_NOSWAP | |
53 | unsigned long r; | |
54 | __asm__("xor.b %w0,%x0\n\t" | |
55 | "xor.b %x0,%w0\n\t" | |
56 | "xor.b %w0,%x0\n\t" | |
57 | "xor.w %e0,%f0\n\t" | |
58 | "xor.w %f0,%e0\n\t" | |
59 | "xor.w %e0,%f0\n\t" | |
60 | "xor.b %w0,%x0\n\t" | |
61 | "xor.b %x0,%w0\n\t" | |
62 | "xor.b %w0,%x0" | |
63 | :"=r"(r) | |
64 | :"0"(v)); | |
65 | return r; | |
66 | #else | |
67 | return v; | |
68 | #endif | |
69 | } | |
70 | ||
71 | #define readb(addr) \ | |
72 | ({ unsigned char __v = \ | |
73 | *(volatile unsigned char *)((unsigned long)(addr) & 0x00ffffff); \ | |
74 | __v; }) | |
75 | #define readw(addr) \ | |
76 | ({ unsigned short __v = \ | |
77 | *(volatile unsigned short *)((unsigned long)(addr) & 0x00ffffff); \ | |
78 | __v; }) | |
79 | #define readl(addr) \ | |
80 | ({ unsigned long __v = \ | |
81 | *(volatile unsigned long *)((unsigned long)(addr) & 0x00ffffff); \ | |
82 | __v; }) | |
83 | ||
84 | #define writeb(b,addr) (void)((*(volatile unsigned char *) \ | |
85 | ((unsigned long)(addr) & 0x00ffffff)) = (b)) | |
86 | #define writew(b,addr) (void)((*(volatile unsigned short *) \ | |
87 | ((unsigned long)(addr) & 0x00ffffff)) = (b)) | |
88 | #define writel(b,addr) (void)((*(volatile unsigned long *) \ | |
89 | ((unsigned long)(addr) & 0x00ffffff)) = (b)) | |
90 | #define readb_relaxed(addr) readb(addr) | |
91 | #define readw_relaxed(addr) readw(addr) | |
92 | #define readl_relaxed(addr) readl(addr) | |
93 | ||
94 | #define __raw_readb readb | |
95 | #define __raw_readw readw | |
96 | #define __raw_readl readl | |
97 | #define __raw_writeb writeb | |
98 | #define __raw_writew writew | |
99 | #define __raw_writel writel | |
100 | ||
101 | static inline int h8300_buswidth(unsigned int addr) | |
102 | { | |
103 | return (*(volatile unsigned char *)ABWCR & (1 << ((addr >> 21) & 7))) == 0; | |
104 | } | |
105 | ||
106 | static inline void io_outsb(unsigned int addr, const void *buf, int len) | |
107 | { | |
108 | volatile unsigned char *ap_b = (volatile unsigned char *) addr; | |
109 | volatile unsigned short *ap_w = (volatile unsigned short *) addr; | |
110 | unsigned char *bp = (unsigned char *) buf; | |
111 | ||
112 | if(h8300_buswidth(addr) && (addr & 1)) { | |
113 | while (len--) | |
114 | *ap_w = *bp++; | |
115 | } else { | |
116 | while (len--) | |
117 | *ap_b = *bp++; | |
118 | } | |
119 | } | |
120 | ||
121 | static inline void io_outsw(unsigned int addr, const void *buf, int len) | |
122 | { | |
123 | volatile unsigned short *ap = (volatile unsigned short *) addr; | |
124 | unsigned short *bp = (unsigned short *) buf; | |
125 | while (len--) | |
126 | *ap = _swapw(*bp++); | |
127 | } | |
128 | ||
129 | static inline void io_outsl(unsigned int addr, const void *buf, int len) | |
130 | { | |
131 | volatile unsigned long *ap = (volatile unsigned long *) addr; | |
132 | unsigned long *bp = (unsigned long *) buf; | |
133 | while (len--) | |
134 | *ap = _swapl(*bp++); | |
135 | } | |
136 | ||
137 | static inline void io_outsw_noswap(unsigned int addr, const void *buf, int len) | |
138 | { | |
139 | volatile unsigned short *ap = (volatile unsigned short *) addr; | |
140 | unsigned short *bp = (unsigned short *) buf; | |
141 | while (len--) | |
142 | *ap = *bp++; | |
143 | } | |
144 | ||
145 | static inline void io_outsl_noswap(unsigned int addr, const void *buf, int len) | |
146 | { | |
147 | volatile unsigned long *ap = (volatile unsigned long *) addr; | |
148 | unsigned long *bp = (unsigned long *) buf; | |
149 | while (len--) | |
150 | *ap = *bp++; | |
151 | } | |
152 | ||
153 | static inline void io_insb(unsigned int addr, void *buf, int len) | |
154 | { | |
155 | volatile unsigned char *ap_b; | |
156 | volatile unsigned short *ap_w; | |
157 | unsigned char *bp = (unsigned char *) buf; | |
158 | ||
159 | if(h8300_buswidth(addr)) { | |
160 | ap_w = (volatile unsigned short *)(addr & ~1); | |
161 | while (len--) | |
162 | *bp++ = *ap_w & 0xff; | |
163 | } else { | |
164 | ap_b = (volatile unsigned char *)addr; | |
165 | while (len--) | |
166 | *bp++ = *ap_b; | |
167 | } | |
168 | } | |
169 | ||
170 | static inline void io_insw(unsigned int addr, void *buf, int len) | |
171 | { | |
172 | volatile unsigned short *ap = (volatile unsigned short *) addr; | |
173 | unsigned short *bp = (unsigned short *) buf; | |
174 | while (len--) | |
175 | *bp++ = _swapw(*ap); | |
176 | } | |
177 | ||
178 | static inline void io_insl(unsigned int addr, void *buf, int len) | |
179 | { | |
180 | volatile unsigned long *ap = (volatile unsigned long *) addr; | |
181 | unsigned long *bp = (unsigned long *) buf; | |
182 | while (len--) | |
183 | *bp++ = _swapl(*ap); | |
184 | } | |
185 | ||
186 | static inline void io_insw_noswap(unsigned int addr, void *buf, int len) | |
187 | { | |
188 | volatile unsigned short *ap = (volatile unsigned short *) addr; | |
189 | unsigned short *bp = (unsigned short *) buf; | |
190 | while (len--) | |
191 | *bp++ = *ap; | |
192 | } | |
193 | ||
194 | static inline void io_insl_noswap(unsigned int addr, void *buf, int len) | |
195 | { | |
196 | volatile unsigned long *ap = (volatile unsigned long *) addr; | |
197 | unsigned long *bp = (unsigned long *) buf; | |
198 | while (len--) | |
199 | *bp++ = *ap; | |
200 | } | |
201 | ||
202 | /* | |
203 | * make the short names macros so specific devices | |
204 | * can override them as required | |
205 | */ | |
206 | ||
207 | #define memset_io(a,b,c) memset((void *)(a),(b),(c)) | |
208 | #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) | |
209 | #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) | |
210 | ||
211 | #define mmiowb() | |
212 | ||
213 | #define inb(addr) ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr)) | |
214 | #define inw(addr) _swapw(readw(addr)) | |
215 | #define inl(addr) _swapl(readl(addr)) | |
216 | #define outb(x,addr) ((void)((h8300_buswidth(addr) && \ | |
217 | ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr))) | |
218 | #define outw(x,addr) ((void) writew(_swapw(x),addr)) | |
219 | #define outl(x,addr) ((void) writel(_swapl(x),addr)) | |
220 | ||
221 | #define inb_p(addr) inb(addr) | |
222 | #define inw_p(addr) inw(addr) | |
223 | #define inl_p(addr) inl(addr) | |
224 | #define outb_p(x,addr) outb(x,addr) | |
225 | #define outw_p(x,addr) outw(x,addr) | |
226 | #define outl_p(x,addr) outl(x,addr) | |
227 | ||
228 | #define outsb(a,b,l) io_outsb(a,b,l) | |
229 | #define outsw(a,b,l) io_outsw(a,b,l) | |
230 | #define outsl(a,b,l) io_outsl(a,b,l) | |
231 | ||
232 | #define insb(a,b,l) io_insb(a,b,l) | |
233 | #define insw(a,b,l) io_insw(a,b,l) | |
234 | #define insl(a,b,l) io_insl(a,b,l) | |
235 | ||
236 | #define IO_SPACE_LIMIT 0xffffff | |
237 | ||
238 | ||
239 | /* Values for nocacheflag and cmode */ | |
240 | #define IOMAP_FULL_CACHING 0 | |
241 | #define IOMAP_NOCACHE_SER 1 | |
242 | #define IOMAP_NOCACHE_NONSER 2 | |
243 | #define IOMAP_WRITETHROUGH 3 | |
244 | ||
245 | extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); | |
246 | extern void __iounmap(void *addr, unsigned long size); | |
247 | ||
248 | static inline void *ioremap(unsigned long physaddr, unsigned long size) | |
249 | { | |
250 | return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); | |
251 | } | |
252 | static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size) | |
253 | { | |
254 | return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); | |
255 | } | |
256 | static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size) | |
257 | { | |
258 | return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); | |
259 | } | |
260 | static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size) | |
261 | { | |
262 | return __ioremap(physaddr, size, IOMAP_FULL_CACHING); | |
263 | } | |
264 | ||
265 | extern void iounmap(void *addr); | |
266 | ||
267 | /* Nothing to do */ | |
268 | ||
269 | #define dma_cache_inv(_start,_size) do { } while (0) | |
270 | #define dma_cache_wback(_start,_size) do { } while (0) | |
271 | #define dma_cache_wback_inv(_start,_size) do { } while (0) | |
272 | ||
273 | /* H8/300 internal I/O functions */ | |
274 | static __inline__ unsigned char ctrl_inb(unsigned long addr) | |
275 | { | |
276 | return *(volatile unsigned char*)addr; | |
277 | } | |
278 | ||
279 | static __inline__ unsigned short ctrl_inw(unsigned long addr) | |
280 | { | |
281 | return *(volatile unsigned short*)addr; | |
282 | } | |
283 | ||
284 | static __inline__ unsigned long ctrl_inl(unsigned long addr) | |
285 | { | |
286 | return *(volatile unsigned long*)addr; | |
287 | } | |
288 | ||
289 | static __inline__ void ctrl_outb(unsigned char b, unsigned long addr) | |
290 | { | |
291 | *(volatile unsigned char*)addr = b; | |
292 | } | |
293 | ||
294 | static __inline__ void ctrl_outw(unsigned short b, unsigned long addr) | |
295 | { | |
296 | *(volatile unsigned short*)addr = b; | |
297 | } | |
298 | ||
299 | static __inline__ void ctrl_outl(unsigned long b, unsigned long addr) | |
300 | { | |
301 | *(volatile unsigned long*)addr = b; | |
302 | } | |
303 | ||
304 | /* Pages to physical address... */ | |
305 | #define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) | |
306 | #define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT) | |
307 | ||
308 | /* | |
309 | * Macros used for converting between virtual and physical mappings. | |
310 | */ | |
311 | #define mm_ptov(vaddr) ((void *) (vaddr)) | |
312 | #define mm_vtop(vaddr) ((unsigned long) (vaddr)) | |
313 | #define phys_to_virt(vaddr) ((void *) (vaddr)) | |
314 | #define virt_to_phys(vaddr) ((unsigned long) (vaddr)) | |
315 | ||
316 | #define virt_to_bus virt_to_phys | |
317 | #define bus_to_virt phys_to_virt | |
318 | ||
319 | /* | |
320 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | |
321 | * access | |
322 | */ | |
323 | #define xlate_dev_mem_ptr(p) __va(p) | |
324 | ||
325 | /* | |
326 | * Convert a virtual cached pointer to an uncached pointer | |
327 | */ | |
328 | #define xlate_dev_kmem_ptr(p) p | |
329 | ||
330 | #endif /* __KERNEL__ */ | |
331 | ||
332 | #endif /* _H8300_IO_H */ |