From nobody Sat Jul 25 01:24:24 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 917183BB9F3; Tue, 21 Jul 2026 08:30:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622613; cv=none; b=SY4f7LAG+AfthckfwGYNhgdTWcHaNeLxhAtPrlHsdIo+0Zab0LKctekCUR9hYKG9ywFnelm1GhcnUEBgd4JA+4qPw6KesBgM9EFA5ELcpDdQ1Sy38afHapNQO12SFFZ/L37/4aDCFjZHuaIvOK+AZcsPL9Lq6kP7Co7fHzBvn8U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622613; c=relaxed/simple; bh=ONBGJZifkZfXtPV90cegqCkmHy/uHZ5pp8nMBX1oGEE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YwTBaPy9FqQNIGELGOyxmKXYdZck9+5CkFPaZt14GyNHYwAUb2qeq45JdDEDrRAJeg6TmH7ZO2J8+w9uj/6uezvH8CUan1ojcae3GRqo7URSsW11MmmMI3rvD/AQB8D+4qWMDwohyfoSB442igZlxl0aB70uOzSPKdREke60p30= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=GbFdWXRF; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="GbFdWXRF" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 158AB4E40E99; Tue, 21 Jul 2026 08:30:09 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id D717C60368; Tue, 21 Jul 2026 08:30:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C5CF211BD0D07; Tue, 21 Jul 2026 10:30:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1784622607; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=IFgJQi8MuNjeZluVZ229O7LKeTgM6ORkynTZgqDFdHA=; b=GbFdWXRFTGyRGe0K6uEqP81WMIjbsGjZQAOYLMGhzS1UEUXi3iAWAmQOpOelkKQE6SnHuk ojuWRO5pOHJBZm4Lr1I+oSAW7ZUKIT5ZOOB+Evfr8O0gfQC7c5dEamn+pkbk36sy5f3ZBR i8LHGoDBGoKag21Y21FWnS3ypk1J4C+ksQ8pZD3FlHlQsuuj1TCT8hzToRbqor9mAlkJpa j1dSkwrL5l5YHHUdnSMXaLmUhouiaCxKJKr098Xywn2di242JowF1KuzkrgDddL2anLZml uskOV7zkuEsmYbJ185+LW3eyUku8xMVHLXf6HrmVhBYzR7J4MUOmjJUyYZNS3A== From: "Herve Codina (Schneider Electric)" To: Wolfram Sang , Herve Codina , Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Pascal Eberhard , Miquel Raynal , Thomas Petazzoni , Krzysztof Kozlowski Subject: [PATCH v4 1/4] dt-bindings: timer: Add the Renesas RZ/N1 timer Date: Tue, 21 Jul 2026 10:29:47 +0200 Message-ID: <20260721082952.215691-2-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260721082952.215691-1-herve.codina@bootlin.com> References: <20260721082952.215691-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" 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 Signed-off-by: Herve Codina (Schneider Electric) Reviewed-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven --- .../bindings/timer/renesas,rzn1-timer.yaml | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/renesas,rzn1-ti= mer.yaml diff --git a/Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yam= l b/Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml new file mode 100644 index 000000000000..f00ad941f8cc --- /dev/null +++ b/Documentation/devicetree/bindings/timer/renesas,rzn1-timer.yaml @@ -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 + +description: | + The Renesas RZ/N1 SoCs timers block controller is composed of 8 independ= ent + 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 + #include + + timer@51001000 { + compatible =3D "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg =3D <0x51001000 0x400>; + clocks =3D <&sysctrl R9A06G032_HCLK_TIMER0>; + clock-names =3D "pclk"; + power-domains =3D <&sysctrl>; + interrupts =3D , + , + , + , + , + , + , + ; + }; +... --=20 2.55.0 From nobody Sat Jul 25 01:24:24 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 080EF3BBFB6 for ; Tue, 21 Jul 2026 08:30:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622618; cv=none; b=hTOF2dylQzVtO7SIGmH5GoIXmFrBlv1K29Ttfr6bUXfCdsYqVZw4DWRWGQQMPnLw2lQGTJfALQ/kUZpY/eSzWng57kjzxoeZ0PJb2KoZVv9K/VS+9qvnVxxB4v0DAjCBaAoZt5v5n4He9dZ1cGPTYCW8Msg8QkBbEUhRV2kMeHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622618; c=relaxed/simple; bh=Tu1iuFcAp3aJPFLWz/z9yil9rnyPlTSwjxZ7lwpSqqg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ve6Ki6ipewWPflfTln6zNHyURl0tVRZgINvVgchV6y44XErYdg8YopKYxrE63yRhhbvTY1Zqd5tNV3XKt4vJLqe7zxabDsmcQZ53PbOJtUyT75jmsLHja2G0oZBJjTGzeNqookZXz+OEwneFDnYkZ13Q77OXMxQkZJWdZwhHsAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=LZvQq7Zz; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="LZvQq7Zz" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 62B6D4E40E9A; Tue, 21 Jul 2026 08:30:11 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 370E660368; Tue, 21 Jul 2026 08:30:11 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 9383811BD2234; Tue, 21 Jul 2026 10:30:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1784622610; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=3RqZriyESepDN2Pj+icpBn8W098LgY3frk3eNygfy2c=; b=LZvQq7ZzZ7gDbK/BPGUFi9NMm5OsXdmA29+TvJwjUnfoVllGXxHmjlPHrUyX5p5Iq/0vAy BBMhlMeNfkw8FT03jg475HUIaU5/vHRWSxeZde/KVQJBKKbpsI0mW2pNtH0FOMpTN2p54q bnXsWI4uqnHGBG36JqutpY5B58d6finZ9dHj7uLEssuGmYKAv5MzoWkerzZ5VZopA8kSTa Piu7NZVAJFDU8mmBax+AnXseU2EvvmifeNAI1++7yuk7a2PbJ6FNsdAWPUz1WwSfEv+3Qq toM5y45k0h87wzN1ZgZgAaxBY3l07gEnDEvHE7VxkMU6ZuqU7jUbF8oxUPamOg== From: "Herve Codina (Schneider Electric)" To: Wolfram Sang , Herve Codina , Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Pascal Eberhard , Miquel Raynal , Thomas Petazzoni Subject: [PATCH v4 2/4] clocksource/drivers: Add support for the Renesas RZ/N1 timers Date: Tue, 21 Jul 2026 10:29:48 +0200 Message-ID: <20260721082952.215691-3-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260721082952.215691-1-herve.codina@bootlin.com> References: <20260721082952.215691-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" 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 divide the clock by 25 and all of them can work in either one-shot or periodic mode. Signed-off-by: Herve Codina (Schneider Electric) --- drivers/clocksource/Kconfig | 11 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-rzn1.c | 487 +++++++++++++++++++++++++++++++ 3 files changed, 499 insertions(+) create mode 100644 drivers/clocksource/timer-rzn1.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index d9c76dd443f8..da83483296d5 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -152,6 +152,17 @@ config REALTEK_OTTO_TIMER RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series such as RTL9301, RTL9302 or RTL9303. =20 +config RZN1_TIMER + bool "Renesas RZ/N1 Timer" + depends on HAS_IOMEM && COMMON_CLK + depends on 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 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index b46376af6b49..464ec6690ab6 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -96,3 +96,4 @@ obj-$(CONFIG_EP93XX_TIMER) +=3D timer-ep93xx.o obj-$(CONFIG_RALINK_TIMER) +=3D timer-ralink.o obj-$(CONFIG_NXP_STM_TIMER) +=3D timer-nxp-stm.o obj-$(CONFIG_RTK_SYSTIMER) +=3D timer-realtek.o +obj-$(CONFIG_RZN1_TIMER) +=3D timer-rzn1.o diff --git a/drivers/clocksource/timer-rzn1.c b/drivers/clocksource/timer-r= zn1.c new file mode 100644 index 000000000000..f6c4dd4b3469 --- /dev/null +++ b/drivers/clocksource/timer-rzn1.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/N1 timers driver + * + * Copyright (C) 2026 Schneider-Electric + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Per-timer register offsets */ +#define RZN1_TIMER_LOAD_COUNT_REG 0x00 +#define RZN1_TIMER_CURRENT_COUNT_REG 0x04 +#define RZN1_TIMER_CONTROL_REG 0x08 +#define RZN1_TIMER_CONTROL_INT_UNMASK BIT(3) +#define RZN1_TIMER_CONTROL_ENABLE BIT(2) +#define RZN1_TIMER_CONTROL_AUTORELOAD BIT(1) +#define RZN1_TIMER_CONTROL_PRESCALER_DIV25 BIT(0) +#define RZN1_TIMER_CLEAR_INT_REG 0x0c +#define RZN1_TIMER_STATUS_INT0_REG 0x10 +#define RZN1_TIMER_STATUS_INT1_REG 0x14 + +/* + * 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_LAST_INDEX_16BIT_TIMERS (RZN1_TIMER_BASE_INDEX_16BIT_TI= MERS + \ + RZN1_TIMER_NB_16BIT_TIMERS - 1) + +#define RZN1_TIMER_BASE_INDEX_32BIT_TIMERS 6 +#define RZN1_TIMER_NB_32BIT_TIMERS 2 +#define RZN1_TIMER_LAST_INDEX_32BIT_TIMERS (RZN1_TIMER_BASE_INDEX_32BIT_TI= MERS + \ + RZN1_TIMER_NB_32BIT_TIMERS - 1) + +#define RZN1_TIMER_IS_16BIT_TIMER(_i) ((_i) < RZN1_TIMER_BASE_INDEX_32BIT_= TIMERS) + +/* Total numbers of timers */ +#define RZN1_TIMER_NB_TIMERS (RZN1_TIMER_NB_16BIT_TIMERS + \ + RZN1_TIMER_NB_32BIT_TIMERS) + +/* Offset of registers related to the timer number _i in the timers regs a= rea */ +#define RZN1_TIMER_REGS_OFFSET(_i) (0x20 * (_i)) + +struct rzn1_timer { + void __iomem *base; + unsigned int width; + unsigned long rate; + unsigned long hz_period; + struct clock_event_device ced; +}; + +static int rzn1_timer_config(struct rzn1_timer *timer, u32 period, bool is= _periodic) +{ + u32 ctrl; + + ctrl =3D readl(timer->base + RZN1_TIMER_CONTROL_REG); + + /* Disable the timer */ + writel(ctrl & ~RZN1_TIMER_CONTROL_ENABLE, + timer->base + RZN1_TIMER_CONTROL_REG); + + /* Set the new period */ + writel(period, timer->base + RZN1_TIMER_LOAD_COUNT_REG); + + /* Prepare the timer mode */ + if (is_periodic) + ctrl |=3D RZN1_TIMER_CONTROL_AUTORELOAD; + else + ctrl &=3D ~RZN1_TIMER_CONTROL_AUTORELOAD; + + /* + * Enable the timer. + * + * This automatically resets the CURRENT_COUNT register. + */ + ctrl |=3D RZN1_TIMER_CONTROL_ENABLE; + writel(ctrl, timer->base + RZN1_TIMER_CONTROL_REG); + + return 0; +} + +static void rzn1_timer_disable(struct rzn1_timer *timer) +{ + u32 ctrl; + + ctrl =3D readl(timer->base + RZN1_TIMER_CONTROL_REG); + ctrl &=3D ~RZN1_TIMER_CONTROL_ENABLE; + writel(ctrl, timer->base + RZN1_TIMER_CONTROL_REG); +} + +static void rzn1_timer_int_enable(struct rzn1_timer *timer) +{ + u32 ctrl; + + ctrl =3D readl(timer->base + RZN1_TIMER_CONTROL_REG); + ctrl |=3D RZN1_TIMER_CONTROL_INT_UNMASK; + writel(ctrl, timer->base + RZN1_TIMER_CONTROL_REG); +} + +static irqreturn_t rzn1_timer_interrupt(int irq, void *dev_id) +{ + struct rzn1_timer *timer =3D dev_id; + + /* Ack the interrupt */ + readl(timer->base + RZN1_TIMER_CLEAR_INT_REG); + + timer->ced.event_handler(&timer->ced); + return IRQ_HANDLED; +} + +static int rzn1_clkevt_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + struct rzn1_timer *timer =3D container_of(evt, struct rzn1_timer, ced); + + return rzn1_timer_config(timer, cycles, false); +} + +static int rzn1_clkevt_shutdown(struct clock_event_device *evt) +{ + struct rzn1_timer *timer =3D container_of(evt, struct rzn1_timer, ced); + + rzn1_timer_disable(timer); + return 0; +} + +static int rzn1_clkevt_set_periodic(struct clock_event_device *evt) +{ + struct rzn1_timer *timer =3D container_of(evt, struct rzn1_timer, ced); + + rzn1_timer_config(timer, timer->hz_period, true); + return 0; +} + +/* + * This global lock is used to prevent race conditions during global timers + * test and set operation in case the driver is using the async probe opti= on. + */ +static DEFINE_MUTEX(rzn1_global_timers_lock); + +static int rzn1_timer_instance; + +/* scheduler and clocksource */ +static struct rzn1_timer *rzn1_sched_clock; + +static u64 notrace rzn1_sched_read(void) +{ + return readl_relaxed(rzn1_sched_clock->base + RZN1_TIMER_CURRENT_COUNT_RE= G); +} + +static u64 rzn1_clksrc_read(struct clocksource *cs) +{ + return readl_relaxed(rzn1_sched_clock->base + RZN1_TIMER_CURRENT_COUNT_RE= G); +} + +static struct clocksource rzn1_clocksource =3D { + .name =3D "rzn1_timer_clocksource", + .rating =3D 200, + .flags =3D CLOCK_SOURCE_IS_CONTINUOUS, + .read =3D rzn1_clksrc_read, +}; + +/* Timers table where 32-bit timers will be assigned per-cpu */ +static struct rzn1_timer *rzn1_tab_timers; + +static int rzn1_local_timer_starting_cpu(unsigned int cpu) +{ + struct rzn1_timer *timer; + + if (cpu >=3D RZN1_TIMER_NB_32BIT_TIMERS) + return 0; + + timer =3D &rzn1_tab_timers[cpu + RZN1_TIMER_BASE_INDEX_32BIT_TIMERS]; + + timer->ced.cpumask =3D cpumask_of(cpu); + irq_force_affinity(timer->ced.irq, cpumask_of(cpu)); + enable_irq(timer->ced.irq); + + clockevents_config_and_register(&timer->ced, timer->rate, 1, + GENMASK(timer->width - 1, 0)); + + return 0; +} + +static int rzn1_local_timer_dying_cpu(unsigned int cpu) +{ + struct rzn1_timer *timer; + + if (cpu >=3D RZN1_TIMER_NB_32BIT_TIMERS) + return 0; + + timer =3D &rzn1_tab_timers[cpu + RZN1_TIMER_BASE_INDEX_32BIT_TIMERS]; + + rzn1_timer_disable(timer); + disable_irq_nosync(timer->ced.irq); + return 0; +} + +static void rzn1_timer_init(struct rzn1_timer *timer, unsigned int index, + void __iomem *timers_base, unsigned long clock_rate) +{ + timer->base =3D timers_base + RZN1_TIMER_REGS_OFFSET(index); + + /* Disable the timer */ + writel(0, timer->base + RZN1_TIMER_CONTROL_REG); + + /* Clear potential interrupts */ + readl(timer->base + RZN1_TIMER_CLEAR_INT_REG); + + if (RZN1_TIMER_IS_16BIT_TIMER(index)) { + timer->width =3D 16; + /* + * Enable pre-scaler for 16-bit timers. + * + * Timers are fed by a 25MHz clock. With this pre-scaler (1/25) + * enabled, the 16-bit timers resolution is 1 microsecond. + */ + writel(RZN1_TIMER_CONTROL_PRESCALER_DIV25, + timer->base + RZN1_TIMER_CONTROL_REG); + timer->rate =3D clock_rate / 25; + } else { + timer->width =3D 32; + timer->rate =3D clock_rate; + } + timer->hz_period =3D DIV_ROUND_UP(timer->rate, HZ); +} + +static void rzn1_timer_clkevt_init_ced(struct rzn1_timer *timer, const cha= r *name, + int irq) +{ + timer->ced.features =3D CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + timer->ced.set_next_event =3D rzn1_clkevt_set_next_event; + timer->ced.set_state_shutdown =3D rzn1_clkevt_shutdown; + timer->ced.set_state_periodic =3D rzn1_clkevt_set_periodic; + timer->ced.cpumask =3D cpu_possible_mask; + + /* + * 32-bit timers are fed with a 25 MHz clock directly derived from the + * main PLL (1 GHz). The arch timer, ARMv7 CP15 in RZ/N1 SoCs, is fed + * with to a 6.25 MHz clock. + * + * The clock of the RZ/N1 timers block is a stable one and the RZ/N1 + * timers have a higher resolution than the ARM CP15 one. + * + * Also those 32-bit RZ/N1 timers are assigned per-cpu. + * + * Use a high rating for the 32-bit RZ/N1 timers in order to have them + * chosen by the system. + */ + timer->ced.rating =3D timer->width =3D=3D 16 ? 200 : 460; + timer->ced.owner =3D THIS_MODULE; + timer->ced.name =3D name; + timer->ced.irq =3D irq; +} + +static int rzn1_timer_setup_timers(struct platform_device *pdev, + struct rzn1_timer *tab_timers, + unsigned int first_timer_index, + unsigned int last_timer_index, + void __iomem *base, unsigned long clock_rate, + bool irq_disabled) +{ + struct device *dev =3D &pdev->dev; + struct rzn1_timer *timer; + unsigned int i; + char *name; + int irq; + int ret; + + for (i =3D first_timer_index; i <=3D last_timer_index; i++) { + timer =3D &tab_timers[i]; + + rzn1_timer_init(timer, i, base, clock_rate); + + irq =3D platform_get_irq(pdev, i); + if (irq < 0) + return irq; + + name =3D devm_kasprintf(dev, GFP_KERNEL, "%s-%u", dev_name(dev), i); + if (!name) + return -ENOMEM; + + rzn1_timer_clkevt_init_ced(timer, name, irq); + + if (irq_disabled) + irq_set_status_flags(timer->ced.irq, IRQ_NOAUTOEN); + + ret =3D devm_request_irq(dev, timer->ced.irq, rzn1_timer_interrupt, + IRQF_TIMER, timer->ced.name, timer); + if (ret < 0) + return dev_err_probe(dev, ret, "timer%u: Failed to request IRQ\n", i); + + rzn1_timer_int_enable(timer); + } + return 0; +} + +static void rzn1_timer_register_clkevt(struct rzn1_timer *tab_timers, + unsigned int first_timer_index, + unsigned int last_timer_index) +{ + struct rzn1_timer *timer; + unsigned int i; + + for (i =3D first_timer_index; i <=3D last_timer_index; i++) { + timer =3D &tab_timers[i]; + clockevents_config_and_register(&timer->ced, timer->rate, + 1, GENMASK(timer->width - 1, 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 =3D &pdev->dev; + struct rzn1_timer *timer; + 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. + */ + ret =3D rzn1_timer_setup_timers(pdev, tab_timers, + RZN1_TIMER_BASE_INDEX_16BIT_TIMERS + 1, + RZN1_TIMER_LAST_INDEX_16BIT_TIMERS, + base, clock_rate, false); + if (ret) + return ret; + + /* + * Do not enable IRQs on 32-bit timers. Those related IRQ will be + * enabled/disabled by CPU hotplug callbacks + */ + ret =3D rzn1_timer_setup_timers(pdev, tab_timers, + RZN1_TIMER_BASE_INDEX_32BIT_TIMERS, + RZN1_TIMER_LAST_INDEX_32BIT_TIMERS, + base, clock_rate, true); + if (ret) + return ret; + + /* + * 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 =3D tab_timers; + ret =3D cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + "clockevents/rzn1/global_timer:starting", + rzn1_local_timer_starting_cpu, + rzn1_local_timer_dying_cpu); + 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 =3D &tab_timers[RZN1_TIMER_BASE_INDEX_16BIT_TIMERS]; + + rzn1_timer_init(timer, RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, base, clock_ra= te); + rzn1_timer_config(timer, GENMASK(timer->width - 1, 0), true); + + rzn1_sched_clock =3D timer; + + sched_clock_register(rzn1_sched_read, rzn1_sched_clock->width, rzn1_sched= _clock->rate); + + rzn1_clocksource.mask =3D 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. + */ + rzn1_timer_register_clkevt(tab_timers, + RZN1_TIMER_BASE_INDEX_16BIT_TIMERS + 1, + RZN1_TIMER_LAST_INDEX_16BIT_TIMERS); + + return 0; +} + +static int rzn1_timer_probe_other(struct platform_device *pdev, + struct rzn1_timer *tab_timers, + void __iomem *base, unsigned long clock_rate) +{ + int ret; + + /* + * 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. + */ + ret =3D rzn1_timer_setup_timers(pdev, tab_timers, + RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, + RZN1_TIMER_LAST_INDEX_32BIT_TIMERS, + base, clock_rate, false); + if (ret) + return ret; + + /* + * Second step, all operation that can fail have been called. We can + * register our timers. + */ + rzn1_timer_register_clkevt(tab_timers, + RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, + RZN1_TIMER_LAST_INDEX_32BIT_TIMERS); + return 0; +} + +static int rzn1_timer_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct rzn1_timer *tab_timers; + unsigned long clock_rate; + void __iomem *base; + struct clk *clk; + int ret; + + tab_timers =3D devm_kcalloc(dev, RZN1_TIMER_NB_TIMERS, sizeof(*tab_timers= ), + GFP_KERNEL); + if (!tab_timers) + return -ENOMEM; + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk =3D devm_clk_get_enabled(dev, "pclk"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "Failed to get pclk\n"); + + clock_rate =3D clk_get_rate(clk); + + scoped_guard(mutex, &rzn1_global_timers_lock) { + ret =3D !rzn1_timer_instance ? + rzn1_timer_probe_first(pdev, tab_timers, base, clock_rate) : + rzn1_timer_probe_other(pdev, tab_timers, base, clock_rate); + if (!ret) + rzn1_timer_instance++; + } + + return ret; +} + +static const struct of_device_id rzn1_timer_of_match[] =3D { + { .compatible =3D "renesas,rzn1-timer", }, + { /* sentinel */ } +}; + +static struct platform_driver rzn1_timer_driver =3D { + .driver =3D { + .name =3D "rzn1_timer", + .of_match_table =3D rzn1_timer_of_match, + .suppress_bind_attrs =3D true, + }, +}; +builtin_platform_driver_probe(rzn1_timer_driver, rzn1_timer_probe); --=20 2.55.0 From nobody Sat Jul 25 01:24:24 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2345C3BBA1A; Tue, 21 Jul 2026 08:30:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622617; cv=none; b=B7EYZL8Bl7e1BSdJ3EXAP1RepmFKdXiRGF44etB3n0uKVaTx/omz2nCvsGphpaIuA5Ckbpf6MukppEuUrt30x81IERZJz5kF5z5mdwCP0lf61TTXv3Wv0ujxjfoYa+02QJXlDsZMH7hTASDUyjyrny59g6Ln5DJSQswDzIoUurc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622617; c=relaxed/simple; bh=HbS4Rpeus8z+CqMlKn9XdXXf2qR3h2VDL55W31Dy2+g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LidsgxOFJWRVtCYUwz51zH9OjYplyoAW4dvVyRdNQIaKzbzofevNRknBg0yxxRz25BXxA0C42+9vpDWMouiWwdzbOiebUcbhCIwvpikzm83wPDe5HDQxBmbOpIQYXKgIT8eewLqr/zUFjePz4dObIwOOoQG8wcg96APXsHNCYvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Jti7Yaem; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Jti7Yaem" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 807DA1A1130; Tue, 21 Jul 2026 08:30:13 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 554C960368; Tue, 21 Jul 2026 08:30:13 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CC4AE11BD1290; Tue, 21 Jul 2026 10:30:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1784622612; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=KC1yk5fADdsigOxHDO3fqt916xnPRpJY0Omipd3mb/I=; b=Jti7YaemgJTuccjnv4HQqQmLRR3gejszd9mYFHkdQ2zUFIZx1YAArvY2jvi4rM6K/fa/YB f3gnk/I5KgCzWyIFTQS+p5CnNcN8FUBiH+lvMb01SPSQRuJ+odIV9uWYg9xWTnCEMunNVe uhwvpmTSwtJMzgfqPi5CxUj4us9BMels2rmLWTDAn5BT+/vtLemzbdG4dMIbYiO4DUC05N Xob/V6JdWgRDHQOPnq2tj3/Rnx9zSkhbOTLkPxV8EVEAiX5tYJqedPTM8LSjm+uzZHi8WU cHHdf3kBF4NqfuKy35gu/WDDIvj4/XKhOzBGXHDAdRG+1gE5COCvd6LFvSZh5w== From: "Herve Codina (Schneider Electric)" To: Wolfram Sang , Herve Codina , Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Pascal Eberhard , Miquel Raynal , Thomas Petazzoni Subject: [PATCH v4 3/4] ARM: dts: r9a06g032: Add support for timers Date: Tue, 21 Jul 2026 10:29:49 +0200 Message-ID: <20260721082952.215691-4-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260721082952.215691-1-herve.codina@bootlin.com> References: <20260721082952.215691-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" 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) Reviewed-by: Geert Uytterhoeven --- arch/arm/boot/dts/renesas/r9a06g032.dtsi | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/r= enesas/r9a06g032.dtsi index 442ea26b40f5..ba3f011e8c17 100644 --- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi +++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi @@ -722,6 +722,40 @@ gpioirqmux: interrupt-controller@51000480 { status =3D "disabled"; }; =20 + timer0: timer@51001000 { + compatible =3D "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg =3D <0x51001000 0x400>; + clocks =3D <&sysctrl R9A06G032_HCLK_TIMER0>; + clock-names =3D "pclk"; + power-domains =3D <&sysctrl>; + interrupts =3D , + , + , + , + , + , + , + ; + status =3D "disabled"; + }; + + timer1: timer@51002000 { + compatible =3D "renesas,r9a06g032-timer", "renesas,rzn1-timer"; + reg =3D <0x51002000 0x400>; + clocks =3D <&sysctrl R9A06G032_HCLK_TIMER1>; + clock-names =3D "pclk"; + power-domains =3D <&sysctrl>; + interrupts =3D , + , + , + , + , + , + , + ; + status =3D "disabled"; + }; + can0: can@52104000 { compatible =3D "renesas,r9a06g032-sja1000", "renesas,rzn1-sja1000"; reg =3D <0x52104000 0x800>; --=20 2.55.0 From nobody Sat Jul 25 01:24:24 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9617C3BCD3B for ; Tue, 21 Jul 2026 08:30:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622619; cv=none; b=uJb9WCV3gwXOJjwq4y2LrERmoxiixa6RSNU9LvhYwlrhNX1kMDaFersh5kyYSz5cDgCWHfAUzKdtNpHITNplEm5/rWyWSkWniceB0+Vaxxv26B+pgv8nsVdH9BiK67jhxPN8tovQ8WBJ2LNMX3zvjpwH715QIv7SA2UFw35jwCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784622619; c=relaxed/simple; bh=53cQQbHnKYTUlIp1/Oe1lnHotiqeGBENPlrWHZNDVy4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Is1JTknd8CYZjdgt/7ynitAPKCcPF/eU3YRdygtno7bTzgEhQvdHchSXC//Vslut151SWUW7E57RO0kiQjrVDFF6XzQt/ApZR7RFzfdbIsqhdoavnwV8Y+Vz7Hha+3t3yd4IqyY4Za2z+nTE11zpvwvuPTAgdNWsOUCfQ1+lT20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=uf3nSZ1l; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="uf3nSZ1l" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 66DF54E40E99; Tue, 21 Jul 2026 08:30:15 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 35F2260368; Tue, 21 Jul 2026 08:30:15 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E24F211BD0D07; Tue, 21 Jul 2026 10:30:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1784622614; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=m09xP2eVOvf/ABP75jSTVRTHgDA66h9ZeoreFZaMOj8=; b=uf3nSZ1lOWLIWV8w2YLPOdAwB8A0PgEYngh2KtN1kWNwA5/WQmsE2J1r1w0FLlB1wXkKTA ZIXSh3X0VwjHdKZlb2NeshGh8SdfyR16+t0Q6yTIWd9JOCpoCP4cw4PqUH+gqMi/KPnVH0 4yNWyvxWJ9LllfQz7B0kxfEoMyeepfLZh3bFVJrUsh3eWj4EJmHrQI58AmZqmbxwbvsfqi SGJpTgtwyEGiCw+IVYzdtNa6XahG4PbADtAtxdbfIWEGQJ44lS+gl0yvA5/aSVsg/Wtxva ONdsxfs4oc/rsfZ3NnQmIqXUSUZ6RPuKKTi+MK3DEMV28fVGUZMGeMcUUMKQBA== From: "Herve Codina (Schneider Electric)" To: Wolfram Sang , Herve Codina , Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Pascal Eberhard , Miquel Raynal , Thomas Petazzoni Subject: [PATCH v4 4/4] MAINTAINERS: Add the Renesas RZ/N1 timers driver entry Date: Tue, 21 Jul 2026 10:29:50 +0200 Message-ID: <20260721082952.215691-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260721082952.215691-1-herve.codina@bootlin.com> References: <20260721082952.215691-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" After contributing the driver, add myself as the maintainer for the Renesas RZ/N1 timers driver. Signed-off-by: Herve Codina (Schneider Electric) Reviewed-by: Geert Uytterhoeven --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a9..17fd5f749344 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23025,6 +23025,13 @@ S: Maintained F: Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml F: drivers/rtc/rtc-rzn1.c =20 +RENESAS RZ/N1 TIMERS DRIVER +M: Herve Codina +L: linux-renesas-soc@vger.kernel.org +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 L: linux-renesas-soc@vger.kernel.org --=20 2.55.0