linux/drivers/clocksource/timer-keystone.c
<<
>>
Prefs
   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 */
  42static struct keystone_timer {
  43        void __iomem *base;
  44        unsigned long hz_period;
  45        struct clock_event_device event_dev;
  46} timer;
  47
  48static inline u32 keystone_timer_readl(unsigned long rg)
  49{
  50        return readl_relaxed(timer.base + rg);
  51}
  52
  53static 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 */
  64static 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 */
  74static 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
 106static 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
 117static 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
 125static 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
 131static int keystone_shutdown(struct clock_event_device *evt)
 132{
 133        keystone_timer_disable();
 134        return 0;
 135}
 136
 137static 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
 143static 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;
 219err:
 220        clk_put(clk);
 221        iounmap(timer.base);
 222        return error;
 223}
 224
 225TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",
 226                           keystone_timer_init);
 227