[PATCH 4/7] arm: initial support for Marvell Armada 370/XP SoCs

Thomas Petazzoni thomas.petazzoni at free-electrons.com
Fri May 3 12:51:08 EDT 2013


This commit adds minimal support for the Armada 370 and Armada XP SoCs
from Marvell.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
---
 arch/arm/Kconfig                            |    8 ++
 arch/arm/Makefile                           |    1 +
 arch/arm/mach-mvebu/Kconfig                 |   40 ++++++++
 arch/arm/mach-mvebu/Makefile                |    1 +
 arch/arm/mach-mvebu/core.c                  |  142 +++++++++++++++++++++++++++
 arch/arm/mach-mvebu/include/mach/clkdev.h   |    7 ++
 arch/arm/mach-mvebu/include/mach/debug_ll.h |   40 ++++++++
 arch/arm/mach-mvebu/include/mach/mvebu.h    |   22 +++++
 drivers/clocksource/Kconfig                 |    4 +
 drivers/clocksource/Makefile                |    1 +
 drivers/clocksource/mvebu.c                 |   90 +++++++++++++++++
 11 files changed, 356 insertions(+)
 create mode 100644 arch/arm/mach-mvebu/Kconfig
 create mode 100644 arch/arm/mach-mvebu/Makefile
 create mode 100644 arch/arm/mach-mvebu/core.c
 create mode 100644 arch/arm/mach-mvebu/include/mach/clkdev.h
 create mode 100644 arch/arm/mach-mvebu/include/mach/debug_ll.h
 create mode 100644 arch/arm/mach-mvebu/include/mach/mvebu.h
 create mode 100644 drivers/clocksource/mvebu.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7ac134e..4053c4d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -67,6 +67,13 @@ config ARCH_IMX
 	select WATCHDOG_IMX_RESET_SOURCE
 	select HAS_DEBUG_LL
 
+config ARCH_MVEBU
+	bool "Marvell EBU platforms"
+	select COMMON_CLK
+	select CLOCKSOURCE_MVEBU
+	select CLKDEV_LOOKUP
+	select HAS_DEBUG_LL
+
 config ARCH_MXS
 	bool "Freescale i.MX23/28 (mxs) based"
 	select GENERIC_GPIO
@@ -138,6 +145,7 @@ source arch/arm/mach-ep93xx/Kconfig
 source arch/arm/mach-highbank/Kconfig
 source arch/arm/mach-imx/Kconfig
 source arch/arm/mach-mxs/Kconfig
+source arch/arm/mach-mvebu/Kconfig
 source arch/arm/mach-netx/Kconfig
 source arch/arm/mach-nomadik/Kconfig
 source arch/arm/mach-omap/Kconfig
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index b98d6b8..6e7acde 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -58,6 +58,7 @@ machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
 machine-$(CONFIG_ARCH_HIGHBANK)		:= highbank
 machine-$(CONFIG_ARCH_IMX)		:= imx
 machine-$(CONFIG_ARCH_MXS)		:= mxs
