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