9de5b9e19e17a3d7d747fb1210c84af52aa91b48
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rk2818 / timer.c
1 /* linux/arch/arm/mach-rk2818/timer.c
2  *
3  * Copyright (C) 2010 ROCKCHIP, Inc.
4  *
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.
8  *
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.
13  *
14  */
15
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>
23 #include <linux/io.h>
24
25 #include <asm/mach/time.h>
26 #include <mach/rk2818_iomap.h>
27
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
36
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
43
44 #define CSR_PROTECTION          0x0020
45 #define CSR_PROTECTION_EN               1
46
47 #define TIMER_HZ        24000000 
48 #define timer_cycle     (TIMER_HZ+HZ/2)/HZ
49 uint32_t        tcount;
50 uint32_t        mycycles = 0;
51 static int      pit_cnt=0;
52 struct rk2818_clock {
53         struct clock_event_device   clockevent;
54         struct clocksource          clocksource;
55         struct irqaction            irq;
56         uint32_t                    regbase;
57         uint32_t                    freq;
58         uint32_t                    shift;
59 };
60
61 static irqreturn_t rk2818_timer_interrupt(int irq, void *dev_id)
62 {
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);
66         pit_cnt +=mycycles;
67         evt->event_handler(evt);
68         return IRQ_HANDLED;
69 }
70
71 static cycle_t rk2818_timer_read(void)
72 {
73
74         unsigned int elapsed;
75         unsigned int t;
76
77         t = readl(RK2818_TIMER3_BASE + TIMER_LOAD_COUNT);
78
79         elapsed = __raw_readl(RK2818_TIMER3_BASE + TIMER_CUR_VALUE);
80         
81         elapsed = t - elapsed;
82         elapsed += pit_cnt;
83     return elapsed;
84 }
85
86 static int rk2818_timer_set_next_event(unsigned long cycles,
87                                     struct clock_event_device *evt)
88 {
89         
90         struct rk2818_clock *clock = container_of(evt, struct rk2818_clock, clockevent);
91
92     writel(4, clock->regbase + TIMER_CONTROL_REG);
93         mycycles = cycles;
94     writel(cycles, clock->regbase + TIMER_LOAD_COUNT);
95     writel(TIMER_ENABLE_EN, clock->regbase + TIMER_CONTROL_REG);
96         return 0;
97 }
98
99 static void rk2818_timer_set_mode(enum clock_event_mode mode,
100                               struct clock_event_device *evt)
101 {
102         struct rk2818_clock *clock = container_of(evt, struct rk2818_clock, clockevent);
103         printk("%s::Enter--mode is %d\n",__FUNCTION__,mode);
104         switch (mode) {
105         case CLOCK_EVT_MODE_RESUME:
106         case CLOCK_EVT_MODE_PERIODIC:
107                 break;
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);
112                 break;
113         case CLOCK_EVT_MODE_UNUSED:
114         case CLOCK_EVT_MODE_SHUTDOWN:
115                 writel(4, clock->regbase + TIMER_CONTROL_REG);
116                 break;
117         }
118 }
119
120 static struct rk2818_clock rk2818_clocks[] = {
121         {
122                 .clockevent = {
123                         .name           = "timer",
124                         .features       = CLOCK_EVT_FEAT_ONESHOT,
125                         .shift          = 32,
126                         .rating         = 200,
127                         .set_next_event = rk2818_timer_set_next_event,
128                         .set_mode       = rk2818_timer_set_mode,
129                 },
130                 .clocksource = {
131                         .name           = "timer",
132                         .rating         = 200,
133                         .read           = rk2818_timer_read,
134                         .mask           = CLOCKSOURCE_MASK(24),
135                         .shift          = 26,
136                         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
137                 },
138                 .irq = {
139                         .name    = "timer",
140                         .flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
141                         .handler = rk2818_timer_interrupt,
142                         .dev_id  = &rk2818_clocks[0].clockevent,
143                         .irq     = IRQ_NR_TIMER3 
144                 },
145                 .regbase = RK2818_TIMER3_BASE,
146                 .freq = TIMER_HZ
147         }
148 };
149
150 static void __init rk2818_timer_init(void)
151 {
152         int i;
153         int res;
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;
161                                 
162                 writel((TIMER_HZ+ HZ/2) / HZ,clock->regbase+TIMER_LOAD_COUNT);
163
164                 writel(0x04, clock->regbase + TIMER_CONTROL_REG);
165                 
166                 ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
167                 /* allow at least 10 seconds to notice that the timer wrapped */
168                 ce->max_delta_ns =
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);
173
174                 cs->mult = clocksource_hz2mult(clock->freq, cs->shift);
175                 printk("mult is %x\n",cs->mult);
176                 res = clocksource_register(cs);
177                 if (res)
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);
182                 if (res)
183                         printk(KERN_ERR "rk2818_timer_init: setup_irq "
184                                "failed for %s\n", cs->name);
185
186                 clockevents_register_device(ce);
187         }
188 }
189
190 struct sys_timer rk2818_timer = {
191         .init = rk2818_timer_init
192 };