1#ifdef __KERNEL__
2#ifndef _PPC_IO_H
3#define _PPC_IO_H
4
5#include <linux/string.h>
6#include <linux/types.h>
7
8#include <asm/page.h>
9#include <asm/byteorder.h>
10#include <asm/synch.h>
11#include <asm/mmu.h>
12
13#define SIO_CONFIG_RA	0x398
14#define SIO_CONFIG_RD	0x399
15
16#define SLOW_DOWN_IO
17
18#define PMAC_ISA_MEM_BASE 	0
19#define PMAC_PCI_DRAM_OFFSET 	0
20#define CHRP_ISA_IO_BASE 	0xf8000000
21#define CHRP_ISA_MEM_BASE 	0xf7000000
22#define CHRP_PCI_DRAM_OFFSET 	0
23#define PREP_ISA_IO_BASE 	0x80000000
24#define PREP_ISA_MEM_BASE 	0xc0000000
25#define PREP_PCI_DRAM_OFFSET 	0x80000000
26
27#if defined(CONFIG_4xx)
28#include <asm/ibm4xx.h>
29#elif defined(CONFIG_8xx)
30#include <asm/mpc8xx.h>
31#elif defined(CONFIG_8260)
32#include <asm/mpc8260.h>
33#elif defined(CONFIG_APUS) || !defined(CONFIG_PCI)
34#define _IO_BASE	0
35#define _ISA_MEM_BASE	0
36#define PCI_DRAM_OFFSET 0
37#else /* Everyone else */
38#define _IO_BASE	isa_io_base
39#define _ISA_MEM_BASE	isa_mem_base
40#define PCI_DRAM_OFFSET	pci_dram_offset
41#endif /* Platform-dependent I/O */
42
43#define ___IO_BASE ((void __iomem *)_IO_BASE)
44extern unsigned long isa_io_base;
45extern unsigned long isa_mem_base;
46extern unsigned long pci_dram_offset;
47
48/*
49 * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
50 *
51 * Read operations have additional twi & isync to make sure the read
52 * is actually performed (i.e. the data has come back) before we start
53 * executing any following instructions.
54 */
55extern inline int in_8(const volatile unsigned char __iomem *addr)
56{
57	int ret;
58
59	__asm__ __volatile__(
60		"sync; lbz%U1%X1 %0,%1;\n"
61		"twi 0,%0,0;\n"
62		"isync" : "=r" (ret) : "m" (*addr));
63	return ret;
64}
65
66extern inline void out_8(volatile unsigned char __iomem *addr, int val)
67{
68	__asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
69}
70
71extern inline int in_le16(const volatile unsigned short __iomem *addr)
72{
73	int ret;
74
75	__asm__ __volatile__("sync; lhbrx %0,0,%1;\n"
76			     "twi 0,%0,0;\n"
77			     "isync" : "=r" (ret) :
78			      "r" (addr), "m" (*addr));
79	return ret;
80}
81
82extern inline int in_be16(const volatile unsigned short __iomem *addr)
83{
84	int ret;
85
86	__asm__ __volatile__("sync; lhz%U1%X1 %0,%1;\n"
87			     "twi 0,%0,0;\n"
88			     "isync" : "=r" (ret) : "m" (*addr));
89	return ret;
90}
91
92extern inline void out_le16(volatile unsigned short __iomem *addr, int val)
93{
94	__asm__ __volatile__("sync; sthbrx %1,0,%2" : "=m" (*addr) :
95			      "r" (val), "r" (addr));
96}
97
98extern inline void out_be16(volatile unsigned short __iomem *addr, int val)
99{
100	__asm__ __volatile__("sync; sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
101}
102
103extern inline unsigned in_le32(const volatile unsigned __iomem *addr)
104{
105	unsigned ret;
106
107	__asm__ __volatile__("sync; lwbrx %0,0,%1;\n"
108			     "twi 0,%0,0;\n"
109			     "isync" : "=r" (ret) :
110			     "r" (addr), "m" (*addr));
111	return ret;
112}
113
114extern inline unsigned in_be32(const volatile unsigned __iomem *addr)
115{
116	unsigned ret;
117
118	__asm__ __volatile__("sync; lwz%U1%X1 %0,%1;\n"
119			     "twi 0,%0,0;\n"
120			     "isync" : "=r" (ret) : "m" (*addr));
121	return ret;
122}
123
124extern inline void out_le32(volatile unsigned __iomem *addr, int val)
125{
126	__asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) :
127			     "r" (val), "r" (addr));
128}
129
130extern inline void out_be32(volatile unsigned __iomem *addr, int val)
131{
132	__asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
133}
134#if defined(CONFIG_8260_PCI9)
135#define readb(addr) in_8((volatile u8 *)(addr))
136#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
137#else
138static inline __u8 readb(const volatile void __iomem *addr)
139{
140	return in_8(addr);
141}
142static inline void writeb(__u8 b, volatile void __iomem *addr)
143{
144	out_8(addr, b);
145}
146#endif
147
148#if defined(CONFIG_APUS)
149static inline __u16 readw(const volatile void __iomem *addr)
150{
151	return *(__force volatile __u16 *)(addr);
152}
153static inline __u32 readl(const volatile void __iomem *addr)
154{
155	return *(__force volatile __u32 *)(addr);
156}
157static inline void writew(__u16 b, volatile void __iomem *addr)
158{
159	*(__force volatile __u16 *)(addr) = b;
160}
161static inline void writel(__u32 b, volatile void __iomem *addr)
162{
163	*(__force volatile __u32 *)(addr) = b;
164}
165#elif defined(CONFIG_8260_PCI9)
166#define readw(addr) in_le16((volatile u16 *)(addr))
167#define readl(addr) in_le32((volatile u32 *)(addr))
168#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
169#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
170#else
171static inline __u16 readw(const volatile void __iomem *addr)
172{
173	return in_le16(addr);
174}
175static inline __u32 readl(const volatile void __iomem *addr)
176{
177	return in_le32(addr);
178}
179static inline void writew(__u16 b, volatile void __iomem *addr)
180{
181	out_le16(addr, b);
182}
183static inline void writel(__u32 b, volatile void __iomem *addr)
184{
185	out_le32(addr, b);
186}
187#endif /* CONFIG_APUS */
188
189#define readb_relaxed(addr) readb(addr)
190#define readw_relaxed(addr) readw(addr)
191#define readl_relaxed(addr) readl(addr)
192
193static inline __u8 __raw_readb(const volatile void __iomem *addr)
194{
195	return *(__force volatile __u8 *)(addr);
196}
197static inline __u16 __raw_readw(const volatile void __iomem *addr)
198{
199	return *(__force volatile __u16 *)(addr);
200}
201static inline __u32 __raw_readl(const volatile void __iomem *addr)
202{
203	return *(__force volatile __u32 *)(addr);
204}
205static inline void __raw_writeb(__u8 b, volatile void __iomem *addr)
206{
207	*(__force volatile __u8 *)(addr) = b;
208}
209static inline void __raw_writew(__u16 b, volatile void __iomem *addr)
210{
211	*(__force volatile __u16 *)(addr) = b;
212}
213static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
214{
215	*(__force volatile __u32 *)(addr) = b;
216}
217
218#define mmiowb()
219
220/*
221 * The insw/outsw/insl/outsl macros don't do byte-swapping.
222 * They are only used in practice for transferring buffers which
223 * are arrays of bytes, and byte-swapping is not appropriate in
224 * that case.  - paulus
225 */
226#define insb(port, buf, ns)	_insb((port)+___IO_BASE, (buf), (ns))
227#define outsb(port, buf, ns)	_outsb((port)+___IO_BASE, (buf), (ns))
228#define insw(port, buf, ns)	_insw_ns((port)+___IO_BASE, (buf), (ns))
229#define outsw(port, buf, ns)	_outsw_ns((port)+___IO_BASE, (buf), (ns))
230#define insl(port, buf, nl)	_insl_ns((port)+___IO_BASE, (buf), (nl))
231#define outsl(port, buf, nl)	_outsl_ns((port)+___IO_BASE, (buf), (nl))
232
233#define readsb(a, b, n)		_insb((a), (b), (n))
234#define readsw(a, b, n)		_insw_ns((a), (b), (n))
235#define readsl(a, b, n)		_insl_ns((a), (b), (n))
236#define writesb(a, b, n)	_outsb((a),(b),(n))
237#define writesw(a, b, n)	_outsw_ns((a),(b),(n))
238#define writesl(a, b, n)	_outsl_ns((a),(b),(n))
239
240
241/*
242 * On powermacs and 8xx we will get a machine check exception
243 * if we try to read data from a non-existent I/O port. Because
244 * the machine check is an asynchronous exception, it isn't
245 * well-defined which instruction SRR0 will point to when the
246 * exception occurs.
247 * With the sequence below (twi; isync; nop), we have found that
248 * the machine check occurs on one of the three instructions on
249 * all PPC implementations tested so far.  The twi and isync are
250 * needed on the 601 (in fact twi; sync works too), the isync and
251 * nop are needed on 604[e|r], and any of twi, sync or isync will
252 * work on 603[e], 750, 74xx.
253 * The twi creates an explicit data dependency on the returned
254 * value which seems to be needed to make the 601 wait for the
255 * load to finish.
256 */
257
258#define __do_in_asm(name, op)				\
259extern __inline__ unsigned int name(unsigned int port)	\
260{							\
261	unsigned int x;					\
262	__asm__ __volatile__(				\
263		"sync\n"				\
264		"0:"	op "	%0,0,%1\n"		\
265		"1:	twi	0,%0,0\n"		\
266		"2:	isync\n"			\
267		"3:	nop\n"				\
268		"4:\n"					\
269		".section .fixup,\"ax\"\n"		\
270		"5:	li	%0,-1\n"		\
271		"	b	4b\n"			\
272		".previous\n"				\
273		".section __ex_table,\"a\"\n"		\
274		"	.align	2\n"			\
275		"	.long	0b,5b\n"		\
276		"	.long	1b,5b\n"		\
277		"	.long	2b,5b\n"		\
278		"	.long	3b,5b\n"		\
279		".previous"				\
280		: "=&r" (x)				\
281		: "r" (port + ___IO_BASE));		\
282	return x;					\
283}
284
285#define __do_out_asm(name, op)				\
286extern __inline__ void name(unsigned int val, unsigned int port) \
287{							\
288	__asm__ __volatile__(				\
289		"sync\n"				\
290		"0:" op " %0,0,%1\n"			\
291		"1:	sync\n"				\
292		"2:\n"					\
293		".section __ex_table,\"a\"\n"		\
294		"	.align	2\n"			\
295		"	.long	0b,2b\n"		\
296		"	.long	1b,2b\n"		\
297		".previous"				\
298		: : "r" (val), "r" (port + ___IO_BASE));	\
299}
300
301__do_out_asm(outb, "stbx")
302#ifdef CONFIG_APUS
303__do_in_asm(inb, "lbzx")
304__do_in_asm(inw, "lhz%U1%X1")
305__do_in_asm(inl, "lwz%U1%X1")
306__do_out_asm(outl,"stw%U0%X0")
307__do_out_asm(outw, "sth%U0%X0")
308#elif defined(CONFIG_8260_PCI9)
309#define inb(port)		in_8((port)+___IO_BASE)
310#define inw(port)		in_le16((port)+___IO_BASE)
311#define inl(port)		in_le32((port)+___IO_BASE)
312__do_out_asm(outw, "sthbrx")
313__do_out_asm(outl, "stwbrx")
314#else
315__do_in_asm(inb, "lbzx")
316__do_in_asm(inw, "lhbrx")
317__do_in_asm(inl, "lwbrx")
318__do_out_asm(outw, "sthbrx")
319__do_out_asm(outl, "stwbrx")
320
321#endif
322
323#define inb_p(port)		inb((port))
324#define outb_p(val, port)	outb((val), (port))
325#define inw_p(port)		inw((port))
326#define outw_p(val, port)	outw((val), (port))
327#define inl_p(port)		inl((port))
328#define outl_p(val, port)	outl((val), (port))
329
330extern void _insb(const volatile u8 __iomem *addr, void *buf, long count);
331extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count);
332extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count);
333extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count);
334extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count);
335extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count);
336
337
338#define IO_SPACE_LIMIT ~0
339
340#if defined(CONFIG_8260_PCI9)
341#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
342#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
343#define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
344#else
345static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
346{
347	memset((void __force *)addr, val, count);
348}
349static inline void memcpy_fromio(void *dst,const volatile void __iomem *src, int count)
350{
351	memcpy(dst, (void __force *) src, count);
352}
353static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
354{
355	memcpy((void __force *) dst, src, count);
356}
357#endif
358
359/*
360 * Map in an area of physical address space, for accessing
361 * I/O devices etc.
362 */
363extern void __iomem *__ioremap(phys_addr_t address, unsigned long size,
364		       unsigned long flags);
365extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
366#ifdef CONFIG_44x
367extern void __iomem *ioremap64(unsigned long long address, unsigned long size);
368#endif
369#define ioremap_nocache(addr, size)	ioremap((addr), (size))
370extern void iounmap(volatile void __iomem *addr);
371extern unsigned long iopa(unsigned long addr);
372extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
373extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
374			     unsigned int size, int flags);
375
376/*
377 * The PCI bus is inherently Little-Endian.  The PowerPC is being
378 * run Big-Endian.  Thus all values which cross the [PCI] barrier
379 * must be endian-adjusted.  Also, the local DRAM has a different
380 * address from the PCI point of view, thus buffer addresses also
381 * have to be modified [mapped] appropriately.
382 */
383extern inline unsigned long virt_to_bus(volatile void * address)
384{
385#ifndef CONFIG_APUS
386        if (address == (void *)0)
387		return 0;
388        return (unsigned long)address - KERNELBASE + PCI_DRAM_OFFSET;
389#else
390	return iopa ((unsigned long) address);
391#endif
392}
393
394extern inline void * bus_to_virt(unsigned long address)
395{
396#ifndef CONFIG_APUS
397        if (address == 0)
398		return NULL;
399        return (void *)(address - PCI_DRAM_OFFSET + KERNELBASE);
400#else
401	return (void*) mm_ptov (address);
402#endif
403}
404
405/*
406 * Change virtual addresses to physical addresses and vv, for
407 * addresses in the area where the kernel has the RAM mapped.
408 */
409extern inline unsigned long virt_to_phys(volatile void * address)
410{
411#ifndef CONFIG_APUS
412	return (unsigned long) address - KERNELBASE;
413#else
414	return iopa ((unsigned long) address);
415#endif
416}
417
418extern inline void * phys_to_virt(unsigned long address)
419{
420#ifndef CONFIG_APUS
421	return (void *) (address + KERNELBASE);
422#else
423	return (void*) mm_ptov (address);
424#endif
425}
426
427/*
428 * Change "struct page" to physical address.
429 */
430#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
431#define page_to_bus(page)	(page_to_phys(page) + PCI_DRAM_OFFSET)
432
433/* Enforce in-order execution of data I/O.
434 * No distinction between read/write on PPC; use eieio for all three.
435 */
436#define iobarrier_rw() eieio()
437#define iobarrier_r()  eieio()
438#define iobarrier_w()  eieio()
439
440/*
441 * Here comes the ppc implementation of the IOMAP
442 * interfaces.
443 */
444static inline unsigned int ioread8(void __iomem *addr)
445{
446	return readb(addr);
447}
448
449static inline unsigned int ioread16(void __iomem *addr)
450{
451	return readw(addr);
452}
453
454static inline unsigned int ioread32(void __iomem *addr)
455{
456	return readl(addr);
457}
458
459static inline void iowrite8(u8 val, void __iomem *addr)
460{
461	writeb(val, addr);
462}
463
464static inline void iowrite16(u16 val, void __iomem *addr)
465{
466	writew(val, addr);
467}
468
469static inline void iowrite32(u32 val, void __iomem *addr)
470{
471	writel(val, addr);
472}
473
474static inline void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
475{
476	_insb(addr, dst, count);
477}
478
479static inline void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
480{
481	_insw_ns(addr, dst, count);
482}
483
484static inline void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
485{
486	_insl_ns(addr, dst, count);
487}
488
489static inline void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
490{
491	_outsb(addr, src, count);
492}
493
494static inline void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
495{
496	_outsw_ns(addr, src, count);
497}
498
499static inline void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
500{
501	_outsl_ns(addr, src, count);
502}
503
504/* Create a virtual mapping cookie for an IO port range */
505extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
506extern void ioport_unmap(void __iomem *);
507
508/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
509struct pci_dev;
510extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
511extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
512
513#endif /* _PPC_IO_H */
514
515#ifdef CONFIG_8260_PCI9
516#include <asm/mpc8260_pci9.h>
517#endif
518
519#ifdef CONFIG_NOT_COHERENT_CACHE
520
521#define dma_cache_inv(_start,_size) \
522	invalidate_dcache_range(_start, (_start + _size))
523#define dma_cache_wback(_start,_size) \
524	clean_dcache_range(_start, (_start + _size))
525#define dma_cache_wback_inv(_start,_size) \
526	flush_dcache_range(_start, (_start + _size))
527
528#else
529
530#define dma_cache_inv(_start,_size)		do { } while (0)
531#define dma_cache_wback(_start,_size)		do { } while (0)
532#define dma_cache_wback_inv(_start,_size)	do { } while (0)
533
534#endif
535
536/*
537 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
538 * access
539 */
540#define xlate_dev_mem_ptr(p)	__va(p)
541
542/*
543 * Convert a virtual cached pointer to an uncached pointer
544 */
545#define xlate_dev_kmem_ptr(p)	p
546
547/* access ports */
548#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) |  (_v))
549#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
550
551#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) |  (_v))
552#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
553
554#endif /* __KERNEL__ */
555