MIPS: Support dynamic I/O port base address

The existing mips_io_port_base variable isn't suitable for use early
during boot since it will be stored in the .data section which may not
be writable pre-relocation. Fix this by moving the I/O port base address
into struct arch_global_data. In order to avoid adding this field for
all targets, make this dependant upon a new Kconfig entry
CONFIG_DYNAMIC_IO_PORT_BASE. Malta is the only board which sets a
non-zero I/O port base, so select this option only for Malta.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
This commit is contained in:
Paul Burton 2016-01-29 13:54:52 +00:00 committed by Daniel Schwierzeck
parent 8ac493cd65
commit 05e342554e
5 changed files with 34 additions and 34 deletions

View file

@ -23,6 +23,7 @@ config TARGET_QEMU_MIPS
config TARGET_MALTA
bool "Support malta"
select DYNAMIC_IO_PORT_BASE
select SUPPORTS_BIG_ENDIAN
select SUPPORTS_LITTLE_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
@ -217,6 +218,9 @@ config MIPS_L1_CACHE_SHIFT
default "4" if MIPS_L1_CACHE_SHIFT_4
default "5"
config DYNAMIC_IO_PORT_BASE
bool
endif
endmenu

View file

@ -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 */

View file

@ -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)); \
\

View file

@ -7,7 +7,6 @@
obj-y += cache.o
obj-y += cache_init.o
obj-y += io.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o

View file

@ -1,12 +0,0 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* mips_io_port_base is the begin of the address space to which x86 style
* I/O ports are mapped.
*/
const unsigned long mips_io_port_base = -1;