clocksource: Conexant CX92755 timers support
Subsystems (3)
Baruch Siach
maintainerv5 cover clocksource: Conexant CX92755 timers support
This short series adds support for the Conexant CX92755 SoC timers. This SoC is part of the Conexant Digicolor series of SoCs.
v5:
* Switch back to use of_iomap (not of_io_request_and_map), as the watchdog driver also needs access to the same registers; add a comment clarifying this
Address more review comments by Daniel Lezcano:
* Properly encapsulate the static objects for the clock_event code
* Use dc_timer_{disable,enable,set_count} accessors to make the code clearer
v4:
http://thread.gmane.org/gmane.linux.kernel/1874017
Address review comments by Daniel Lezcano:
* Use macros for register configuration values
* Encapsulate static objects in a struct
* Use of_io_request_and_map to exclusively map registers
* Use UINT_MAX instead of ~0
* Use request_irq instead of setup_irq, obviating the need for a separate irqaction struct
v3:
http://article.gmane.org/gmane.linux.kernel/1870628
http://article.gmane.org/gmane.linux.kernel/1870627
* Split into a separate clocksource series
v2:
http://article.gmane.org/gmane.linux.kernel/1861850
http://article.gmane.org/gmane.linux.kernel/1861853
* Change the timer dt binding, so that the 'reg' property points to the first "Agent Communication" register. This should improve the chance of reusing this binding for other SoCs in this series.
* Add the CONTROL() and COUNT() macros to the timer driver to make the code clearer.
* Move arch/arm Kconfig changes from the clocksource driver patch to the base arch support patch to reduce dependency between them
v1:
http://article.gmane.org/gmane.linux.kernel/1855028
http://article.gmane.org/gmane.linux.kernel/1855025
Baruch Siach (2):
clocksource: devicetree: document Conexant Digicolor timer binding
clocksource: driver for Conexant Digicolor SoC timer
.../devicetree/bindings/timer/digicolor-timer.txt | 18 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-digicolor.c | 199 +++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/digicolor-timer.txt create mode 100644 drivers/clocksource/timer-digicolor.c
Signature · 1 line
2.1.4
Baruch Siach
maintainerPATCH v5 1/2 clocksource: devicetree: document Conexant Digicolor timer binding
The Conexant CX92755 SoC provides 8 32-bit timers as part of its so called "Agent Communication" block. Timers can be configures either as free running or one shot. Each timer has a dedicated interrupt source in the CX92755 interrupts controller. The first timer (Timer A) can also be configured as watchdog.
This commit adds devicetree binding definition of this hardware module. The binding defined here should be reusable for other SoCs in the Digicolor series.
--- .../devicetree/bindings/timer/digicolor-timer.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/digicolor-timer.txt
Documentation/devicetree/bindings/timer/digicolor-timer.txt new file +18 -0
@@ -0,0 +1,18 @@ +Conexant Digicolor SoCs Timer Controller + +Required properties: + +- compatible : should be "cnxt,cx92755-timer" +- reg : Specifies base physical address and size of the "Agent Communication" + timer registers +- interrupts : Contains 8 interrupts, one for each timer +- clocks: phandle to the main clock + +Example: + + timer at f0000fc0 { + compatible = "cnxt,cx92755-timer"; + reg = <0xf0000fc0 0x40>; + interrupts = <19>, <31>, <34>, <35>, <52>, <53>, <54>, <55>; + clocks = <&main_clk>; + };
Signature · 1 line
2.1.4
Baruch Siach
maintainerPATCH v5 2/2 clocksource: driver for Conexant Digicolor SoC timer
In reply to Baruch SiachAdd clocksource driver to the Conexant CX92755 SoC, part of the Digicolor SoCs series. Hardware provides 8 timers, A to H. Timer A is dedicated to a future watchdog driver so we don't use it here. Use timer B for sched_clock, and timer C for clock_event.
--- drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-digicolor.c | 199 ++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 drivers/clocksource/timer-digicolor.c
drivers/clocksource/Makefile +1 -0
@@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_ARCH_DIGICOLOR) += timer-digicolor.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o
drivers/clocksource/timer-digicolor.c new file +199 -0
199 lines not on this page · raw message
Signature · 1 line
2.1.4
Re: [PATCH v5 2/2] clocksource: driver for Conexant Digicolor SoC timer
Quoted 17 lines · Baruch Siach
Add clocksource driver to the Conexant CX92755 SoC, part of the Digicolor SoCs series. Hardware provides 8 timers, A to H. Timer A is dedicated to a future watchdog driver so we don't use it here. Use timer B for
sched_clock, and timer C forclock_event.Signed-off-by Baruch Siach <[email protected]>--- drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-digicolor.c | 199 ++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+)create mode 100644
drivers/clocksource/timer-digicolor.cdrivers/clocksource/Makefile +0
-0
drivers/clocksource/Makefile obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o · line 13
Quoted 4 lines
drivers/clocksource/Makefile +1
-0@@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_ARCH_DIGICOLOR) += timer-digicolor.o
Ah, one minor change I forgot to mention in the last review (sorry about that).
Don't depend on the ARCH, add and select a TIMER_DIGICOLOR (or whatever the name you prefer) in the mach-digicolor/Kconfig and use it here.
Other than that, it looks good for me.
Thanks
-- Daniel
Quoted 209 lines
drivers/clocksource/Makefile +0
-0obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.odrivers/clocksource/timer-digicolor.c new file +199
-0@@ -0,0 +1,199 @@ +/* +* Conexant Digicolor timer driver +* +* Author: Baruch Siach <[email protected]> +* +* Copyright (C) 2014 Paradox Innovation Ltd. +* +* Based on: +* Allwinner SoCs hstimer driver +* +* Copyright (C) 2013 Maxime Ripard +* +* Maxime Ripard <[email protected]> +* +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any +* warranty of any kind, whether express or implied. +*/ + +/* +* Conexant Digicolor SoCs have 8 configurable timers, named from "Timer A" to +* "Timer H". Timer A is the only one with watchdog support, so it is dedicated +* to the watchdog driver. This driver uses Timer B for sched_clock(), and +* Timer C for clockevents. +*/ + +#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt + +#include <linux/clk.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqreturn.h> +#include <linux/sched_clock.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> + +enum { +TIMER_A , +TIMER_B , +TIMER_C , +TIMER_D , +TIMER_E , +TIMER_F , +TIMER_G , +TIMER_H , +}; + +#define CONTROL (t) ((t)*8) +#define COUNT (t) ((t)*8 + 4) + +#define CONTROL_DISABLE 0 +#define CONTROL_ENABLE BIT(0) +#define CONTROL_MODE (m) ((m) << 4) +#define CONTROL_MODE_ONESHOT CONTROL_MODE(1) +#define CONTROL_MODE_PERIODIC CONTROL_MODE(2) + +struct digicolor_timer { +struct clock_event_device ce; +void __iomem *base; +u32 ticks_per_jiffy; +int timer_id;/* one of TIMER_* */ +}; + +struct digicolor_timer *dc_timer (struct clock_event_device *ce) +{ + return container_of(ce, struct digicolor_timer, ce); +} + +static inline void dc_timer_disable (struct clock_event_device *ce) +{ +struct digicolor_timer *dt =dc_timer (ce); +writeb (CONTROL_DISABLE , dt->base +CONTROL (dt->timer_id)); +} + +static inline void dc_timer_enable (struct clock_event_device *ce,u32 mode) +{ +struct digicolor_timer *dt =dc_timer (ce); +writeb (CONTROL_ENABLE | mode, dt->base +CONTROL (dt->timer_id)); +} + +static inline void dc_timer_set_count (struct clock_event_device *ce, +unsigned long count) +{ +struct digicolor_timer *dt =dc_timer (ce); +writel (count, dt->base +COUNT (dt->timer_id)); +} + +static void digicolor_clkevt_mode (enum clock_event_mode mode, +struct clock_event_device *ce) +{ +struct digicolor_timer *dt =dc_timer (ce); + +switch (mode) { +case CLOCK_EVT_MODE_PERIODIC : +dc_timer_disable (ce); +dc_timer_set_count (ce, dt->ticks_per_jiffy); +dc_timer_enable (ce,CONTROL_MODE_PERIODIC ); +break ; +case CLOCK_EVT_MODE_ONESHOT : +dc_timer_disable (ce); +dc_timer_enable (ce,CONTROL_MODE_ONESHOT ); +break ; +case CLOCK_EVT_MODE_UNUSED : +case CLOCK_EVT_MODE_SHUTDOWN : +default : +dc_timer_disable (ce); +break ; + } +} + +static int digicolor_clkevt_next_event (unsigned long evt, +struct clock_event_device *ce) +{ +dc_timer_disable (ce); +dc_timer_set_count (ce, evt); +dc_timer_enable (ce,CONTROL_MODE_ONESHOT ); + +return 0 ; +} + +static struct digicolor_timer dc_timer_dev = { + .ce = { + .name ="digicolor_tick" , + .rating =340 , + .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT , + .set_mode = digicolor_clkevt_mode, + .set_next_event = digicolor_clkevt_next_event, + }, + .timer_id =TIMER_C , +}; + +static irqreturn_t digicolor_timer_interrupt (int irq,void *dev_id) +{ +struct clock_event_device *evt = dev_id; + + evt->event_handler (evt); + +return IRQ_HANDLED ; +} + +static u64 digicolor_timer_sched_read (void ) +{ +return ~readl (dc_timer_dev.base +COUNT (TIMER_B )); +} + +static void __init digicolor_timer_init (struct device_node *node) +{ +unsigned long rate; +struct clk *clk; +int ret, irq; + +/* +* timer registers are shared with the watchdog timer; +* don't map exclusively +*/ + dc_timer_dev.base =of_iomap (node,0 ); +if (!dc_timer_dev.base) { +pr_err ("Can't map registers" ); +return ; + } + + irq =irq_of_parse_and_map (node, dc_timer_dev.timer_id); +if (irq <=0 ) { +pr_err ("Can't parse IRQ" ); +return ; + } + + clk =of_clk_get (node,0 ); +if (IS_ERR (clk)) { +pr_err ("Can't get timer clock" ); +return ; + } +clk_prepare_enable (clk); + rate =clk_get_rate (clk); + dc_timer_dev.ticks_per_jiffy =DIV_ROUND_UP (rate,HZ ); + +writeb (CONTROL_DISABLE , dc_timer_dev.base +CONTROL (TIMER_B )); +writel (UINT_MAX , dc_timer_dev.base +COUNT (TIMER_B )); +writeb (CONTROL_ENABLE , dc_timer_dev.base +CONTROL (TIMER_B )); + +sched_clock_register (digicolor_timer_sched_read,32 , rate); +clocksource_mmio_init (dc_timer_dev.base +COUNT (TIMER_B ), node->name, + rate,340 ,32 , clocksource_mmio_readl_down); + + ret =request_irq (irq, digicolor_timer_interrupt, +IRQF_TIMER |IRQF_IRQPOLL ,"digicolor_timerC" , + &dc_timer_dev.ce); +if (ret) +pr_warn ("request of timer irq %d failed (%d)\n" , irq, ret); + + dc_timer_dev.ce.cpumask = cpu_possible_mask; + dc_timer_dev.ce.irq = irq; + +clockevents_config_and_register (&dc_timer_dev.ce, rate,0 ,0xffffffff ); +} +CLOCKSOURCE_OF_DECLARE (conexant_digicolor,"cnxt,cx92755-timer" , + digicolor_timer_init);
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
Baruch Siach
maintainerRe: [PATCH v5 2/2] clocksource: driver for Conexant Digicolor SoC timer
Hi Daniel,
Quoted 13 lines · Daniel Lezcano
drivers/clocksource/Makefile obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o · line 13
Quoted 9 lines
drivers/clocksource/Makefile +1
-0@@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_ARCH_DIGICOLOR) += timer-digicolor.oAh, one minor change I forgot to mention in the last review (sorry about that).
Quoted 2 lines
Don't depend on the ARCH, add and select a
TIMER_DIGICOLOR(or whatever the name you prefer) in the mach-digicolor/Kconfig and use it here.
OK. I'll make the change. I'm just curious: what is the advantage of having a separate config symbol for the timer?
baruch
Signature · 3 lines
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -Re: [PATCH v5 2/2] clocksource: driver for Conexant Digicolor SoC timer
Quoted 16 lines · Baruch Siach
Hi Daniel,
Quoted 13 lines · Daniel Lezcano
drivers/clocksource/Makefile obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o · line 13
Quoted 9 lines
drivers/clocksource/Makefile +1
-0@@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_ARCH_DIGICOLOR) += timer-digicolor.oAh, one minor change I forgot to mention in the last review (sorry about that).
Quoted 5 lines
Quoted 2 lines
Don't depend on the ARCH, add and select a
TIMER_DIGICOLOR(or whatever the name you prefer) in the mach-digicolor/Kconfig and use it here.OK. I'll make the change. I'm just curious: what is the advantage of having a separate config symbol for the timer?
It is because some timers could be used in different platforms, so the policy of the house is to let the platform Kconfig to select the timer.
Also, that let one platform to not select the timer if it is not needed. For example one SoC uses the architected timers and there is not power management on the board, hence no cpu is powered down and no backup timer is needed.
Even if the timer is expected to be used on only one platform, we try to keep the rule consistent across the different drivers (even if I admit some cleanups should be done in the Kconfig file).
Signature · 5 lines
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog