1#ifndef _PPC64_IO_H
2#define _PPC64_IO_H
3
4/*
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include <linux/config.h>
12#include <asm/page.h>
13#include <asm/byteorder.h>
14#ifdef CONFIG_PPC_ISERIES
15#include <asm/iSeries/iSeries_io.h>
16#endif
17#include <asm/memory.h>
18#include <asm/delay.h>
19
20#define SIO_CONFIG_RA	0x398
21#define SIO_CONFIG_RD	0x399
22
23#define SLOW_DOWN_IO
24/* Define this if you want to see virt_to_* messages */
25#undef __IO_DEBUG
26
27extern unsigned long isa_io_base;
28extern unsigned long isa_mem_base;
29extern unsigned long pci_io_base;
30extern unsigned long pci_dram_offset;
31extern int have_print;
32#define _IO_BASE	isa_io_base
33#define _ISA_MEM_BASE	isa_mem_base
34#define PCI_DRAM_OFFSET	pci_dram_offset
35
36#ifdef CONFIG_PPC_ISERIES
37#define readb(addr)		iSeries_Read_Byte((void*)(addr))
38#define readw(addr)		iSeries_Read_Word((void*)(addr))
39#define readl(addr)		iSeries_Read_Long((void*)(addr))
40#define writeb(data, addr)	iSeries_Write_Byte(data,((void*)(addr)))
41#define writew(data, addr)	iSeries_Write_Word(data,((void*)(addr)))
42#define writel(data, addr)	iSeries_Write_Long(data,((void*)(addr)))
43#define memset_io(a,b,c)	iSeries_memset_io((void *)(a),(b),(c))
44#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((void *)(a), (void *)(b), (c))
45#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((void *)(a), (void *)(b), (c))
46#define inb(addr)		readb(((unsigned long)(addr)))
47#define inw(addr)		readw(((unsigned long)(addr)))
48#define inl(addr)		readl(((unsigned long)(addr)))
49#define outb(data,addr)		writeb(data,((unsigned long)(addr)))
50#define outw(data,addr)		writew(data,((unsigned long)(addr)))
51#define outl(data,addr)		writel(data,((unsigned long)(addr)))
52#else
53#define IS_MAPPED_VADDR(port)	((unsigned long)(port) >> 60UL)
54#define readb(addr)		eeh_readb((void*)(addr))
55#define readw(addr)		eeh_readw((void*)(addr))
56#define readl(addr)		eeh_readl((void*)(addr))
57#define writeb(data, addr)	eeh_writeb((data), ((void*)(addr)))
58#define writew(data, addr)	eeh_writew((data), ((void*)(addr)))
59#define writel(data, addr)	eeh_writel((data), ((void*)(addr)))
60#define memset_io(a,b,c)	eeh_memset_io((void *)(a),(b),(c))
61#define memcpy_fromio(a,b,c)	eeh_memcpy_fromio((a),(void *)(b),(c))
62#define memcpy_toio(a,b,c)	eeh_memcpy_toio((void *)(a),(b),(c))
63#define inb(port)		_inb((unsigned long)port)
64#define outb(val, port)		_outb(val, (unsigned long)port)
65#define inw(port)		_inw((unsigned long)port)
66#define outw(val, port)		_outw(val, (unsigned long)port)
67#define inl(port)		_inl((unsigned long)port)
68#define outl(val, port)		_outl(val, (unsigned long)port)
69
70/*
71 * The insw/outsw/insl/outsl macros don't do byte-swapping.
72 * They are only used in practice for transferring buffers which
73 * are arrays of bytes, and byte-swapping is not appropriate in
74 * that case.  - paulus */
75#define insb(port, buf, ns)	eeh_insb((u8 *)(port), (buf), (ns))
76#define outsb(port, buf, ns)	eeh_outsb((u8 *)(port), (buf), (ns))
77#define insw(port, buf, ns)	eeh_insw_ns((u16 *)(port), (buf), (ns))
78#define outsw(port, buf, ns)	eeh_outsw_ns((u16 *)(port), (buf), (ns))
79#define insl(port, buf, nl)	eeh_insl_ns((u32 *)(port), (buf), (nl))
80#define outsl(port, buf, nl)	eeh_outsl_ns((u32 *)(port), (buf), (nl))
81#endif
82
83
84/*
85 * output pause versions need a delay at least for the
86 * w83c105 ide controller in a p610.
87 */
88#define inb_p(port)             inb(port)
89#define outb_p(val, port)       (udelay(1), outb((val), (port)))
90#define inw_p(port)             inw(port)
91#define outw_p(val, port)       (udelay(1), outw((val), (port)))
92#define inl_p(port)             inl(port)
93#define outl_p(val, port)       (udelay(1), outl((val, (port)))
94
95
96extern void _insb(volatile u8 *port, void *buf, int ns);
97extern void _outsb(volatile u8 *port, const void *buf, int ns);
98extern void _insw(volatile u16 *port, void *buf, int ns);
99extern void _outsw(volatile u16 *port, const void *buf, int ns);
100extern void _insl(volatile u32 *port, void *buf, int nl);
101extern void _outsl(volatile u32 *port, const void *buf, int nl);
102extern void _insw_ns(volatile u16 *port, void *buf, int ns);
103extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
104extern void _insl_ns(volatile u32 *port, void *buf, int nl);
105extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
106
107/*
108 * The *_ns versions below don't do byte-swapping.
109 * Neither do the standard versions now, these are just here
110 * for older code.
111 */
112#define insw_ns(port, buf, ns)	insw(port, buf, ns)
113#define outsw_ns(port, buf, ns)	outsw(port, buf, ns)
114#define insl_ns(port, buf, nl)	insl(port, buf, nl)
115#define outsl_ns(port, buf, nl)	outsl(port, buf, nl)
116
117
118#define IO_SPACE_LIMIT ~(0UL)
119#define MEM_SPACE_LIMIT ~(0UL)
120
121
122#ifdef __KERNEL__
123/*
124 * Map in an area of physical address space, for accessing
125 * I/O devices etc.
126 */
127extern void *__ioremap(unsigned long address, unsigned long size,
128		       unsigned long flags);
129extern void *ioremap(unsigned long address, unsigned long size);
130#define ioremap_nocache(addr, size)	ioremap((addr), (size))
131extern void iounmap(void *addr);
132
133/*
134 * Change virtual addresses to physical addresses and vv, for
135 * addresses in the area where the kernel has the RAM mapped.
136 */
137static inline unsigned long virt_to_phys(volatile void * address)
138{
139#ifdef __IO_DEBUG
140	printk("virt_to_phys: 0x%08lx -> 0x%08lx\n",
141			(unsigned long) address,
142			__pa((unsigned long)address));
143#endif
144	return __pa((unsigned long)address);
145}
146
147static inline void * phys_to_virt(unsigned long address)
148{
149#ifdef __IO_DEBUG
150	printk("phys_to_virt: 0x%08lx -> 0x%08lx\n", address, __va(address));
151#endif
152	return (void *) __va(address);
153}
154
155/*
156 * Change "struct page" to physical address.
157 */
158#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
159
160#endif /* __KERNEL__ */
161
162static inline void iosync(void)
163{
164        __asm__ __volatile__ ("sync" : : : "memory");
165}
166
167/* Enforce in-order execution of data I/O.
168 * No distinction between read/write on PPC; use eieio for all three.
169 */
170#define iobarrier_rw() eieio()
171#define iobarrier_r()  eieio()
172#define iobarrier_w()  eieio()
173
174/*
175 * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
176 * Until we can validate all required device drivers are weakc safe, an
177 * excess of syncs before the MMIO operations will make things work.  On
178 * sstar, sync time is << than mmio time, so this should not be a big impact.
179 */
180static inline int in_8(volatile unsigned char *addr)
181{
182	int ret;
183
184	__asm__ __volatile__("sync; lbz%U1%X1 %0,%1; sync" : "=r" (ret) : "m" (*addr));
185	return ret;
186}
187
188static inline void out_8(volatile unsigned char *addr, int val)
189{
190	__asm__ __volatile__("sync; stb%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
191}
192
193static inline int in_le16(volatile unsigned short *addr)
194{
195	int ret;
196
197	__asm__ __volatile__("sync; lhbrx %0,0,%1; sync" : "=r" (ret) :
198			      "r" (addr), "m" (*addr));
199	return ret;
200}
201
202static inline int in_be16(volatile unsigned short *addr)
203{
204	int ret;
205
206	__asm__ __volatile__("sync; lhz%U1%X1 %0,%1; sync" : "=r" (ret) : "m" (*addr));
207	return ret;
208}
209
210static inline void out_le16(volatile unsigned short *addr, int val)
211{
212	__asm__ __volatile__("sync; sthbrx %1,0,%2; sync" : "=m" (*addr) :
213			      "r" (val), "r" (addr));
214}
215
216static inline void out_be16(volatile unsigned short *addr, int val)
217{
218	__asm__ __volatile__("sync; sth%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
219}
220
221static inline unsigned in_le32(volatile unsigned *addr)
222{
223	unsigned ret;
224
225	__asm__ __volatile__("sync; lwbrx %0,0,%1; sync" : "=r" (ret) :
226			     "r" (addr), "m" (*addr));
227	return ret;
228}
229
230static inline unsigned in_be32(volatile unsigned *addr)
231{
232	unsigned ret;
233
234	__asm__ __volatile__("sync; lwz%U1%X1 %0,%1; sync" : "=r" (ret) : "m" (*addr));
235	return ret;
236}
237
238static inline void out_le32(volatile unsigned *addr, int val)
239{
240	__asm__ __volatile__("sync; stwbrx %1,0,%2; sync" : "=m" (*addr) :
241			     "r" (val), "r" (addr));
242}
243
244static inline void out_be32(volatile unsigned *addr, int val)
245{
246	__asm__ __volatile__("sync; stw%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
247}
248
249#ifndef CONFIG_PPC_ISERIES
250#include <asm/eeh.h>
251
252static inline u8 _inb(unsigned long port) {
253	if (IS_MAPPED_VADDR(port))
254		return readb((void *)port);
255	else if (_IO_BASE)
256		return in_8((u8 *)((port)+_IO_BASE));
257	else
258		return 0xff;
259}
260static inline void _outb(u8 val, unsigned long port) {
261	if (IS_MAPPED_VADDR(port))
262		return writeb(val, (void *)port);
263	else if (_IO_BASE)
264		out_8((u8 *)((port)+_IO_BASE), val);
265}
266static inline u16 _inw(unsigned long port) {
267	if (IS_MAPPED_VADDR(port))
268		return readw((void *)port);
269	else if (_IO_BASE)
270		return in_le16((u16 *)((port)+_IO_BASE));
271	else
272		return 0xffff;
273}
274static inline void _outw(u16 val, unsigned long port) {
275	if (IS_MAPPED_VADDR(port))
276		return writew(val, (void *)port);
277	else if (_IO_BASE)
278		out_le16((u16 *)((port)+_IO_BASE), val);
279}
280static inline u32 _inl(unsigned long port) {
281	if (IS_MAPPED_VADDR(port))
282		return readl((void *)port);
283	else if (_IO_BASE)
284		return in_le32((u32 *)((port)+_IO_BASE));
285	else
286		return 0xffffffff;
287}
288static inline void _outl(u32 val, unsigned long port) {
289	if (IS_MAPPED_VADDR(port))
290		return writel(val, (void *)port);
291	else if (_IO_BASE)
292		out_le32((u32 *)((port)+_IO_BASE), val);
293}
294#endif
295
296#ifdef __KERNEL__
297static inline int check_signature(unsigned long io_addr,
298	const unsigned char *signature, int length)
299{
300	int retval = 0;
301#ifndef CONFIG_PPC_ISERIES
302	do {
303		if (readb(io_addr) != *signature)
304			goto out;
305		io_addr++;
306		signature++;
307		length--;
308	} while (length);
309	retval = 1;
310out:
311#endif
312	return retval;
313}
314
315/* Nothing to do */
316
317#define dma_cache_inv(_start,_size)		do { } while (0)
318#define dma_cache_wback(_start,_size)		do { } while (0)
319#define dma_cache_wback_inv(_start,_size)	do { } while (0)
320
321#endif /* __KERNEL__ */
322
323#endif /* _PPC64_IO_H */
324