diff options
author | Stefan Roese <sr@denx.de> | 2015-07-01 10:44:51 (GMT) |
---|---|---|
committer | Luka Perkov <luka.perkov@sartura.hr> | 2015-08-17 16:48:46 (GMT) |
commit | 5b72dbfc23e4f9a62cfe787816c5b5e75a0aa597 (patch) | |
tree | e07ea9225e244c110ae268c3606c108706eb36db /arch/arm/mach-mvebu/mbus.c | |
parent | 8ed20d65010d46fd58121ea9ee9c913abc3d8e13 (diff) | |
download | u-boot-5b72dbfc23e4f9a62cfe787816c5b5e75a0aa597.tar.xz |
arm: mvebu: Setup the MBUS bridge registers
With this patch, the MBUS bridge registers (base and size) are
configured upon each call to mbus_dt_setup_win(). This is needed, since
the board code can also call this function in later boot stages. As
done in the maxbcm board.
This is needed to fix a problem with the secondary CPU's not booting
in Linux on AXP.
Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Peter Morrow <peter@senient.com>
Cc: Luka Perkov <luka.perkov@sartura.hr>
Diffstat (limited to 'arch/arm/mach-mvebu/mbus.c')
-rw-r--r-- | arch/arm/mach-mvebu/mbus.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c index 9b76bce..71fa693 100644 --- a/arch/arm/mach-mvebu/mbus.c +++ b/arch/arm/mach-mvebu/mbus.c @@ -52,6 +52,7 @@ #include <asm/io.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> +#include <linux/compat.h> #include <linux/mbus.h> #define BIT(nr) (1UL << (nr)) @@ -407,6 +408,53 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size) return 0; } +static void mvebu_mbus_get_lowest_base(struct mvebu_mbus_state *mbus, + phys_addr_t *base) +{ + int win; + *base = 0xffffffff; + + for (win = 0; win < mbus->soc->num_wins; win++) { + u64 wbase; + u32 wsize; + u8 wtarget, wattr; + int enabled; + + mvebu_mbus_read_window(mbus, win, + &enabled, &wbase, &wsize, + &wtarget, &wattr, NULL); + + if (!enabled) + continue; + + if (wbase < *base) + *base = wbase; + } +} + +static void mvebu_config_mbus_bridge(struct mvebu_mbus_state *mbus) +{ + phys_addr_t base; + u32 val; + u32 size; + + /* Set MBUS bridge base/ctrl */ + mvebu_mbus_get_lowest_base(&mbus_state, &base); + + size = 0xffffffff - base + 1; + if (!is_power_of_2(size)) { + /* Round up to next power of 2 */ + size = 1 << (ffs(base) + 1); + base = 0xffffffff - size + 1; + } + + /* Now write base and size */ + writel(base, MBUS_BRIDGE_WIN_BASE_REG); + /* Align window size to 64KiB */ + val = (size / (64 << 10)) - 1; + writel((val << 16) | 0x1, MBUS_BRIDGE_WIN_CTRL_REG); +} + int mbus_dt_setup_win(struct mvebu_mbus_state *mbus, u32 base, u32 size, u8 target, u8 attr) { @@ -426,6 +474,13 @@ int mbus_dt_setup_win(struct mvebu_mbus_state *mbus, return -ENOMEM; } + /* + * Re-configure the mbus bridge registers each time this function + * is called. Since it may get called from the board code in + * later boot stages as well. + */ + mvebu_config_mbus_bridge(mbus); + return 0; } |