2 * Copyright (C) 2001-2006 Storlink, Corp.
3 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 #include <linux/interrupt.h>
11 #include <linux/irq.h>
13 #include <mach/hardware.h>
14 #include <mach/global_reg.h>
15 #include <asm/mach/time.h>
16 #include <linux/clockchips.h>
17 #include <linux/clocksource.h>
20 * Register definitions for the timers
22 #define TIMER_COUNT(BASE_ADDR) (BASE_ADDR + 0x00)
23 #define TIMER_LOAD(BASE_ADDR) (BASE_ADDR + 0x04)
24 #define TIMER_MATCH1(BASE_ADDR) (BASE_ADDR + 0x08)
25 #define TIMER_MATCH2(BASE_ADDR) (BASE_ADDR + 0x0C)
26 #define TIMER_CR(BASE_ADDR) (BASE_ADDR + 0x30)
28 #define TIMER_1_CR_ENABLE (1 << 0)
29 #define TIMER_1_CR_CLOCK (1 << 1)
30 #define TIMER_1_CR_INT (1 << 2)
31 #define TIMER_2_CR_ENABLE (1 << 3)
32 #define TIMER_2_CR_CLOCK (1 << 4)
33 #define TIMER_2_CR_INT (1 << 5)
34 #define TIMER_3_CR_ENABLE (1 << 6)
35 #define TIMER_3_CR_CLOCK (1 << 7)
36 #define TIMER_3_CR_INT (1 << 8)
38 static unsigned int tick_rate
;
40 static int gemini_timer_set_next_event(unsigned long cycles
,
41 struct clock_event_device
*evt
)
45 cr
= readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
47 /* This may be overdoing it, feel free to test without this */
48 cr
&= ~TIMER_2_CR_ENABLE
;
49 cr
&= ~TIMER_2_CR_INT
;
50 writel(cr
, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
53 writel(cycles
, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE
)));
54 writel(cycles
, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE
)));
55 cr
|= TIMER_2_CR_ENABLE
;
57 writel(cr
, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
62 static void gemini_timer_set_mode(enum clock_event_mode mode
,
63 struct clock_event_device
*evt
)
65 u32 period
= DIV_ROUND_CLOSEST(tick_rate
, HZ
);
69 case CLOCK_EVT_MODE_PERIODIC
:
72 TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE
)));
74 TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE
)));
75 cr
= readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
76 cr
|= TIMER_2_CR_ENABLE
;
78 writel(cr
, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
80 case CLOCK_EVT_MODE_ONESHOT
:
81 case CLOCK_EVT_MODE_UNUSED
:
82 case CLOCK_EVT_MODE_SHUTDOWN
:
83 case CLOCK_EVT_MODE_RESUME
:
85 * Disable also for oneshot: the set_next() call will
86 * arm the timer instead.
88 cr
= readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
89 cr
&= ~TIMER_2_CR_ENABLE
;
90 cr
&= ~TIMER_2_CR_INT
;
91 writel(cr
, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
98 /* Use TIMER2 as clock event */
99 static struct clock_event_device gemini_clockevent
= {
101 .rating
= 300, /* Reasonably fast and accurate clock event */
102 .features
= CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT
,
103 .set_next_event
= gemini_timer_set_next_event
,
104 .set_mode
= gemini_timer_set_mode
,
108 * IRQ handler for the timer
110 static irqreturn_t
gemini_timer_interrupt(int irq
, void *dev_id
)
112 struct clock_event_device
*evt
= &gemini_clockevent
;
114 evt
->event_handler(evt
);
118 static struct irqaction gemini_timer_irq
= {
119 .name
= "Gemini Timer Tick",
121 .handler
= gemini_timer_interrupt
,
125 * Set up timer interrupt, and return the current time in seconds.
127 void __init
gemini_timer_init(void)
131 reg_v
= readl(IO_ADDRESS(GEMINI_GLOBAL_BASE
+ GLOBAL_STATUS
));
132 tick_rate
= REG_TO_AHB_SPEED(reg_v
) * 1000000;
134 printk(KERN_INFO
"Bus: %dMHz", tick_rate
/ 1000000);
136 tick_rate
/= 6; /* APB bus run AHB*(1/6) */
138 switch(reg_v
& CPU_AHB_RATIO_MASK
) {
140 printk(KERN_CONT
"(1/1)\n");
143 printk(KERN_CONT
"(3/2)\n");
146 printk(KERN_CONT
"(24/13)\n");
149 printk(KERN_CONT
"(2/1)\n");
154 * Make irqs happen for the system timer
156 setup_irq(IRQ_TIMER2
, &gemini_timer_irq
);
158 /* Enable and use TIMER1 as clock source */
159 writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE
)));
160 writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE
)));
161 writel(TIMER_1_CR_ENABLE
, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE
)));
162 if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE
)),
163 "TIMER1", tick_rate
, 300, 32,
164 clocksource_mmio_readl_up
))
165 pr_err("timer: failed to initialize gemini clock source\n");
167 /* Configure and register the clockevent */
168 clockevents_config_and_register(&gemini_clockevent
, tick_rate
,