root/drivers/clocksource/arm_global_timer.c

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

DEFINITIONS

This source file includes following definitions.
  1. _gt_counter_read
  2. gt_counter_read
  3. gt_compare_set
  4. gt_clockevent_shutdown
  5. gt_clockevent_set_periodic
  6. gt_clockevent_set_next_event
  7. gt_clockevent_interrupt
  8. gt_starting_cpu
  9. gt_dying_cpu
  10. gt_clocksource_read
  11. gt_resume
  12. gt_sched_clock_read
  13. gt_read_long
  14. gt_delay_timer_init
  15. gt_clocksource_init
  16. global_timer_of_register

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * drivers/clocksource/arm_global_timer.c
   4  *
   5  * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
   6  * Author: Stuart Menefy <stuart.menefy@st.com>
   7  * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
   8  */
   9 
  10 #include <linux/init.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/clocksource.h>
  13 #include <linux/clockchips.h>
  14 #include <linux/cpu.h>
  15 #include <linux/clk.h>
  16 #include <linux/delay.h>
  17 #include <linux/err.h>
  18 #include <linux/io.h>
  19 #include <linux/of.h>
  20 #include <linux/of_irq.h>
  21 #include <linux/of_address.h>
  22 #include <linux/sched_clock.h>
  23 
  24 #include <asm/cputype.h>
  25 
  26 #define GT_COUNTER0     0x00
  27 #define GT_COUNTER1     0x04
  28 
  29 #define GT_CONTROL      0x08
  30 #define GT_CONTROL_TIMER_ENABLE         BIT(0)  /* this bit is NOT banked */
  31 #define GT_CONTROL_COMP_ENABLE          BIT(1)  /* banked */
  32 #define GT_CONTROL_IRQ_ENABLE           BIT(2)  /* banked */
  33 #define GT_CONTROL_AUTO_INC             BIT(3)  /* banked */
  34 
  35 #define GT_INT_STATUS   0x0c
  36 #define GT_INT_STATUS_EVENT_FLAG        BIT(0)
  37 
  38 #define GT_COMP0        0x10
  39 #define GT_COMP1        0x14
  40 #define GT_AUTO_INC     0x18
  41 
  42 /*
  43  * We are expecting to be clocked by the ARM peripheral clock.
  44  *
  45  * Note: it is assumed we are using a prescaler value of zero, so this is
  46  * the units for all operations.
  47  */
  48 static void __iomem *gt_base;
  49 static unsigned long gt_clk_rate;
  50 static int gt_ppi;
  51 static struct clock_event_device __percpu *gt_evt;
  52 
  53 /*
  54  * To get the value from the Global Timer Counter register proceed as follows:
  55  * 1. Read the upper 32-bit timer counter register
  56  * 2. Read the lower 32-bit timer counter register
  57  * 3. Read the upper 32-bit timer counter register again. If the value is
  58  *  different to the 32-bit upper value read previously, go back to step 2.
  59  *  Otherwise the 64-bit timer counter value is correct.
  60  */
  61 static u64 notrace _gt_counter_read(void)
  62 {
  63         u64 counter;
  64         u32 lower;
  65         u32 upper, old_upper;
  66 
  67         upper = readl_relaxed(gt_base + GT_COUNTER1);
  68         do {
  69                 old_upper = upper;
  70                 lower = readl_relaxed(gt_base + GT_COUNTER0);
  71                 upper = readl_relaxed(gt_base + GT_COUNTER1);
  72         } while (upper != old_upper);
  73 
  74         counter = upper;
  75         counter <<= 32;
  76         counter |= lower;
  77         return counter;
  78 }
  79 
  80 static u64 gt_counter_read(void)
  81 {
  82         return _gt_counter_read();
  83 }
  84 
  85 /**
  86  * To ensure that updates to comparator value register do not set the
  87  * Interrupt Status Register proceed as follows:
  88  * 1. Clear the Comp Enable bit in the Timer Control Register.
  89  * 2. Write the lower 32-bit Comparator Value Register.
  90  * 3. Write the upper 32-bit Comparator Value Register.
  91  * 4. Set the Comp Enable bit and, if necessary, the IRQ enable bit.
  92  */
  93 static void gt_compare_set(unsigned long delta, int periodic)
  94 {
  95         u64 counter = gt_counter_read();
  96         unsigned long ctrl;
  97 
  98         counter += delta;
  99         ctrl = GT_CONTROL_TIMER_ENABLE;
 100         writel_relaxed(ctrl, gt_base + GT_CONTROL);
 101         writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0);
 102         writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1);
 103 
 104         if (periodic) {
 105                 writel_relaxed(delta, gt_base + GT_AUTO_INC);
 106                 ctrl |= GT_CONTROL_AUTO_INC;
 107         }
 108 
 109         ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
 110         writel_relaxed(ctrl, gt_base + GT_CONTROL);
 111 }
 112 
 113 static int gt_clockevent_shutdown(struct clock_event_device *evt)
 114 {
 115         unsigned long ctrl;
 116 
 117         ctrl = readl(gt_base + GT_CONTROL);
 118         ctrl &= ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE |
 119                   GT_CONTROL_AUTO_INC);
 120         writel(ctrl, gt_base + GT_CONTROL);
 121         return 0;
 122 }
 123 
 124 static int gt_clockevent_set_periodic(struct clock_event_device *evt)
 125 {
 126         gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
 127         return 0;
 128 }
 129 
 130 static int gt_clockevent_set_next_event(unsigned long evt,
 131                                         struct clock_event_device *unused)
 132 {
 133         gt_compare_set(evt, 0);
 134         return 0;
 135 }
 136 
 137 static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
 138 {
 139         struct clock_event_device *evt = dev_id;
 140 
 141         if (!(readl_relaxed(gt_base + GT_INT_STATUS) &
 142                                 GT_INT_STATUS_EVENT_FLAG))
 143                 return IRQ_NONE;
 144 
 145         /**
 146          * ERRATA 740657( Global Timer can send 2 interrupts for
 147          * the same event in single-shot mode)
 148          * Workaround:
 149          *      Either disable single-shot mode.
 150          *      Or
 151          *      Modify the Interrupt Handler to avoid the
 152          *      offending sequence. This is achieved by clearing
 153          *      the Global Timer flag _after_ having incremented
 154          *      the Comparator register value to a higher value.
 155          */
 156         if (clockevent_state_oneshot(evt))
 157                 gt_compare_set(ULONG_MAX, 0);
 158 
 159         writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
 160         evt->event_handler(evt);
 161 
 162         return IRQ_HANDLED;
 163 }
 164 
 165 static int gt_starting_cpu(unsigned int cpu)
 166 {
 167         struct clock_event_device *clk = this_cpu_ptr(gt_evt);
 168 
 169         clk->name = "arm_global_timer";
 170         clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
 171                 CLOCK_EVT_FEAT_PERCPU;
 172         clk->set_state_shutdown = gt_clockevent_shutdown;
 173         clk->set_state_periodic = gt_clockevent_set_periodic;
 174         clk->set_state_oneshot = gt_clockevent_shutdown;
 175         clk->set_state_oneshot_stopped = gt_clockevent_shutdown;
 176         clk->set_next_event = gt_clockevent_set_next_event;
 177         clk->cpumask = cpumask_of(cpu);
 178         clk->rating = 300;
 179         clk->irq = gt_ppi;
 180         clockevents_config_and_register(clk, gt_clk_rate,
 181                                         1, 0xffffffff);
 182         enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
 183         return 0;
 184 }
 185 
 186 static int gt_dying_cpu(unsigned int cpu)
 187 {
 188         struct clock_event_device *clk = this_cpu_ptr(gt_evt);
 189 
 190         gt_clockevent_shutdown(clk);
 191         disable_percpu_irq(clk->irq);
 192         return 0;
 193 }
 194 
 195 static u64 gt_clocksource_read(struct clocksource *cs)
 196 {
 197         return gt_counter_read();
 198 }
 199 
 200 static void gt_resume(struct clocksource *cs)
 201 {
 202         unsigned long ctrl;
 203 
 204         ctrl = readl(gt_base + GT_CONTROL);
 205         if (!(ctrl & GT_CONTROL_TIMER_ENABLE))
 206                 /* re-enable timer on resume */
 207                 writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 208 }
 209 
 210 static struct clocksource gt_clocksource = {
 211         .name   = "arm_global_timer",
 212         .rating = 300,
 213         .read   = gt_clocksource_read,
 214         .mask   = CLOCKSOURCE_MASK(64),
 215         .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 216         .resume = gt_resume,
 217 };
 218 
 219 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 220 static u64 notrace gt_sched_clock_read(void)
 221 {
 222         return _gt_counter_read();
 223 }
 224 #endif
 225 
 226 static unsigned long gt_read_long(void)
 227 {
 228         return readl_relaxed(gt_base + GT_COUNTER0);
 229 }
 230 
 231 static struct delay_timer gt_delay_timer = {
 232         .read_current_timer = gt_read_long,
 233 };
 234 
 235 static void __init gt_delay_timer_init(void)
 236 {
 237         gt_delay_timer.freq = gt_clk_rate;
 238         register_current_timer_delay(&gt_delay_timer);
 239 }
 240 
 241 static int __init gt_clocksource_init(void)
 242 {
 243         writel(0, gt_base + GT_CONTROL);
 244         writel(0, gt_base + GT_COUNTER0);
 245         writel(0, gt_base + GT_COUNTER1);
 246         /* enables timer on all the cores */
 247         writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 248 
 249 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 250         sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate);
 251 #endif
 252         return clocksource_register_hz(&gt_clocksource, gt_clk_rate);
 253 }
 254 
 255 static int __init global_timer_of_register(struct device_node *np)
 256 {
 257         struct clk *gt_clk;
 258         int err = 0;
 259 
 260         /*
 261          * In A9 r2p0 the comparators for each processor with the global timer
 262          * fire when the timer value is greater than or equal to. In previous
 263          * revisions the comparators fired when the timer value was equal to.
 264          */
 265         if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9
 266             && (read_cpuid_id() & 0xf0000f) < 0x200000) {
 267                 pr_warn("global-timer: non support for this cpu version.\n");
 268                 return -ENOSYS;
 269         }
 270 
 271         gt_ppi = irq_of_parse_and_map(np, 0);
 272         if (!gt_ppi) {
 273                 pr_warn("global-timer: unable to parse irq\n");
 274                 return -EINVAL;
 275         }
 276 
 277         gt_base = of_iomap(np, 0);
 278         if (!gt_base) {
 279                 pr_warn("global-timer: invalid base address\n");
 280                 return -ENXIO;
 281         }
 282 
 283         gt_clk = of_clk_get(np, 0);
 284         if (!IS_ERR(gt_clk)) {
 285                 err = clk_prepare_enable(gt_clk);
 286                 if (err)
 287                         goto out_unmap;
 288         } else {
 289                 pr_warn("global-timer: clk not found\n");
 290                 err = -EINVAL;
 291                 goto out_unmap;
 292         }
 293 
 294         gt_clk_rate = clk_get_rate(gt_clk);
 295         gt_evt = alloc_percpu(struct clock_event_device);
 296         if (!gt_evt) {
 297                 pr_warn("global-timer: can't allocate memory\n");
 298                 err = -ENOMEM;
 299                 goto out_clk;
 300         }
 301 
 302         err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt,
 303                                  "gt", gt_evt);
 304         if (err) {
 305                 pr_warn("global-timer: can't register interrupt %d (%d)\n",
 306                         gt_ppi, err);
 307                 goto out_free;
 308         }
 309 
 310         /* Register and immediately configure the timer on the boot CPU */
 311         err = gt_clocksource_init();
 312         if (err)
 313                 goto out_irq;
 314         
 315         err = cpuhp_setup_state(CPUHP_AP_ARM_GLOBAL_TIMER_STARTING,
 316                                 "clockevents/arm/global_timer:starting",
 317                                 gt_starting_cpu, gt_dying_cpu);
 318         if (err)
 319                 goto out_irq;
 320 
 321         gt_delay_timer_init();
 322 
 323         return 0;
 324 
 325 out_irq:
 326         free_percpu_irq(gt_ppi, gt_evt);
 327 out_free:
 328         free_percpu(gt_evt);
 329 out_clk:
 330         clk_disable_unprepare(gt_clk);
 331 out_unmap:
 332         iounmap(gt_base);
 333         WARN(err, "ARM Global timer register failed (%d)\n", err);
 334 
 335         return err;
 336 }
 337 
 338 /* Only tested on r2p2 and r3p0  */
 339 TIMER_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
 340                         global_timer_of_register);

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