Commit a8433137 authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle

[MIPS] Make I/O helpers more customizable

    
1. Move ioswab*() and __mem_ioswab*() to mangle-port.h.  This gets rid
   of CONFIG_SGI_IP22 from include/asm-mips/io.h.
    
2. Pass a virtual address to *ioswab*().  Then we can provide
   mach-specific *ioswab*() and can do every evil thing based on its
   argument.  It could be useful on machines which have regions with
   different endian conversion scheme.
    
3. Call __swizzle_addr*() _after_ adding mips_io_port_base.  This
   unifies the meaning of the argument of __swizzle_addr*() (always
   virtual address).  Then mach-specific __swizzle_addr*() can do every
   evil thing based on the argument.
Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent c1449c8f
...@@ -40,56 +40,13 @@ ...@@ -40,56 +40,13 @@
* hardware. An example use would be for flash memory that's used for * hardware. An example use would be for flash memory that's used for
* execute in place. * execute in place.
*/ */
# define __raw_ioswabb(x) (x) # define __raw_ioswabb(a,x) (x)
# define __raw_ioswabw(x) (x) # define __raw_ioswabw(a,x) (x)
# define __raw_ioswabl(x) (x) # define __raw_ioswabl(a,x) (x)
# define __raw_ioswabq(x) (x) # define __raw_ioswabq(a,x) (x)
# define ____raw_ioswabq(x) (x) # define ____raw_ioswabq(a,x) (x)
/* /* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
* Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware;
* less sane hardware forces software to fiddle with this...
*
* Regardless, if the host bus endianness mismatches that of PCI/ISA, then
* you can't have the numerical value of data and byte addresses within
* multibyte quantities both preserved at the same time. Hence two
* variations of functions: non-prefixed ones that preserve the value
* and prefixed ones that preserve byte addresses. The latters are
* typically used for moving raw data between a peripheral and memory (cf.
* string I/O functions), hence the "__mem_" prefix.
*/
#if defined(CONFIG_SWAP_IO_SPACE)
# define ioswabb(x) (x)
# define __mem_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 ioswabw(x) (x)
# define __mem_ioswabw(x) le16_to_cpu(x)
# else
# define ioswabw(x) le16_to_cpu(x)
# define __mem_ioswabw(x) (x)
# endif
# define ioswabl(x) le32_to_cpu(x)
# define __mem_ioswabl(x) (x)
# define ioswabq(x) le64_to_cpu(x)
# define __mem_ioswabq(x) (x)
#else
# define ioswabb(x) (x)
# define __mem_ioswabb(x) (x)
# define ioswabw(x) (x)
# define __mem_ioswabw(x) cpu_to_le16(x)
# define ioswabl(x) (x)
# define __mem_ioswabl(x) cpu_to_le32(x)
# define ioswabq(x) (x)
# define __mem_ioswabq(x) cpu_to_le32(x)
#endif
#define IO_SPACE_LIMIT 0xffff #define IO_SPACE_LIMIT 0xffff
...@@ -346,7 +303,7 @@ static inline void pfx##write##bwlq(type val, \ ...@@ -346,7 +303,7 @@ static inline void pfx##write##bwlq(type val, \
\ \
__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \
\ \
__val = pfx##ioswab##bwlq(val); \ __val = pfx##ioswab##bwlq(__mem, val); \
\ \
if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \
*__mem = __val; \ *__mem = __val; \
...@@ -401,7 +358,7 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ ...@@ -401,7 +358,7 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \
BUG(); \ BUG(); \
} \ } \
\ \
return pfx##ioswab##bwlq(__val); \ return pfx##ioswab##bwlq(__mem, __val); \
} }
#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ #define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \
...@@ -411,10 +368,9 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ ...@@ -411,10 +368,9 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \
volatile type *__addr; \ volatile type *__addr; \
type __val; \ type __val; \
\ \
port = __swizzle_addr_##bwlq(port); \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
__addr = (void *)(mips_io_port_base + port); \
\ \
__val = pfx##ioswab##bwlq(val); \ __val = pfx##ioswab##bwlq(__addr, val); \
\ \
/* Really, we want this to be atomic */ \ /* Really, we want this to be atomic */ \
BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
...@@ -428,15 +384,14 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ ...@@ -428,15 +384,14 @@ static inline type pfx##in##bwlq##p(unsigned long port) \
volatile type *__addr; \ volatile type *__addr; \
type __val; \ type __val; \
\ \
port = __swizzle_addr_##bwlq(port); \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
__addr = (void *)(mips_io_port_base + port); \
\ \
BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \
\ \
__val = *__addr; \ __val = *__addr; \
slow; \ slow; \
\ \
return pfx##ioswab##bwlq(__val); \ return pfx##ioswab##bwlq(__addr, __val); \
} }
#define __BUILD_MEMORY_PFX(bus, bwlq, type) \ #define __BUILD_MEMORY_PFX(bus, bwlq, type) \
......
...@@ -13,4 +13,40 @@ ...@@ -13,4 +13,40 @@
#define __swizzle_addr_l(port) (port) #define __swizzle_addr_l(port) (port)
#define __swizzle_addr_q(port) (port) #define __swizzle_addr_q(port) (port)
/*
* Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware;
* less sane hardware forces software to fiddle with this...
*
* Regardless, if the host bus endianness mismatches that of PCI/ISA, then
* you can't have the numerical value of data and byte addresses within
* multibyte quantities both preserved at the same time. Hence two
* variations of functions: non-prefixed ones that preserve the value
* and prefixed ones that preserve byte addresses. The latters are
* typically used for moving raw data between a peripheral and memory (cf.
* string I/O functions), hence the "__mem_" prefix.
*/
#if defined(CONFIG_SWAP_IO_SPACE)
# define ioswabb(a,x) (x)
# define __mem_ioswabb(a,x) (x)
# define ioswabw(a,x) le16_to_cpu(x)
# define __mem_ioswabw(a,x) (x)
# define ioswabl(a,x) le32_to_cpu(x)
# define __mem_ioswabl(a,x) (x)
# define ioswabq(a,x) le64_to_cpu(x)
# define __mem_ioswabq(a,x) (x)
#else
# define ioswabb(a,x) (x)
# define __mem_ioswabb(a,x) (x)
# define ioswabw(a,x) (x)
# define __mem_ioswabw(a,x) cpu_to_le16(x)
# define ioswabl(a,x) (x)
# define __mem_ioswabl(a,x) cpu_to_le32(x)
# define ioswabq(a,x) (x)
# define __mem_ioswabq(a,x) cpu_to_le32(x)
#endif
#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */ #endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */
...@@ -13,4 +13,13 @@ ...@@ -13,4 +13,13 @@
#define __swizzle_addr_l(port) (port) #define __swizzle_addr_l(port) (port)
#define __swizzle_addr_q(port) (port) #define __swizzle_addr_q(port) (port)
# define ioswabb(a,x) (x)
# define __mem_ioswabb(a,x) (x)
# define ioswabw(a,x) (x)
# define __mem_ioswabw(a,x) cpu_to_le16(x)
# define ioswabl(a,x) (x)
# define __mem_ioswabl(a,x) cpu_to_le32(x)
# define ioswabq(a,x) (x)
# define __mem_ioswabq(a,x) cpu_to_le32(x)
#endif /* __ASM_MACH_IP27_MANGLE_PORT_H */ #endif /* __ASM_MACH_IP27_MANGLE_PORT_H */
...@@ -14,4 +14,13 @@ ...@@ -14,4 +14,13 @@
#define __swizzle_addr_l(port) (port) #define __swizzle_addr_l(port) (port)
#define __swizzle_addr_q(port) (port) #define __swizzle_addr_q(port) (port)
# define ioswabb(a,x) (x)
# define __mem_ioswabb(a,x) (x)
# define ioswabw(a,x) (x)
# define __mem_ioswabw(a,x) cpu_to_le16(x)
# define ioswabl(a,x) (x)
# define __mem_ioswabl(a,x) cpu_to_le32(x)
# define ioswabq(a,x) (x)
# define __mem_ioswabq(a,x) cpu_to_le32(x)
#endif /* __ASM_MACH_IP32_MANGLE_PORT_H */ #endif /* __ASM_MACH_IP32_MANGLE_PORT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment