blob: 5e56b47446e0c4a2ba6e8fe9ea1d7a5dd3ed9e02 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/include/asm-arm/arch-ixp2000/io.h
3 *
4 * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
5 * Maintainer: Deepak Saxena <dsaxena@plexity.net>
6 *
7 * Copyright (C) 2002 Intel Corp.
8 * Copyrgiht (C) 2003-2004 MontaVista Software, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __ASM_ARM_ARCH_IO_H
16#define __ASM_ARM_ARCH_IO_H
17
18#define IO_SPACE_LIMIT 0xffffffff
19#define __mem_pci(a) (a)
20#define ___io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
21
22/*
23 * The IXP2400 before revision B0 asserts byte lanes for PCI I/O
24 * transactions the other way round (MEM transactions don't have this
25 * issue), so we need to override the standard functions. B0 and later
26 * have a bit that can be set to 1 to get the 'proper' behavior, but
27 * since that isn't available on the A? revisions we just keep doing
28 * things manually.
29 */
Lennert Buytenhekc6b56942005-06-24 20:54:34 +010030#define alignb(addr) (void __iomem *)((unsigned long)(addr) ^ 3)
31#define alignw(addr) (void __iomem *)((unsigned long)(addr) ^ 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#define outb(v,p) __raw_writeb((v),alignb(___io(p)))
34#define outw(v,p) __raw_writew((v),alignw(___io(p)))
35#define outl(v,p) __raw_writel((v),___io(p))
36
37#define inb(p) ({ unsigned int __v = __raw_readb(alignb(___io(p))); __v; })
38#define inw(p) \
39 ({ unsigned int __v = (__raw_readw(alignw(___io(p)))); __v; })
40#define inl(p) \
41 ({ unsigned int __v = (__raw_readl(___io(p))); __v; })
42
43#define outsb(p,d,l) __raw_writesb(alignb(___io(p)),d,l)
44#define outsw(p,d,l) __raw_writesw(alignw(___io(p)),d,l)
45#define outsl(p,d,l) __raw_writesl(___io(p),d,l)
46
47#define insb(p,d,l) __raw_readsb(alignb(___io(p)),d,l)
48#define insw(p,d,l) __raw_readsw(alignw(___io(p)),d,l)
49#define insl(p,d,l) __raw_readsl(___io(p),d,l)
50
Lennert Buytenhek29662072005-06-24 23:11:31 +010051#define __is_io_address(p) ((((unsigned long)(p)) & ~(IXP2000_PCI_IO_SIZE - 1)) == IXP2000_PCI_IO_VIRT_BASE)
52
53#define ioread8(p) \
54 ({ \
55 unsigned int __v; \
56 \
57 if (__is_io_address(p)) { \
58 __v = __raw_readb(alignb(p)); \
59 } else { \
60 __v = __raw_readb(p); \
61 } \
62 \
63 __v; \
64 }) \
65
66#define ioread16(p) \
67 ({ \
68 unsigned int __v; \
69 \
70 if (__is_io_address(p)) { \
71 __v = __raw_readw(alignw(p)); \
72 } else { \
73 __v = le16_to_cpu(__raw_readw(p)); \
74 } \
75 \
76 __v; \
77 })
78
79#define ioread32(p) \
80 ({ \
81 unsigned int __v; \
82 \
83 if (__is_io_address(p)) { \
84 __v = __raw_readl(p); \
85 } else { \
86 __v = le32_to_cpu(__raw_readl(p)); \
87 } \
88 \
89 __v; \
90 })
91
92#define iowrite8(v,p) \
93 ({ \
94 if (__is_io_address(p)) { \
95 __raw_writeb((v), alignb(p)); \
96 } else { \
97 __raw_writeb((v), p); \
98 } \
99 })
100
101#define iowrite16(v,p) \
102 ({ \
103 if (__is_io_address(p)) { \
104 __raw_writew((v), alignw(p)); \
105 } else { \
106 __raw_writew(cpu_to_le16(v), p); \
107 } \
108 })
109
110#define iowrite32(v,p) \
111 ({ \
112 if (__is_io_address(p)) { \
113 __raw_writel((v), p); \
114 } else { \
115 __raw_writel(cpu_to_le32(v), p); \
116 } \
117 })
118
119#define ioport_map(port, nr) ___io(port)
120
121#define ioport_unmap(addr)
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124#ifdef CONFIG_ARCH_IXDP2X01
125/*
126 * This is an ugly hack but the CS8900 on the 2x01's does not sit in any sort
127 * of "I/O space" and is just direct mapped into a 32-bit-only addressable
128 * bus. The address space for this bus is such that we can't really easily
129 * make it contiguous to the PCI I/O address range, and it also does not
130 * need swapping like PCI addresses do (IXDP2x01 is a BE platform).
131 * B/C of this we can't use the standard in/out functions and need to
132 * runtime check if the incoming address is a PCI address or for
133 * the CS89x0.
134 */
135#undef inw
136#undef outw
137#undef insw
138#undef outsw
139
140#include <asm/mach-types.h>
141
142static inline void insw(u32 ptr, void *buf, int length)
143{
144 register volatile u32 *port = (volatile u32 *)ptr;
145
146 /*
147 * Is this cycle meant for the CS8900?
148 */
149 if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
Deepak Saxena4ab5c012005-06-03 20:52:25 +0100150 (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
151 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 u8 *buf8 = (u8*)buf;
153 register u32 tmp32;
154
155 do {
156 tmp32 = *port;
157 *buf8++ = (u8)tmp32;
158 *buf8++ = (u8)(tmp32 >> 8);
159 } while(--length);
160
161 return;
162 }
163
164 __raw_readsw(alignw(___io(ptr)),buf,length);
165}
166
167static inline void outsw(u32 ptr, void *buf, int length)
168{
169 register volatile u32 *port = (volatile u32 *)ptr;
170
171 /*
172 * Is this cycle meant for the CS8900?
173 */
174 if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
Deepak Saxena4ab5c012005-06-03 20:52:25 +0100175 (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
176 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 register u32 tmp32;
178 u8 *buf8 = (u8*)buf;
179 do {
180 tmp32 = *buf8++;
181 tmp32 |= (*buf8++) << 8;
182 *port = tmp32;
183 } while(--length);
184 return;
185 }
186
187 __raw_writesw(alignw(___io(ptr)),buf,length);
188}
189
190
191static inline u16 inw(u32 ptr)
192{
193 register volatile u32 *port = (volatile u32 *)ptr;
194
195 /*
196 * Is this cycle meant for the CS8900?
197 */
198 if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
Deepak Saxena4ab5c012005-06-03 20:52:25 +0100199 (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
200 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 return (u16)(*port);
202 }
203
204 return __raw_readw(alignw(___io(ptr)));
205}
206
207static inline void outw(u16 value, u32 ptr)
208{
209 register volatile u32 *port = (volatile u32 *)ptr;
210
211 if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
Deepak Saxena4ab5c012005-06-03 20:52:25 +0100212 (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
213 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 *port = value;
215 return;
216 }
217
218 __raw_writew((value),alignw(___io(ptr)));
219}
220#endif /* IXDP2x01 */
221
222#endif