File: /usr/src/linux/include/asm-mips64/io.h
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994, 1995 Waldorf GmbH
7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
10 #ifndef _ASM_IO_H
11 #define _ASM_IO_H
12
13 #include <linux/config.h>
14 #include <asm/addrspace.h>
15 #include <asm/page.h>
16
17 #ifdef CONFIG_SGI_IP22
18 #include <asm/sgi/io.h>
19 #endif
20
21 #ifdef CONFIG_SGI_IP27
22 #include <asm/sn/io.h>
23 #endif
24
25 extern unsigned long bus_to_baddr[256];
26
27 /*
28 * Slowdown I/O port space accesses for antique hardware.
29 */
30 #undef CONF_SLOWDOWN_IO
31
32 /*
33 * On MIPS, we have the whole physical address space mapped at all
34 * times, so "ioremap()" and "iounmap()" do not need to do anything.
35 *
36 * We cheat a bit and always return uncachable areas until we've fixed
37 * the drivers to handle caching properly.
38 */
39 extern inline void *
40 ioremap(unsigned long offset, unsigned long size)
41 {
42 return (void *) (IO_SPACE_BASE | offset);
43 }
44
45 /* This one maps high address device memory and turns off caching for that
46 * area. It's useful if some control registers are in such an area and write
47 * combining or read caching is not desirable.
48 */
49 extern inline void *
50 ioremap_nocache (unsigned long offset, unsigned long size)
51 {
52 return (void *) (IO_SPACE_BASE | offset);
53 }
54
55 extern inline void iounmap(void *addr)
56 {
57 }
58
59 /*
60 * This assumes sane hardware. The Origin is.
61 */
62 #define readb(addr) (*(volatile unsigned char *) (addr))
63 #define readw(addr) (*(volatile unsigned short *) (addr))
64 #define readl(addr) (*(volatile unsigned int *) (addr))
65
66 #define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
67 #define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
68 #define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
69
70 #define memset_io(a,b,c) memset((void *) a,(b),(c))
71 #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
72 #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
73
74 /* The ISA versions are supplied by system specific code */
75
76 /*
77 * On MIPS I/O ports are memory mapped, so we access them using normal
78 * load/store instructions. mips_io_port_base is the virtual address to
79 * which all ports are being mapped. For sake of efficiency some code
80 * assumes that this is an address that can be loaded with a single lui
81 * instruction, so the lower 16 bits must be zero. Should be true on
82 * on any sane architecture; generic code does not use this assumption.
83 */
84 extern unsigned long mips_io_port_base;
85
86 #define __SLOW_DOWN_IO \
87 __asm__ __volatile__( \
88 "sb\t$0,0x80(%0)" \
89 : : "r" (mips_io_port_base));
90
91 #ifdef CONF_SLOWDOWN_IO
92 #ifdef REALLY_SLOW_IO
93 #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
94 #else
95 #define SLOW_DOWN_IO __SLOW_DOWN_IO
96 #endif
97 #else
98 #define SLOW_DOWN_IO
99 #endif
100
101 /*
102 * Change virtual addresses to physical addresses and vv.
103 * These are trivial on the 1:1 Linux/MIPS mapping
104 */
105 extern inline unsigned long virt_to_phys(volatile void * address)
106 {
107 return (unsigned long)address - PAGE_OFFSET;
108 }
109
110 extern inline void * phys_to_virt(unsigned long address)
111 {
112 return (void *)(address + PAGE_OFFSET);
113 }
114
115 /*
116 * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped
117 * for the processor. This implies the assumption that there is only
118 * one of these busses.
119 */
120 extern unsigned long isa_slot_offset;
121
122 /*
123 * We don't have csum_partial_copy_fromio() yet, so we cheat here and
124 * just copy it. The net code will then do the checksum later.
125 */
126 #define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len))
127
128 static inline int
129 check_signature(unsigned long io_addr, const unsigned char *signature,
130 int length)
131 {
132 int retval = 0;
133 do {
134 if (readb(io_addr) != *signature)
135 goto out;
136 io_addr++;
137 signature++;
138 length--;
139 } while (length);
140 retval = 1;
141 out:
142 return retval;
143 }
144
145 /*
146 * Talk about misusing macros..
147 */
148
149 #define __OUT1(s) \
150 extern inline void __out##s(unsigned int value, unsigned long port) {
151
152 #define __OUT2(m) \
153 __asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
154
155 #define __OUT(m,s) \
156 __OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); } \
157 __OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); } \
158 __OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); \
159 SLOW_DOWN_IO; } \
160 __OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); \
161 SLOW_DOWN_IO; }
162
163 #define __IN1(t,s) \
164 extern __inline__ t __in##s(unsigned long port) { t _v;
165
166 /*
167 * Required nops will be inserted by the assembler
168 */
169 #define __IN2(m) \
170 __asm__ __volatile__ ("l" #m "\t%0,%1(%2)"
171
172 #define __IN(t,m,s) \
173 __IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return _v; } \
174 __IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return _v; } \
175 __IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return _v; } \
176 __IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; }
177
178 #define __INS1(s) \
179 extern inline void __ins##s(unsigned long port, void * addr, unsigned long count) {
180
181 #define __INS2(m) \
182 if (count) \
183 __asm__ __volatile__ ( \
184 ".set\tnoreorder\n\t" \
185 ".set\tnoat\n" \
186 "1:\tl" #m "\t$1, %4(%5)\n\t" \
187 "dsubu\t%1, 1\n\t" \
188 "s" #m "\t$1,(%0)\n\t" \
189 "bnez\t%1, 1b\n\t" \
190 "daddiu\t%0, %6\n\t" \
191 ".set\tat\n\t" \
192 ".set\treorder"
193
194 #define __INS(m,s,i) \
195 __INS1(s) __INS2(m) \
196 : "=r" (addr), "=r" (count) \
197 : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \
198 : "$1");} \
199 __INS1(s##c) __INS2(m) \
200 : "=r" (addr), "=r" (count) \
201 : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \
202 : "$1");}
203
204 #define __OUTS1(s) \
205 extern inline void __outs##s(unsigned long port, const void * addr, unsigned long count) {
206
207 #define __OUTS2(m) \
208 if (count) \
209 __asm__ __volatile__ ( \
210 ".set\tnoreorder\n\t" \
211 ".set\tnoat\n" \
212 "1:\tl" #m "\t$1, (%0)\n\t" \
213 "dsubu\t%1, 1\n\t" \
214 "s" #m "\t$1, %4(%5)\n\t" \
215 "bnez\t%1, 1b\n\t" \
216 "daddiu\t%0, %6\n\t" \
217 ".set\tat\n\t" \
218 ".set\treorder"
219
220 #define __OUTS(m,s,i) \
221 __OUTS1(s) __OUTS2(m) \
222 : "=r" (addr), "=r" (count) \
223 : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \
224 : "$1");} \
225 __OUTS1(s##c) __OUTS2(m) \
226 : "=r" (addr), "=r" (count) \
227 : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \
228 : "$1");}
229
230 __IN(unsigned char,b,b)
231 __IN(unsigned short,h,w)
232 __IN(unsigned int,w,l)
233
234 __OUT(b,b)
235 __OUT(h,w)
236 __OUT(w,l)
237
238 __INS(b,b,1)
239 __INS(h,w,2)
240 __INS(w,l,4)
241
242 __OUTS(b,b,1)
243 __OUTS(h,w,2)
244 __OUTS(w,l,4)
245
246 /*
247 * Note that due to the way __builtin_constant_p() works, you
248 * - can't use it inside an inline function (it will never be true)
249 * - you don't have to worry about side effects within the __builtin..
250 */
251 #define outb(val,port) \
252 ((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
253 __outbc((val),(port)^(3)) : \
254 __outb((val),(port)^(3)))
255
256 #define inb(port) \
257 ((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
258 __inbc((port)^(3)) : \
259 __inb((port)^(3)))
260
261 #define outb_p(val,port) \
262 ((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
263 __outbc_p((val),(port)^(3)) : \
264 __outb_p((val),(port)^(3)))
265
266 #define inb_p(port) \
267 ((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
268 __inbc_p((port)^(3)) : \
269 __inb_p((port)^(3)))
270
271 #define outw(val,port) \
272 ((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \
273 __outwc((val),((port)^(2))) : \
274 __outw((val),((port)^(2))))
275
276 #define inw(port) \
277 ((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \
278 __inwc((port)^(2)) : \
279 __inw((port)^(2)))
280
281 #define outw_p(val,port) \
282 ((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \
283 __outwc_p((val),(port)^(2)) : \
284 __outw_p((val),(port)^(2)))
285
286 #define inw_p(port) \
287 ((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \
288 __inwc_p((port)^(2)) : \
289 __inw_p((port)^(2)))
290
291 #define outl(val,port) \
292 ((__builtin_constant_p((port)) && (port) < 32768) ? \
293 __outlc((val),(port)) : \
294 __outl((val),(port)))
295
296 #define inl(port) \
297 ((__builtin_constant_p((port)) && (port) < 32768) ? \
298 __inlc(port) : \
299 __inl(port))
300
301 #define outl_p(val,port) \
302 ((__builtin_constant_p((port)) && (port) < 32768) ? \
303 __outlc_p((val),(port)) : \
304 __outl_p((val),(port)))
305
306 #define inl_p(port) \
307 ((__builtin_constant_p((port)) && (port) < 32768) ? \
308 __inlc_p(port) : \
309 __inl_p(port))
310
311
312 #define outsb(port,addr,count) \
313 ((__builtin_constant_p((port)) && (port) < 32768) ? \
314 __outsbc((port),(addr),(count)) : \
315 __outsb ((port),(addr),(count)))
316
317 #define insb(port,addr,count) \
318 ((__builtin_constant_p((port)) && (port) < 32768) ? \
319 __insbc((port),(addr),(count)) : \
320 __insb((port),(addr),(count)))
321
322 #define outsw(port,addr,count) \
323 ((__builtin_constant_p((port)) && (port) < 32768) ? \
324 __outswc((port),(addr),(count)) : \
325 __outsw ((port),(addr),(count)))
326
327 #define insw(port,addr,count) \
328 ((__builtin_constant_p((port)) && (port) < 32768) ? \
329 __inswc((port),(addr),(count)) : \
330 __insw((port),(addr),(count)))
331
332 #define outsl(port,addr,count) \
333 ((__builtin_constant_p((port)) && (port) < 32768) ? \
334 __outslc((port),(addr),(count)) : \
335 __outsl ((port),(addr),(count)))
336
337 #define insl(port,addr,count) \
338 ((__builtin_constant_p((port)) && (port) < 32768) ? \
339 __inslc((port),(addr),(count)) : \
340 __insl((port),(addr),(count)))
341
342 /*
343 * The caches on some architectures aren't dma-coherent and have need to
344 * handle this in software. There are three types of operations that
345 * can be applied to dma buffers.
346 *
347 * - dma_cache_wback_inv(start, size) makes caches and coherent by
348 * writing the content of the caches back to memory, if necessary.
349 * The function also invalidates the affected part of the caches as
350 * necessary before DMA transfers from outside to memory.
351 * - dma_cache_wback(start, size) makes caches and coherent by
352 * writing the content of the caches back to memory, if necessary.
353 * The function also invalidates the affected part of the caches as
354 * necessary before DMA transfers from outside to memory.
355 * - dma_cache_inv(start, size) invalidates the affected parts of the
356 * caches. Dirty lines of the caches may be written back or simply
357 * be discarded. This operation is necessary before dma operations
358 * to the memory.
359 */
360 #ifdef CONFIG_COHERENT_IO
361
362 /* This is for example for IP27. */
363 extern inline void dma_cache_wback_inv(unsigned long start, unsigned long size)
364 {
365 }
366
367 extern inline void dma_cache_wback(unsigned long start, unsigned long size)
368 {
369 }
370
371 extern inline void dma_cache_inv(unsigned long start, unsigned long size)
372 {
373 }
374
375 #else
376
377 extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
378 extern void (*_dma_cache_wback)(unsigned long start, unsigned long size);
379 extern void (*_dma_cache_inv)(unsigned long start, unsigned long size);
380
381 #define dma_cache_wback_inv(start,size) _dma_cache_wback_inv(start,size)
382 #define dma_cache_wback(start,size) _dma_cache_wback(start,size)
383 #define dma_cache_inv(start,size) _dma_cache_inv(start,size)
384
385 #endif
386
387 #endif /* _ASM_IO_H */
388