summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2013-05-12 15:09:04 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-05-15 07:39:27 +0200
commit98a8c2f28bf93bcdf410bc4e560c4690f9994f93 (patch)
tree68099b9be65086ec49fee8f4288cf9dd46352310
parent87f486c7f1878cdd9de45c4e7962e3009092d270 (diff)
downloadbarebox-98a8c2f28bf93bcdf410bc4e560c4690f9994f93.tar.gz
barebox-98a8c2f28bf93bcdf410bc4e560c4690f9994f93.tar.xz
arm: initial support for Marvell Dove SoCs
This commit adds minimal support for the Marvell Dove SoC (88AP510) as first SoC of the Marvell Orion family. Orion SoCs have a different timer, therefore current mach-mvebu and Armada 370/XP Kconfig and Makefiles are slightly modified and a new clocksource drivers is added. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-mvebu/Kconfig16
-rw-r--r--arch/arm/mach-mvebu/Makefile4
-rw-r--r--arch/arm/mach-mvebu/dove.c161
-rw-r--r--arch/arm/mach-mvebu/include/mach/dove-regs.h59
-rw-r--r--arch/arm/mach-mvebu/include/mach/dove.h23
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/orion.c76
9 files changed, 343 insertions, 2 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a044ab3362..cfb82b0515 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -82,7 +82,6 @@ config ARCH_IMX
config ARCH_MVEBU
bool "Marvell EBU platforms"
select COMMON_CLK
- select CLOCKSOURCE_MVEBU
select CLKDEV_LOOKUP
select HAS_DEBUG_LL
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index e553e2dc0c..c02eea1c8d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -17,10 +17,17 @@ choice
config ARCH_ARMADA_370
bool "Armada 370"
select CPU_V7
+ select CLOCKSOURCE_MVEBU
config ARCH_ARMADA_XP
bool "Armada XP"
select CPU_V7
+ select CLOCKSOURCE_MVEBU
+
+config ARCH_DOVE
+ bool "Dove 88AP510"
+ select CPU_V7
+ select CLOCKSOURCE_ORION
endchoice
@@ -51,4 +58,13 @@ endchoice
endif # ARCH_ARMADA_XP
+if ARCH_DOVE
+
+choice
+ prompt "Dove 88AP510 Board Type"
+
+endchoice
+
+endif # ARCH_DOVE
+
endif # ARCH_MVEBU
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 820eb10ac2..0257b732e8 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1 +1,3 @@
-obj-y += core.o
+obj-$(CONFIG_ARCH_ARMADA_370) += core.o
+obj-$(CONFIG_ARCH_ARMADA_XP) += core.o
+obj-$(CONFIG_ARCH_DOVE) += dove.o
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
new file mode 100644
index 0000000000..f073596cc5
--- /dev/null
+++ b/arch/arm/mach-mvebu/dove.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright
+ * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <ns16550.h>
+#include <mach/dove-regs.h>
+#include <asm/memory.h>
+#include <asm/barebox-arm.h>
+
+static struct clk *tclk;
+
+static inline void dove_remap_reg_base(uint32_t intbase,
+ uint32_t mcbase)
+{
+ uint32_t val;
+
+ /* remap ahb slave base */
+ val = readl(DOVE_CPU_CTRL) & 0xffff0000;
+ val |= (mcbase & 0xffff0000) >> 16;
+ writel(val, DOVE_CPU_CTRL);
+
+ /* remap axi bridge address */
+ val = readl(DOVE_AXI_CTRL) & 0x007fffff;
+ val |= mcbase & 0xff800000;
+ writel(val, DOVE_AXI_CTRL);
+
+ /* remap memory controller base address */
+ val = readl(DOVE_SDRAM_BASE + SDRAM_REGS_BASE_DECODE) & 0x0000ffff;
+ val |= mcbase & 0xffff0000;
+ writel(val, DOVE_SDRAM_BASE + SDRAM_REGS_BASE_DECODE);
+
+ /* remap internal register */
+ val = intbase & 0xfff00000;
+ writel(val, DOVE_BRIDGE_BASE + INT_REGS_BASE_MAP);
+}
+
+static inline void dove_memory_find(unsigned long *phys_base,
+ unsigned long *phys_size)
+{
+ int n;
+
+ *phys_base = ~0;
+ *phys_size = 0;
+
+ for (n = 0; n < 2; n++) {
+ uint32_t map = readl(DOVE_SDRAM_BASE + SDRAM_MAPn(n));
+ uint32_t base, size;
+
+ /* skip disabled areas */
+ if ((map & SDRAM_MAP_VALID) != SDRAM_MAP_VALID)
+ continue;
+
+ base = map & SDRAM_START_MASK;
+ if (base < *phys_base)
+ *phys_base = base;
+
+ /* real size is encoded as ld(2^(16+length)) */
+ size = (map & SDRAM_LENGTH_MASK) >> SDRAM_LENGTH_SHIFT;
+ *phys_size += 1 << (16 + size);
+ }
+}
+
+void __naked __noreturn dove_barebox_entry(void)
+{
+ unsigned long phys_base, phys_size;
+ dove_memory_find(&phys_base, &phys_size);
+ barebox_arm_entry(phys_base, phys_size, 0);
+}
+
+static struct NS16550_plat uart_plat[] = {
+ [0] = { .shift = 2, },
+ [1] = { .shift = 2, },
+ [2] = { .shift = 2, },
+ [3] = { .shift = 2, },
+};
+
+int dove_add_uart(int num)
+{
+ struct NS16550_plat *plat;
+
+ if (num < 0 || num > 4)
+ return -EINVAL;
+
+ plat = &uart_plat[num];
+ plat->clock = clk_get_rate(tclk);
+ if (!add_ns16550_device(DEVICE_ID_DYNAMIC,
+ (unsigned int)DOVE_UARTn_BASE(num),
+ 32, IORESOURCE_MEM_32BIT, plat))
+ return -ENODEV;
+ return 0;
+}
+
+/*
+ * Dove TCLK sample-at-reset configuation
+ *
+ * SAR0[24:23] : TCLK frequency
+ * 0 = 166 MHz
+ * 1 = 125 MHz
+ * others reserved.
+ */
+static int dove_init_clocks(void)
+{
+ uint32_t strap, sar = readl(DOVE_SAR_BASE + SAR0);
+ unsigned int rate;
+
+ strap = (sar & TCLK_FREQ_MASK) >> TCLK_FREQ_SHIFT;
+ switch (strap) {
+ case 0:
+ rate = 166666667;
+ break;
+ case 1:
+ rate = 125000000;
+ break;
+ default:
+ panic("Unknown TCLK strapping %d\n", strap);
+ }
+
+ tclk = clk_fixed("tclk", rate);
+ return clk_register_clkdev(tclk, NULL, "orion-timer");
+}
+
+static int dove_init_soc(void)
+{
+ unsigned long phys_base, phys_size;
+
+ dove_init_clocks();
+ add_generic_device("orion-timer", DEVICE_ID_SINGLE, NULL,
+ (unsigned int)DOVE_TIMER_BASE, 0x30,
+ IORESOURCE_MEM, NULL);
+ dove_memory_find(&phys_base, &phys_size);
+ arm_add_mem_device("ram0", phys_base, phys_size);
+ return 0;
+}
+postcore_initcall(dove_init_soc);
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ /* enable and assert RSTOUTn */
+ writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
+ writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
+ while (1)
+ ;
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-mvebu/include/mach/dove-regs.h b/arch/arm/mach-mvebu/include/mach/dove-regs.h
new file mode 100644
index 0000000000..5e203688de
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/dove-regs.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright
+ * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_MVEBU_DOVE_REGS_H
+#define __MACH_MVEBU_DOVE_REGS_H
+
+/* At Boot-up register base is at 0xd000000 */
+#define DOVE_INT_REGS_BOOTUP 0xd0000000
+#define DOVE_MC_REGS_BOOTUP 0xd0800000
+/* Linux wants it remapped to 0xf1000000 */
+#define DOVE_INT_REGS_REMAP 0xf1000000
+#define DOVE_MC_REGS_REMAP 0xf1800000
+
+#define DOVE_INT_REGS_BASE IOMEM(DOVE_INT_REGS_BOOTUP)
+#define DOVE_MC_REGS_BASE IOMEM(DOVE_MC_REGS_BOOTUP)
+
+#define DOVE_UART_BASE (DOVE_INT_REGS_BASE + 0x12000)
+#define DOVE_UARTn_BASE(n) (DOVE_UART_BASE + ((n) * 0x100))
+
+#define DOVE_BRIDGE_BASE (DOVE_INT_REGS_BASE + 0x20000)
+#define INT_REGS_BASE_MAP 0x080
+#define BRIDGE_RSTOUT_MASK 0x108
+#define SOFT_RESET_OUT_EN BIT(2)
+#define BRIDGE_SYS_SOFT_RESET 0x10c
+#define SOFT_RESET_EN BIT(0)
+#define DOVE_TIMER_BASE (DOVE_INT_REGS_BASE + 0x20300)
+
+#define DOVE_SAR_BASE (DOVE_INT_REGS_BASE + 0xd0214)
+#define SAR0 0x000
+#define TCLK_FREQ_SHIFT 23
+#define TCLK_FREQ_MASK (0x3 << TCLK_FREQ_SHIFT)
+#define SAR1 0x004
+
+#define DOVE_AXI_CTRL (DOVE_INT_REGS_BASE + 0xd0224)
+#define DOVE_CPU_CTRL (DOVE_INT_REGS_BASE + 0xd025c)
+
+#define DOVE_SDRAM_BASE (DOVE_MC_REGS_BASE)
+#define SDRAM_REGS_BASE_DECODE 0x010
+#define SDRAM_MAPn(n) (0x100 + ((n) * 0x10))
+#define SDRAM_START_MASK (0x1ff << 23)
+#define SDRAM_LENGTH_SHIFT 16
+#define SDRAM_LENGTH_MASK (0x00f << SDRAM_LENGTH_SHIFT)
+#define SDRAM_ADDRESS_MASK (0x1ff << 7)
+#define SDRAM_MAP_VALID BIT(0)
+
+#endif /* __MACH_MVEBU_DOVE_REGS_H */
diff --git a/arch/arm/mach-mvebu/include/mach/dove.h b/arch/arm/mach-mvebu/include/mach/dove.h
new file mode 100644
index 0000000000..1712fa7a1d
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/dove.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright
+ * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_MVEBU_DOVE_H
+#define __MACH_MVEBU_DOVE_H
+
+int dove_add_uart(int num);
+void __naked __noreturn dove_barebox_entry(void);
+
+#endif /* __MACH_MVEBU_DOVE_H */
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index dfc89ddea8..4ef25ec45b 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -21,3 +21,7 @@ config CLOCKSOURCE_MVEBU
config CLOCKSOURCE_NOMADIK
bool
depends on ARM
+
+config CLOCKSOURCE_ORION
+ bool
+ depends on ARCH_MVEBU
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 0b42ce48d6..25b7f460da 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o
obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
+obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
diff --git a/drivers/clocksource/orion.c b/drivers/clocksource/orion.c
new file mode 100644
index 0000000000..604b414742
--- /dev/null
+++ b/drivers/clocksource/orion.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright
+ * (C) 2013 Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <linux/clk.h>
+#include <io.h>
+
+#define TIMER_CTRL 0x00
+#define TIMER0_EN BIT(0)
+#define TIMER0_RELOAD_EN BIT(1)
+#define TIMER1_EN BIT(2)
+#define TIMER1_RELOAD_EN BIT(3)
+#define TIMER0_RELOAD 0x10
+#define TIMER0_VAL 0x14
+#define TIMER1_RELOAD 0x18
+#define TIMER1_VAL 0x1c
+
+static __iomem void *timer_base;
+
+static uint64_t orion_clocksource_read(void)
+{
+ return __raw_readl(timer_base + TIMER0_VAL);
+}
+
+static struct clocksource clksrc = {
+ .read = orion_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+};
+
+static int orion_timer_probe(struct device_d *dev)
+{
+ struct clk *tclk;
+ uint32_t val;
+
+ timer_base = dev_request_mem_region(dev, 0);
+ tclk = clk_get(dev, "tclk");
+
+ /* setup TIMER0 as free-running clock source */
+ __raw_writel(~0, timer_base + TIMER0_VAL);
+ __raw_writel(~0, timer_base + TIMER0_RELOAD);
+ val = __raw_readl(timer_base + TIMER_CTRL);
+ __raw_writel(val | TIMER0_EN | TIMER0_RELOAD_EN,
+ timer_base + TIMER_CTRL);
+
+ clksrc.mult = clocksource_hz2mult(clk_get_rate(tclk), clksrc.shift);
+ init_clock(&clksrc);
+
+ return 0;
+}
+
+static struct driver_d orion_timer_driver = {
+ .name = "orion-timer",
+ .probe = orion_timer_probe,
+};
+
+static int orion_timer_init(void)
+{
+ return platform_driver_register(&orion_timer_driver);
+}
+postcore_initcall(orion_timer_init);