diff options
Diffstat (limited to 'arch/mips/include')
-rw-r--r-- | arch/mips/include/asm/global_data.h | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/io.h | 48 |
2 files changed, 30 insertions, 21 deletions
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index 2d9a0c9..a1ca257 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -12,6 +12,9 @@ /* Architecture-specific global data */ struct arch_global_data { +#ifdef CONFIG_DYNAMIC_IO_PORT_BASE + unsigned long io_port_base; +#endif #ifdef CONFIG_JZSOC /* There are other clocks in the jz4740 */ unsigned long per_clk; /* Peripheral bus clock */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 4f9ec19..723a60a 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -41,31 +41,37 @@ #define IO_SPACE_LIMIT 0xffff -/* - * On MIPS I/O ports are memory mapped, so we access them using normal - * load/store instructions. mips_io_port_base is the virtual address to - * which all ports are being mapped. For sake of efficiency some code - * assumes that this is an address that can be loaded with a single lui - * instruction, so the lower 16 bits must be zero. Should be true on - * on any sane architecture; generic code does not use this assumption. - */ -extern const unsigned long mips_io_port_base; +#ifdef CONFIG_DYNAMIC_IO_PORT_BASE + +static inline ulong mips_io_port_base(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + return gd->arch.io_port_base; +} -/* - * Gcc will generate code to load the value of mips_io_port_base after each - * function call which may be fairly wasteful in some cases. So we don't - * play quite by the book. We tell gcc mips_io_port_base is a long variable - * which solves the code generation issue. Now we need to violate the - * aliasing rules a little to make initialization possible and finally we - * will need the barrier() to fight side effects of the aliasing chat. - * This trickery will eventually collapse under gcc's optimizer. Oh well. - */ static inline void set_io_port_base(unsigned long base) { - * (unsigned long *) &mips_io_port_base = base; + DECLARE_GLOBAL_DATA_PTR; + + gd->arch.io_port_base = base; barrier(); } +#else /* !CONFIG_DYNAMIC_IO_PORT_BASE */ + +static inline ulong mips_io_port_base(void) +{ + return 0; +} + +static inline void set_io_port_base(unsigned long base) +{ + BUG_ON(base); +} + +#endif /* !CONFIG_DYNAMIC_IO_PORT_BASE */ + /* * virt_to_phys - map virtual addresses to physical * @address: address to remap @@ -293,7 +299,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ \ war_octeon_io_reorder_wmb(); \ \ - __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base() + port); \ \ __val = pfx##ioswab##bwlq(__addr, val); \ \ @@ -308,7 +314,7 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ volatile type *__addr; \ type __val; \ \ - __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base() + port); \ \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ |