ARM: Orion: Consolidate the address map setup

Compile tested on Dove, orion5x, mv78xx0. Boot tested on Kirkwood.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Michael Walle <michael@walle.cc>
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
new file mode 100644
index 0000000..d3abb34
--- /dev/null
+++ b/arch/arm/plat-orion/addr-map.c
@@ -0,0 +1,166 @@
+/*
+ * arch/arm/plat-orion/addr-map.c
+ *
+ * Address map functions for Marvell Orion based SoCs
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <plat/addr-map.h>
+
+/*
+ * DDR target is the same on all Orion platforms.
+ */
+#define TARGET_DDR		0
+
+/*
+ * Helpers to get DDR bank info
+ */
+#define DDR_BASE_CS_OFF(n)	(0x0000 + ((n) << 3))
+#define DDR_SIZE_CS_OFF(n)	(0x0004 + ((n) << 3))
+
+/*
+ * CPU Address Decode Windows registers
+ */
+#define WIN_CTRL_OFF		0x0000
+#define WIN_BASE_OFF		0x0004
+#define WIN_REMAP_LO_OFF	0x0008
+#define WIN_REMAP_HI_OFF	0x000c
+
+/*
+ * Default implementation
+ */
+static void __init __iomem *
+orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
+{
+	return (void __iomem *)(cfg->bridge_virt_base + (win << 4));
+}
+
+/*
+ * Default implementation
+ */
+static int __init orion_cpu_win_can_remap(const struct orion_addr_map_cfg *cfg,
+					  const int win)
+{
+	if (win < cfg->remappable_wins)
+		return 1;
+
+	return 0;
+}
+
+void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
+				const int win, const u32 base,
+				const u32 size, const u8 target,
+				const u8 attr, const int remap)
+{
+	void __iomem *addr = cfg->win_cfg_base(cfg, win);
+	u32 ctrl, base_high, remap_addr;
+
+	if (win >= cfg->num_wins) {
+		printk(KERN_ERR "setup_cpu_win: trying to allocate window "
+		       "%d when only %d allowed\n", win, cfg->num_wins);
+	}
+
+	base_high = base & 0xffff0000;
+	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1;
+
+	writel(base_high, addr + WIN_BASE_OFF);
+	writel(ctrl, addr + WIN_CTRL_OFF);
+	if (cfg->cpu_win_can_remap(cfg, win)) {
+		if (remap < 0)
+			remap_addr = base;
+		else
+			remap_addr = remap;
+		writel(remap_addr & 0xffff0000, addr + WIN_REMAP_LO_OFF);
+		writel(0, addr + WIN_REMAP_HI_OFF);
+	}
+}
+
+/*
+ * Configure a number of windows.
+ */
+static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg,
+					const struct orion_addr_map_info *info)
+{
+	while (info->win != -1) {
+		orion_setup_cpu_win(cfg, info->win, info->base, info->size,
+				    info->target, info->attr, info->remap);
+		info++;
+	}
+}
+
+static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg)
+{
+	void __iomem *addr;
+	int i;
+
+	for (i = 0; i < cfg->num_wins; i++) {
+		addr = cfg->win_cfg_base(cfg, i);
+
+		writel(0, addr + WIN_BASE_OFF);
+		writel(0, addr + WIN_CTRL_OFF);
+		if (cfg->cpu_win_can_remap(cfg, i)) {
+			writel(0, addr + WIN_REMAP_LO_OFF);
+			writel(0, addr + WIN_REMAP_HI_OFF);
+		}
+	}
+}
+
+/*
+ * Disable, clear and configure windows.
+ */
+void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
+			      const struct orion_addr_map_info *info)
+{
+	if (!cfg->cpu_win_can_remap)
+		cfg->cpu_win_can_remap = orion_cpu_win_can_remap;
+
+	if (!cfg->win_cfg_base)
+		cfg->win_cfg_base = orion_win_cfg_base;
+
+	orion_disable_wins(cfg);
+
+	if (info)
+		orion_setup_cpu_wins(cfg, info);
+}
+
+/*
+ * Setup MBUS dram target info.
+ */
+void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
+					struct mbus_dram_target_info *info,
+					const u32 ddr_window_cpu_base)
+{
+	void __iomem *addr;
+	int i;
+	int cs;
+
+	info->mbus_dram_target_id = TARGET_DDR;
+
+	addr = (void __iomem *)ddr_window_cpu_base;
+
+	for (i = 0, cs = 0; i < 4; i++) {
+		u32 base = readl(addr + DDR_BASE_CS_OFF(i));
+		u32 size = readl(addr + DDR_SIZE_CS_OFF(i));
+
+		/*
+		 * Chip select enabled?
+		 */
+		if (size & 1) {
+			struct mbus_dram_window *w;
+
+			w = &info->cs[cs++];
+			w->cs_index = i;
+			w->mbus_attr = 0xf & ~(1 << i);
+			w->base = base & 0xffff0000;
+			w->size = (size | 0x0000ffff) + 1;
+		}
+	}
+	info->num_cs = cs;
+}