linux/arch/arm/plat-mxc/time.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/plat-mxc/time.c
   3 *
   4 *  Copyright (C) 2000-2001 Deep Blue Solutions
   5 *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
   6 *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
   7 *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License
  11 * as published by the Free Software Foundation; either version 2
  12 * of the License, or (at your option) any later version.
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21 * MA 02110-1301, USA.
  22 */
  23
  24#include <linux/interrupt.h>
  25#include <linux/irq.h>
  26#include <linux/clockchips.h>
  27#include <linux/clk.h>
  28
  29#include <mach/hardware.h>
  30#include <asm/mach/time.h>
  31#include <mach/common.h>
  32
  33/* defines common for all i.MX */
  34#define MXC_TCTL                0x00
  35#define MXC_TCTL_TEN            (1 << 0)
  36#define MXC_TPRER               0x04
  37
  38/* MX1, MX21, MX27 */
  39#define MX1_2_TCTL_CLK_PCLK1    (1 << 1)
  40#define MX1_2_TCTL_IRQEN        (1 << 4)
  41#define MX1_2_TCTL_FRR          (1 << 8)
  42#define MX1_2_TCMP              0x08
  43#define MX1_2_TCN               0x10
  44#define MX1_2_TSTAT             0x14
  45
  46/* MX21, MX27 */
  47#define MX2_TSTAT_CAPT          (1 << 1)
  48#define MX2_TSTAT_COMP          (1 << 0)
  49
  50/* MX31, MX35, MX25, MXC91231 */
  51#define MX3_TCTL_WAITEN         (1 << 3)
  52#define MX3_TCTL_CLK_IPG        (1 << 6)
  53#define MX3_TCTL_FRR            (1 << 9)
  54#define MX3_IR                  0x0c
  55#define MX3_TSTAT               0x08
  56#define MX3_TSTAT_OF1           (1 << 0)
  57#define MX3_TCN                 0x24
  58#define MX3_TCMP                0x10
  59
  60static struct clock_event_device clockevent_mxc;
  61static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
  62
  63static void __iomem *timer_base;
  64
  65static inline void gpt_irq_disable(void)
  66{
  67        unsigned int tmp;
  68
  69        if (cpu_is_mx3() || cpu_is_mx25())
  70                __raw_writel(0, timer_base + MX3_IR);
  71        else {
  72                tmp = __raw_readl(timer_base + MXC_TCTL);
  73                __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
  74        }
  75}
  76
  77static inline void gpt_irq_enable(void)
  78{
  79        if (cpu_is_mx3() || cpu_is_mx25())
  80                __raw_writel(1<<0, timer_base + MX3_IR);
  81        else {
  82                __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
  83                        timer_base + MXC_TCTL);
  84        }
  85}
  86
  87static void gpt_irq_acknowledge(void)
  88{
  89        if (cpu_is_mx1())
  90                __raw_writel(0, timer_base + MX1_2_TSTAT);
  91        if (cpu_is_mx2())
  92                __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
  93        if (cpu_is_mx3() || cpu_is_mx25())
  94                __raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
  95}
  96
  97static cycle_t mx1_2_get_cycles(struct clocksource *cs)
  98{
  99        return __raw_readl(timer_base + MX1_2_TCN);
 100}
 101
 102static cycle_t mx3_get_cycles(struct clocksource *cs)
 103{
 104        return __raw_readl(timer_base + MX3_TCN);
 105}
 106
 107static struct clocksource clocksource_mxc = {
 108        .name           = "mxc_timer1",
 109        .rating         = 200,
 110        .read           = mx1_2_get_cycles,
 111        .mask           = CLOCKSOURCE_MASK(32),
 112        .shift          = 20,
 113        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 114};
 115
 116static int __init mxc_clocksource_init(struct clk *timer_clk)
 117{
 118        unsigned int c = clk_get_rate(timer_clk);
 119
 120        if (cpu_is_mx3() || cpu_is_mx25())
 121                clocksource_mxc.read = mx3_get_cycles;
 122
 123        clocksource_mxc.mult = clocksource_hz2mult(c,
 124                                        clocksource_mxc.shift);
 125        clocksource_register(&clocksource_mxc);
 126
 127        return 0;
 128}
 129
 130/* clock event */
 131
 132static int mx1_2_set_next_event(unsigned long evt,
 133                              struct clock_event_device *unused)
 134{
 135        unsigned long tcmp;
 136
 137        tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
 138
 139        __raw_writel(tcmp, timer_base + MX1_2_TCMP);
 140
 141        return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
 142                                -ETIME : 0;
 143}
 144
 145static int mx3_set_next_event(unsigned long evt,
 146                              struct clock_event_device *unused)
 147{
 148        unsigned long tcmp;
 149
 150        tcmp = __raw_readl(timer_base + MX3_TCN) + evt;
 151
 152        __raw_writel(tcmp, timer_base + MX3_TCMP);
 153
 154        return (int)(tcmp - __raw_readl(timer_base + MX3_TCN)) < 0 ?
 155                                -ETIME : 0;
 156}
 157
 158#ifdef DEBUG
 159static const char *clock_event_mode_label[] = {
 160        [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
 161        [CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
 162        [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
 163        [CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
 164};
 165#endif /* DEBUG */
 166
 167static void mxc_set_mode(enum clock_event_mode mode,
 168                                struct clock_event_device *evt)
 169{
 170        unsigned long flags;
 171
 172        /*
 173         * The timer interrupt generation is disabled at least
 174         * for enough time to call mxc_set_next_event()
 175         */
 176        local_irq_save(flags);
 177
 178        /* Disable interrupt in GPT module */
 179        gpt_irq_disable();
 180
 181        if (mode != clockevent_mode) {
 182                /* Set event time into far-far future */
 183                if (cpu_is_mx3() || cpu_is_mx25())
 184                        __raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
 185                                        timer_base + MX3_TCMP);
 186                else
 187                        __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
 188                                        timer_base + MX1_2_TCMP);
 189
 190                /* Clear pending interrupt */
 191                gpt_irq_acknowledge();
 192        }
 193
 194#ifdef DEBUG
 195        printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
 196                clock_event_mode_label[clockevent_mode],
 197                clock_event_mode_label[mode]);
 198#endif /* DEBUG */
 199
 200        /* Remember timer mode */
 201        clockevent_mode = mode;
 202        local_irq_restore(flags);
 203
 204        switch (mode) {
 205        case CLOCK_EVT_MODE_PERIODIC:
 206                printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
 207                                "supported for i.MX\n");
 208                break;
 209        case CLOCK_EVT_MODE_ONESHOT:
 210        /*
 211         * Do not put overhead of interrupt enable/disable into
 212         * mxc_set_next_event(), the core has about 4 minutes
 213         * to call mxc_set_next_event() or shutdown clock after
 214         * mode switching
 215         */
 216                local_irq_save(flags);
 217                gpt_irq_enable();
 218                local_irq_restore(flags);
 219                break;
 220        case CLOCK_EVT_MODE_SHUTDOWN:
 221        case CLOCK_EVT_MODE_UNUSED:
 222        case CLOCK_EVT_MODE_RESUME:
 223                /* Left event sources disabled, no more interrupts appear */
 224                break;
 225        }
 226}
 227
 228/*
 229 * IRQ handler for the timer
 230 */
 231static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 232{
 233        struct clock_event_device *evt = &clockevent_mxc;
 234        uint32_t tstat;
 235
 236        if (cpu_is_mx3() || cpu_is_mx25())
 237                tstat = __raw_readl(timer_base + MX3_TSTAT);
 238        else
 239                tstat = __raw_readl(timer_base + MX1_2_TSTAT);
 240
 241        gpt_irq_acknowledge();
 242
 243        evt->event_handler(evt);
 244
 245        return IRQ_HANDLED;
 246}
 247
 248static struct irqaction mxc_timer_irq = {
 249        .name           = "i.MX Timer Tick",
 250        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 251        .handler        = mxc_timer_interrupt,
 252};
 253
 254static struct clock_event_device clockevent_mxc = {
 255        .name           = "mxc_timer1",
 256        .features       = CLOCK_EVT_FEAT_ONESHOT,
 257        .shift          = 32,
 258        .set_mode       = mxc_set_mode,
 259        .set_next_event = mx1_2_set_next_event,
 260        .rating         = 200,
 261};
 262
 263static int __init mxc_clockevent_init(struct clk *timer_clk)
 264{
 265        unsigned int c = clk_get_rate(timer_clk);
 266
 267        if (cpu_is_mx3() || cpu_is_mx25())
 268                clockevent_mxc.set_next_event = mx3_set_next_event;
 269
 270        clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
 271                                        clockevent_mxc.shift);
 272        clockevent_mxc.max_delta_ns =
 273                        clockevent_delta2ns(0xfffffffe, &clockevent_mxc);
 274        clockevent_mxc.min_delta_ns =
 275                        clockevent_delta2ns(0xff, &clockevent_mxc);
 276
 277        clockevent_mxc.cpumask = cpumask_of(0);
 278
 279        clockevents_register_device(&clockevent_mxc);
 280
 281        return 0;
 282}
 283
 284void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
 285{
 286        uint32_t tctl_val;
 287
 288        clk_enable(timer_clk);
 289
 290        timer_base = base;
 291
 292        /*
 293         * Initialise to a known state (all timers off, and timing reset)
 294         */
 295
 296        __raw_writel(0, timer_base + MXC_TCTL);
 297        __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
 298
 299        if (cpu_is_mx3() || cpu_is_mx25())
 300                tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
 301        else
 302                tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
 303
 304        __raw_writel(tctl_val, timer_base + MXC_TCTL);
 305
 306        /* init and register the timer to the framework */
 307        mxc_clocksource_init(timer_clk);
 308        mxc_clockevent_init(timer_clk);
 309
 310        /* Make irqs happen */
 311        setup_irq(irq, &mxc_timer_irq);
 312}
 313