diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-06 21:15:42 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-06 21:15:42 +0300 |
commit | 64b1b217f1a20f15dbedf47e49a25a0b5ee3d53b (patch) | |
tree | cd704f096ac0a5c26449ffe4c808c4735c5fe098 /drivers/clocksource | |
parent | fb686ad25be0343a9dab23acff674d0cb84bb516 (diff) | |
parent | c889e2a0b053703be7e7591c9a574975440e5502 (diff) |
Merge tag 'armsoc-newsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM new SoC family support from Arnd Bergmann:
"Two new SoC families are added this time.
Sugaya Taichi submitted support for the Milbeaut SoC family from
Socionext and explains:
"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"
Interestingly, this one has a history dating back to older chips made
by Socionext and previously Matsushita/Panasonic based on their own
mn10300 CPU architecture that was removed from the kernel last year.
Manivannan Sadhasivam adds support for another SoC family, this is the
Bitmain BM1880 chip used in the Sophon Edge TPU developer board.
The chip is intended for Deep Learning applications, and comes with
dual-core Arm Cortex-A53 to run Linux as well as a RISC-V
microcontroller core to control the tensor unit. For the moment, the
TPU is not accessible in mainline Linux, so we treat it as a generic
Arm SoC.
More information is available at
https://www.sophon.ai/"
* tag 'armsoc-newsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc:
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
MAINTAINERS: Add entry for Bitmain SoC platform
arm64: dts: bitmain: Add Sophon Egde board support
arm64: dts: bitmain: Add BM1880 SoC support
arm64: Add ARCH_BITMAIN platform
dt-bindings: arm: Document Bitmain BM1880 SoC
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-milbeaut.c | 161 |
3 files changed, 171 insertions, 0 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5d93e580e5dc..171502a356aa 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -645,4 +645,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 c4a8e9ef932a..be6e0fbc7489 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); |