linux/arch/arm/mach-davinci/time.c
<<
>>
Prefs
   1/*
   2 * DaVinci timer subsystem
   3 *
   4 * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
   5 *
   6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
   7 * the terms of the GNU General Public License version 2. This program
   8 * is licensed "as is" without any warranty of any kind, whether express
   9 * or implied.
  10 */
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/types.h>
  14#include <linux/interrupt.h>
  15#include <linux/clocksource.h>
  16#include <linux/clockchips.h>
  17#include <linux/spinlock.h>
  18#include <linux/io.h>
  19#include <linux/clk.h>
  20#include <linux/err.h>
  21#include <linux/device.h>
  22#include <linux/platform_device.h>
  23
  24#include <mach/hardware.h>
  25#include <asm/system.h>
  26#include <asm/irq.h>
  27#include <asm/mach/irq.h>
  28#include <asm/mach/time.h>
  29#include <asm/errno.h>
  30#include <mach/io.h>
  31#include <mach/cputype.h>
  32#include <mach/time.h>
  33#include "clock.h"
  34
  35static struct clock_event_device clockevent_davinci;
  36static unsigned int davinci_clock_tick_rate;
  37
  38/*
  39 * This driver configures the 2 64-bit count-up timers as 4 independent
  40 * 32-bit count-up timers used as follows:
  41 */
  42
  43enum {
  44        TID_CLOCKEVENT,
  45        TID_CLOCKSOURCE,
  46};
  47
  48/* Timer register offsets */
  49#define PID12                   0x0
  50#define TIM12                   0x10
  51#define TIM34                   0x14
  52#define PRD12                   0x18
  53#define PRD34                   0x1c
  54#define TCR                     0x20
  55#define TGCR                    0x24
  56#define WDTCR                   0x28
  57
  58/* Offsets of the 8 compare registers */
  59#define CMP12_0                 0x60
  60#define CMP12_1                 0x64
  61#define CMP12_2                 0x68
  62#define CMP12_3                 0x6c
  63#define CMP12_4                 0x70
  64#define CMP12_5                 0x74
  65#define CMP12_6                 0x78
  66#define CMP12_7                 0x7c
  67
  68/* Timer register bitfields */
  69#define TCR_ENAMODE_DISABLE          0x0
  70#define TCR_ENAMODE_ONESHOT          0x1
  71#define TCR_ENAMODE_PERIODIC         0x2
  72#define TCR_ENAMODE_MASK             0x3
  73
  74#define TGCR_TIMMODE_SHIFT           2
  75#define TGCR_TIMMODE_64BIT_GP        0x0
  76#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
  77#define TGCR_TIMMODE_64BIT_WDOG      0x2
  78#define TGCR_TIMMODE_32BIT_CHAINED   0x3
  79
  80#define TGCR_TIM12RS_SHIFT           0
  81#define TGCR_TIM34RS_SHIFT           1
  82#define TGCR_RESET                   0x0
  83#define TGCR_UNRESET                 0x1
  84#define TGCR_RESET_MASK              0x3
  85
  86#define WDTCR_WDEN_SHIFT             14
  87#define WDTCR_WDEN_DISABLE           0x0
  88#define WDTCR_WDEN_ENABLE            0x1
  89#define WDTCR_WDKEY_SHIFT            16
  90#define WDTCR_WDKEY_SEQ0             0xa5c6
  91#define WDTCR_WDKEY_SEQ1             0xda7e
  92
  93struct timer_s {
  94        char *name;
  95        unsigned int id;
  96        unsigned long period;
  97        unsigned long opts;
  98        unsigned long flags;
  99        void __iomem *base;
 100        unsigned long tim_off;
 101        unsigned long prd_off;
 102        unsigned long enamode_shift;
 103        struct irqaction irqaction;
 104};
 105static struct timer_s timers[];
 106
 107/* values for 'opts' field of struct timer_s */
 108#define TIMER_OPTS_DISABLED             0x01
 109#define TIMER_OPTS_ONESHOT              0x02
 110#define TIMER_OPTS_PERIODIC             0x04
 111#define TIMER_OPTS_STATE_MASK           0x07
 112
 113#define TIMER_OPTS_USE_COMPARE          0x80000000
 114#define USING_COMPARE(t)                ((t)->opts & TIMER_OPTS_USE_COMPARE)
 115
 116static char *id_to_name[] = {
 117        [T0_BOT]        = "timer0_0",
 118        [T0_TOP]        = "timer0_1",
 119        [T1_BOT]        = "timer1_0",
 120        [T1_TOP]        = "timer1_1",
 121};
 122
 123static int timer32_config(struct timer_s *t)
 124{
 125        u32 tcr;
 126        struct davinci_soc_info *soc_info = &davinci_soc_info;
 127
 128        if (USING_COMPARE(t)) {
 129                struct davinci_timer_instance *dtip =
 130                                soc_info->timer_info->timers;
 131                int event_timer = ID_TO_TIMER(timers[TID_CLOCKEVENT].id);
 132
 133                /*
 134                 * Next interrupt should be the current time reg value plus
 135                 * the new period (using 32-bit unsigned addition/wrapping
 136                 * to 0 on overflow).  This assumes that the clocksource
 137                 * is setup to count to 2^32-1 before wrapping around to 0.
 138                 */
 139                __raw_writel(__raw_readl(t->base + t->tim_off) + t->period,
 140                        t->base + dtip[event_timer].cmp_off);
 141        } else {
 142                tcr = __raw_readl(t->base + TCR);
 143
 144                /* disable timer */
 145                tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
 146                __raw_writel(tcr, t->base + TCR);
 147
 148                /* reset counter to zero, set new period */
 149                __raw_writel(0, t->base + t->tim_off);
 150                __raw_writel(t->period, t->base + t->prd_off);
 151
 152                /* Set enable mode */
 153                if (t->opts & TIMER_OPTS_ONESHOT)
 154                        tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
 155                else if (t->opts & TIMER_OPTS_PERIODIC)
 156                        tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
 157
 158                __raw_writel(tcr, t->base + TCR);
 159        }
 160        return 0;
 161}
 162
 163static inline u32 timer32_read(struct timer_s *t)
 164{
 165        return __raw_readl(t->base + t->tim_off);
 166}
 167
 168static irqreturn_t timer_interrupt(int irq, void *dev_id)
 169{
 170        struct clock_event_device *evt = &clockevent_davinci;
 171
 172        evt->event_handler(evt);
 173        return IRQ_HANDLED;
 174}
 175
 176/* called when 32-bit counter wraps */
 177static irqreturn_t freerun_interrupt(int irq, void *dev_id)
 178{
 179        return IRQ_HANDLED;
 180}
 181
 182static struct timer_s timers[] = {
 183        [TID_CLOCKEVENT] = {
 184                .name      = "clockevent",
 185                .opts      = TIMER_OPTS_DISABLED,
 186                .irqaction = {
 187                        .flags   = IRQF_DISABLED | IRQF_TIMER,
 188                        .handler = timer_interrupt,
 189                }
 190        },
 191        [TID_CLOCKSOURCE] = {
 192                .name       = "free-run counter",
 193                .period     = ~0,
 194                .opts       = TIMER_OPTS_PERIODIC,
 195                .irqaction = {
 196                        .flags   = IRQF_DISABLED | IRQF_TIMER,
 197                        .handler = freerun_interrupt,
 198                }
 199        },
 200};
 201
 202static void __init timer_init(void)
 203{
 204        struct davinci_soc_info *soc_info = &davinci_soc_info;
 205        struct davinci_timer_instance *dtip = soc_info->timer_info->timers;
 206        int i;
 207
 208        /* Global init of each 64-bit timer as a whole */
 209        for(i=0; i<2; i++) {
 210                u32 tgcr;
 211                void __iomem *base = dtip[i].base;
 212
 213                /* Disabled, Internal clock source */
 214                __raw_writel(0, base + TCR);
 215
 216                /* reset both timers, no pre-scaler for timer34 */
 217                tgcr = 0;
 218                __raw_writel(tgcr, base + TGCR);
 219
 220                /* Set both timers to unchained 32-bit */
 221                tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
 222                __raw_writel(tgcr, base + TGCR);
 223
 224                /* Unreset timers */
 225                tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
 226                        (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
 227                __raw_writel(tgcr, base + TGCR);
 228
 229                /* Init both counters to zero */
 230                __raw_writel(0, base + TIM12);
 231                __raw_writel(0, base + TIM34);
 232        }
 233
 234        /* Init of each timer as a 32-bit timer */
 235        for (i=0; i< ARRAY_SIZE(timers); i++) {
 236                struct timer_s *t = &timers[i];
 237                int timer = ID_TO_TIMER(t->id);
 238                u32 irq;
 239
 240                t->base = dtip[timer].base;
 241
 242                if (IS_TIMER_BOT(t->id)) {
 243                        t->enamode_shift = 6;
 244                        t->tim_off = TIM12;
 245                        t->prd_off = PRD12;
 246                        irq = dtip[timer].bottom_irq;
 247                } else {
 248                        t->enamode_shift = 22;
 249                        t->tim_off = TIM34;
 250                        t->prd_off = PRD34;
 251                        irq = dtip[timer].top_irq;
 252                }
 253
 254                /* Register interrupt */
 255                t->irqaction.name = t->name;
 256                t->irqaction.dev_id = (void *)t;
 257
 258                if (t->irqaction.handler != NULL) {
 259                        irq = USING_COMPARE(t) ? dtip[i].cmp_irq : irq;
 260                        setup_irq(irq, &t->irqaction);
 261                }
 262
 263                timer32_config(&timers[i]);
 264        }
 265}
 266
 267/*
 268 * clocksource
 269 */
 270static cycle_t read_cycles(struct clocksource *cs)
 271{
 272        struct timer_s *t = &timers[TID_CLOCKSOURCE];
 273
 274        return (cycles_t)timer32_read(t);
 275}
 276
 277static struct clocksource clocksource_davinci = {
 278        .rating         = 300,
 279        .read           = read_cycles,
 280        .mask           = CLOCKSOURCE_MASK(32),
 281        .shift          = 24,
 282        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 283};
 284
 285/*
 286 * clockevent
 287 */
 288static int davinci_set_next_event(unsigned long cycles,
 289                                  struct clock_event_device *evt)
 290{
 291        struct timer_s *t = &timers[TID_CLOCKEVENT];
 292
 293        t->period = cycles;
 294        timer32_config(t);
 295        return 0;
 296}
 297
 298static void davinci_set_mode(enum clock_event_mode mode,
 299                             struct clock_event_device *evt)
 300{
 301        struct timer_s *t = &timers[TID_CLOCKEVENT];
 302
 303        switch (mode) {
 304        case CLOCK_EVT_MODE_PERIODIC:
 305                t->period = davinci_clock_tick_rate / (HZ);
 306                t->opts &= ~TIMER_OPTS_STATE_MASK;
 307                t->opts |= TIMER_OPTS_PERIODIC;
 308                timer32_config(t);
 309                break;
 310        case CLOCK_EVT_MODE_ONESHOT:
 311                t->opts &= ~TIMER_OPTS_STATE_MASK;
 312                t->opts |= TIMER_OPTS_ONESHOT;
 313                break;
 314        case CLOCK_EVT_MODE_UNUSED:
 315        case CLOCK_EVT_MODE_SHUTDOWN:
 316                t->opts &= ~TIMER_OPTS_STATE_MASK;
 317                t->opts |= TIMER_OPTS_DISABLED;
 318                break;
 319        case CLOCK_EVT_MODE_RESUME:
 320                break;
 321        }
 322}
 323
 324static struct clock_event_device clockevent_davinci = {
 325        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 326        .shift          = 32,
 327        .set_next_event = davinci_set_next_event,
 328        .set_mode       = davinci_set_mode,
 329};
 330
 331
 332static void __init davinci_timer_init(void)
 333{
 334        struct clk *timer_clk;
 335        struct davinci_soc_info *soc_info = &davinci_soc_info;
 336        unsigned int clockevent_id;
 337        unsigned int clocksource_id;
 338        static char err[] __initdata = KERN_ERR
 339                "%s: can't register clocksource!\n";
 340
 341        clockevent_id = soc_info->timer_info->clockevent_id;
 342        clocksource_id = soc_info->timer_info->clocksource_id;
 343
 344        timers[TID_CLOCKEVENT].id = clockevent_id;
 345        timers[TID_CLOCKSOURCE].id = clocksource_id;
 346
 347        /*
 348         * If using same timer for both clock events & clocksource,
 349         * a compare register must be used to generate an event interrupt.
 350         * This is equivalent to a oneshot timer only (not periodic).
 351         */
 352        if (clockevent_id == clocksource_id) {
 353                struct davinci_timer_instance *dtip =
 354                                soc_info->timer_info->timers;
 355                int event_timer = ID_TO_TIMER(clockevent_id);
 356
 357                /* Only bottom timers can use compare regs */
 358                if (IS_TIMER_TOP(clockevent_id))
 359                        pr_warning("davinci_timer_init: Invalid use"
 360                                " of system timers.  Results unpredictable.\n");
 361                else if ((dtip[event_timer].cmp_off == 0)
 362                                || (dtip[event_timer].cmp_irq == 0))
 363                        pr_warning("davinci_timer_init:  Invalid timer instance"
 364                                " setup.  Results unpredictable.\n");
 365                else {
 366                        timers[TID_CLOCKEVENT].opts |= TIMER_OPTS_USE_COMPARE;
 367                        clockevent_davinci.features = CLOCK_EVT_FEAT_ONESHOT;
 368                }
 369        }
 370
 371        /* init timer hw */
 372        timer_init();
 373
 374        timer_clk = clk_get(NULL, "timer0");
 375        BUG_ON(IS_ERR(timer_clk));
 376        clk_enable(timer_clk);
 377
 378        davinci_clock_tick_rate = clk_get_rate(timer_clk);
 379
 380        /* setup clocksource */
 381        clocksource_davinci.name = id_to_name[clocksource_id];
 382        clocksource_davinci.mult =
 383                clocksource_khz2mult(davinci_clock_tick_rate/1000,
 384                                     clocksource_davinci.shift);
 385        if (clocksource_register(&clocksource_davinci))
 386                printk(err, clocksource_davinci.name);
 387
 388        /* setup clockevent */
 389        clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
 390        clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
 391                                         clockevent_davinci.shift);
 392        clockevent_davinci.max_delta_ns =
 393                clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
 394        clockevent_davinci.min_delta_ns = 50000; /* 50 usec */
 395
 396        clockevent_davinci.cpumask = cpumask_of(0);
 397        clockevents_register_device(&clockevent_davinci);
 398}
 399
 400struct sys_timer davinci_timer = {
 401        .init   = davinci_timer_init,
 402};
 403
 404
 405/* reset board using watchdog timer */
 406void davinci_watchdog_reset(void)
 407{
 408        u32 tgcr, wdtcr;
 409        struct platform_device *pdev = &davinci_wdt_device;
 410        void __iomem *base = IO_ADDRESS(pdev->resource[0].start);
 411        struct clk *wd_clk;
 412
 413        wd_clk = clk_get(&pdev->dev, NULL);
 414        if (WARN_ON(IS_ERR(wd_clk)))
 415                return;
 416        clk_enable(wd_clk);
 417
 418        /* disable, internal clock source */
 419        __raw_writel(0, base + TCR);
 420
 421        /* reset timer, set mode to 64-bit watchdog, and unreset */
 422        tgcr = 0;
 423        __raw_writel(tgcr, base + TGCR);
 424        tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
 425        tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
 426                (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
 427        __raw_writel(tgcr, base + TGCR);
 428
 429        /* clear counter and period regs */
 430        __raw_writel(0, base + TIM12);
 431        __raw_writel(0, base + TIM34);
 432        __raw_writel(0, base + PRD12);
 433        __raw_writel(0, base + PRD34);
 434
 435        /* put watchdog in pre-active state */
 436        wdtcr = __raw_readl(base + WDTCR);
 437        wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
 438                (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
 439        __raw_writel(wdtcr, base + WDTCR);
 440
 441        /* put watchdog in active state */
 442        wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
 443                (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
 444        __raw_writel(wdtcr, base + WDTCR);
 445
 446        /* write an invalid value to the WDKEY field to trigger
 447         * a watchdog reset */
 448        wdtcr = 0x00004000;
 449        __raw_writel(wdtcr, base + WDTCR);
 450}
 451