~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/arm/mach-at91/at91rm9200_time.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
31
static unsigned long last_crtr;
 
32
static u32 irqmask;
 
33
static 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
 */
 
40
static 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
 */
 
57
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 
58
{
 
59
        u32     sr = at91_sys_read(AT91_ST_SR) & irqmask;
 
60
 
 
61
        /*
 
62
         * irqs should be disabled here, but as the irq is shared they are only
 
63
         * guaranteed to be off if the timer irq is registered first.
 
64
         */
 
65
        WARN_ON_ONCE(!irqs_disabled());
 
66
 
 
67
        /* simulate "oneshot" timer with alarm */
 
68
        if (sr & AT91_ST_ALMS) {
 
69
                clkevt.event_handler(&clkevt);
 
70
                return IRQ_HANDLED;
 
71
        }
 
72
 
 
73
        /* periodic mode should handle delayed ticks */
 
74
        if (sr & AT91_ST_PITS) {
 
75
                u32     crtr = read_CRTR();
 
76
 
 
77
                while (((crtr - last_crtr) & AT91_ST_CRTV) >= LATCH) {
 
78
                        last_crtr += LATCH;
 
79
                        clkevt.event_handler(&clkevt);
 
80
                }
 
81
                return IRQ_HANDLED;
 
82
        }
 
83
 
 
84
        /* this irq is shared ... */
 
85
        return IRQ_NONE;
 
86
}
 
87
 
 
88
static struct irqaction at91rm9200_timer_irq = {
 
89
        .name           = "at91_tick",
 
90
        .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 
91
        .handler        = at91rm9200_timer_interrupt
 
92
};
 
93
 
 
94
static cycle_t read_clk32k(struct clocksource *cs)
 
95
{
 
96
        return read_CRTR();
 
97
}
 
98
 
 
99
static struct clocksource clk32k = {
 
100
        .name           = "32k_counter",
 
101
        .rating         = 150,
 
102
        .read           = read_clk32k,
 
103
        .mask           = CLOCKSOURCE_MASK(20),
 
104
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 
105
};
 
106
 
 
107
static void
 
108
clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 
109
{
 
110
        /* Disable and flush pending timer interrupts */
 
111
        at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
 
112
        (void) at91_sys_read(AT91_ST_SR);
 
113
 
 
114
        last_crtr = read_CRTR();
 
115
        switch (mode) {
 
116
        case CLOCK_EVT_MODE_PERIODIC:
 
117
                /* PIT for periodic irqs; fixed rate of 1/HZ */
 
118
                irqmask = AT91_ST_PITS;
 
119
                at91_sys_write(AT91_ST_PIMR, LATCH);
 
120
                break;
 
121
        case CLOCK_EVT_MODE_ONESHOT:
 
122
                /* ALM for oneshot irqs, set by next_event()
 
123
                 * before 32 seconds have passed
 
124
                 */
 
125
                irqmask = AT91_ST_ALMS;
 
126
                at91_sys_write(AT91_ST_RTAR, last_crtr);
 
127
                break;
 
128
        case CLOCK_EVT_MODE_SHUTDOWN:
 
129
        case CLOCK_EVT_MODE_UNUSED:
 
130
        case CLOCK_EVT_MODE_RESUME:
 
131
                irqmask = 0;
 
132
                break;
 
133
        }
 
134
        at91_sys_write(AT91_ST_IER, irqmask);
 
135
}
 
136
 
 
137
static int
 
138
clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 
139
{
 
140
        u32             alm;
 
141
        int             status = 0;
 
142
 
 
143
        BUG_ON(delta < 2);
 
144
 
 
145
        /* The alarm IRQ uses absolute time (now+delta), not the relative
 
146
         * time (delta) in our calling convention.  Like all clockevents
 
147
         * using such "match" hardware, we have a race to defend against.
 
148
         *
 
149
         * Our defense here is to have set up the clockevent device so the
 
150
         * delta is at least two.  That way we never end up writing RTAR
 
151
         * with the value then held in CRTR ... which would mean the match
 
152
         * wouldn't trigger until 32 seconds later, after CRTR wraps.
 
153
         */
 
154
        alm = read_CRTR();
 
155
 
 
156
        /* Cancel any pending alarm; flush any pending IRQ */
 
157
        at91_sys_write(AT91_ST_RTAR, alm);
 
158
        (void) at91_sys_read(AT91_ST_SR);
 
159
 
 
160
        /* Schedule alarm by writing RTAR. */
 
161
        alm += delta;
 
162
        at91_sys_write(AT91_ST_RTAR, alm);
 
163
 
 
164
        return status;
 
165
}
 
166
 
 
167
static 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
        .set_next_event = clkevt32k_next_event,
 
173
        .set_mode       = clkevt32k_mode,
 
174
};
 
175
 
 
176
/*
 
177
 * ST (system timer) module supports both clockevents and clocksource.
 
178
 */
 
179
void __init at91rm9200_timer_init(void)
 
180
{
 
181
        /* Disable all timer interrupts, and clear any pending ones */
 
182
        at91_sys_write(AT91_ST_IDR,
 
183
                AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 
184
        (void) at91_sys_read(AT91_ST_SR);
 
185
 
 
186
        /* Make IRQs happen for the system timer */
 
187
        setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
 
188
 
 
189
        /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
 
190
         * directly for the clocksource and all clockevents, after adjusting
 
191
         * its prescaler from the 1 Hz default.
 
192
         */
 
193
        at91_sys_write(AT91_ST_RTMR, 1);
 
194
 
 
195
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
 
196
        clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
 
197
        clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
 
198
        clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
 
199
        clkevt.cpumask = cpumask_of(0);
 
200
        clockevents_register_device(&clkevt);
 
201
 
 
202
        /* register clocksource */
 
203
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
 
204
}
 
205
 
 
206
struct sys_timer at91rm9200_timer = {
 
207
        .init           = at91rm9200_timer_init,
 
208
};
 
209