X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-mips%2Fio.h;h=8e5ac32ae857d078bd1274234421f3803bd539d5;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=9ec7ced7a0f0c7d463f997a9c505e52cd440e82b;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h index 9ec7ced7a..8e5ac32ae 100644 --- a/include/asm-mips/io.h +++ b/include/asm-mips/io.h @@ -6,20 +6,26 @@ * Copyright (C) 1994, 1995 Waldorf GmbH * Copyright (C) 1994 - 2000 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Author: Maciej W. Rozycki */ #ifndef _ASM_IO_H #define _ASM_IO_H #include +#include +#include #include #include +#include +#include #include #include #include #include #include -#include + #include /* @@ -28,34 +34,54 @@ #undef CONF_SLOWDOWN_IO /* - * Sane hardware offers swapping of I/O space accesses in hardware; less - * sane hardware forces software to fiddle with this ... + * Raw operations are never swapped in software. Otoh values that raw + * operations are working on may or may not have been swapped by the bus + * hardware. An example use would be for flash memory that's used for + * execute in place. */ -#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) +# define __raw_ioswabb(x) (x) +# define __raw_ioswabw(x) (x) +# define __raw_ioswabl(x) (x) +# define __raw_ioswabq(x) (x) -#define __ioswab8(x) (x) +/* + * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware; + * less sane hardware forces software to fiddle with this... + */ +#if defined(CONFIG_SWAP_IO_SPACE) -#ifdef CONFIG_SGI_IP22 +# define ioswabb(x) (x) +# ifdef CONFIG_SGI_IP22 /* * IP22 seems braindead enough to swap 16bits values in hardware, but * not 32bits. Go figure... Can't tell without documentation. */ -#define __ioswab16(x) (x) -#else -#define __ioswab16(x) swab16(x) -#endif -#define __ioswab32(x) swab32(x) -#define __ioswab64(x) swab64(x) +# define ioswabw(x) (x) +# else +# define ioswabw(x) le16_to_cpu(x) +# endif +# define ioswabl(x) le32_to_cpu(x) +# define ioswabq(x) le64_to_cpu(x) #else -#define __ioswab8(x) (x) -#define __ioswab16(x) (x) -#define __ioswab32(x) (x) -#define __ioswab64(x) (x) +# define ioswabb(x) (x) +# define ioswabw(x) (x) +# define ioswabl(x) (x) +# define ioswabq(x) (x) #endif +/* + * Native bus accesses never swapped. + */ +#define bus_ioswabb(x) (x) +#define bus_ioswabw(x) (x) +#define bus_ioswabl(x) (x) +#define bus_ioswabq(x) (x) + +#define __bus_ioswabq bus_ioswabq + #define IO_SPACE_LIMIT 0xffff /* @@ -169,9 +195,9 @@ extern unsigned long isa_slot_offset; #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags); -extern void __iounmap(void *addr); +extern void __iounmap(volatile void __iomem *addr); -static inline void * __ioremap_mode(unsigned long offset, unsigned long size, +static inline void * __ioremap_mode(phys_t offset, unsigned long size, unsigned long flags) { if (cpu_has_64bit_addresses) { @@ -236,99 +262,252 @@ static inline void * __ioremap_mode(unsigned long offset, unsigned long size, #define ioremap_uncached_accelerated(offset, size) \ __ioremap_mode((offset), (size), _CACHE_UNCACHED_ACCELERATED) -static inline void iounmap(void *addr) +static inline void iounmap(volatile void __iomem *addr) { - if (cpu_has_64bits) + if (cpu_has_64bit_addresses) return; __iounmap(addr); } -#define __raw_readb(addr) (*(volatile unsigned char *)(addr)) -#define __raw_readw(addr) (*(volatile unsigned short *)(addr)) -#define __raw_readl(addr) (*(volatile unsigned int *)(addr)) -#ifdef CONFIG_MIPS32 -#define ____raw_readq(addr) \ -({ \ - u64 __res; \ + +#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ \ - __asm__ __volatile__ ( \ - " .set mips3 # ____raw_readq \n" \ - " ld %L0, (%1) \n" \ - " dsra32 %M0, %L0, 0 \n" \ - " sll %L0, %L0, 0 \n" \ - " .set mips0 \n" \ - : "=r" (__res) \ - : "r" (addr)); \ - __res; \ -}) -#define __raw_readq(addr) \ -({ \ - unsigned long __flags; \ - u64 __res; \ +static inline void pfx##write##bwlq(type val, \ + volatile void __iomem *mem) \ +{ \ + volatile type *__mem; \ + type __val; \ \ - local_irq_save(__flags); \ - __res = ____raw_readq(addr); \ - local_irq_restore(__flags); \ - __res; \ -}) -#endif -#ifdef CONFIG_MIPS64 -#define ____raw_readq(addr) (*(volatile unsigned long *)(addr)) -#define __raw_readq(addr) ____raw_readq(addr) -#endif + __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ + \ + __val = pfx##ioswab##bwlq(val); \ + \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ + *__mem = __val; \ + else if (cpu_has_64bits) { \ + unsigned long __flags; \ + type __tmp; \ + \ + if (irq) \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set mips3" "\t\t# __writeq""\n\t" \ + "dsll32 %L0, %L0, 0" "\n\t" \ + "dsrl32 %L0, %L0, 0" "\n\t" \ + "dsll32 %M0, %M0, 0" "\n\t" \ + "or %L0, %L0, %M0" "\n\t" \ + "sd %L0, %2" "\n\t" \ + ".set mips0" "\n" \ + : "=r" (__tmp) \ + : "0" (__val), "m" (*__mem)); \ + if (irq) \ + local_irq_restore(__flags); \ + } else \ + BUG(); \ +} \ + \ +static inline type pfx##read##bwlq(volatile void __iomem *mem) \ +{ \ + volatile type *__mem; \ + type __val; \ + \ + __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ + \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ + __val = *__mem; \ + else if (cpu_has_64bits) { \ + unsigned long __flags; \ + \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set mips3" "\t\t# __readq" "\n\t" \ + "ld %L0, %1" "\n\t" \ + "dsra32 %M0, %L0, 0" "\n\t" \ + "sll %L0, %L0, 0" "\n\t" \ + ".set mips0" "\n" \ + : "=r" (__val) \ + : "m" (*__mem)); \ + local_irq_restore(__flags); \ + } else { \ + __val = 0; \ + BUG(); \ + } \ + \ + return pfx##ioswab##bwlq(__val); \ +} -#define readb(addr) __ioswab8(__raw_readb(addr)) -#define readw(addr) __ioswab16(__raw_readw(addr)) -#define readl(addr) __ioswab32(__raw_readl(addr)) -#define readq(addr) __ioswab64(__raw_readq(addr)) -#define readb_relaxed(addr) readb(addr) -#define readw_relaxed(addr) readw(addr) -#define readl_relaxed(addr) readl(addr) -#define readq_relaxed(addr) readq(addr) - -#define __raw_writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (b)) -#define __raw_writew(w,addr) ((*(volatile unsigned short *)(addr)) = (w)) -#define __raw_writel(l,addr) ((*(volatile unsigned int *)(addr)) = (l)) -#ifdef CONFIG_MIPS32 -#define ____raw_writeq(val,addr) \ -({ \ - u64 __tmp; \ +#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ \ - __asm__ __volatile__ ( \ - " .set mips3 \n" \ - " dsll32 %L0, %L0, 0 # ____raw_writeq\n" \ - " dsrl32 %L0, %L0, 0 \n" \ - " dsll32 %M0, %M0, 0 \n" \ - " or %L0, %L0, %M0 \n" \ - " sd %L0, (%2) \n" \ - " .set mips0 \n" \ - : "=r" (__tmp) \ - : "0" ((unsigned long long)val), "r" (addr)); \ -}) -#define __raw_writeq(val,addr) \ -({ \ - unsigned long __flags; \ +static inline void pfx##out##bwlq##p(type val, unsigned long port) \ +{ \ + volatile type *__addr; \ + type __val; \ \ - local_irq_save(__flags); \ - ____raw_writeq(val, addr); \ - local_irq_restore(__flags); \ -}) -#endif -#ifdef CONFIG_MIPS64 -#define ____raw_writeq(q,addr) ((*(volatile unsigned long *)(addr)) = (q)) -#define __raw_writeq(q,addr) ____raw_writeq(q, addr) -#endif + port = __swizzle_addr_##bwlq(port); \ + __addr = (void *)(mips_io_port_base + port); \ + \ + __val = pfx##ioswab##bwlq(val); \ + \ + if (sizeof(type) != sizeof(u64)) { \ + *__addr = __val; \ + slow; \ + } else \ + BUILD_BUG(); \ +} \ + \ +static inline type pfx##in##bwlq##p(unsigned long port) \ +{ \ + volatile type *__addr; \ + type __val; \ + \ + port = __swizzle_addr_##bwlq(port); \ + __addr = (void *)(mips_io_port_base + port); \ + \ + if (sizeof(type) != sizeof(u64)) { \ + __val = *__addr; \ + slow; \ + } else { \ + __val = 0; \ + BUILD_BUG(); \ + } \ + \ + return pfx##ioswab##bwlq(__val); \ +} + +#define __BUILD_MEMORY_PFX(bus, bwlq, type) \ + \ +__BUILD_MEMORY_SINGLE(bus, bwlq, type, 1) + +#define __BUILD_IOPORT_PFX(bus, bwlq, type) \ + \ +__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,) \ +__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO) + +#define BUILDIO(bwlq, type) \ + \ +__BUILD_MEMORY_PFX(, bwlq, type) \ +__BUILD_MEMORY_PFX(__raw_, bwlq, type) \ +__BUILD_MEMORY_PFX(bus_, bwlq, type) \ +__BUILD_IOPORT_PFX(, bwlq, type) \ +__BUILD_IOPORT_PFX(__raw_, bwlq, type) + +#define __BUILDIO(bwlq, type) \ + \ +__BUILD_MEMORY_SINGLE(__bus_, bwlq, type, 0) -#define writeb(b,addr) __raw_writeb(__ioswab8(b),(addr)) -#define writew(w,addr) __raw_writew(__ioswab16(w),(addr)) -#define writel(l,addr) __raw_writel(__ioswab32(l),(addr)) -#define writeq(q,addr) __raw_writeq(__ioswab64(q),(addr)) +BUILDIO(b, u8) +BUILDIO(w, u16) +BUILDIO(l, u32) +BUILDIO(q, u64) + +__BUILDIO(q, u64) + +#define readb_relaxed readb +#define readw_relaxed readw +#define readl_relaxed readl +#define readq_relaxed readq + +/* + * Some code tests for these symbols + */ +#define readq readq +#define writeq writeq + +#define __BUILD_MEMORY_STRING(bwlq, type) \ + \ +static inline void writes##bwlq(volatile void __iomem *mem, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + __raw_write##bwlq(*__addr, mem); \ + __addr++; \ + } \ +} \ + \ +static inline void reads##bwlq(volatile void __iomem *mem, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + *__addr = __raw_read##bwlq(mem); \ + __addr++; \ + } \ +} + +#define __BUILD_IOPORT_STRING(bwlq, type) \ + \ +static inline void outs##bwlq(unsigned long port, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + __raw_out##bwlq(*__addr, port); \ + __addr++; \ + } \ +} \ + \ +static inline void ins##bwlq(unsigned long port, void *addr, \ + unsigned int count) \ +{ \ + volatile type *__addr = addr; \ + \ + while (count--) { \ + *__addr = __raw_in##bwlq(port); \ + __addr++; \ + } \ +} + +#define BUILDSTRING(bwlq, type) \ + \ +__BUILD_MEMORY_STRING(bwlq, type) \ +__BUILD_IOPORT_STRING(bwlq, type) + +BUILDSTRING(b, u8) +BUILDSTRING(w, u16) +BUILDSTRING(l, u32) +BUILDSTRING(q, u64) + + +/* Depends on MIPS II instruction set */ +#define mmiowb() asm volatile ("sync" ::: "memory") #define memset_io(a,b,c) memset((void *)(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) +/* + * Memory Mapped I/O + */ +#define ioread8(addr) readb(addr) +#define ioread16(addr) readw(addr) +#define ioread32(addr) readl(addr) + +#define iowrite8(b,addr) writeb(b,addr) +#define iowrite16(w,addr) writew(w,addr) +#define iowrite32(l,addr) writel(l,addr) + +#define ioread8_rep(a,b,c) readsb(a,b,c) +#define ioread16_rep(a,b,c) readsw(a,b,c) +#define ioread32_rep(a,b,c) readsl(a,b,c) + +#define iowrite8_rep(a,b,c) writesb(a,b,c) +#define iowrite16_rep(a,b,c) writesw(a,b,c) +#define iowrite32_rep(a,b,c) writesl(a,b,c) + +/* Create a virtual mapping cookie for an IO port range */ +extern void __iomem *ioport_map(unsigned long port, unsigned int nr); +extern void ioport_unmap(void __iomem *); + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +struct pci_dev; +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +extern void pci_iounmap(struct pci_dev *dev, void __iomem *); + /* * ISA space is 'always mapped' on currently supported MIPS systems, no need * to explicitly ioremap() it. The fact that the ISA IO space is mapped @@ -368,7 +547,7 @@ static inline void iounmap(void *addr) * address should have been obtained by ioremap. * Returns 1 on a match. */ -static inline int check_signature(unsigned long io_addr, +static inline int check_signature(char __iomem *io_addr, const unsigned char *signature, int length) { int retval = 0; @@ -384,191 +563,6 @@ out: return retval; } -/* - * isa_check_signature - find BIOS signatures - * @io_addr: mmio address to check - * @signature: signature block - * @length: length of signature - * - * Perform a signature comparison with the ISA mmio address io_addr. - * Returns 1 on a match. - * - * This function is deprecated. New drivers should use ioremap and - * check_signature. - */ -#define isa_check_signature(io, s, l) check_signature(i,s,l) - -static inline void __outb(unsigned char val, unsigned long port) -{ - port = __swizzle_addr_b(port); - - *(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val); -} - -static inline void __outw(unsigned short val, unsigned long port) -{ - port = __swizzle_addr_w(port); - - *(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val); -} - -static inline void __outl(unsigned int val, unsigned long port) -{ - port = __swizzle_addr_l(port); - - *(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val); -} - -static inline void __outb_p(unsigned char val, unsigned long port) -{ - port = __swizzle_addr_b(port); - - *(volatile u8 *)(mips_io_port_base + port) = __ioswab8(val); - SLOW_DOWN_IO; -} - -static inline void __outw_p(unsigned short val, unsigned long port) -{ - port = __swizzle_addr_w(port); - - *(volatile u16 *)(mips_io_port_base + port) = __ioswab16(val); - SLOW_DOWN_IO; -} - -static inline void __outl_p(unsigned int val, unsigned long port) -{ - port = __swizzle_addr_l(port); - - *(volatile u32 *)(mips_io_port_base + port) = __ioswab32(val); - SLOW_DOWN_IO; -} - -#define outb(val, port) __outb(val, port) -#define outw(val, port) __outw(val, port) -#define outl(val, port) __outl(val, port) -#define outb_p(val, port) __outb_p(val, port) -#define outw_p(val, port) __outw_p(val, port) -#define outl_p(val, port) __outl_p(val, port) - -static inline unsigned char __inb(unsigned long port) -{ - port = __swizzle_addr_b(port); - - return __ioswab8(*(volatile u8 *)(mips_io_port_base + port)); -} - -static inline unsigned short __inw(unsigned long port) -{ - port = __swizzle_addr_w(port); - - return __ioswab16(*(volatile u16 *)(mips_io_port_base + port)); -} - -static inline unsigned int __inl(unsigned long port) -{ - port = __swizzle_addr_l(port); - - return __ioswab32(*(volatile u32 *)(mips_io_port_base + port)); -} - -static inline unsigned char __inb_p(unsigned long port) -{ - u8 __val; - - port = __swizzle_addr_b(port); - - __val = *(volatile u8 *)(mips_io_port_base + port); - SLOW_DOWN_IO; - - return __ioswab8(__val); -} - -static inline unsigned short __inw_p(unsigned long port) -{ - u16 __val; - - port = __swizzle_addr_w(port); - - __val = *(volatile u16 *)(mips_io_port_base + port); - SLOW_DOWN_IO; - - return __ioswab16(__val); -} - -static inline unsigned int __inl_p(unsigned long port) -{ - u32 __val; - - port = __swizzle_addr_l(port); - - __val = *(volatile u32 *)(mips_io_port_base + port); - SLOW_DOWN_IO; - - return __ioswab32(__val); -} - -#define inb(port) __inb(port) -#define inw(port) __inw(port) -#define inl(port) __inl(port) -#define inb_p(port) __inb_p(port) -#define inw_p(port) __inw_p(port) -#define inl_p(port) __inl_p(port) - -static inline void __outsb(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - outb(*(u8 *)addr, port); - addr++; - } -} - -static inline void __insb(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u8 *)addr = inb(port); - addr++; - } -} - -static inline void __outsw(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - outw(*(u16 *)addr, port); - addr += 2; - } -} - -static inline void __insw(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u16 *)addr = inw(port); - addr += 2; - } -} - -static inline void __outsl(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - outl(*(u32 *)addr, port); - addr += 4; - } -} - -static inline void __insl(unsigned long port, void *addr, unsigned int count) -{ - while (count--) { - *(u32 *)addr = inl(port); - addr += 4; - } -} - -#define outsb(port, addr, count) __outsb(port, addr, count) -#define insb(port, addr, count) __insb(port, addr, count) -#define outsw(port, addr, count) __outsw(port, addr, count) -#define insw(port, addr, count) __insw(port, addr, count) -#define outsl(port, addr, count) __outsl(port, addr, count) -#define insl(port, addr, count) __insl(port, addr, count) - /* * The caches on some architectures aren't dma-coherent and have need to * handle this in software. There are three types of operations that