+machine-$(CONFIG_ARCH_MVEBU)		:= mvebu
 machine-$(CONFIG_ARCH_NOMADIK)		:= nomadik
 machine-$(CONFIG_ARCH_NETX)		:= netx
 machine-$(CONFIG_ARCH_OMAP)		:= omap
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
new file mode 100644
index 0000000..4cbe546
--- /dev/null
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -0,0 +1,40 @@
+if ARCH_MVEBU
+
+config ARCH_TEXT_BASE
+	hex
+
+config BOARDINFO
+	default
+
+choice
+	prompt "Marvell EBU Processor"
+
+config ARCH_ARMADA_370
+	bool "Armada 370"
+	select CPU_V7
+
+config ARCH_ARMADA_XP
+	bool "Armada XP"
+	select CPU_V7
+
+endchoice
+
+if ARCH_ARMADA_370
+
+choice
+	prompt "Armada 370 Board Type"
+
+endchoice
+
+endif # ARCH_ARMADA_370
+
+if ARCH_ARMADA_XP
+
+choice
+	prompt "Armada XP Board Type"
+
+endchoice
+
+endif # ARCH_ARMADA_XP
+
+endif # ARCH_MVEBU
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
new file mode 100644
index 0000000..820eb10
--- /dev/null
+++ b/arch/arm/mach-mvebu/Makefile
@@ -0,0 +1 @@
+obj-y += core.o
diff --git a/arch/arm/mach-mvebu/core.c b/arch/arm/mach-mvebu/core.c
new file mode 100644
index 0000000..f4672a3
--- /dev/null
+++ b/arch/arm/mach-mvebu/core.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni at free-electrons.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 <asm/memory.h>
+#include <asm/barebox-arm.h>
+
+#define MVEBU_INT_REGS_BASE (0xd0000000)
+#define  MVEBU_UART0_BASE     (MVEBU_INT_REGS_BASE + 0x12000)
+#define  MVEBU_SYSCTL_BASE    (MVEBU_INT_REGS_BASE + 0x18200)
+#define  MVEBU_SDRAM_WIN_BASE (MVEBU_INT_REGS_BASE + 0x20180)
+#define  MVEBU_TIMER_BASE     (MVEBU_INT_REGS_BASE + 0x20300)
+#define  MVEBU_SAR_BASE       (MVEBU_INT_REGS_BASE + 0x18230)
+
+#define DDR_BASE_CS_OFF(n)     (0x0000 + ((n) << 3))
+#define  DDR_BASE_CS_HIGH_MASK  0xf
+#define  DDR_BASE_CS_LOW_MASK   0xff000000
+#define DDR_SIZE_CS_OFF(n)     (0x0004 + ((n) << 3))
+#define  DDR_SIZE_ENABLED       (1 << 0)
+#define  DDR_SIZE_CS_MASK       0x1c
+#define  DDR_SIZE_CS_SHIFT      2
+#define  DDR_SIZE_MASK          0xff000000
+
+#define SAR_LOW_REG_OFF         0
+#define  SAR_TCLK_FREQ_BIT      20
+#define SAR_HIGH_REG_OFF        0x4
+
+static struct clk *tclk;
+
+static inline void mvebu_memory_find(unsigned long *phys_base,
+				     unsigned long *phys_size)
+{
+	void __iomem *sdram_win = IOMEM(MVEBU_SDRAM_WIN_BASE);
+	int cs;
+
+	*phys_base = ~0;
+	*phys_size = 0;
+
+	for (cs = 0; cs < 4; cs++) {
+		uint32_t base = readl(sdram_win + DDR_BASE_CS_OFF(cs));
+		uint32_t ctrl = readl(sdram_win + DDR_SIZE_CS_OFF(cs));
+
+		/* Skip non-enabled CS */
+		if (! (ctrl & DDR_SIZE_ENABLED))
+			continue;
+
+		base &= DDR_BASE_CS_LOW_MASK;
+		if (base < *phys_base)
+			*phys_base = base;
+		*phys_size += (ctrl | ~DDR_SIZE_MASK) + 1;
+	}
+}
+
+void __naked __noreturn mvebu_barebox_entry(void)
+{
+	unsigned long phys_base, phys_size;
+	mvebu_memory_find(&phys_base, &phys_size);
+	barebox_arm_entry(phys_base, phys_size, 0);
+}
+
+static struct NS16550_plat uart0_plat = {
+	.shift = 2,
+};
+
+int mvebu_add_uart0(void)
+{
+	uart0_plat.clock = clk_get_rate(tclk);
+	add_ns16550_device(DEVICE_ID_DYNAMIC, MVEBU_UART0_BASE, 32,
+			   IORESOURCE_MEM_32BIT, &uart0_plat);
+	return 0;
+}
+
+#if defined(CONFIG_ARCH_ARMADA_370)
+static int mvebu_init_clocks(void)
+{
+	uint32_t val;
+	unsigned int rate;
+	void __iomem *sar = IOMEM(MVEBU_SAR_BASE) + SAR_LOW_REG_OFF;
+
+	val = readl(sar);
+
+	/* On Armada 370, the TCLK frequency can be either 166 Mhz or
+	 * 200 Mhz */
+	if (val & (1 << SAR_TCLK_FREQ_BIT))
+		rate = 200 * 1000 * 1000;
+	else
+		rate = 166 * 1000 * 1000;
+
+	tclk = clk_fixed("tclk", rate);
+	return clk_register_clkdev(tclk, NULL, "mvebu-timer");
+}
+#endif
+
+#if defined(CONFIG_ARCH_ARMADA_XP)
+static int mvebu_init_clocks(void)
+{
+	/* On Armada XP, the TCLK frequency is always 250 Mhz */
+	tclk = clk_fixed("tclk", 250 * 1000 * 1000);
+	return clk_register_clkdev(tclk, NULL, "mvebu-timer");
+}
+#endif
+
+static int mvebu_init_soc(void)
+{
+	unsigned long phys_base, phys_size;
+
+	mvebu_init_clocks();
+	add_generic_device("mvebu-timer", DEVICE_ID_SINGLE, NULL,
+			   MVEBU_TIMER_BASE, 0x30, IORESOURCE_MEM,
+			   NULL);
+	mvebu_memory_find(&phys_base, &phys_size);
+	arm_add_mem_device("ram0", phys_base, phys_size);
+	return 0;
+}
+
+postcore_initcall(mvebu_init_soc);
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+	writel(0x1, MVEBU_SYSCTL_BASE + 0x60);
+	writel(0x1, MVEBU_SYSCTL_BASE + 0x64);
+	while (1)
+		;
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-mvebu/include/mach/clkdev.h b/arch/arm/mach-mvebu/include/mach/clkdev.h
new file mode 100644
index 0000000..04b37a8
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/debug_ll.h b/arch/arm/mach-mvebu/include/mach/debug_ll.h
new file mode 100644
index 0000000..2653573
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/debug_ll.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni at free-electrons.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_DEBUG_LL_H__
+#define __MACH_DEBUG_LL_H__
+
+#include <io.h>
+
+#define UART_BASE 0xd0012000
+#define UART_THR  0x0
+#define UART_LSR  0x14
+#define   UART_LSR_THRE   (1 << 5)
+
+static inline void PUTC_LL(char c)
+{
+	/* Wait until there is space in the FIFO */
+	while (!(readl(UART_BASE + UART_LSR) & UART_LSR_THRE))
+		;
+
+	/* Send the character */
+	writel(c, UART_BASE + UART_THR)
+		;
+
+	/* Wait to make sure it hits the line, in case we die too soon. */
+	while (!(readl(UART_BASE + UART_LSR) & UART_LSR_THRE))
+		;
+}
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/mvebu.h b/arch/arm/mach-mvebu/include/mach/mvebu.h
new file mode 100644
index 0000000..e13a446
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/mvebu.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni at free-electrons.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_H
+#define __MACH_MVEBU_H
+
+int mvebu_add_uart0(void);
+void __naked __noreturn mvebu_barebox_entry(void);
+
+#endif /* __MACH_MVEBU_H */
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 3f27cf2..073ffd5 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -10,6 +10,10 @@ config CLOCKSOURCE_BCM2835
 	bool
 	depends on ARCH_BCM2835
 
