aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Burton2016-01-29 13:54:52 +0000
committerDaniel Schwierzeck2016-02-01 22:13:25 +0100
commit05e342554e51767830d7e60f2dab09192fd2a0e1 (patch)
treecabb4ea65f984769ddf00424672ac08bdaf1c161
parent8ac493cd65ea2af5f9b79f7f71edf543b46da112 (diff)
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>
-rw-r--r--arch/mips/Kconfig4
-rw-r--r--arch/mips/include/asm/global_data.h3
-rw-r--r--arch/mips/include/asm/io.h48
-rw-r--r--arch/mips/lib/Makefile1
-rw-r--r--arch/mips/lib/io.c12
5 files changed, 34 insertions, 34 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1b39c4c0c65..585887c4371 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -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
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 2d9a0c9e75d..a1ca257db59 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 4f9ec194b14..723a60a199a 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)); \
\
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index ac536da674d..b7ce5df7652 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -7,7 +7,6 @@
obj-y += cache.o
obj-y += cache_init.o
-obj-y += io.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/mips/lib/io.c b/arch/mips/lib/io.c
deleted file mode 100644
index b2d4a094dab..00000000000
--- a/arch/mips/lib/io.c
+++ /dev/null
@@ -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;