Message ID | 1423763164-5606-4-git-send-email-mcoquelin.stm32@gmail.com |
---|---|
State | New |
Headers | show |
On Thu, Feb 12, 2015 at 11:45 AM, Maxime Coquelin <mcoquelin.stm32@gmail.com> wrote: > This patch adds clocksource support for ARMv7-M's System timer, > also known as SysTick. > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com> > --- > .../devicetree/bindings/arm/system_timer.txt | 15 +++++ Please include v7M in the name. System timer sounds very generic. This is the only timer architecturally defined IIRC, so perhaps just "armv7m_systick". > drivers/clocksource/Kconfig | 7 ++ > drivers/clocksource/Makefile | 1 + > drivers/clocksource/arm_system_timer.c | 74 ++++++++++++++++++++++ Same here. > 4 files changed, 97 insertions(+) > create mode 100644 Documentation/devicetree/bindings/arm/system_timer.txt > create mode 100644 drivers/clocksource/arm_system_timer.c > > diff --git a/Documentation/devicetree/bindings/arm/system_timer.txt b/Documentation/devicetree/bindings/arm/system_timer.txt > new file mode 100644 > index 0000000..35268b7 > --- /dev/null > +++ b/Documentation/devicetree/bindings/arm/system_timer.txt > @@ -0,0 +1,15 @@ > +* ARM System Timer > + > +ARMv7-M includes a system timer, known as SysTick. Current driver only > +implements the clocksource feature. > + > +Required properties: > +- compatible : Should be "arm,armv7m-systick" > +- reg : The address range of the timer > +- clocks : The input clock of the timer You may want to consider supporting "clock-frequency" here too. In more simple chips you may just have fixed clocks and may want to run a kernel with COMMON_CLK disabled for size savings. > + > +systick: system-timer { This should be "systick: timer@e000e010". Same for your dts file. > + compatible = "arm,armv7m-systick"; > + reg = <0xe000e010 0x10>; > + clocks = <&clk_systick>; > +}; > diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig > index fc01ec2..f9fe4ac 100644 > --- a/drivers/clocksource/Kconfig > +++ b/drivers/clocksource/Kconfig > @@ -124,6 +124,13 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK > help > Use ARM global timer clock source as sched_clock > > +config ARM_SYSTEM_TIMER > + bool > + select CLKSRC_OF if OF > + select CLKSRC_MMIO > + help > + This options enables support for the ARM system timer unit > + > config ATMEL_PIT > select CLKSRC_OF if OF > def_bool SOC_AT91SAM9 || SOC_SAMA5 > diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile > index 94d90b2..194400b 100644 > --- a/drivers/clocksource/Makefile > +++ b/drivers/clocksource/Makefile > @@ -42,6 +42,7 @@ obj-$(CONFIG_MTK_TIMER) += mtk_timer.o > > obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o > obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o > +obj-$(CONFIG_ARM_SYSTEM_TIMER) += arm_system_timer.o > obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o > obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o > obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o > diff --git a/drivers/clocksource/arm_system_timer.c b/drivers/clocksource/arm_system_timer.c > new file mode 100644 > index 0000000..69e6ef9 > --- /dev/null > +++ b/drivers/clocksource/arm_system_timer.c > @@ -0,0 +1,74 @@ > +/* > + * Copyright (C) Maxime Coquelin 2015 > + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> > + * License terms: GNU General Public License (GPL), version 2 > + */ > + > +#include <linux/kernel.h> > +#include <linux/clocksource.h> > +#include <linux/clockchips.h> > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/clk.h> > +#include <linux/bitops.h> > + > +#define SYST_CSR 0x00 > +#define SYST_RVR 0x04 > +#define SYST_CVR 0x08 > +#define SYST_CALIB 0x0c > + > +#define SYST_CSR_ENABLE BIT(0) > + > +#define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF > + > +static void __init system_timer_of_register(struct device_node *np) > +{ > + struct clk *clk; > + void __iomem *base; > + unsigned long rate; > + int ret; > + > + base = of_iomap(np, 0); > + if (!base) { > + pr_warn("system-timer: invalid base address\n"); > + return; > + } > + > + clk = of_clk_get(np, 0); > + if (IS_ERR(clk)) { > + pr_warn("system-timer: clk not found\n"); > + ret = PTR_ERR(clk); > + goto out_unmap; > + } > + > + ret = clk_prepare_enable(clk); > + if (ret) > + goto out_clk_put; > + > + rate = clk_get_rate(clk); > + > + writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR); > + writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR); > + > + ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate, > + 200, 24, clocksource_mmio_readl_down); > + if (ret) { > + pr_err("failed to init clocksource (%d)\n", ret); > + goto out_clk_disable; > + } > + > + pr_info("ARM System timer initialized as clocksource\n"); > + > + return; > + > +out_clk_disable: > + clk_disable_unprepare(clk); > +out_clk_put: > + clk_put(clk); > +out_unmap: > + iounmap(base); > + WARN(ret, "ARM System timer register failed (%d)\n", ret); > +} > + > +CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick", > + system_timer_of_register); > -- > 1.9.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Am 12.02.2015 um 18:45 schrieb Maxime Coquelin: > This patch adds clocksource support for ARMv7-M's System timer, > also known as SysTick. > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com> > --- > .../devicetree/bindings/arm/system_timer.txt | 15 +++++ > drivers/clocksource/Kconfig | 7 ++ > drivers/clocksource/Makefile | 1 + > drivers/clocksource/arm_system_timer.c | 74 ++++++++++++++++++++++ > 4 files changed, 97 insertions(+) > create mode 100644 Documentation/devicetree/bindings/arm/system_timer.txt > create mode 100644 drivers/clocksource/arm_system_timer.c > > diff --git a/Documentation/devicetree/bindings/arm/system_timer.txt b/Documentation/devicetree/bindings/arm/system_timer.txt > new file mode 100644 > index 0000000..35268b7 > --- /dev/null > +++ b/Documentation/devicetree/bindings/arm/system_timer.txt > @@ -0,0 +1,15 @@ > +* ARM System Timer > + > +ARMv7-M includes a system timer, known as SysTick. Current driver only > +implements the clocksource feature. > + > +Required properties: > +- compatible : Should be "arm,armv7m-systick" > +- reg : The address range of the timer > +- clocks : The input clock of the timer > + > +systick: system-timer { > + compatible = "arm,armv7m-systick"; > + reg = <0xe000e010 0x10>; > + clocks = <&clk_systick>; > +}; Binding documentation is supposed to go into its own patch: https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/Documentation/devicetree/bindings/submitting-patches.txt > diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig > index fc01ec2..f9fe4ac 100644 > --- a/drivers/clocksource/Kconfig > +++ b/drivers/clocksource/Kconfig > @@ -124,6 +124,13 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK > help > Use ARM global timer clock source as sched_clock > > +config ARM_SYSTEM_TIMER > + bool > + select CLKSRC_OF if OF > + select CLKSRC_MMIO > + help > + This options enables support for the ARM system timer unit > + > config ATMEL_PIT > select CLKSRC_OF if OF > def_bool SOC_AT91SAM9 || SOC_SAMA5 > diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile > index 94d90b2..194400b 100644 > --- a/drivers/clocksource/Makefile > +++ b/drivers/clocksource/Makefile > @@ -42,6 +42,7 @@ obj-$(CONFIG_MTK_TIMER) += mtk_timer.o > > obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o > obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o > +obj-$(CONFIG_ARM_SYSTEM_TIMER) += arm_system_timer.o > obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o > obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o > obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o > diff --git a/drivers/clocksource/arm_system_timer.c b/drivers/clocksource/arm_system_timer.c > new file mode 100644 > index 0000000..69e6ef9 > --- /dev/null > +++ b/drivers/clocksource/arm_system_timer.c > @@ -0,0 +1,74 @@ > +/* > + * Copyright (C) Maxime Coquelin 2015 > + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> > + * License terms: GNU General Public License (GPL), version 2 > + */ > + > +#include <linux/kernel.h> > +#include <linux/clocksource.h> > +#include <linux/clockchips.h> > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/clk.h> > +#include <linux/bitops.h> > + > +#define SYST_CSR 0x00 > +#define SYST_RVR 0x04 > +#define SYST_CVR 0x08 > +#define SYST_CALIB 0x0c > + > +#define SYST_CSR_ENABLE BIT(0) > + > +#define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF > + > +static void __init system_timer_of_register(struct device_node *np) > +{ > + struct clk *clk; > + void __iomem *base; > + unsigned long rate; > + int ret; > + > + base = of_iomap(np, 0); > + if (!base) { > + pr_warn("system-timer: invalid base address\n"); > + return; > + } > + > + clk = of_clk_get(np, 0); > + if (IS_ERR(clk)) { > + pr_warn("system-timer: clk not found\n"); > + ret = PTR_ERR(clk); > + goto out_unmap; > + } > + > + ret = clk_prepare_enable(clk); > + if (ret) > + goto out_clk_put; > + > + rate = clk_get_rate(clk); > + > + writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR); > + writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR); > + > + ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate, > + 200, 24, clocksource_mmio_readl_down); > + if (ret) { > + pr_err("failed to init clocksource (%d)\n", ret); > + goto out_clk_disable; > + } > + > + pr_info("ARM System timer initialized as clocksource\n"); > + > + return; > + > +out_clk_disable: > + clk_disable_unprepare(clk); > +out_clk_put: > + clk_put(clk); > +out_unmap: > + iounmap(base); > + WARN(ret, "ARM System timer register failed (%d)\n", ret); > +} > + > +CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick", > + system_timer_of_register); I've used a SysTick based implementation on my stm32 branch myself, but looking at efm32 I got the impression that it would be better to use one of the 32-bit TIM2/TIM5 as clocksource and the other as clockevents? Still this implementation will be handy to have, also for other targets. Regards, Andreas
2015-02-15 23:31 GMT+01:00 Rob Herring <robherring2@gmail.com>: > On Thu, Feb 12, 2015 at 11:45 AM, Maxime Coquelin > <mcoquelin.stm32@gmail.com> wrote: >> This patch adds clocksource support for ARMv7-M's System timer, >> also known as SysTick. >> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com> >> --- >> .../devicetree/bindings/arm/system_timer.txt | 15 +++++ > > Please include v7M in the name. System timer sounds very generic. This > is the only timer architecturally defined IIRC, so perhaps just > "armv7m_systick". Ok, let's go for "armv7m_systick". > >> drivers/clocksource/Kconfig | 7 ++ >> drivers/clocksource/Makefile | 1 + >> drivers/clocksource/arm_system_timer.c | 74 ++++++++++++++++++++++ > > Same here. Agree, will be in the v2. > > >> 4 files changed, 97 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/arm/system_timer.txt >> create mode 100644 drivers/clocksource/arm_system_timer.c >> >> diff --git a/Documentation/devicetree/bindings/arm/system_timer.txt b/Documentation/devicetree/bindings/arm/system_timer.txt >> new file mode 100644 >> index 0000000..35268b7 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/arm/system_timer.txt >> @@ -0,0 +1,15 @@ >> +* ARM System Timer >> + >> +ARMv7-M includes a system timer, known as SysTick. Current driver only >> +implements the clocksource feature. >> + >> +Required properties: >> +- compatible : Should be "arm,armv7m-systick" >> +- reg : The address range of the timer >> +- clocks : The input clock of the timer > > You may want to consider supporting "clock-frequency" here too. In > more simple chips you may just have fixed clocks and may want to run a > kernel with COMMON_CLK disabled for size savings. Ok, I will add this option in the v2. > >> + >> +systick: system-timer { > > This should be "systick: timer@e000e010". > > Same for your dts file. Right, it will be fixed in the v2. Thanks for the review, Maxime -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
2015-02-16 0:43 GMT+01:00 Andreas Färber <afaerber@suse.de>: > Am 12.02.2015 um 18:45 schrieb Maxime Coquelin: >> This patch adds clocksource support for ARMv7-M's System timer, >> also known as SysTick. >> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com> >> --- >> .../devicetree/bindings/arm/system_timer.txt | 15 +++++ >> drivers/clocksource/Kconfig | 7 ++ >> drivers/clocksource/Makefile | 1 + >> drivers/clocksource/arm_system_timer.c | 74 ++++++++++++++++++++++ >> 4 files changed, 97 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/arm/system_timer.txt >> create mode 100644 drivers/clocksource/arm_system_timer.c >> >> diff --git a/Documentation/devicetree/bindings/arm/system_timer.txt b/Documentation/devicetree/bindings/arm/system_timer.txt >> new file mode 100644 >> index 0000000..35268b7 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/arm/system_timer.txt >> @@ -0,0 +1,15 @@ >> +* ARM System Timer >> + >> +ARMv7-M includes a system timer, known as SysTick. Current driver only >> +implements the clocksource feature. >> + >> +Required properties: >> +- compatible : Should be "arm,armv7m-systick" >> +- reg : The address range of the timer >> +- clocks : The input clock of the timer >> + >> +systick: system-timer { >> + compatible = "arm,armv7m-systick"; >> + reg = <0xe000e010 0x10>; >> + clocks = <&clk_systick>; >> +}; > > Binding documentation is supposed to go into its own patch: > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/tree/Documentation/devicetree/bindings/submitting-patches.txt Ok, will change this in the v2. > ... > > I've used a SysTick based implementation on my stm32 branch myself, but > looking at efm32 I got the impression that it would be better to use one > of the 32-bit TIM2/TIM5 as clocksource and the other as clockevents? > > Still this implementation will be handy to have, also for other targets. My view is that we should use as much generic parts of the Cortex-M as possible. Moreover, doing, that, we can keep one more IP instance under reset with associated clock gated, and so maybe reduce the power consumption a little (I haven't done any measurements) Do you see a case where it could be better to use the STM32 timers? Thanks, Maxime > > Regards, > Andreas > > -- > SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany > GF: Felix Imendörffer, Jane Smithard, Jennifer Guild, Dilip Upmanyu, > Graham Norton; HRB 21284 (AG Nürnberg) -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/devicetree/bindings/arm/system_timer.txt b/Documentation/devicetree/bindings/arm/system_timer.txt new file mode 100644 index 0000000..35268b7 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/system_timer.txt @@ -0,0 +1,15 @@ +* ARM System Timer + +ARMv7-M includes a system timer, known as SysTick. Current driver only +implements the clocksource feature. + +Required properties: +- compatible : Should be "arm,armv7m-systick" +- reg : The address range of the timer +- clocks : The input clock of the timer + +systick: system-timer { + compatible = "arm,armv7m-systick"; + reg = <0xe000e010 0x10>; + clocks = <&clk_systick>; +}; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index fc01ec2..f9fe4ac 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -124,6 +124,13 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK help Use ARM global timer clock source as sched_clock +config ARM_SYSTEM_TIMER + bool + select CLKSRC_OF if OF + select CLKSRC_MMIO + help + This options enables support for the ARM system timer unit + config ATMEL_PIT select CLKSRC_OF if OF def_bool SOC_AT91SAM9 || SOC_SAMA5 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 94d90b2..194400b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_MTK_TIMER) += mtk_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o +obj-$(CONFIG_ARM_SYSTEM_TIMER) += arm_system_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o diff --git a/drivers/clocksource/arm_system_timer.c b/drivers/clocksource/arm_system_timer.c new file mode 100644 index 0000000..69e6ef9 --- /dev/null +++ b/drivers/clocksource/arm_system_timer.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> + * License terms: GNU General Public License (GPL), version 2 + */ + +#include <linux/kernel.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk.h> +#include <linux/bitops.h> + +#define SYST_CSR 0x00 +#define SYST_RVR 0x04 +#define SYST_CVR 0x08 +#define SYST_CALIB 0x0c + +#define SYST_CSR_ENABLE BIT(0) + +#define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF + +static void __init system_timer_of_register(struct device_node *np) +{ + struct clk *clk; + void __iomem *base; + unsigned long rate; + int ret; + + base = of_iomap(np, 0); + if (!base) { + pr_warn("system-timer: invalid base address\n"); + return; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_warn("system-timer: clk not found\n"); + ret = PTR_ERR(clk); + goto out_unmap; + } + + ret = clk_prepare_enable(clk); + if (ret) + goto out_clk_put; + + rate = clk_get_rate(clk); + + writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR); + writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR); + + ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate, + 200, 24, clocksource_mmio_readl_down); + if (ret) { + pr_err("failed to init clocksource (%d)\n", ret); + goto out_clk_disable; + } + + pr_info("ARM System timer initialized as clocksource\n"); + + return; + +out_clk_disable: + clk_disable_unprepare(clk); +out_clk_put: + clk_put(clk); +out_unmap: + iounmap(base); + WARN(ret, "ARM System timer register failed (%d)\n", ret); +} + +CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick", + system_timer_of_register);
This patch adds clocksource support for ARMv7-M's System timer, also known as SysTick. Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com> --- .../devicetree/bindings/arm/system_timer.txt | 15 +++++ drivers/clocksource/Kconfig | 7 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_system_timer.c | 74 ++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/system_timer.txt create mode 100644 drivers/clocksource/arm_system_timer.c