timers: Add support for RZ/N1 SoCs timers
Subsystems (4)
Herve Codina (Schneider Electric)
maintainerv2 cover timers: Add support for RZ/N1 SoCs timers
The Renesas RZ/N1 SoCs family has two timers block controller available.
Each controller is charge of 8 timers (six 16-bit timers + two 32-bit timers).
Each timer has its own interrupt, its own prescaler that can be used to device the clock by 25 (timers block are fed with a 25 MHz clock) and all timers can work in either one-shot or periodic mode.
This series adds support for those timers blocks.
Best regards,
Hervé
Changes v1 -> v2
v1: https://lore.kernel.org/all/[email protected]/
Rebase on top of v7.1-rc1.
Patch 1:
- Drop minItems related to interrupts property
- Add 'Reviewed-by: Krzysztof Kozlowski'
Patches 2, 3 and 4:
No changes
Herve Codina (Schneider Electric) (4):
dt-bindings: timer: Add the Renesas RZ/N1 timer clocksource/drivers: Add support for the Renesas RZ/N1 timers
ARM: dts: r9a06g032: Add support for timers
MAINTAINERS: Add the Renesas RZ/N1 timers driver entry
.../bindings/timer/renesas,rzn1-timer.yaml | 74 +++ MAINTAINERS | 7 + arch/arm/boot/dts/renesas/r9a06g032.dtsi | 34 ++ drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-rzn1.c | 442 ++++++++++++++++++ 6 files changed, 568 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml create mode 100644 drivers/clocksource/timer-rzn1.c
Signature · 1 line
2.53.0
Herve Codina (Schneider Electric)
maintainerPATCH v2 1/4 dt-bindings: timer: Add the Renesas RZ/N1 timer
The Renesas RZ/N1 timer block controller is the controller in charge of timers available in the Renesas RZ/N1 SoCs family.
This controller handles 8 timers:
- 6 16-bit timers
- 2 32-bit timers
--- .../bindings/timer/renesas,rzn1-timer.yaml | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml
Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml new file +74 -0
@@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/renesas,rzn1-timer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/N1 timers + +maintainers: + - Herve Codina <[email protected]> + +description: | + The Renesas RZ/N1 SoCs timers block controller is composed of 8 independent + timers. + - 6 are 16-bit timers + - 2 are 32-bit timers + + Each timer has its own interrupt line and can work in either one-shot or + periodic mode. + +properties: + compatible: + items: + - const: renesas,r9a06g032-timer # RZ/N1D + - const: renesas,rzn1-timer + + reg: + maxItems: 1 + + clocks: + items: + - description: APB internal bus clock + + clock-names: + items: + - const: pclk + + power-domains: + maxItems: 1 + + interrupts: + maxItems: 8 + +required: + - compatible + - reg + - clocks + - clock-names + - power-domains + - interrupts + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/r9a06g032-sysctrl.h> + + timer@51001000 { + compatible = "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg = <0x51001000 0x400>; + clocks = <&sysctrl R9A06G032_HCLK_TIMER0>; + clock-names = "pclk"; + power-domains = <&sysctrl>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; + }; +...
Signature · 1 line
2.53.0
Re: [PATCH v2 1/4] dt-bindings: timer: Add the Renesas RZ/N1 timer
Quoted 9 lines · Herve Codina (Schneider Electric)
The Renesas RZ/N1 timer block controller is the controller in charge of timers available in the Renesas RZ/N1 SoCs family.
This controller handles 8 timers:
- 6 16-bit timers
- 2 32-bit timersSigned-off-by Herve Codina (Schneider Electric) <[email protected]>Reviewed-by Krzysztof Kozlowski <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Herve Codina (Schneider Electric)
maintainerPATCH v2 2/4 clocksource/drivers: Add support for the Renesas RZ/N1 timers
In reply to Herve Codina (Schneider Electric)The Renesas RZ/N1 timer block controller is the controller in charge of timers available in the Renesas RZ/N1 SoCs family.
This controller handles 8 timers:
- 6 16-bit timers
- 2 32-bit timers
Each timer has its own interrupt, its own prescaler that can be used to device the clock by 25 and all of them can work in either one-shot or periodic mode.
--- drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-rzn1.c | 442 +++++++++++++++++++++++++++++++ 3 files changed, 453 insertions(+) create mode 100644 drivers/clocksource/timer-rzn1.c
drivers/clocksource/Kconfig +10 -0
@@ -152,6 +152,16 @@ config REALTEK_OTTO_TIMER RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series such as RTL9301, RTL9302 or RTL9303. +config RZN1_TIMER + bool "Renesas RZ/N1 Timer" + depends on HAS_IOMEM && COMMON_CLK && (ARCH_RZN1 || COMPILE_TEST) + help + Enables support for RZ/N1 SoC timers. + A timers block in RZ/N1 SoCs is composed of 8 timers + - 6 16-bit timers + - 2 32-bit timers + Two timers blocks are available in RZ/N1 SoCs. + config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on HAS_IOMEM
drivers/clocksource/Makefile +1 -0
@@ -96,3 +96,4 @@ obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o obj-$(CONFIG_NXP_STM_TIMER) += timer-nxp-stm.o obj-$(CONFIG_RTK_SYSTIMER) += timer-realtek.o +obj-$(CONFIG_RZN1_TIMER) += timer-rzn1.o
drivers/clocksource/timer-rzn1.c new file +442 -0
442 lines not on this page · raw message
Signature · 1 line
2.53.0
Re: [PATCH v2 2/4] clocksource/drivers: Add support for the Renesas RZ/N1 timers
Hi Hervé,
Thanks for your patch!
Just a few generic comments, as I am not a timer expert, and have no access to the hardware.
Quoted 9 lines · Herve Codina (Schneider Electric)
The Renesas RZ/N1 timer block controller is the controller in charge of timers available in the Renesas RZ/N1 SoCs family.
This controller handles 8 timers:
- 6 16-bit timers
- 2 32-bit timersEach timer has its own interrupt, its own prescaler that can be used to device the clock by 25 and all of them can work in either one-shot or
divide
Quoted 15 lines
periodic mode.
Signed-off-by Herve Codina (Schneider Electric) <[email protected]>--- drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-rzn1.c | 442 +++++++++++++++++++++++++++++++ 3 files changed, 453 insertions(+) create mode 100644 drivers/clocksource/timer-rzn1.cdrivers/clocksource/Kconfig +0
-0
drivers/clocksource/Kconfig config REALTEK_OTTO_TIMER · line 156
Quoted 5 lines
drivers/clocksource/Kconfig +2
-0@@ -152,6 +152,16 @@ config REALTEK_OTTO_TIMER RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series such as RTL9301, RTL9302 or RTL9303. +config RZN1_TIMER + bool "Renesas RZ/N1 Timer"
So this cannot be a module.
drivers/clocksource/Kconfig config REALTEK_OTTO_TIMER · line 157
Quoted 1 line
drivers/clocksource/Kconfig +1
-0+ depends on HAS_IOMEM && COMMON_CLK && (ARCH_RZN1 || COMPILE_TEST)
I would split this in two lines, to make it easier to read (and maintain, if the same timer ends up in a different SoC series).
Quoted 13 lines
drivers/clocksource/Kconfig +7
-0+ help + Enables support for RZ/N1 SoC timers. + A timers block in RZ/N1 SoCs is composed of 8 timers + - 6 16-bit timers + - 2 32-bit timers + Two timers blocks are available in RZ/N1 SoCs. + config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on HAS_IOMEM
drivers/clocksource/timer-rzn1.c line 40
Quoted 10 lines
drivers/clocksource/timer-rzn1.c new file +9
-0+/* +* 8 timers are available. Among those 8 timers, the first 6 timers are 16-bit +* timers and the last two ones are 32-bit timers. +*/ +#define RZN1_TIMER_BASE_INDEX_16BIT_TIMERS 0 +#define RZN1_TIMER_NB_16BIT_TIMERS 6 + +#define RZN1_TIMER_BASE_INDEX_32BIT_TIMER 6 +#define RZN1_TIMER_NB_32BIT_TIMERS 2
Align the number columns?
Quoted 37 lines
drivers/clocksource/timer-rzn1.c new file +37
-0+static int rzn1_timer_probe_first (struct platform_device *pdev,struct rzn1_timer *tab_timers, +void __iomem *base,unsigned long clock_rate) +{ +struct device *dev = &pdev->dev; +struct rzn1_timer *timer; +unsigned int i; +char *name; +int irq; +int ret; + +/* +* Probe the first instance. In that case, timers are assigned as +* follow: +* - First 16-bit timer: clocksource and sched_clock +* - Other 16-bit timers: clock events for all possible CPUs +* - 32-bit timers: clock events per CPU +* +* First step, perform all operation that could fail without calling +* clockevents_config_and_register(), sched_clock_register() nor +* cpuhp_setup_state(). Those operation don't have unregister nor +* teardown counterparts and so, once called, we cannot remove the +* related resource. +*/ + +/* +* First step for 16-bit timers except the first one and all 32-bit +* timers. +*/ +for (i =RZN1_TIMER_BASE_INDEX_16BIT_TIMERS +1 ; i <RZN1_TIMER_NB_TIMERS ; i++) { + timer = &tab_timers[i]; + +rzn1_timer_init (timer, i, base, clock_rate); + + irq =platform_get_irq (pdev, i); +if (irq <0 ) +return irq; +
drivers/clocksource/timer-rzn1.c line 293
Quoted 10 lines
drivers/clocksource/timer-rzn1.c new file +10
-0+ name =devm_kasprintf (dev,GFP_KERNEL ,"%s-%u" ,dev_name (dev), i); +if (!name) +return -ENOMEM ; + +rzn1_timer_clkevt_init_ced (timer, name, irq); + + ret =devm_request_irq (dev, timer->ced.irq, rzn1_timer_interrupt, +IRQF_TIMER , timer->ced.name, timer); +if (ret <0 ) +return dev_err_probe (dev, irq,"timer%d: Failed to request IRQ\n" , i);
%u
Quoted 56 lines
drivers/clocksource/timer-rzn1.c new file +56
-0+ +rzn1_timer_int_enable (timer); + } + +/* +* Second step, almost all operations that can fail have been called. +* Timers are ready to work. Start with the last operation that can fail, +* installing and invoking hotplug callbacks +*/ + rzn1_tab_timers = tab_timers; + ret =cpuhp_setup_state (CPUHP_AP_ONLINE_DYN , +"clockevents/rzn1/global_timer:starting" , + rzn1_local_timer_starting_cpu,NULL ); +if (ret <0 ) +return dev_err_probe (dev, ret,"Setup CPU hotplug state failed\n" ); + +/* +* At this point, no more operations can fail. Perform remaining +* operations. Starting by handling the first 16-bit timer +*/ + timer = &tab_timers[RZN1_TIMER_BASE_INDEX_16BIT_TIMERS ]; + +rzn1_timer_init (timer,RZN1_TIMER_BASE_INDEX_16BIT_TIMERS , base, clock_rate); +rzn1_timer_config (timer,GENMASK (timer->width -1 ,0 ), true); + + rzn1_sched_clock = timer; + +sched_clock_register (rzn1_sched_read, rzn1_sched_clock->width, rzn1_sched_clock->rate); + + rzn1_clocksource.mask =CLOCKSOURCE_MASK (rzn1_sched_clock->width); +clocksource_register_hz (&rzn1_clocksource, rzn1_sched_clock->rate); + +/* +* Register clockevents only for 16-bit timers. 32-bit timers clockevents +* are registered by CPU hotplug startup function set previously by the +* cpuhp_setup_state() call. +*/ +for (i =RZN1_TIMER_BASE_INDEX_16BIT_TIMERS +1 ; i <RZN1_TIMER_NB_16BIT_TIMERS ; i++) { + timer = &tab_timers[i]; +clockevents_config_and_register (&timer->ced, timer->rate, +1 ,GENMASK (timer->width -1 ,0 )); + } + +return 0 ; +} + +static int rzn1_timer_probe_other (struct platform_device *pdev,struct rzn1_timer *tab_timers, +void __iomem *base,unsigned long clock_rate) +{ +struct device *dev = &pdev->dev; +struct rzn1_timer *timer; +unsigned int i; +char *name; +int irq; +int ret; +
drivers/clocksource/timer-rzn1.c line 359
Quoted 10 lines
drivers/clocksource/timer-rzn1.c new file +10
-0+/* +* Probe other instance(s), i.e. not the first one. In that case, +* all timers are used as clock events and available for all possible +* CPUs +* +* First step, perform all operation that could fail without calling +* clockevents_config_and_register(). Unregister counterpart does not +* exist and so, once called, we cannot remove the related resource. +*/ +for (i =0 ; i <RZN1_TIMER_NB_TIMERS ; i++) {
Technically "0" is RZN1_TIMER_BASE_INDEX_16BIT_TIMERS.
Quoted 8 lines
drivers/clocksource/timer-rzn1.c new file +8
-0+ timer = &tab_timers[i]; + +rzn1_timer_init (timer, i, base, clock_rate); + + irq =platform_get_irq (pdev, i); +if (irq <0 ) +return irq; +
drivers/clocksource/timer-rzn1.c line 293
Quoted 10 lines
drivers/clocksource/timer-rzn1.c new file +10
-0+ name =devm_kasprintf (dev,GFP_KERNEL ,"%s-%u" ,dev_name (dev), i); +if (!name) +return -ENOMEM ; + +rzn1_timer_clkevt_init_ced (timer, name, irq); + + ret =devm_request_irq (dev, timer->ced.irq, rzn1_timer_interrupt, +IRQF_TIMER , timer->ced.name, timer); +if (ret <0 ) +return dev_err_probe (dev, irq,"timer%d: Failed to request IRQ\n" , i);
%u
drivers/clocksource/timer-rzn1.c line 296
Quoted 3 lines
drivers/clocksource/timer-rzn1.c new file +3
-0+ +rzn1_timer_int_enable (timer); + }
This loop is identical to the first loop in rzn1_timer_probe_first(), except for the lower bound. Perhaps it can be factored out?
drivers/clocksource/timer-rzn1.c line 387
Quoted 7 lines
drivers/clocksource/timer-rzn1.c new file +7
-0+ +/* +* Second step, all operation that can fail have been called. We can +* register our timers +*/ + +for (i =0 ; i <RZN1_TIMER_NB_TIMERS ; i++) {
Technically "0" is RZN1_TIMER_BASE_INDEX_16BIT_TIMERS.
drivers/clocksource/timer-rzn1.c line 338
Quoted 7 lines
drivers/clocksource/timer-rzn1.c new file +7
-0+ timer = &tab_timers[i]; +clockevents_config_and_register (&timer->ced, timer->rate, +1 ,GENMASK (timer->width -1 ,0 )); + } + +return 0 ; +}
This loop is identical to the second loop in rzn1_timer_probe_first(), except for the lower and upper bound. Perhaps it can be factored out?
Alternatively, you can
1. Unify rzn1_timer_probe_{first,other}(), and pass the different bounds as parameters, OR
2. Split rzn1_timer_probe_first() in three sub-functions, and call these from rzn1_timer_probe() directly.
drivers/clocksource/timer-rzn1.c line 439
Quoted 4 lines
drivers/clocksource/timer-rzn1.c new file +4
-0+static struct platform_driver rzn1_timer_driver = { + .driver = { + .name ="rzn1_timer" , + .of_match_table = rzn1_timer_of_match,
This driver can't be modular, and can't be unbound:
.suppress_bind_attrs = true
drivers/clocksource/timer-rzn1.c line 442
Quoted 3 lines
drivers/clocksource/timer-rzn1.c new file +3
-0+ }, +}; +builtin_platform_driver_probe (rzn1_timer_driver, rzn1_timer_probe);
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Herve Codina (Schneider Electric)
maintainerPATCH v2 3/4 ARM: dts: r9a06g032: Add support for timers
In reply to Herve Codina (Schneider Electric)In the Renesas RZ/N1 SoCs family, two timers block are available.
Each block contains 8 timers composed of 6 16-bits timers and 2 32-bits timers.
Each timer has its own interrupt line.
Describe those timers blocks.
--- arch/arm/boot/dts/renesas/r9a06g032.dtsi | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
arch/arm/boot/dts/renesas/r9a06g032.dtsi +34 -0
@@ -722,6 +722,40 @@ gpioirqmux: interrupt-controller@51000480 { status = "disabled"; }; + timer0: timer@51001000 { + compatible = "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg = <0x51001000 0x400>; + clocks = <&sysctrl R9A06G032_HCLK_TIMER0>; + clock-names = "pclk"; + power-domains = <&sysctrl>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer1: timer@51002000 { + compatible = "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg = <0x51002000 0x400>; + clocks = <&sysctrl R9A06G032_HCLK_TIMER1>; + clock-names = "pclk"; + power-domains = <&sysctrl>; + interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + can0: can@52104000 { compatible = "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000"; reg = <0x52104000 0x800>;
Signature · 1 line
2.53.0
Re: [PATCH v2 3/4] ARM: dts: r9a06g032: Add support for timers
Quoted 10 lines · Herve Codina (Schneider Electric)
In the Renesas RZ/N1 SoCs family, two timers block are available.
Each block contains 8 timers composed of 6 16-bits timers and 2 32-bits timers.
Each timer has its own interrupt line.
Describe those timers blocks.
Signed-off-by Herve Codina (Schneider Electric) <[email protected]>
i.e. will queue in renesas-devel for v7.3, pending acceptance of the DT bindings.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Herve Codina (Schneider Electric)
maintainerPATCH v2 4/4 MAINTAINERS: Add the Renesas RZ/N1 timers driver entry
In reply to Herve Codina (Schneider Electric)After contributing the driver, add myself as the maintainer for the Renesas RZ/N1 timers driver.
--- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
@@ -22708,6 +22708,13 @@ S: Maintained F: Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml F: drivers/rtc/rtc-rzn1.c +RENESAS RZ/N1 TIMERS DRIVER +M: Herve Codina <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml +F: drivers/clocksource/timer-rzn1.c + RENESAS RZ/N1 USBF CONTROLLER DRIVER M: Herve Codina <[email protected]> L: [email protected]
Signature · 1 line
2.53.0
Re: [PATCH v2 4/4] MAINTAINERS: Add the Renesas RZ/N1 timers driver entry
Quoted 4 lines · Herve Codina (Schneider Electric)
After contributing the driver, add myself as the maintainer for the Renesas RZ/N1 timers driver.
Signed-off-by Herve Codina (Schneider Electric) <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds