Blame view

arch/arm/mach-at91/at91rm9200_time.c 5.7 KB
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
1
  /*
9d0412680   Andrew Victor   [ARM] 4124/1: Ren...
2
   * linux/arch/arm/mach-at91/at91rm9200_time.c
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   *
   *  Copyright (C) 2003 SAN People
   *  Copyright (C) 2003 ATMEL
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
5e802dfab   David Brownell   [ARM] 4539/1: clo...
21
  #include <linux/kernel.h>
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
22
  #include <linux/interrupt.h>
07d265dd5   Thomas Gleixner   [ARM] 3683/2: AR...
23
  #include <linux/irq.h>
5e802dfab   David Brownell   [ARM] 4539/1: clo...
24
  #include <linux/clockchips.h>
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
25

73a59c1c4   SAN People   [ARM] 3240/2: AT9...
26
  #include <asm/mach/time.h>
a09e64fbc   Russell King   [ARM] Move includ...
27
  #include <mach/at91_st.h>
55d8baee4   Andrew Victor   [ARM] 3954/1: AT9...
28

963151f24   Andrew Victor   [ARM] 3579/1: AT9...
29
  static unsigned long last_crtr;
5e802dfab   David Brownell   [ARM] 4539/1: clo...
30
31
  static u32 irqmask;
  static struct clock_event_device clkevt;
963151f24   Andrew Victor   [ARM] 3579/1: AT9...
32

2f5893cf4   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: define...
33
  #define RM9200_TIMER_LATCH	((AT91_SLOW_CLOCK + HZ/2) / HZ)
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
34
  /*
5e802dfab   David Brownell   [ARM] 4539/1: clo...
35
36
37
   * The ST_CRTR is updated asynchronously to the master clock ... but
   * the updates as seen by the CPU don't seem to be strictly monotonic.
   * Waiting until we read the same value twice avoids glitching.
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
38
   */
5e802dfab   David Brownell   [ARM] 4539/1: clo...
39
40
  static inline unsigned long read_CRTR(void)
  {
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
41
  	unsigned long x1, x2;
5e802dfab   David Brownell   [ARM] 4539/1: clo...
42
  	x1 = at91_sys_read(AT91_ST_CRTR);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
43
  	do {
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
44
  		x2 = at91_sys_read(AT91_ST_CRTR);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
45
46
47
48
  		if (x1 == x2)
  			break;
  		x1 = x2;
  	} while (1);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
49
50
51
52
  	return x1;
  }
  
  /*
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
53
54
   * IRQ handler for the timer.
   */
0cd61b68c   Linus Torvalds   Initial blind fix...
55
  static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
56
  {
5e802dfab   David Brownell   [ARM] 4539/1: clo...
57
  	u32	sr = at91_sys_read(AT91_ST_SR) & irqmask;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
58

501d70383   Uwe Kleine-König   arm/at91: Don't d...
59
60
61
62
63
  	/*
  	 * irqs should be disabled here, but as the irq is shared they are only
  	 * guaranteed to be off if the timer irq is registered first.
  	 */
  	WARN_ON_ONCE(!irqs_disabled());
5e802dfab   David Brownell   [ARM] 4539/1: clo...
64
65
66
67
68
  	/* simulate "oneshot" timer with alarm */
  	if (sr & AT91_ST_ALMS) {
  		clkevt.event_handler(&clkevt);
  		return IRQ_HANDLED;
  	}
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
69

5e802dfab   David Brownell   [ARM] 4539/1: clo...
70
71
72
  	/* periodic mode should handle delayed ticks */
  	if (sr & AT91_ST_PITS) {
  		u32	crtr = read_CRTR();
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
73

2f5893cf4   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: define...
74
75
  		while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) {
  			last_crtr += RM9200_TIMER_LATCH;
5e802dfab   David Brownell   [ARM] 4539/1: clo...
76
77
  			clkevt.event_handler(&clkevt);
  		}
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
78
79
  		return IRQ_HANDLED;
  	}
5e802dfab   David Brownell   [ARM] 4539/1: clo...
80
81
82
  
  	/* this irq is shared ... */
  	return IRQ_NONE;
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
83
84
85
86
  }
  
  static struct irqaction at91rm9200_timer_irq = {
  	.name		= "at91_tick",
b30fabada   Bernhard Walle   Add IRQF_IRQPOLL ...
87
  	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
88
89
  	.handler	= at91rm9200_timer_interrupt
  };
8e19608e8   Magnus Damm   clocksource: pass...
90
  static cycle_t read_clk32k(struct clocksource *cs)
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
91
  {
5e802dfab   David Brownell   [ARM] 4539/1: clo...
92
93
  	return read_CRTR();
  }
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
94

