1 /* linux/arch/arm/mach-rk2818/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>
22 #include <linux/delay.h>
25 #include <asm/mach/time.h>
26 #include <mach/rk2818_iomap.h>
28 #define RK2818_TIMER1_BASE RK2818_TIMER_BASE
29 #define RK2818_TIMER2_BASE RK2818_TIMER_BASE + 0x14
30 #define RK2818_TIMER3_BASE RK2818_TIMER_BASE + 0x28
31 #define TIMER_LOAD_COUNT 0x0000
32 #define TIMER_CUR_VALUE 0x0004
33 #define TIMER_CONTROL_REG 0x0008
34 #define TIMER_EOI 0x000C
35 #define TIMER_INT_STATUS 0x0010
37 #define TIMER_MATCH_VAL 0x0000
38 #define TIMER_COUNT_VAL 0x0004
39 #define TIMER_ENABLE 0x0008
40 #define TIMER_ENABLE_CLR_ON_MATCH_EN 2
41 #define TIMER_ENABLE_EN 3
42 #define TIMER_CLEAR 0x000C
44 #define CSR_PROTECTION 0x0020
45 #define CSR_PROTECTION_EN 1
47 #define TIMER_HZ 24000000
48 #define timer_cycle (TIMER_HZ+HZ/2)/HZ
50 uint32_t mycycles = 0;
53 struct clock_event_device clockevent;
54 struct clocksource clocksource;
61 static irqreturn_t rk2818_timer_interrupt(int irq, void *dev_id)
63 struct clock_event_device *evt = dev_id;
64 struct rk2818_clock *clock = container_of(evt, struct rk2818_clock, clockevent);
65 readl(clock->regbase + TIMER_EOI);
67 evt->event_handler(evt);
71 static cycle_t rk2818_timer_read(void)
77 t = readl(RK2818_TIMER3_BASE + TIMER_LOAD_COUNT);
79 elapsed = __raw_readl(RK2818_TIMER3_BASE + TIMER_CUR_VALUE);
81 elapsed = t - elapsed;
86 static int rk2818_timer_set_next_event(unsigned long cycles,
87 struct clock_event_device *evt)
90 struct rk2818_clock *clock = container_of(evt, struct rk2818_clock, clockevent);
92 writel(4, clock->regbase + TIMER_CONTROL_REG);
94 writel(cycles, clock->regbase + TIMER_LOAD_COUNT);
95 writel(TIMER_ENABLE_EN, clock->regbase + TIMER_CONTROL_REG);
99 static void rk2818_timer_set_mode(enum clock_event_mode mode,
100 struct clock_event_device *evt)
102 struct rk2818_clock *clock = container_of(evt, struct rk2818_clock, clockevent);
103 printk("%s::Enter--mode is %d\n",__FUNCTION__,mode);
105 case CLOCK_EVT_MODE_RESUME:
106 case CLOCK_EVT_MODE_PERIODIC:
108 case CLOCK_EVT_MODE_ONESHOT:
109 readl(clock->regbase+TIMER_EOI);
110 writel((TIMER_HZ+ HZ/2) / HZ,clock->regbase+TIMER_LOAD_COUNT);
111 writel(TIMER_ENABLE_EN, clock->regbase + TIMER_CONTROL_REG);
113 case CLOCK_EVT_MODE_UNUSED:
114 case CLOCK_EVT_MODE_SHUTDOWN:
115 writel(4, clock->regbase + TIMER_CONTROL_REG);
120 static struct rk2818_clock rk2818_clocks[] = {
124 .features = CLOCK_EVT_FEAT_ONESHOT,
127 .set_next_event = rk2818_timer_set_next_event,
128 .set_mode = rk2818_timer_set_mode,
133 .read = rk2818_timer_read,
134 .mask = CLOCKSOURCE_MASK(24),
136 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
140 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
141 .handler = rk2818_timer_interrupt,
142 .dev_id = &rk2818_clocks[0].clockevent,
145 .regbase = RK2818_TIMER3_BASE,
150 static void __init rk2818_timer_init(void)
154 printk("%s [%d]\n",__FUNCTION__,__LINE__);
155 //rk2818_clock_init();
156 for (i = 0; i < ARRAY_SIZE(rk2818_clocks); i++) {
157 printk("%s::Enter %d\n",__FUNCTION__,i+1);
158 struct rk2818_clock *clock = &rk2818_clocks[i];
159 struct clock_event_device *ce = &clock->clockevent;
160 struct clocksource *cs = &clock->clocksource;
162 writel((TIMER_HZ+ HZ/2) / HZ,clock->regbase+TIMER_LOAD_COUNT);
164 writel(0x04, clock->regbase + TIMER_CONTROL_REG);
166 ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
167 /* allow at least 10 seconds to notice that the timer wrapped */
169 clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
170 /* 4 gets rounded down to 3 */
171 ce->min_delta_ns = clockevent_delta2ns(4, ce);
172 ce->cpumask = cpumask_of(0);
174 cs->mult = clocksource_hz2mult(clock->freq, cs->shift);
175 printk("mult is %x\n",cs->mult);
176 res = clocksource_register(cs);
178 printk(KERN_ERR "rk2818_timer_init: clocksource_register "
179 "failed for %s\n", cs->name);
180 printk("%s::irq is %d\n",__FUNCTION__,clock->irq.irq);
181 res = setup_irq(clock->irq.irq, &clock->irq);
183 printk(KERN_ERR "rk2818_timer_init: setup_irq "
184 "failed for %s\n", cs->name);
186 clockevents_register_device(ce);
190 struct sys_timer rk2818_timer = {
191 .init = rk2818_timer_init