root/drivers/clocksource/timer-keystone.c

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

DEFINITIONS

This source file includes following definitions.
  1. keystone_timer_readl
  2. keystone_timer_writel
  3. keystone_timer_barrier
  4. keystone_timer_config
  5. keystone_timer_disable
  6. keystone_timer_interrupt
  7. keystone_set_next_event
  8. keystone_shutdown
  9. keystone_set_periodic
  10. keystone_timer_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Keystone broadcast clock-event
   4  *
   5  * Copyright 2013 Texas Instruments, Inc.
   6  *
   7  * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
   8  */
   9 
  10 #include <linux/clk.h>
  11 #include <linux/clockchips.h>
  12 #include <linux/clocksource.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/of_address.h>
  15 #include <linux/of_irq.h>
  16 
  17 #define TIMER_NAME                      "timer-keystone"
  18 
  19 /* Timer register offsets */
  20 #define TIM12                           0x10
  21 #define TIM34                           0x14
  22 #define PRD12                           0x18
  23 #define PRD34                           0x1c
  24 #define TCR                             0x20
  25 #define TGCR                            0x24
  26 #define INTCTLSTAT                      0x44
  27 
  28 /* Timer register bitfields */
  29 #define TCR_ENAMODE_MASK                0xC0
  30 #define TCR_ENAMODE_ONESHOT_MASK        0x40
  31 #define TCR_ENAMODE_PERIODIC_MASK       0x80
  32 
  33 #define TGCR_TIM_UNRESET_MASK           0x03
  34 #define INTCTLSTAT_ENINT_MASK           0x01
  35 
  36 /**
  37  * struct keystone_timer: holds timer's data
  38  * @base: timer memory base address
  39  * @hz_period: cycles per HZ period
  40  * @event_dev: event device based on timer
  41  */
  42 static struct keystone_timer {
  43         void __iomem *base;
  44         unsigned long hz_period;
  45         struct clock_event_device event_dev;
  46 } timer;
  47 
  48 static inline u32 keystone_timer_readl(unsigned long rg)
  49 {
  50         return readl_relaxed(timer.base + rg);
  51 }
  52 
  53 static inline void keystone_timer_writel(u32 val, unsigned long rg)
  54 {
  55         writel_relaxed(val, timer.base + rg);
  56 }
  57 
  58 /**
  59  * keystone_timer_barrier: write memory barrier
  60  * use explicit barrier to avoid using readl/writel non relaxed function
  61  * variants, because in our case non relaxed variants hide the true places
  62  * where barrier is needed.
  63  */
  64 static inline void keystone_timer_barrier(void)
  65 {
  66         __iowmb();
  67 }
  68 
  69 /**
  70  * keystone_timer_config: configures timer to work in oneshot/periodic modes.
  71  * @ mask: mask of the mode to configure
  72  * @ period: cycles number to configure for
  73  */
  74 static int keystone_timer_config(u64 period, int mask)
  75 {
  76         u32 tcr;
  77         u32 off;
  78 
  79         tcr = keystone_timer_readl(TCR);
  80         off = tcr & ~(TCR_ENAMODE_MASK);
  81 
  82         /* set enable mode */
  83         tcr |= mask;
  84 
  85         /* disable timer */
  86         keystone_timer_writel(off, TCR);
  87         /* here we have to be sure the timer has been disabled */
  88         keystone_timer_barrier();
  89 
  90         /* reset counter to zero, set new period */
  91         keystone_timer_writel(0, TIM12);
  92         keystone_timer_writel(0, TIM34);
  93         keystone_timer_writel(period & 0xffffffff, PRD12);
  94         keystone_timer_writel(period >> 32, PRD34);
  95 
  96         /*
  97          * enable timer
  98          * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
  99          * have been written.
 100          */
 101         keystone_timer_barrier();
 102         keystone_timer_writel(tcr, TCR);
 103         return 0;
 104 }
 105 
 106 static void keystone_timer_disable(void)
 107 {
 108         u32 tcr;
 109 
 110         tcr = keystone_timer_readl(TCR);
 111 
 112         /* disable timer */
 113         tcr &= ~(TCR_ENAMODE_MASK);
 114         keystone_timer_writel(tcr, TCR);
 115 }
 116 
 117 static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id)
 118 {
 119         struct clock_event_device *evt = dev_id;
 120 
 121         evt->event_handler(evt);
 122         return IRQ_HANDLED;
 123 }
 124 
 125 static int keystone_set_next_event(unsigned long cycles,
 126                                   struct clock_event_device *evt)
 127 {
 128         return keystone_timer_config(cycles, TCR_ENAMODE_ONESHOT_MASK);
 129 }
 130 
 131 static int keystone_shutdown(struct clock_event_device *evt)
 132 {
 133         keystone_timer_disable();
 134         return 0;
 135 }
 136 
 137 static int keystone_set_periodic(struct clock_event_device *evt)
 138 {
 139         keystone_timer_config(timer.hz_period, TCR_ENAMODE_PERIODIC_MASK);
 140         return 0;
 141 }
 142 
 143 static int __init keystone_timer_init(struct device_node *np)
 144 {
 145         struct clock_event_device *event_dev = &timer.event_dev;
 146         unsigned long rate;
 147         struct clk *clk;
 148         int irq, error;
 149 
 150         irq  = irq_of_parse_and_map(np, 0);
 151         if (!irq) {
 152                 pr_err("%s: failed to map interrupts\n", __func__);
 153                 return -EINVAL;
 154         }
 155 
 156         timer.base = of_iomap(np, 0);
 157         if (!timer.base) {
 158                 pr_err("%s: failed to map registers\n", __func__);
 159                 return -ENXIO;
 160         }
 161 
 162         clk = of_clk_get(np, 0);
 163         if (IS_ERR(clk)) {
 164                 pr_err("%s: failed to get clock\n", __func__);
 165                 iounmap(timer.base);
 166                 return PTR_ERR(clk);
 167         }
 168 
 169         error = clk_prepare_enable(clk);
 170         if (error) {
 171                 pr_err("%s: failed to enable clock\n", __func__);
 172                 goto err;
 173         }
 174 
 175         rate = clk_get_rate(clk);
 176 
 177         /* disable, use internal clock source */
 178         keystone_timer_writel(0, TCR);
 179         /* here we have to be sure the timer has been disabled */
 180         keystone_timer_barrier();
 181 
 182         /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
 183         keystone_timer_writel(0, TGCR);
 184 
 185         /* unreset timer */
 186         keystone_timer_writel(TGCR_TIM_UNRESET_MASK, TGCR);
 187 
 188         /* init counter to zero */
 189         keystone_timer_writel(0, TIM12);
 190         keystone_timer_writel(0, TIM34);
 191 
 192         timer.hz_period = DIV_ROUND_UP(rate, HZ);
 193 
 194         /* enable timer interrupts */
 195         keystone_timer_writel(INTCTLSTAT_ENINT_MASK, INTCTLSTAT);
 196 
 197         error = request_irq(irq, keystone_timer_interrupt, IRQF_TIMER,
 198                             TIMER_NAME, event_dev);
 199         if (error) {
 200                 pr_err("%s: failed to setup irq\n", __func__);
 201                 goto err;
 202         }
 203 
 204         /* setup clockevent */
 205         event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 206         event_dev->set_next_event = keystone_set_next_event;
 207         event_dev->set_state_shutdown = keystone_shutdown;
 208         event_dev->set_state_periodic = keystone_set_periodic;
 209         event_dev->set_state_oneshot = keystone_shutdown;
 210         event_dev->cpumask = cpu_possible_mask;
 211         event_dev->owner = THIS_MODULE;
 212         event_dev->name = TIMER_NAME;
 213         event_dev->irq = irq;
 214 
 215         clockevents_config_and_register(event_dev, rate, 1, ULONG_MAX);
 216 
 217         pr_info("keystone timer clock @%lu Hz\n", rate);
 218         return 0;
 219 err:
 220         clk_put(clk);
 221         iounmap(timer.base);
 222         return error;
 223 }
 224 
 225 TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",
 226                            keystone_timer_init);

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