1#ifndef _H8300_IO_H
2#define _H8300_IO_H
3
4#ifdef __KERNEL__
5
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
35static 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
50static 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
101static inline int h8300_buswidth(unsigned int addr)
102{
103	return (*(volatile unsigned char *)ABWCR & (1 << ((addr >> 21) & 7))) == 0;
104}
105
106static 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
121static 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
129static 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
137static 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
145static 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
153static 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
170static 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
178static 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
186static 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
194static 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
245extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
246extern void __iounmap(void *addr, unsigned long size);
247
248static inline void *ioremap(unsigned long physaddr, unsigned long size)
249{
250	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
251}
252static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
253{
254	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
255}
256static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
257{
258	return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
259}
260static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
261{
262	return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
263}
264
265extern 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 */
274static __inline__ unsigned char ctrl_inb(unsigned long addr)
275{
276	return *(volatile unsigned char*)addr;
277}
278
279static __inline__ unsigned short ctrl_inw(unsigned long addr)
280{
281	return *(volatile unsigned short*)addr;
282}
283
284static __inline__ unsigned long ctrl_inl(unsigned long addr)
285{
286	return *(volatile unsigned long*)addr;
287}
288
289static __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
290{
291	*(volatile unsigned char*)addr = b;
292}
293
294static __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
295{
296	*(volatile unsigned short*)addr = b;
297}
298
299static __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 */
333