summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2019-03-01 15:21:04 +0100
committerArnd Bergmann <arnd@arndb.de>2019-03-01 15:21:04 +0100
commitc889e2a0b053703be7e7591c9a574975440e5502 (patch)
tree09810287d9ed4d57e133ba4184deebb0db14c283 /drivers
parentee036df9bd1d3ca8b138c6376792c0b72f96a903 (diff)
parent2781204594c2705868c1f9388f80ae6cdcdabd22 (diff)
downloadlinux-c889e2a0b053703be7e7591c9a574975440e5502.tar.bz2
Merge branch 'milbeaut/newsoc' into arm/newsoc
Sugaya Taichi <sugaya.taichi@socionext.com> explains: Here is the series of patches the initial support for SC2000(M10V) of Milbeaut SoCs. "M10V" is the internal name of SC2000, so commonly used in source code. SC2000 is a SoC of the Milbeaut series. equipped with a DSP optimized for computer vision. It also features advanced functionalities such as 360-degree, real-time spherical stitching with multi cameras, image stabilization for without mechanical gimbals, and rolling shutter correction. More detail is below: https://www.socionext.com/en/products/assp/milbeaut/SC2000.html Specifications for developers are below: - Quad-core 32bit Cortex-A7 on ARMv7-A architecture - NEON support - DSP - GPU - MAX 3GB DDR3 - Cortex-M0 for power control - NAND Flash Interface - SD UHS-I - SD UHS-II - SDIO - USB2.0 HOST / Device - USB3.0 HOST / Device - PCI express Gen2 - Ethernet Engine - I2C - UART - SPI - PWM Support is quite minimal for now, since it only includes timer, clock, pictrl and serial controller drivers, so we can only boot to userspace through initramfs. Support for the other peripherals will come eventually. * milbeaut/newsoc: ARM: multi_v7_defconfig: add ARCH_MILBEAUT and ARCH_MILBEAUT_M10V ARM: configs: Add Milbeaut M10V defconfig ARM: dts: milbeaut: Add device tree set for the Milbeaut M10V board clocksource/drivers/timer-milbeaut: Introduce timer for Milbeaut SoCs dt-bindings: timer: Add Milbeaut M10V timer description ARM: milbeaut: Add basic support for Milbeaut m10v SoC dt-bindings: Add documentation for Milbeaut SoCs dt-bindings: arm: Add SMP enable-method for Milbeaut dt-bindings: sram: milbeaut: Add binding for Milbeaut smp-sram Link: https://lore.kernel.org/linux-arm-kernel/1551243056-10521-1-git-send-email-sugaya.taichi@socionext.com/ Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clocksource/Kconfig9
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-milbeaut.c161
3 files changed, 171 insertions, 0 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a9e26f6a81a1..9101b8fde93c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -634,4 +634,13 @@ config GX6605S_TIMER
help
This option enables support for gx6605s SOC's timer.
+config MILBEAUT_TIMER
+ bool "Milbeaut timer driver" if COMPILE_TEST
+ depends on OF
+ depends on ARM
+ select TIMER_OF
+ select CLKSRC_MMIO
+ help
+ Enables the support for Milbeaut timer driver.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cdd210ff89ea..6f2543bd5fdb 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
obj-$(CONFIG_OWL_TIMER) += timer-owl.o
+obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
obj-$(CONFIG_RDA_TIMER) += timer-rda.o
diff --git a/drivers/clocksource/timer-milbeaut.c b/drivers/clocksource/timer-milbeaut.c
new file mode 100644
index 000000000000..f2019a88e3ee
--- /dev/null
+++ b/drivers/clocksource/timer-milbeaut.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Socionext Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/sched_clock.h>
+#include "timer-of.h"
+
+#define MLB_TMR_TMCSR_OFS 0x0
+#define MLB_TMR_TMR_OFS 0x4
+#define MLB_TMR_TMRLR1_OFS 0x8
+#define MLB_TMR_TMRLR2_OFS 0xc
+#define MLB_TMR_REGSZPCH 0x10
+
+#define MLB_TMR_TMCSR_OUTL BIT(5)
+#define MLB_TMR_TMCSR_RELD BIT(4)
+#define MLB_TMR_TMCSR_INTE BIT(3)
+#define MLB_TMR_TMCSR_UF BIT(2)
+#define MLB_TMR_TMCSR_CNTE BIT(1)
+#define MLB_TMR_TMCSR_TRG BIT(0)
+
+#define MLB_TMR_TMCSR_CSL_DIV2 0
+#define MLB_TMR_DIV_CNT 2
+
+#define MLB_TMR_SRC_CH (1)
+#define MLB_TMR_EVT_CH (0)
+
+#define MLB_TMR_SRC_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_SRC_CH)
+#define MLB_TMR_EVT_CH_OFS (MLB_TMR_REGSZPCH * MLB_TMR_EVT_CH)
+
+#define MLB_TMR_SRC_TMCSR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMCSR_OFS)
+#define MLB_TMR_SRC_TMR_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMR_OFS)
+#define MLB_TMR_SRC_TMRLR1_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR1_OFS)
+#define MLB_TMR_SRC_TMRLR2_OFS (MLB_TMR_SRC_CH_OFS + MLB_TMR_TMRLR2_OFS)
+
+#define MLB_TMR_EVT_TMCSR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMCSR_OFS)
+#define MLB_TMR_EVT_TMR_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMR_OFS)
+#define MLB_TMR_EVT_TMRLR1_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR1_OFS)
+#define MLB_TMR_EVT_TMRLR2_OFS (MLB_TMR_EVT_CH_OFS + MLB_TMR_TMRLR2_OFS)
+
+#define MLB_TIMER_RATING 500
+
+static irqreturn_t mlb_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *clk = dev_id;
+ struct timer_of *to = to_timer_of(clk);
+ u32 val;
+
+ val = readl_relaxed(timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ val &= ~MLB_TMR_TMCSR_UF;
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+
+ clk->event_handler(clk);
+
+ return IRQ_HANDLED;
+}
+
+static int mlb_set_state_periodic(struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+ u32 val = MLB_TMR_TMCSR_CSL_DIV2;
+
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+
+ writel_relaxed(to->of_clk.period, timer_of_base(to) +
+ MLB_TMR_EVT_TMRLR1_OFS);
+ val |= MLB_TMR_TMCSR_RELD | MLB_TMR_TMCSR_CNTE |
+ MLB_TMR_TMCSR_TRG | MLB_TMR_TMCSR_INTE;
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_set_state_oneshot(struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+ u32 val = MLB_TMR_TMCSR_CSL_DIV2;
+
+ writel_relaxed(val, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_clkevt_next_event(unsigned long event,
+ struct clock_event_device *clk)
+{
+ struct timer_of *to = to_timer_of(clk);
+
+ writel_relaxed(event, timer_of_base(to) + MLB_TMR_EVT_TMRLR1_OFS);
+ writel_relaxed(MLB_TMR_TMCSR_CSL_DIV2 |
+ MLB_TMR_TMCSR_CNTE | MLB_TMR_TMCSR_INTE |
+ MLB_TMR_TMCSR_TRG, timer_of_base(to) +
+ MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_config_clock_source(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + MLB_TMR_SRC_TMCSR_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMR_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR1_OFS);
+ writel_relaxed(~0, timer_of_base(to) + MLB_TMR_SRC_TMRLR2_OFS);
+ writel_relaxed(BIT(4) | BIT(1) | BIT(0), timer_of_base(to) +
+ MLB_TMR_SRC_TMCSR_OFS);
+ return 0;
+}
+
+static int mlb_config_clock_event(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + MLB_TMR_EVT_TMCSR_OFS);
+ return 0;
+}
+
+static struct timer_of to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+
+ .clkevt = {
+ .name = "mlb-clkevt",
+ .rating = MLB_TIMER_RATING,
+ .cpumask = cpu_possible_mask,
+ .features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_oneshot = mlb_set_state_oneshot,
+ .set_state_periodic = mlb_set_state_periodic,
+ .set_next_event = mlb_clkevt_next_event,
+ },
+
+ .of_irq = {
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = mlb_timer_interrupt,
+ },
+};
+
+static u64 notrace mlb_timer_sched_read(void)
+{
+ return ~readl_relaxed(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS);
+}
+
+static int __init mlb_timer_init(struct device_node *node)
+{
+ int ret;
+ unsigned long rate;
+
+ ret = timer_of_init(node, &to);
+ if (ret)
+ return ret;
+
+ rate = timer_of_rate(&to) / MLB_TMR_DIV_CNT;
+ mlb_config_clock_source(&to);
+ clocksource_mmio_init(timer_of_base(&to) + MLB_TMR_SRC_TMR_OFS,
+ node->name, rate, MLB_TIMER_RATING, 32,
+ clocksource_mmio_readl_down);
+ sched_clock_register(mlb_timer_sched_read, 32, rate);
+ mlb_config_clock_event(&to);
+ clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), 15,
+ 0xffffffff);
+ return 0;
+}
+TIMER_OF_DECLARE(mlb_peritimer, "socionext,milbeaut-timer",
+ mlb_timer_init);