Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef __ALPHA_IO_H |
2 | #define __ALPHA_IO_H | |
3 | ||
4 | #ifdef __KERNEL__ | |
5 | ||
1da177e4 LT |
6 | #include <linux/kernel.h> |
7 | #include <asm/compiler.h> | |
8 | #include <asm/system.h> | |
9 | #include <asm/pgtable.h> | |
10 | #include <asm/machvec.h> | |
11 | #include <asm/hwrpb.h> | |
12 | ||
13 | /* The generic header contains only prototypes. Including it ensures that | |
14 | the implementation we have here matches that interface. */ | |
15 | #include <asm-generic/iomap.h> | |
16 | ||
17 | /* We don't use IO slowdowns on the Alpha, but.. */ | |
18 | #define __SLOW_DOWN_IO do { } while (0) | |
19 | #define SLOW_DOWN_IO do { } while (0) | |
20 | ||
21 | /* | |
22 | * Virtual -> physical identity mapping starts at this offset | |
23 | */ | |
24 | #ifdef USE_48_BIT_KSEG | |
25 | #define IDENT_ADDR 0xffff800000000000UL | |
26 | #else | |
27 | #define IDENT_ADDR 0xfffffc0000000000UL | |
28 | #endif | |
29 | ||
30 | /* | |
31 | * We try to avoid hae updates (thus the cache), but when we | |
32 | * do need to update the hae, we need to do it atomically, so | |
33 | * that any interrupts wouldn't get confused with the hae | |
34 | * register not being up-to-date with respect to the hardware | |
35 | * value. | |
36 | */ | |
37 | static inline void __set_hae(unsigned long new_hae) | |
38 | { | |
39 | unsigned long flags; | |
40 | local_irq_save(flags); | |
41 | ||
42 | alpha_mv.hae_cache = new_hae; | |
43 | *alpha_mv.hae_register = new_hae; | |
44 | mb(); | |
45 | /* Re-read to make sure it was written. */ | |
46 | new_hae = *alpha_mv.hae_register; | |
47 | ||
48 | local_irq_restore(flags); | |
49 | } | |
50 | ||
51 | static inline void set_hae(unsigned long new_hae) | |
52 | { | |
53 | if (new_hae != alpha_mv.hae_cache) | |
54 | __set_hae(new_hae); | |
55 | } | |
56 | ||
57 | /* | |
58 | * Change virtual addresses to physical addresses and vv. | |
59 | */ | |
60 | #ifdef USE_48_BIT_KSEG | |
61 | static inline unsigned long virt_to_phys(void *address) | |
62 | { | |
63 | return (unsigned long)address - IDENT_ADDR; | |
64 | } | |
65 | ||
66 | static inline void * phys_to_virt(unsigned long address) | |
67 | { | |
68 | return (void *) (address + IDENT_ADDR); | |
69 | } | |
70 | #else | |
71 | static inline unsigned long virt_to_phys(void *address) | |
72 | { | |
73 | unsigned long phys = (unsigned long)address; | |
74 | ||
75 | /* Sign-extend from bit 41. */ | |
76 | phys <<= (64 - 41); | |
77 | phys = (long)phys >> (64 - 41); | |
78 | ||
79 | /* Crop to the physical address width of the processor. */ | |
80 | phys &= (1ul << hwrpb->pa_bits) - 1; | |
81 | ||
82 | return phys; | |
83 | } | |
84 | ||
85 | static inline void * phys_to_virt(unsigned long address) | |
86 | { | |
87 | return (void *)(IDENT_ADDR + (address & ((1ul << 41) - 1))); | |
88 | } | |
89 | #endif | |
90 | ||
91 | #define page_to_phys(page) page_to_pa(page) | |
92 | ||
93 | /* This depends on working iommu. */ | |
94 | #define BIO_VMERGE_BOUNDARY (alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0) | |
95 | ||
96 | /* Maximum PIO space address supported? */ | |
97 | #define IO_SPACE_LIMIT 0xffff | |
98 | ||
99 | /* | |
100 | * Change addresses as seen by the kernel (virtual) to addresses as | |
101 | * seen by a device (bus), and vice versa. | |
102 | * | |
103 | * Note that this only works for a limited range of kernel addresses, | |
104 | * and very well may not span all memory. Consider this interface | |
105 | * deprecated in favour of the mapping functions in <asm/pci.h>. | |
106 | */ | |
107 | extern unsigned long __direct_map_base; | |
108 | extern unsigned long __direct_map_size; | |
109 | ||
110 | static inline unsigned long virt_to_bus(void *address) | |
111 | { | |
112 | unsigned long phys = virt_to_phys(address); | |
113 | unsigned long bus = phys + __direct_map_base; | |
114 | return phys <= __direct_map_size ? bus : 0; | |
115 | } | |
116 | ||
117 | static inline void *bus_to_virt(unsigned long address) | |
118 | { | |
119 | void *virt; | |
120 | ||
121 | /* This check is a sanity check but also ensures that bus address 0 | |
122 | maps to virtual address 0 which is useful to detect null pointers | |
123 | (the NCR driver is much simpler if NULL pointers are preserved). */ | |
124 | address -= __direct_map_base; | |
125 | virt = phys_to_virt(address); | |
126 | return (long)address <= 0 ? NULL : virt; | |
127 | } | |
128 | ||
129 | /* | |
130 | * There are different chipsets to interface the Alpha CPUs to the world. | |
131 | */ | |
132 | ||
133 | #define IO_CONCAT(a,b) _IO_CONCAT(a,b) | |
134 | #define _IO_CONCAT(a,b) a ## _ ## b | |
135 | ||
136 | #ifdef CONFIG_ALPHA_GENERIC | |
137 | ||
138 | /* In a generic kernel, we always go through the machine vector. */ | |
139 | ||
140 | #define REMAP1(TYPE, NAME, QUAL) \ | |
141 | static inline TYPE generic_##NAME(QUAL void __iomem *addr) \ | |
142 | { \ | |
143 | return alpha_mv.mv_##NAME(addr); \ | |
144 | } | |
145 | ||
146 | #define REMAP2(TYPE, NAME, QUAL) \ | |
147 | static inline void generic_##NAME(TYPE b, QUAL void __iomem *addr) \ | |
148 | { \ | |
149 | alpha_mv.mv_##NAME(b, addr); \ | |
150 | } | |
151 | ||
152 | REMAP1(unsigned int, ioread8, /**/) | |
153 | REMAP1(unsigned int, ioread16, /**/) | |
154 | REMAP1(unsigned int, ioread32, /**/) | |
155 | REMAP1(u8, readb, const volatile) | |
156 | REMAP1(u16, readw, const volatile) | |
157 | REMAP1(u32, readl, const volatile) | |
158 | REMAP1(u64, readq, const volatile) | |
159 | ||
160 | REMAP2(u8, iowrite8, /**/) | |
161 | REMAP2(u16, iowrite16, /**/) | |
162 | REMAP2(u32, iowrite32, /**/) | |
163 | REMAP2(u8, writeb, volatile) | |
164 | REMAP2(u16, writew, volatile) | |
165 | REMAP2(u32, writel, volatile) | |
166 | REMAP2(u64, writeq, volatile) | |
167 | ||
168 | #undef REMAP1 | |
169 | #undef REMAP2 | |
170 | ||
171 | static inline void __iomem *generic_ioportmap(unsigned long a) | |
172 | { | |
173 | return alpha_mv.mv_ioportmap(a); | |
174 | } | |
175 | ||
176 | static inline void __iomem *generic_ioremap(unsigned long a, unsigned long s) | |
177 | { | |
178 | return alpha_mv.mv_ioremap(a, s); | |
179 | } | |
180 | ||
181 | static inline void generic_iounmap(volatile void __iomem *a) | |
182 | { | |
183 | return alpha_mv.mv_iounmap(a); | |
184 | } | |
185 | ||
186 | static inline int generic_is_ioaddr(unsigned long a) | |
187 | { | |
188 | return alpha_mv.mv_is_ioaddr(a); | |
189 | } | |
190 | ||
191 | static inline int generic_is_mmio(const volatile void __iomem *a) | |
192 | { | |
193 | return alpha_mv.mv_is_mmio(a); | |
194 | } | |
195 | ||
196 | #define __IO_PREFIX generic | |
197 | #define generic_trivial_rw_bw 0 | |
198 | #define generic_trivial_rw_lq 0 | |
199 | #define generic_trivial_io_bw 0 | |
200 | #define generic_trivial_io_lq 0 | |
201 | #define generic_trivial_iounmap 0 | |
202 | ||
203 | #else | |
204 | ||
205 | #if defined(CONFIG_ALPHA_APECS) | |
206 | # include <asm/core_apecs.h> | |
207 | #elif defined(CONFIG_ALPHA_CIA) | |
208 | # include <asm/core_cia.h> | |
209 | #elif defined(CONFIG_ALPHA_IRONGATE) | |
210 | # include <asm/core_irongate.h> | |
211 | #elif defined(CONFIG_ALPHA_JENSEN) | |
212 | # include <asm/jensen.h> | |
213 | #elif defined(CONFIG_ALPHA_LCA) | |
214 | # include <asm/core_lca.h> | |
215 | #elif defined(CONFIG_ALPHA_MARVEL) | |
216 | # include <asm/core_marvel.h> | |
217 | #elif defined(CONFIG_ALPHA_MCPCIA) | |
218 | # include <asm/core_mcpcia.h> | |
219 | #elif defined(CONFIG_ALPHA_POLARIS) | |
220 | # include <asm/core_polaris.h> | |
221 | #elif defined(CONFIG_ALPHA_T2) | |
222 | # include <asm/core_t2.h> | |
223 | #elif defined(CONFIG_ALPHA_TSUNAMI) | |
224 | # include <asm/core_tsunami.h> | |
225 | #elif defined(CONFIG_ALPHA_TITAN) | |
226 | # include <asm/core_titan.h> | |
227 | #elif defined(CONFIG_ALPHA_WILDFIRE) | |
228 | # include <asm/core_wildfire.h> | |
229 | #else | |
230 | #error "What system is this?" | |
231 | #endif | |
232 | ||
233 | #endif /* GENERIC */ | |
234 | ||
235 | /* | |
236 | * We always have external versions of these routines. | |
237 | */ | |
238 | extern u8 inb(unsigned long port); | |
239 | extern u16 inw(unsigned long port); | |
240 | extern u32 inl(unsigned long port); | |
241 | extern void outb(u8 b, unsigned long port); | |
242 | extern void outw(u16 b, unsigned long port); | |
243 | extern void outl(u32 b, unsigned long port); | |
244 | ||
245 | extern u8 readb(const volatile void __iomem *addr); | |
246 | extern u16 readw(const volatile void __iomem *addr); | |
247 | extern u32 readl(const volatile void __iomem *addr); | |
248 | extern u64 readq(const volatile void __iomem *addr); | |
249 | extern void writeb(u8 b, volatile void __iomem *addr); | |
250 | extern void writew(u16 b, volatile void __iomem *addr); | |
251 | extern void writel(u32 b, volatile void __iomem *addr); | |
252 | extern void writeq(u64 b, volatile void __iomem *addr); | |
253 | ||
254 | extern u8 __raw_readb(const volatile void __iomem *addr); | |
255 | extern u16 __raw_readw(const volatile void __iomem *addr); | |
256 | extern u32 __raw_readl(const volatile void __iomem *addr); | |
257 | extern u64 __raw_readq(const volatile void __iomem *addr); | |
258 | extern void __raw_writeb(u8 b, volatile void __iomem *addr); | |
259 | extern void __raw_writew(u16 b, volatile void __iomem *addr); | |
260 | extern void __raw_writel(u32 b, volatile void __iomem *addr); | |
261 | extern void __raw_writeq(u64 b, volatile void __iomem *addr); | |
262 | ||
263 | /* | |
264 | * Mapping from port numbers to __iomem space is pretty easy. | |
265 | */ | |
266 | ||
267 | /* These two have to be extern inline because of the extern prototype from | |
268 | <asm-generic/iomap.h>. It is not legal to mix "extern" and "static" for | |
269 | the same declaration. */ | |
270 | extern inline void __iomem *ioport_map(unsigned long port, unsigned int size) | |
271 | { | |
272 | return IO_CONCAT(__IO_PREFIX,ioportmap) (port); | |
273 | } | |
274 | ||
275 | extern inline void ioport_unmap(void __iomem *addr) | |
276 | { | |
277 | } | |
278 | ||
279 | static inline void __iomem *ioremap(unsigned long port, unsigned long size) | |
280 | { | |
281 | return IO_CONCAT(__IO_PREFIX,ioremap) (port, size); | |
282 | } | |
283 | ||
284 | static inline void __iomem *__ioremap(unsigned long port, unsigned long size, | |
285 | unsigned long flags) | |
286 | { | |
287 | return ioremap(port, size); | |
288 | } | |
289 | ||
290 | static inline void __iomem * ioremap_nocache(unsigned long offset, | |
291 | unsigned long size) | |
292 | { | |
293 | return ioremap(offset, size); | |
294 | } | |
295 | ||
296 | static inline void iounmap(volatile void __iomem *addr) | |
297 | { | |
298 | IO_CONCAT(__IO_PREFIX,iounmap)(addr); | |
299 | } | |
300 | ||
301 | static inline int __is_ioaddr(unsigned long addr) | |
302 | { | |
303 | return IO_CONCAT(__IO_PREFIX,is_ioaddr)(addr); | |
304 | } | |
305 | #define __is_ioaddr(a) __is_ioaddr((unsigned long)(a)) | |
306 | ||
307 | static inline int __is_mmio(const volatile void __iomem *addr) | |
308 | { | |
309 | return IO_CONCAT(__IO_PREFIX,is_mmio)(addr); | |
310 | } | |
311 | ||
312 | ||
313 | /* | |
314 | * If the actual I/O bits are sufficiently trivial, then expand inline. | |
315 | */ | |
316 | ||
317 | #if IO_CONCAT(__IO_PREFIX,trivial_io_bw) | |
318 | extern inline unsigned int ioread8(void __iomem *addr) | |
319 | { | |
320 | unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr); | |
321 | mb(); | |
322 | return ret; | |
323 | } | |
324 | ||
325 | extern inline unsigned int ioread16(void __iomem *addr) | |
326 | { | |
327 | unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr); | |
328 | mb(); | |
329 | return ret; | |
330 | } | |
331 | ||
332 | extern inline void iowrite8(u8 b, void __iomem *addr) | |
333 | { | |
334 | IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr); | |
335 | mb(); | |
336 | } | |
337 | ||
338 | extern inline void iowrite16(u16 b, void __iomem *addr) | |
339 | { | |
340 | IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr); | |
341 | mb(); | |
342 | } | |
343 | ||
344 | extern inline u8 inb(unsigned long port) | |
345 | { | |
346 | return ioread8(ioport_map(port, 1)); | |
347 | } | |
348 | ||
349 | extern inline u16 inw(unsigned long port) | |
350 | { | |
351 | return ioread16(ioport_map(port, 2)); | |
352 | } | |
353 | ||
354 | extern inline void outb(u8 b, unsigned long port) | |
355 | { | |
356 | iowrite8(b, ioport_map(port, 1)); | |
357 | } | |
358 | ||
359 | extern inline void outw(u16 b, unsigned long port) | |
360 | { | |
361 | iowrite16(b, ioport_map(port, 2)); | |
362 | } | |
363 | #endif | |
364 | ||
365 | #if IO_CONCAT(__IO_PREFIX,trivial_io_lq) | |
366 | extern inline unsigned int ioread32(void __iomem *addr) | |
367 | { | |
368 | unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr); | |
369 | mb(); | |
370 | return ret; | |
371 | } | |
372 | ||
373 | extern inline void iowrite32(u32 b, void __iomem *addr) | |
374 | { | |
375 | IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr); | |
376 | mb(); | |
377 | } | |
378 | ||
379 | extern inline u32 inl(unsigned long port) | |
380 | { | |
381 | return ioread32(ioport_map(port, 4)); | |
382 | } | |
383 | ||
384 | extern inline void outl(u32 b, unsigned long port) | |
385 | { | |
386 | iowrite32(b, ioport_map(port, 4)); | |
387 | } | |
388 | #endif | |
389 | ||
390 | #if IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 1 | |
391 | extern inline u8 __raw_readb(const volatile void __iomem *addr) | |
392 | { | |
393 | return IO_CONCAT(__IO_PREFIX,readb)(addr); | |
394 | } | |
395 | ||
396 | extern inline u16 __raw_readw(const volatile void __iomem *addr) | |
397 | { | |
398 | return IO_CONCAT(__IO_PREFIX,readw)(addr); | |
399 | } | |
400 | ||
401 | extern inline void __raw_writeb(u8 b, volatile void __iomem *addr) | |
402 | { | |
403 | IO_CONCAT(__IO_PREFIX,writeb)(b, addr); | |
404 | } | |
405 | ||
406 | extern inline void __raw_writew(u16 b, volatile void __iomem *addr) | |
407 | { | |
408 | IO_CONCAT(__IO_PREFIX,writew)(b, addr); | |
409 | } | |
410 | ||
411 | extern inline u8 readb(const volatile void __iomem *addr) | |
412 | { | |
413 | u8 ret = __raw_readb(addr); | |
414 | mb(); | |
415 | return ret; | |
416 | } | |
417 | ||
418 | extern inline u16 readw(const volatile void __iomem *addr) | |
419 | { | |
420 | u16 ret = __raw_readw(addr); | |
421 | mb(); | |
422 | return ret; | |
423 | } | |
424 | ||
425 | extern inline void writeb(u8 b, volatile void __iomem *addr) | |
426 | { | |
427 | __raw_writeb(b, addr); | |
428 | mb(); | |
429 | } | |
430 | ||
431 | extern inline void writew(u16 b, volatile void __iomem *addr) | |
432 | { | |
433 | __raw_writew(b, addr); | |
434 | mb(); | |
435 | } | |
436 | #endif | |
437 | ||
438 | #if IO_CONCAT(__IO_PREFIX,trivial_rw_lq) == 1 | |
439 | extern inline u32 __raw_readl(const volatile void __iomem *addr) | |
440 | { | |
441 | return IO_CONCAT(__IO_PREFIX,readl)(addr); | |
442 | } | |
443 | ||
444 | extern inline u64 __raw_readq(const volatile void __iomem *addr) | |
445 | { | |
446 | return IO_CONCAT(__IO_PREFIX,readq)(addr); | |
447 | } | |
448 | ||
449 | extern inline void __raw_writel(u32 b, volatile void __iomem *addr) | |
450 | { | |
451 | IO_CONCAT(__IO_PREFIX,writel)(b, addr); | |
452 | } | |
453 | ||
454 | extern inline void __raw_writeq(u64 b, volatile void __iomem *addr) | |
455 | { | |
456 | IO_CONCAT(__IO_PREFIX,writeq)(b, addr); | |
457 | } | |
458 | ||
459 | extern inline u32 readl(const volatile void __iomem *addr) | |
460 | { | |
461 | u32 ret = __raw_readl(addr); | |
462 | mb(); | |
463 | return ret; | |
464 | } | |
465 | ||
466 | extern inline u64 readq(const volatile void __iomem *addr) | |
467 | { | |
468 | u64 ret = __raw_readq(addr); | |
469 | mb(); | |
470 | return ret; | |
471 | } | |
472 | ||
473 | extern inline void writel(u32 b, volatile void __iomem *addr) | |
474 | { | |
475 | __raw_writel(b, addr); | |
476 | mb(); | |
477 | } | |
478 | ||
479 | extern inline void writeq(u64 b, volatile void __iomem *addr) | |
480 | { | |
481 | __raw_writeq(b, addr); | |
482 | mb(); | |
483 | } | |
484 | #endif | |
485 | ||
486 | #define inb_p inb | |
487 | #define inw_p inw | |
488 | #define inl_p inl | |
489 | #define outb_p outb | |
490 | #define outw_p outw | |
491 | #define outl_p outl | |
492 | #define readb_relaxed(addr) __raw_readb(addr) | |
493 | #define readw_relaxed(addr) __raw_readw(addr) | |
494 | #define readl_relaxed(addr) __raw_readl(addr) | |
495 | #define readq_relaxed(addr) __raw_readq(addr) | |
496 | ||
497 | #define mmiowb() | |
498 | ||
499 | /* | |
500 | * String version of IO memory access ops: | |
501 | */ | |
502 | extern void memcpy_fromio(void *, const volatile void __iomem *, long); | |
503 | extern void memcpy_toio(volatile void __iomem *, const void *, long); | |
504 | extern void _memset_c_io(volatile void __iomem *, unsigned long, long); | |
505 | ||
506 | static inline void memset_io(volatile void __iomem *addr, u8 c, long len) | |
507 | { | |
508 | _memset_c_io(addr, 0x0101010101010101UL * c, len); | |
509 | } | |
510 | ||
511 | #define __HAVE_ARCH_MEMSETW_IO | |
512 | static inline void memsetw_io(volatile void __iomem *addr, u16 c, long len) | |
513 | { | |
514 | _memset_c_io(addr, 0x0001000100010001UL * c, len); | |
515 | } | |
516 | ||
517 | /* | |
518 | * String versions of in/out ops: | |
519 | */ | |
520 | extern void insb (unsigned long port, void *dst, unsigned long count); | |
521 | extern void insw (unsigned long port, void *dst, unsigned long count); | |
522 | extern void insl (unsigned long port, void *dst, unsigned long count); | |
523 | extern void outsb (unsigned long port, const void *src, unsigned long count); | |
524 | extern void outsw (unsigned long port, const void *src, unsigned long count); | |
525 | extern void outsl (unsigned long port, const void *src, unsigned long count); | |
526 | ||
1da177e4 LT |
527 | /* |
528 | * The Alpha Jensen hardware for some rather strange reason puts | |
529 | * the RTC clock at 0x170 instead of 0x70. Probably due to some | |
530 | * misguided idea about using 0x70 for NMI stuff. | |
531 | * | |
532 | * These defines will override the defaults when doing RTC queries | |
533 | */ | |
534 | ||
535 | #ifdef CONFIG_ALPHA_GENERIC | |
536 | # define RTC_PORT(x) ((x) + alpha_mv.rtc_port) | |
537 | #else | |
538 | # ifdef CONFIG_ALPHA_JENSEN | |
539 | # define RTC_PORT(x) (0x170+(x)) | |
540 | # else | |
541 | # define RTC_PORT(x) (0x70 + (x)) | |
542 | # endif | |
543 | #endif | |
544 | #define RTC_ALWAYS_BCD 0 | |
545 | ||
546 | /* Nothing to do */ | |
547 | ||
548 | #define dma_cache_inv(_start,_size) do { } while (0) | |
549 | #define dma_cache_wback(_start,_size) do { } while (0) | |
550 | #define dma_cache_wback_inv(_start,_size) do { } while (0) | |
551 | ||
552 | /* | |
553 | * Some mucking forons use if[n]def writeq to check if platform has it. | |
554 | * It's a bloody bad idea and we probably want ARCH_HAS_WRITEQ for them | |
555 | * to play with; for now just use cpp anti-recursion logics and make sure | |
556 | * that damn thing is defined and expands to itself. | |
557 | */ | |
558 | ||
559 | #define writeq writeq | |
560 | #define readq readq | |
561 | ||
562 | /* | |
563 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | |
564 | * access | |
565 | */ | |
566 | #define xlate_dev_mem_ptr(p) __va(p) | |
567 | ||
568 | /* | |
569 | * Convert a virtual cached pointer to an uncached pointer | |
570 | */ | |
571 | #define xlate_dev_kmem_ptr(p) p | |
572 | ||
573 | #endif /* __KERNEL__ */ | |
574 | ||
575 | #endif /* __ALPHA_IO_H */ |