aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/time.c
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@mvista.com>2009-04-15 15:40:11 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2009-05-26 11:19:04 -0400
commitf64691b3ab795268072e76ddb89290b6277cdf33 (patch)
treecc8de5ab3c90674905f6d8e141bcf345a81121f4 /arch/arm/mach-davinci/time.c
parent673dd36f0d0cf8893d6b46d524ad80e81076b885 (diff)
davinci: Add base address and timer flexibility
The davinci timer code currently hardcodes the timer register base addresses, the timer irq numbers, and the timers to use for clock events and clocksource. This won't work for some a new SoC so put those values into the soc_info structure and set them up in the SoC-specific files. Signed-off-by: Mark A. Greer <mgreer@mvista.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/time.c')
-rw-r--r--arch/arm/mach-davinci/time.c100
1 files changed, 45 insertions, 55 deletions
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index efbbc2ac63b4..faafb897f4bd 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -29,42 +29,23 @@
29#include <asm/errno.h> 29#include <asm/errno.h>
30#include <mach/io.h> 30#include <mach/io.h>
31#include <mach/cputype.h> 31#include <mach/cputype.h>
32#include <mach/time.h>
32#include "clock.h" 33#include "clock.h"
33 34
34static struct clock_event_device clockevent_davinci; 35static struct clock_event_device clockevent_davinci;
35static unsigned int davinci_clock_tick_rate; 36static unsigned int davinci_clock_tick_rate;
36 37
37#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
38#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
39#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) 38#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
40 39
41enum {
42 T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
43};
44
45#define IS_TIMER1(id) (id & 0x2)
46#define IS_TIMER0(id) (!IS_TIMER1(id))
47#define IS_TIMER_TOP(id) ((id & 0x1))
48#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
49
50static int timer_irqs[NUM_TIMERS] = {
51 IRQ_TINT0_TINT12,
52 IRQ_TINT0_TINT34,
53 IRQ_TINT1_TINT12,
54 IRQ_TINT1_TINT34,
55};
56
57/* 40/*
58 * This driver configures the 2 64-bit count-up timers as 4 independent 41 * This driver configures the 2 64-bit count-up timers as 4 independent
59 * 32-bit count-up timers used as follows: 42 * 32-bit count-up timers used as follows:
60 *
61 * T0_BOT: Timer 0, bottom: clockevent source for hrtimers
62 * T0_TOP: Timer 0, top : clocksource for generic timekeeping
63 * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
64 * T1_TOP: Timer 1, top : <unused>
65 */ 43 */
66#define TID_CLOCKEVENT T0_BOT 44
67#define TID_CLOCKSOURCE T0_TOP 45enum {
46 TID_CLOCKEVENT,
47 TID_CLOCKSOURCE,
48};
68 49
69/* Timer register offsets */ 50/* Timer register offsets */
70#define PID12 0x0 51#define PID12 0x0
@@ -119,6 +100,13 @@ static struct timer_s timers[];
119#define TIMER_OPTS_ONESHOT 0x01 100#define TIMER_OPTS_ONESHOT 0x01
120#define TIMER_OPTS_PERIODIC 0x02 101#define TIMER_OPTS_PERIODIC 0x02
121 102
103static char *id_to_name[] = {
104 [T0_BOT] = "timer0_0",
105 [T0_TOP] = "timer0_1",
106 [T1_BOT] = "timer1_0",
107 [T1_TOP] = "timer1_1",
108};
109
122static int timer32_config(struct timer_s *t) 110static int timer32_config(struct timer_s *t)
123{ 111{
124 u32 tcr = __raw_readl(t->base + TCR); 112 u32 tcr = __raw_readl(t->base + TCR);
@@ -183,13 +171,14 @@ static struct timer_s timers[] = {
183 171
184static void __init timer_init(void) 172static void __init timer_init(void)
185{ 173{
186 u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; 174 struct davinci_soc_info *soc_info = &davinci_soc_info;
175 struct davinci_timer_instance *dtip = soc_info->timer_info->timers;
187 int i; 176 int i;
188 177
189 /* Global init of each 64-bit timer as a whole */ 178 /* Global init of each 64-bit timer as a whole */
190 for(i=0; i<2; i++) { 179 for(i=0; i<2; i++) {
191 u32 tgcr; 180 u32 tgcr;
192 void __iomem *base = IO_ADDRESS(phys_bases[i]); 181 void __iomem *base = dtip[i].base;
193 182
194 /* Disabled, Internal clock source */ 183 /* Disabled, Internal clock source */
195 __raw_writel(0, base + TCR); 184 __raw_writel(0, base + TCR);
@@ -215,33 +204,30 @@ static void __init timer_init(void)
215 /* Init of each timer as a 32-bit timer */ 204 /* Init of each timer as a 32-bit timer */
216 for (i=0; i< ARRAY_SIZE(timers); i++) { 205 for (i=0; i< ARRAY_SIZE(timers); i++) {
217 struct timer_s *t = &timers[i]; 206 struct timer_s *t = &timers[i];
218 u32 phys_base; 207 int timer = ID_TO_TIMER(t->id);
219 208 u32 irq;
220 if (t->name) { 209
221 t->id = i; 210 t->base = dtip[timer].base;
222 phys_base = (IS_TIMER1(t->id) ? 211
223 DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); 212 if (IS_TIMER_BOT(t->id)) {
224 t->base = IO_ADDRESS(phys_base); 213 t->enamode_shift = 6;
225 214 t->tim_off = TIM12;
226 if (IS_TIMER_BOT(t->id)) { 215 t->prd_off = PRD12;
227 t->enamode_shift = 6; 216 irq = dtip[timer].bottom_irq;
228 t->tim_off = TIM12; 217 } else {
229 t->prd_off = PRD12; 218 t->enamode_shift = 22;
230 } else { 219 t->tim_off = TIM34;
231 t->enamode_shift = 22; 220 t->prd_off = PRD34;
232 t->tim_off = TIM34; 221 irq = dtip[timer].top_irq;
233 t->prd_off = PRD34;
234 }
235
236 /* Register interrupt */
237 t->irqaction.name = t->name;
238 t->irqaction.dev_id = (void *)t;
239 if (t->irqaction.handler != NULL) {
240 setup_irq(timer_irqs[t->id], &t->irqaction);
241 }
242
243 timer32_config(&timers[i]);
244 } 222 }
223
224 /* Register interrupt */
225 t->irqaction.name = t->name;
226 t->irqaction.dev_id = (void *)t;
227 if (t->irqaction.handler != NULL)
228 setup_irq(irq, &t->irqaction);
229
230 timer32_config(&timers[i]);
245 } 231 }
246} 232}
247 233
@@ -256,7 +242,6 @@ static cycle_t read_cycles(struct clocksource *cs)
256} 242}
257 243
258static struct clocksource clocksource_davinci = { 244static struct clocksource clocksource_davinci = {
259 .name = "timer0_1",
260 .rating = 300, 245 .rating = 300,
261 .read = read_cycles, 246 .read = read_cycles,
262 .mask = CLOCKSOURCE_MASK(32), 247 .mask = CLOCKSOURCE_MASK(32),
@@ -301,7 +286,6 @@ static void davinci_set_mode(enum clock_event_mode mode,
301} 286}
302 287
303static struct clock_event_device clockevent_davinci = { 288static struct clock_event_device clockevent_davinci = {
304 .name = "timer0_0",
305 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 289 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
306 .shift = 32, 290 .shift = 32,
307 .set_next_event = davinci_set_next_event, 291 .set_next_event = davinci_set_next_event,
@@ -312,10 +296,14 @@ static struct clock_event_device clockevent_davinci = {
312static void __init davinci_timer_init(void) 296static void __init davinci_timer_init(void)
313{ 297{
314 struct clk *timer_clk; 298 struct clk *timer_clk;
299 struct davinci_soc_info *soc_info = &davinci_soc_info;
315 300
316 static char err[] __initdata = KERN_ERR 301 static char err[] __initdata = KERN_ERR
317 "%s: can't register clocksource!\n"; 302 "%s: can't register clocksource!\n";
318 303
304 timers[TID_CLOCKEVENT].id = soc_info->timer_info->clockevent_id;
305 timers[TID_CLOCKSOURCE].id = soc_info->timer_info->clocksource_id;
306
319 /* init timer hw */ 307 /* init timer hw */
320 timer_init(); 308 timer_init();
321 309
@@ -326,6 +314,7 @@ static void __init davinci_timer_init(void)
326 davinci_clock_tick_rate = clk_get_rate(timer_clk); 314 davinci_clock_tick_rate = clk_get_rate(timer_clk);
327 315
328 /* setup clocksource */ 316 /* setup clocksource */
317 clocksource_davinci.name = id_to_name[timers[TID_CLOCKSOURCE].id];
329 clocksource_davinci.mult = 318 clocksource_davinci.mult =
330 clocksource_khz2mult(davinci_clock_tick_rate/1000, 319 clocksource_khz2mult(davinci_clock_tick_rate/1000,
331 clocksource_davinci.shift); 320 clocksource_davinci.shift);
@@ -333,6 +322,7 @@ static void __init davinci_timer_init(void)
333 printk(err, clocksource_davinci.name); 322 printk(err, clocksource_davinci.name);
334 323
335 /* setup clockevent */ 324 /* setup clockevent */
325 clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
336 clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, 326 clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
337 clockevent_davinci.shift); 327 clockevent_davinci.shift);
338 clockevent_davinci.max_delta_ns = 328 clockevent_davinci.max_delta_ns =