root/drivers/clocksource/timer-stm32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stm32_timer_of_bits_set
  2. stm32_timer_of_bits_get
  3. stm32_read_sched_clock
  4. stm32_read_delay
  5. stm32_clock_event_disable
  6. stm32_timer_start
  7. stm32_clock_event_shutdown
  8. stm32_clock_event_set_next_event
  9. stm32_clock_event_set_periodic
  10. stm32_clock_event_set_oneshot
  11. stm32_clock_event_handler
  12. stm32_timer_set_width
  13. stm32_timer_set_prescaler
  14. stm32_clocksource_init
  15. stm32_clockevent_init
  16. stm32_timer_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) Maxime Coquelin 2015
   4  * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
   5  *
   6  * Inspired by time-efm32.c from Uwe Kleine-Koenig
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/clocksource.h>
  11 #include <linux/clockchips.h>
  12 #include <linux/delay.h>
  13 #include <linux/irq.h>
  14 #include <linux/interrupt.h>
  15 #include <linux/of.h>
  16 #include <linux/of_address.h>
  17 #include <linux/of_irq.h>
  18 #include <linux/clk.h>
  19 #include <linux/reset.h>
  20 #include <linux/sched_clock.h>
  21 #include <linux/slab.h>
  22 
  23 #include "timer-of.h"
  24 
  25 #define TIM_CR1         0x00
  26 #define TIM_DIER        0x0c
  27 #define TIM_SR          0x10
  28 #define TIM_EGR         0x14
  29 #define TIM_CNT         0x24
  30 #define TIM_PSC         0x28
  31 #define TIM_ARR         0x2c
  32 #define TIM_CCR1        0x34
  33 
  34 #define TIM_CR1_CEN     BIT(0)
  35 #define TIM_CR1_UDIS    BIT(1)
  36 #define TIM_CR1_OPM     BIT(3)
  37 #define TIM_CR1_ARPE    BIT(7)
  38 
  39 #define TIM_DIER_UIE    BIT(0)
  40 #define TIM_DIER_CC1IE  BIT(1)
  41 
  42 #define TIM_SR_UIF      BIT(0)
  43 
  44 #define TIM_EGR_UG      BIT(0)
  45 
  46 #define TIM_PSC_MAX     USHRT_MAX
  47 #define TIM_PSC_CLKRATE 10000
  48 
  49 struct stm32_timer_private {
  50         int bits;
  51 };
  52 
  53 /**
  54  * stm32_timer_of_bits_set - set accessor helper
  55  * @to: a timer_of structure pointer
  56  * @bits: the number of bits (16 or 32)
  57  *
  58  * Accessor helper to set the number of bits in the timer-of private
  59  * structure.
  60  *
  61  */
  62 static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
  63 {
  64         struct stm32_timer_private *pd = to->private_data;
  65 
  66         pd->bits = bits;
  67 }
  68 
  69 /**
  70  * stm32_timer_of_bits_get - get accessor helper
  71  * @to: a timer_of structure pointer
  72  *
  73  * Accessor helper to get the number of bits in the timer-of private
  74  * structure.
  75  *
  76  * Returns an integer corresponding to the number of bits.
  77  */
  78 static int stm32_timer_of_bits_get(struct timer_of *to)
  79 {
  80         struct stm32_timer_private *pd = to->private_data;
  81 
  82         return pd->bits;
  83 }
  84 
  85 static void __iomem *stm32_timer_cnt __read_mostly;
  86 
  87 static u64 notrace stm32_read_sched_clock(void)
  88 {
  89         return readl_relaxed(stm32_timer_cnt);
  90 }
  91 
  92 static struct delay_timer stm32_timer_delay;
  93 
  94 static unsigned long stm32_read_delay(void)
  95 {
  96         return readl_relaxed(stm32_timer_cnt);
  97 }
  98 
  99 static void stm32_clock_event_disable(struct timer_of *to)
 100 {
 101         writel_relaxed(0, timer_of_base(to) + TIM_DIER);
 102 }
 103 
 104 /**
 105  * stm32_timer_start - Start the counter without event
 106  * @to: a timer_of structure pointer
 107  *
 108  * Start the timer in order to have the counter reset and start
 109  * incrementing but disable interrupt event when there is a counter
 110  * overflow. By default, the counter direction is used as upcounter.
 111  */
 112 static void stm32_timer_start(struct timer_of *to)
 113 {
 114         writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
 115 }
 116 
 117 static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
 118 {
 119         struct timer_of *to = to_timer_of(clkevt);
 120 
 121         stm32_clock_event_disable(to);
 122 
 123         return 0;
 124 }
 125 
 126 static int stm32_clock_event_set_next_event(unsigned long evt,
 127                                             struct clock_event_device *clkevt)
 128 {
 129         struct timer_of *to = to_timer_of(clkevt);
 130         unsigned long now, next;
 131 
 132         next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
 133         writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
 134         now = readl_relaxed(timer_of_base(to) + TIM_CNT);
 135 
 136         if ((next - now) > evt)
 137                 return -ETIME;
 138 
 139         writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
 140 
 141         return 0;
 142 }
 143 
 144 static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
 145 {
 146         struct timer_of *to = to_timer_of(clkevt);
 147 
 148         stm32_timer_start(to);
 149 
 150         return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
 151 }
 152 
 153 static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
 154 {
 155         struct timer_of *to = to_timer_of(clkevt);
 156 
 157         stm32_timer_start(to);
 158 
 159         return 0;
 160 }
 161 
 162 static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 163 {
 164         struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
 165         struct timer_of *to = to_timer_of(clkevt);
 166 
 167         writel_relaxed(0, timer_of_base(to) + TIM_SR);
 168 
 169         if (clockevent_state_periodic(clkevt))
 170                 stm32_clock_event_set_periodic(clkevt);
 171         else
 172                 stm32_clock_event_shutdown(clkevt);
 173 
 174         clkevt->event_handler(clkevt);
 175 
 176         return IRQ_HANDLED;
 177 }
 178 
 179 /**
 180  * stm32_timer_width - Sort out the timer width (32/16)
 181  * @to: a pointer to a timer-of structure
 182  *
 183  * Write the 32-bit max value and read/return the result. If the timer
 184  * is 32 bits wide, the result will be UINT_MAX, otherwise it will
 185  * be truncated by the 16-bit register to USHRT_MAX.
 186  *
 187  */
 188 static void __init stm32_timer_set_width(struct timer_of *to)
 189 {
 190         u32 width;
 191 
 192         writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
 193 
 194         width = readl_relaxed(timer_of_base(to) + TIM_ARR);
 195 
 196         stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
 197 }
 198 
 199 /**
 200  * stm32_timer_set_prescaler - Compute and set the prescaler register
 201  * @to: a pointer to a timer-of structure
 202  *
 203  * Depending on the timer width, compute the prescaler to always
 204  * target a 10MHz timer rate for 16 bits. 32-bit timers are
 205  * considered precise and long enough to not use the prescaler.
 206  */
 207 static void __init stm32_timer_set_prescaler(struct timer_of *to)
 208 {
 209         int prescaler = 1;
 210 
 211         if (stm32_timer_of_bits_get(to) != 32) {
 212                 prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
 213                                               TIM_PSC_CLKRATE);
 214                 /*
 215                  * The prescaler register is an u16, the variable
 216                  * can't be greater than TIM_PSC_MAX, let's cap it in
 217                  * this case.
 218                  */
 219                 prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
 220         }
 221 
 222         writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
 223         writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
 224         writel_relaxed(0, timer_of_base(to) + TIM_SR);
 225 
 226         /* Adjust rate and period given the prescaler value */
 227         to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
 228         to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
 229 }
 230 
 231 static int __init stm32_clocksource_init(struct timer_of *to)
 232 {
 233         u32 bits = stm32_timer_of_bits_get(to);
 234         const char *name = to->np->full_name;
 235 
 236         /*
 237          * This driver allows to register several timers and relies on
 238          * the generic time framework to select the right one.
 239          * However, nothing allows to do the same for the
 240          * sched_clock. We are not interested in a sched_clock for the
 241          * 16-bit timers but only for the 32-bit one, so if no 32-bit
 242          * timer is registered yet, we select this 32-bit timer as a
 243          * sched_clock.
 244          */
 245         if (bits == 32 && !stm32_timer_cnt) {
 246 
 247                 /*
 248                  * Start immediately the counter as we will be using
 249                  * it right after.
 250                  */
 251                 stm32_timer_start(to);
 252 
 253                 stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
 254                 sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
 255                 pr_info("%s: STM32 sched_clock registered\n", name);
 256 
 257                 stm32_timer_delay.read_current_timer = stm32_read_delay;
 258                 stm32_timer_delay.freq = timer_of_rate(to);
 259                 register_current_timer_delay(&stm32_timer_delay);
 260                 pr_info("%s: STM32 delay timer registered\n", name);
 261         }
 262 
 263         return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
 264                                      timer_of_rate(to), bits == 32 ? 250 : 100,
 265                                      bits, clocksource_mmio_readl_up);
 266 }
 267 
 268 static void __init stm32_clockevent_init(struct timer_of *to)
 269 {
 270         u32 bits = stm32_timer_of_bits_get(to);
 271 
 272         to->clkevt.name = to->np->full_name;
 273         to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 274         to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
 275         to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
 276         to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
 277         to->clkevt.tick_resume = stm32_clock_event_shutdown;
 278         to->clkevt.set_next_event = stm32_clock_event_set_next_event;
 279         to->clkevt.rating = bits == 32 ? 250 : 100;
 280 
 281         clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
 282                                         (1 <<  bits) - 1);
 283 
 284         pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
 285                 to->np, bits);
 286 }
 287 
 288 static int __init stm32_timer_init(struct device_node *node)
 289 {
 290         struct reset_control *rstc;
 291         struct timer_of *to;
 292         int ret;
 293 
 294         to = kzalloc(sizeof(*to), GFP_KERNEL);
 295         if (!to)
 296                 return -ENOMEM;
 297 
 298         to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
 299         to->of_irq.handler = stm32_clock_event_handler;
 300 
 301         ret = timer_of_init(node, to);
 302         if (ret)
 303                 goto err;
 304 
 305         to->private_data = kzalloc(sizeof(struct stm32_timer_private),
 306                                    GFP_KERNEL);
 307         if (!to->private_data) {
 308                 ret = -ENOMEM;
 309                 goto deinit;
 310         }
 311 
 312         rstc = of_reset_control_get(node, NULL);
 313         if (!IS_ERR(rstc)) {
 314                 reset_control_assert(rstc);
 315                 reset_control_deassert(rstc);
 316         }
 317 
 318         stm32_timer_set_width(to);
 319 
 320         stm32_timer_set_prescaler(to);
 321 
 322         ret = stm32_clocksource_init(to);
 323         if (ret)
 324                 goto deinit;
 325 
 326         stm32_clockevent_init(to);
 327         return 0;
 328 
 329 deinit:
 330         timer_of_cleanup(to);
 331 err:
 332         kfree(to);
 333         return ret;
 334 }
 335 
 336 TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);

/* [<][>][^][v][top][bottom][index][help] */