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