mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 14:10:43 +00:00
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:
parent
8ac493cd65
commit
05e342554e
5 changed files with 34 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)); \
|
||||
\
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
obj-y += cache.o
|
||||
obj-y += cache_init.o
|
||||
obj-y += io.o
|
||||
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
|
||||
|
|
|
@ -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;
|
Loading…
Reference in a new issue