| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * RZ/N1 timers driver | |
| * | |
| * Copyright (C) 2026 Schneider-Electric | |
| * | |
| * Author: Herve Codina <herve.codina@bootlin.com> | |
| */ | |
| #include <linux/bits.h> | |
| #include <linux/clk.h> | |
| #include <linux/clockchips.h> | |
| #include <linux/clocksource.h> | |
| #include <linux/cpuhotplug.h> | |
| #include <linux/interrupt.h> | |
| #include <linux/of.h> | |
| #include <linux/platform_device.h> | |
| #include <linux/sched_clock.h> | |
| /* 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_TIMERS + \ | |
| 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_TIMERS + \ | |
| 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 area */ | |
| #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 = 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 |= RZN1_TIMER_CONTROL_AUTORELOAD; | |
| else | |
| ctrl &= ~RZN1_TIMER_CONTROL_AUTORELOAD; | |
| /* | |
| * Enable the timer. | |
| * | |
| * This automatically resets the CURRENT_COUNT register. | |
| */ | |
| ctrl |= 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 = readl(timer->base + RZN1_TIMER_CONTROL_REG); | |
| ctrl &= ~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 = readl(timer->base + RZN1_TIMER_CONTROL_REG); | |
| ctrl |= 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 = dev_id; | |
| /* Ack the interrupt */ | |
| readl(timer->base + RZN1_TIMER_CLEAR_INT_REG); | |
| if (timer->ced.event_handler) | |
| 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 = 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 = 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 = 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 option. | |
| */ | |
| 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_REG); | |
| } | |
| static u64 rzn1_clksrc_read(struct clocksource *cs) | |
| { | |
| return readl_relaxed(rzn1_sched_clock->base + RZN1_TIMER_CURRENT_COUNT_REG); | |
| } | |
| static struct clocksource rzn1_clocksource = { | |
| .name = "rzn1_timer_clocksource", | |
| .rating = 200, | |
| .flags = CLOCK_SOURCE_IS_CONTINUOUS, | |
| .read = rzn1_clksrc_read, | |
| }; | |
| /* Timers table where 16-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; | |
| /* We assign the first and second 16-bit timer as per-cpu timers. */ | |
| if (cpu >= 2) | |
| return 0; | |
| timer = &rzn1_tab_timers[cpu + RZN1_TIMER_BASE_INDEX_16BIT_TIMERS]; | |
| timer->ced.cpumask = cpumask_of(cpu); | |
| irq_force_affinity(timer->ced.irq, cpumask_of(cpu)); | |
| clockevents_config_and_register(&timer->ced, timer->rate, 1, | |
| GENMASK(timer->width - 1, 0)); | |
| /* | |
| * Time to enable the interrupt even if no interrupt can be fired yet. | |
| * Indeed, the timer is still globally disabled. | |
| * It will be enabled when rzn1_timer_config() is called | |
| */ | |
| enable_irq(timer->ced.irq); | |
| return 0; | |
| } | |
| static int rzn1_local_timer_dying_cpu(unsigned int cpu) | |
| { | |
| struct rzn1_timer *timer; | |
| if (cpu >= 2) | |
| return 0; | |
| timer = &rzn1_tab_timers[cpu + RZN1_TIMER_BASE_INDEX_16BIT_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 = 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 = 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 = clock_rate / 25; | |
| } else { | |
| timer->width = 32; | |
| timer->rate = clock_rate; | |
| } | |
| timer->hz_period = DIV_ROUND_UP(timer->rate, HZ); | |
| } | |
| static void rzn1_timer_clkevt_init_ced(struct rzn1_timer *timer, const char *name, | |
| int irq) | |
| { | |
| timer->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | |
| timer->ced.set_next_event = rzn1_clkevt_set_next_event; | |
| timer->ced.set_state_shutdown = rzn1_clkevt_shutdown; | |
| timer->ced.set_state_periodic = rzn1_clkevt_set_periodic; | |
| timer->ced.cpumask = 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. | |
| * | |
| * Use a high rating for the 32-bit RZ/N1 timers. | |
| */ | |
| timer->ced.rating = timer->width == 16 ? 200 : 460; | |
| timer->ced.owner = THIS_MODULE; | |
| timer->ced.name = name; | |
| timer->ced.irq = 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) | |
| { | |
| struct device *dev = &pdev->dev; | |
| struct rzn1_timer *timer; | |
| unsigned int i; | |
| char *name; | |
| int irq; | |
| int ret; | |
| for (i = first_timer_index; i <= last_timer_index; i++) { | |
| timer = &tab_timers[i]; | |
| rzn1_timer_init(timer, i, base, clock_rate); | |
| irq = platform_get_irq(pdev, i); | |
| if (irq < 0) | |
| return irq; | |
| 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 | IRQF_NO_AUTOEN, | |
| 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 = first_timer_index; i <= last_timer_index; i++) { | |
| timer = &tab_timers[i]; | |
| clockevents_config_and_register(&timer->ced, timer->rate, | |
| 1, GENMASK(timer->width - 1, 0)); | |
| /* | |
| * Time to enable the interrupt even if no interrupt can be | |
| * fired yet. Indeed, the timer is still globally disabled. | |
| * It will be enabled when rzn1_timer_config() is called | |
| */ | |
| enable_irq(timer->ced.irq); | |
| } | |
| } | |
| 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; | |
| int ret; | |
| /* | |
| * Each timer instance has 6 x 16-bit timers and 2 x 32-bit timers. | |
| * | |
| * Probe the first instance. In that case, timers are assigned as | |
| * follow: | |
| * - First and second 16-bit timers: clock events per CPU | |
| * - Last (second one) 32-bit timer: clocksource and sched_clock | |
| * - Other timers: clock events for all possible CPUs | |
| * | |
| * 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 and the first 32-bit timers. */ | |
| ret = rzn1_timer_setup_timers(pdev, tab_timers, | |
| RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, | |
| RZN1_TIMER_BASE_INDEX_32BIT_TIMERS, | |
| base, clock_rate); | |
| 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 = tab_timers; | |
| ret = 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 last (second one) 32-bit timer | |
| */ | |
| timer = &tab_timers[RZN1_TIMER_LAST_INDEX_32BIT_TIMERS]; | |
| rzn1_timer_init(timer, RZN1_TIMER_LAST_INDEX_32BIT_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 for 16-bit timers (except the first and second | |
| * ones) and for the first 32-bit timer. The first and second 16-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 + 2, | |
| RZN1_TIMER_BASE_INDEX_32BIT_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 = rzn1_timer_setup_timers(pdev, tab_timers, | |
| RZN1_TIMER_BASE_INDEX_16BIT_TIMERS, | |
| RZN1_TIMER_LAST_INDEX_32BIT_TIMERS, | |
| base, clock_rate); | |
| 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 = &pdev->dev; | |
| struct rzn1_timer *tab_timers; | |
| unsigned long clock_rate; | |
| void __iomem *base; | |
| struct clk *clk; | |
| int ret; | |
| tab_timers = devm_kcalloc(dev, RZN1_TIMER_NB_TIMERS, sizeof(*tab_timers), | |
| GFP_KERNEL); | |
| if (!tab_timers) | |
| return -ENOMEM; | |
| base = devm_platform_ioremap_resource(pdev, 0); | |
| if (IS_ERR(base)) | |
| return PTR_ERR(base); | |
| clk = 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 = clk_get_rate(clk); | |
| scoped_guard(mutex, &rzn1_global_timers_lock) { | |
| ret = !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[] = { | |
| { .compatible = "renesas,rzn1-timer", }, | |
| { /* sentinel */ } | |
| }; | |
| static struct platform_driver rzn1_timer_driver = { | |
| .driver = { | |
| .name = "rzn1_timer", | |
| .of_match_table = rzn1_timer_of_match, | |
| .suppress_bind_attrs = true, | |
| }, | |
| }; | |
| builtin_platform_driver_probe(rzn1_timer_driver, rzn1_timer_probe); |