linux/arch/arm/mach-at91/at91rm9200_time.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-at91/at91rm9200_time.c
   3 *
   4 *  Copyright (C) 2003 SAN People
   5 *  Copyright (C) 2003 ATMEL
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21
  22#include <linux/kernel.h>
  23#include <linux/interrupt.h>
  24#include <linux/irq.h>
  25#include <linux/clockchips.h>
  26
  27#include <asm/mach/time.h>
  28
  29#include <mach/at91_st.h>
  30
  31static unsigned long last_crtr;
  32static u32 irqmask;
  33static struct clock_event_device clkevt;
  34
  35/*
  36 * The ST_CRTR is updated asynchronously to the master clock ... but
  37 * the updates as seen by the CPU don't seem to be strictly monotonic.
  38 * Waiting until we read the same value twice avoids glitching.
  39 */
  40static inline unsigned long read_CRTR(void)
  41{
  42        unsigned long x1, x2;
  43
  44        x1 = at91_sys_read(AT91_ST_CRTR);
  45        do {
  46                x2 = at91_sys_read(AT91_ST_CRTR);
  47                if (x1 == x2)
  48                        break;
  49                x1 = x2;
  50        } while (1);
  51        return x1;
  52}
  53
  54/*
  55 * IRQ handler for the timer.
  56 */
  57static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
  58{
  59        u32     sr = at91_sys_read(AT91_ST_SR) & irqmask;
  60
  61        /* simulate "oneshot" timer with alarm */
  62        if (sr & AT91_ST_ALMS) {
  63                clkevt.event_handler(&clkevt);
  64                return IRQ_HANDLED;
  65        }
  66
  67        /* periodic mode should handle delayed ticks */
  68        if (sr & AT91_ST_PITS) {
  69                u32     crtr = read_CRTR();
  70
  71                while (((crtr - last_crtr) & AT91_ST_CRTV) >= LATCH) {
  72                        last_crtr += LATCH;
  73                        clkevt.event_handler(&clkevt);
  74                }
  75                return IRQ_HANDLED;
  76        }
  77
  78        /* this irq is shared ... */
  79        return IRQ_NONE;
  80}
  81
  82static struct irqaction at91rm9200_timer_irq = {
  83        .name           = "at91_tick",
  84        .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  85        .handler        = at91rm9200_timer_interrupt
  86};
  87
  88static cycle_t read_clk32k(void)
  89{
  90        return read_CRTR();
  91}
  92
  93static struct clocksource clk32k = {
  94        .name           = "32k_counter",
  95        .rating         = 150,
  96        .read           = read_clk32k,
  97        .mask           = CLOCKSOURCE_MASK(20),
  98        .shift          = 10,
  99        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 100};
 101
 102static void
 103clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 104{
 105        /* Disable and flush pending timer interrupts */
 106        at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
 107        (void) at91_sys_read(AT91_ST_SR);
 108
 109        last_crtr = read_CRTR();
 110        switch (mode) {
 111        case CLOCK_EVT_MODE_PERIODIC:
 112                /* PIT for periodic irqs; fixed rate of 1/HZ */
 113                irqmask = AT91_ST_PITS;
 114                at91_sys_write(AT91_ST_PIMR, LATCH);
 115                break;
 116        case CLOCK_EVT_MODE_ONESHOT:
 117                /* ALM for oneshot irqs, set by next_event()
 118                 * before 32 seconds have passed
 119                 */
 120                irqmask = AT91_ST_ALMS;
 121                at91_sys_write(AT91_ST_RTAR, last_crtr);
 122                break;
 123        case CLOCK_EVT_MODE_SHUTDOWN:
 124        case CLOCK_EVT_MODE_UNUSED:
 125        case CLOCK_EVT_MODE_RESUME:
 126                irqmask = 0;
 127                break;
 128        }
 129        at91_sys_write(AT91_ST_IER, irqmask);
 130}
 131
 132static int
 133clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 134{
 135        unsigned long   flags;
 136        u32             alm;
 137        int             status = 0;
 138
 139        BUG_ON(delta < 2);
 140
 141        /* Use "raw" primitives so we behave correctly on RT kernels. */
 142        raw_local_irq_save(flags);
 143
 144        /* The alarm IRQ uses absolute time (now+delta), not the relative
 145         * time (delta) in our calling convention.  Like all clockevents
 146         * using such "match" hardware, we have a race to defend against.
 147         *
 148         * Our defense here is to have set up the clockevent device so the
 149         * delta is at least two.  That way we never end up writing RTAR
 150         * with the value then held in CRTR ... which would mean the match
 151         * wouldn't trigger until 32 seconds later, after CRTR wraps.
 152         */
 153        alm = read_CRTR();
 154
 155        /* Cancel any pending alarm; flush any pending IRQ */
 156        at91_sys_write(AT91_ST_RTAR, alm);
 157        (void) at91_sys_read(AT91_ST_SR);
 158
 159        /* Schedule alarm by writing RTAR. */
 160        alm += delta;
 161        at91_sys_write(AT91_ST_RTAR, alm);
 162
 163        raw_local_irq_restore(flags);
 164        return status;
 165}
 166
 167static struct clock_event_device clkevt = {
 168        .name           = "at91_tick",
 169        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 170        .shift          = 32,
 171        .rating         = 150,
 172        .cpumask        = CPU_MASK_CPU0,
 173        .set_next_event = clkevt32k_next_event,
 174        .set_mode       = clkevt32k_mode,
 175};
 176
 177/*
 178 * ST (system timer) module supports both clockevents and clocksource.
 179 */
 180void __init at91rm9200_timer_init(void)
 181{
 182        /* Disable all timer interrupts, and clear any pending ones */
 183        at91_sys_write(AT91_ST_IDR,
 184                AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 185        (void) at91_sys_read(AT91_ST_SR);
 186
 187        /* Make IRQs happen for the system timer */
 188        setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
 189
 190        /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
 191         * directly for the clocksource and all clockevents, after adjusting
 192         * its prescaler from the 1 Hz default.
 193         */
 194        at91_sys_write(AT91_ST_RTMR, 1);
 195
 196        /* Setup timer clockevent, with minimum of two ticks (important!!) */
 197        clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
 198        clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
 199        clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
 200        clkevt.cpumask = cpumask_of_cpu(0);
 201        clockevents_register_device(&clkevt);
 202
 203        /* register clocksource */
 204        clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift);
 205        clocksource_register(&clk32k);
 206}
 207
 208struct sys_timer at91rm9200_timer = {
 209        .init           = at91rm9200_timer_init,
 210};
 211
 212