5e802dfab   David Brownell   [ARM] 4539/1: clo...
95
96
97
98
99
  static struct clocksource clk32k = {
  	.name		= "32k_counter",
  	.rating		= 150,
  	.read		= read_clk32k,
  	.mask		= CLOCKSOURCE_MASK(20),
5e802dfab   David Brownell   [ARM] 4539/1: clo...
100
101
102
103
104
105
106
107
108
  	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
  };
  
  static void
  clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
  {
  	/* Disable and flush pending timer interrupts */
  	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
  	(void) at91_sys_read(AT91_ST_SR);
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
109

5e802dfab   David Brownell   [ARM] 4539/1: clo...
110
111
112
113
114
  	last_crtr = read_CRTR();
  	switch (mode) {
  	case CLOCK_EVT_MODE_PERIODIC:
  		/* PIT for periodic irqs; fixed rate of 1/HZ */
  		irqmask = AT91_ST_PITS;
2f5893cf4   Jean-Christophe PLAGNIOL-VILLARD   ARM: at91: define...
115
  		at91_sys_write(AT91_ST_PIMR, RM9200_TIMER_LATCH);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  		break;
  	case CLOCK_EVT_MODE_ONESHOT:
  		/* ALM for oneshot irqs, set by next_event()
  		 * before 32 seconds have passed
  		 */
  		irqmask = AT91_ST_ALMS;
  		at91_sys_write(AT91_ST_RTAR, last_crtr);
  		break;
  	case CLOCK_EVT_MODE_SHUTDOWN:
  	case CLOCK_EVT_MODE_UNUSED:
  	case CLOCK_EVT_MODE_RESUME:
  		irqmask = 0;
  		break;
  	}
  	at91_sys_write(AT91_ST_IER, irqmask);
  }
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
132

5e802dfab   David Brownell   [ARM] 4539/1: clo...
133
134
135
  static int
  clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
  {
5e802dfab   David Brownell   [ARM] 4539/1: clo...
136
137
138
139
  	u32		alm;
  	int		status = 0;
  
  	BUG_ON(delta < 2);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
140
141
142
143
144
145
146
147
148
149
150
151
152
  	/* The alarm IRQ uses absolute time (now+delta), not the relative
  	 * time (delta) in our calling convention.  Like all clockevents
  	 * using such "match" hardware, we have a race to defend against.
  	 *
  	 * Our defense here is to have set up the clockevent device so the
  	 * delta is at least two.  That way we never end up writing RTAR
  	 * with the value then held in CRTR ... which would mean the match
  	 * wouldn't trigger until 32 seconds later, after CRTR wraps.
  	 */
  	alm = read_CRTR();
  
  	/* Cancel any pending alarm; flush any pending IRQ */
  	at91_sys_write(AT91_ST_RTAR, alm);
d100f2595   Andrew Victor   [ARM] 3955/1: AT9...
153
  	(void) at91_sys_read(AT91_ST_SR);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
154
155
156
  	/* Schedule alarm by writing RTAR. */
  	alm += delta;
  	at91_sys_write(AT91_ST_RTAR, alm);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
157
  	return status;
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
158
  }
5e802dfab   David Brownell   [ARM] 4539/1: clo...
159
160
161
162
163
  static struct clock_event_device clkevt = {
  	.name		= "at91_tick",
  	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  	.shift		= 32,
  	.rating		= 150,
5e802dfab   David Brownell   [ARM] 4539/1: clo...
164
165
166
  	.set_next_event	= clkevt32k_next_event,
  	.set_mode	= clkevt32k_mode,
  };
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
167
  /*
5e802dfab   David Brownell   [ARM] 4539/1: clo...
168
   * ST (system timer) module supports both clockevents and clocksource.
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
169
170
171
   */
  void __init at91rm9200_timer_init(void)
  {
5e802dfab   David Brownell   [ARM] 4539/1: clo...
172
173
174
175
  	/* Disable all timer interrupts, and clear any pending ones */
  	at91_sys_write(AT91_ST_IDR,
  		AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
  	(void) at91_sys_read(AT91_ST_SR);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
176

2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
177
  	/* Make IRQs happen for the system timer */
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
178
  	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
179
180
181
182
183
  	/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
  	 * directly for the clocksource and all clockevents, after adjusting
  	 * its prescaler from the 1 Hz default.
  	 */
  	at91_sys_write(AT91_ST_RTMR, 1);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
184

5e802dfab   David Brownell   [ARM] 4539/1: clo...
185
186
187
188
  	/* Setup timer clockevent, with minimum of two ticks (important!!) */
  	clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
  	clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
  	clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
320ab2b0b   Rusty Russell   cpumask: convert ...
189
  	clkevt.cpumask = cpumask_of(0);
5e802dfab   David Brownell   [ARM] 4539/1: clo...
190
  	clockevents_register_device(&clkevt);
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
191

5e802dfab   David Brownell   [ARM] 4539/1: clo...
192
  	/* register clocksource */
132b16325   Russell King   ARM: AT91: update...
193
  	clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
194
195
196
197
  }
  
  struct sys_timer at91rm9200_timer = {
  	.init		= at91rm9200_timer_init,
73a59c1c4   SAN People   [ARM] 3240/2: AT9...
198
  };
2a6f9902c   Andrew Victor   [ARM] 3580/1: AT9...
199