1 /* linux/arch/arm/mach-rk29/timer.c
3 * Copyright (C) 2010 ROCKCHIP, Inc.
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/init.h>
17 #include <linux/time.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <linux/clk.h>
21 #include <linux/clockchips.h>
23 #include <linux/cpufreq.h>
25 #include <asm/mach/time.h>
26 #include <mach/rk29_iomap.h>
28 #define TIMER_LOAD_COUNT 0x0000
29 #define TIMER_CUR_VALUE 0x0004
30 #define TIMER_CONTROL_REG 0x0008
31 #define TIMER_EOI 0x000C
32 #define TIMER_INT_STATUS 0x0010
34 #define TIMER_DISABLE 4
35 #define TIMER_ENABLE 3
36 #define TIMER_ENABLE_FREE_RUNNING 1
38 #define CHECK_VBUS_MS 1000 /* ms */
40 #define RK_TIMER_ENABLE(n) writel(TIMER_ENABLE, RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_CONTROL_REG)
41 #define RK_TIMER_ENABLE_FREE_RUNNING(n) writel(TIMER_ENABLE_FREE_RUNNING, RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_CONTROL_REG)
42 #define RK_TIMER_DISABLE(n) writel(TIMER_DISABLE, RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_CONTROL_REG)
44 #define RK_TIMER_SETCOUNT(n, count) writel(count, RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_LOAD_COUNT)
45 #define RK_TIMER_GETCOUNT(n) readl(RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_LOAD_COUNT)
47 #define RK_TIMER_READVALUE(n) readl(RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_CUR_VALUE)
48 #define RK_TIMER_INT_CLEAR(n) readl(RK29_TIMER0_BASE + 0x14 * (n - 1) + TIMER_EOI)
50 #define TIMER_CLKEVT 2 /* timer2 */
51 #define IRQ_NR_TIMER_CLKEVT IRQ_NR_TIMER2
52 #define TIMER_CLKEVT_NAME "timer2"
54 #define TIMER_CLKSRC 3 /* timer3 */
55 #define IRQ_NR_TIMER_CLKSRC IRQ_NR_TIMER3
56 #define TIMER_CLKSRC_NAME "timer3"
58 static struct clk *timer_clk;
59 static volatile unsigned long timer_mult; /* timer count = cycle * timer_mult */
61 void rk29_timer_update_mult(void)
64 // timer_mult = clk_get_rate(timer_clk) / 1000000;
67 static int rk29_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt)
69 RK_TIMER_DISABLE(TIMER_CLKEVT);
70 RK_TIMER_SETCOUNT(TIMER_CLKEVT, cycles * timer_mult);
71 RK_TIMER_ENABLE(TIMER_CLKEVT);
76 static void rk29_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
79 case CLOCK_EVT_MODE_RESUME:
80 case CLOCK_EVT_MODE_PERIODIC:
81 case CLOCK_EVT_MODE_ONESHOT:
83 case CLOCK_EVT_MODE_UNUSED:
84 case CLOCK_EVT_MODE_SHUTDOWN:
85 RK_TIMER_DISABLE(TIMER_CLKEVT);
90 static struct clock_event_device rk29_timer_clockevent = {
91 .name = TIMER_CLKEVT_NAME,
92 .features = CLOCK_EVT_FEAT_ONESHOT,
95 .set_next_event = rk29_timer_set_next_event,
96 .set_mode = rk29_timer_set_mode,
99 static irqreturn_t rk29_timer_clockevent_interrupt(int irq, void *dev_id)
101 struct clock_event_device *evt = dev_id;
103 RK_TIMER_INT_CLEAR(TIMER_CLKEVT);
104 RK_TIMER_DISABLE(TIMER_CLKEVT);
106 evt->event_handler(evt);
111 static struct irqaction rk29_timer_clockevent_irq = {
112 .name = TIMER_CLKEVT_NAME,
113 .flags = IRQF_DISABLED | IRQF_TIMER,
114 .handler = rk29_timer_clockevent_interrupt,
115 .irq = IRQ_NR_TIMER_CLKEVT,
116 .dev_id = &rk29_timer_clockevent,
119 static int rk29_timer_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
121 if (val == CPUFREQ_POSTCHANGE) {
122 rk29_timer_update_mult();
128 static struct notifier_block rk29_timer_cpufreq_notifier_block = {
129 .notifier_call = rk29_timer_cpufreq_notifier,
130 .priority = 0x7ffffff,
133 static __init int rk29_timer_init_cpufreq(void)
135 cpufreq_register_notifier(&rk29_timer_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
139 arch_initcall_sync(rk29_timer_init_cpufreq);
141 static __init int rk29_timer_init_clockevent(void)
143 struct clock_event_device *ce = &rk29_timer_clockevent;
145 //timer_clk = clk_get(NULL, "timer");
146 rk29_timer_update_mult();
148 RK_TIMER_DISABLE(TIMER_CLKEVT);
150 setup_irq(rk29_timer_clockevent_irq.irq, &rk29_timer_clockevent_irq);
152 ce->mult = div_sc(1000000, NSEC_PER_SEC, ce->shift);
153 ce->max_delta_ns = clockevent_delta2ns(0xFFFFFFFFUL / 256, ce); // max pclk < 256MHz
154 ce->min_delta_ns = clockevent_delta2ns(1, ce) + 1;
156 ce->cpumask = cpumask_of(0);
158 clockevents_register_device(ce);
163 static cycle_t rk29_timer_read(struct clocksource *cs)
165 return ~RK_TIMER_READVALUE(TIMER_CLKSRC);
168 static struct clocksource rk29_timer_clocksource = {
169 .name = TIMER_CLKSRC_NAME,
171 .read = rk29_timer_read,
172 .mask = CLOCKSOURCE_MASK(32),
174 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
177 static void __init rk29_timer_init_clocksource(void)
179 static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n";
180 struct clocksource *cs = &rk29_timer_clocksource;
182 RK_TIMER_DISABLE(TIMER_CLKSRC);
183 RK_TIMER_SETCOUNT(TIMER_CLKSRC, 0xFFFFFFFF);
184 RK_TIMER_ENABLE_FREE_RUNNING(TIMER_CLKSRC);
186 cs->mult = clocksource_hz2mult(24000000, cs->shift);
187 if (clocksource_register(cs))
188 printk(err, cs->name);
192 static void __init rk29_timer_init(void)
194 rk29_timer_init_clocksource();
195 rk29_timer_init_clockevent();
198 struct sys_timer rk29_timer = {
199 .init = rk29_timer_init