+config CLOCKSOURCE_MVEBU
+	bool
+	depends on ARCH_MVEBU
+
 config CLOCKSOURCE_NOMADIK
 	bool
 	depends on ARM
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b0bc8bd..0ab7c37 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_AMBA_SP804) += amba-sp804.o
 obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
 obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
+obj-$(CONFIG_CLOCKSOURCE_MVEBU)   += mvebu.o
 obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
diff --git a/drivers/clocksource/mvebu.c b/drivers/clocksource/mvebu.c
new file mode 100644
index 0000000..2b48a5c
--- /dev/null
+++ b/drivers/clocksource/mvebu.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 Thomas Petazzoni <thomas.petazzoni at free-electrons.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_OFF          0x0000
+#define  TIMER0_EN               0x0001
+#define  TIMER0_RELOAD_EN        0x0002
+#define  TIMER0_25MHZ            0x0800
+#define  TIMER0_DIV(div)         ((div) << 19)
+#define  TIMER1_EN               0x0004
+#define  TIMER1_RELOAD_EN        0x0008
+#define  TIMER1_25MHZ            0x1000
+#define  TIMER1_DIV(div)         ((div) << 22)
+#define TIMER_EVENTS_STATUS     0x0004
+#define  TIMER0_CLR_MASK         (~0x1)
+#define  TIMER1_CLR_MASK         (~0x100)
+#define TIMER0_RELOAD_OFF       0x0010
+#define TIMER0_VAL_OFF          0x0014
+#define TIMER1_RELOAD_OFF       0x0018
+#define TIMER1_VAL_OFF          0x001c
+
+#define TIMER_DIVIDER_SHIFT     5
+
+static __iomem void *timer_base;
+
+uint64_t mvebu_clocksource_read(void)
+{
+	return __raw_readl(timer_base + TIMER0_VAL_OFF);
+}
+
+static struct clocksource cs = {
+	.read	= mvebu_clocksource_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.shift	= 10,
+};
+
+static int mvebu_timer_probe(struct device_d *dev)
+{
+	struct clk *tclk;
+	u32 val;
+
+	timer_base = dev_request_mem_region(dev, 0);
+
+	tclk = clk_get(dev, "tclk");
+
+	val = __raw_readl(timer_base + TIMER_CTRL_OFF);
+	val &= ~TIMER0_25MHZ;
+	__raw_writel(val, timer_base + TIMER_CTRL_OFF);
+
+	__raw_writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+	__raw_writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+
+	val = __raw_readl(timer_base + TIMER_CTRL_OFF);
+	val |= TIMER0_EN | TIMER0_RELOAD_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT);
+	__raw_writel(val, timer_base + TIMER_CTRL_OFF);
+
+	cs.mult = clocksource_hz2mult(clk_get_rate(tclk), cs.shift);
+
+	init_clock(&cs);
+
+	return 0;
+}
+
+static struct driver_d mvebu_timer_driver = {
+	.name = "mvebu-timer",
+	.probe = mvebu_timer_probe,
+};
+
+static int mvebu_timer_init(void)
+{
+	return platform_driver_register(&mvebu_timer_driver);
+}
+postcore_initcall(mvebu_timer_init);
-- 
1.7.9.5




More information about the barebox mailing list