Revert "clocksource: tegra210: use old timers"
[linux-3.10.git] / drivers / clocksource / tegra210_timer.c
1 /*
2  * drivers/clocksource/tegra210_timer.c
3  *
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/clockchips.h>
20 #include <linux/cpu.h>
21 #include <linux/cpumask.h>
22 #include <linux/err.h>
23 #include <linux/interrupt.h>
24 #include <linux/io.h>
25 #include <linux/of_address.h>
26 #include <linux/of_irq.h>
27 #include <linux/percpu.h>
28 #include <linux/syscore_ops.h>
29
30 static u32 tegra210_timer_freq;
31 static void __iomem *tegra210_timer_reg_base;
32 phys_addr_t timer_reg_base_pa = 0x60005000;
33 static u32 usec_config;
34
35 #define TIMERUS_CNTR_1US 0x10
36 #define TIMERUS_USEC_CFG 0x14
37
38 #define TIMER10_OFFSET 0x90
39 #define TIMER11_OFFSET 0x98
40 #define TIMER12_OFFSET 0xa0
41 #define TIMER13_OFFSET 0xa8
42
43 #define TIMER_PTV 0x0 /* present trigger value register */
44 #define TIMER_PCR 0x4 /* present counter value register */
45
46 #define TIMER_FOR_CPU(cpu) (TIMER10_OFFSET + (cpu) * 8)
47
48 #define TNAMELEN 20
49
50 struct tegra210_clockevent {
51         struct clock_event_device evt;
52         char name[TNAMELEN];
53         void __iomem *reg_base;
54 };
55
56 static DEFINE_PER_CPU(struct tegra210_clockevent, tegra210_evt);
57
58 static int tegra210_timer_set_next_event(unsigned long cycles,
59                                          struct clock_event_device *evt)
60 {
61         struct tegra210_clockevent *tevt;
62         tevt = container_of(evt, struct tegra210_clockevent, evt);
63         __raw_writel((1 << 31) /* EN=1, enable timer */
64                      | ((cycles > 1) ? (cycles - 1) : 0), /* n+1 scheme */
65                      tevt->reg_base + TIMER_PTV);
66         return 0;
67 }
68
69 static void tegra210_timer_set_mode(enum clock_event_mode mode,
70                                     struct clock_event_device *evt)
71 {
72         struct tegra210_clockevent *tevt;
73
74         tevt = container_of(evt, struct tegra210_clockevent, evt);
75         __raw_writel(0, tevt->reg_base + TIMER_PTV);
76
77         switch (mode) {
78         case CLOCK_EVT_MODE_PERIODIC:
79                 __raw_writel((1 << 31) /* EN=1, enable timer */
80                              | (1 << 30) /* PER=1, periodic mode */
81                              | ((tegra210_timer_freq / HZ) - 1),
82                              tevt->reg_base + TIMER_PTV);
83                 break;
84         case CLOCK_EVT_MODE_ONESHOT:
85                 break;
86         case CLOCK_EVT_MODE_UNUSED:
87         case CLOCK_EVT_MODE_SHUTDOWN:
88         case CLOCK_EVT_MODE_RESUME:
89                 break;
90         }
91 }
92
93 static irqreturn_t tegra210_timer_isr(int irq, void *dev_id)
94 {
95         struct tegra210_clockevent *tevt;
96         tevt = (struct tegra210_clockevent *)dev_id;
97         __raw_writel(1 << 30, /* INTR_CLR */
98                      tevt->reg_base + TIMER_PCR);
99         tevt->evt.event_handler(&tevt->evt);
100         return IRQ_HANDLED;
101 }
102
103 static void tegra210_timer_setup(struct tegra210_clockevent *tevt)
104 {
105         int cpu = smp_processor_id();
106         sprintf(tevt->name, "tegra210_timer%d", cpu);
107         tevt->evt.name = tevt->name;
108         tevt->evt.cpumask = cpumask_of(cpu);
109         tevt->evt.set_next_event = tegra210_timer_set_next_event;
110         tevt->evt.set_mode = tegra210_timer_set_mode;
111         tevt->evt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
112         tevt->evt.rating = 460; /* want to be preferred over arch timers */
113         if (request_irq(tevt->evt.irq, tegra210_timer_isr,
114                         IRQF_TIMER | IRQF_TRIGGER_HIGH | IRQF_NOBALANCING,
115                         tevt->name, tevt)) {
116                 pr_err("%s: cannot request irq %d for CPU%d\n",
117                        __func__, tevt->evt.irq, cpu);
118                 BUG();
119         }
120         if (irq_force_affinity(tevt->evt.irq, cpumask_of(cpu))) {
121                 pr_err("%s: cannot set irq %d affinity to CPU%d\n",
122                        __func__, tevt->evt.irq, cpu);
123                 BUG();
124         }
125         clockevents_config_and_register(&tevt->evt, tegra210_timer_freq,
126                                         1, /* min */
127                                         0x1fffffff); /* 29 bits */
128 }
129
130 static void tegra210_timer_stop(struct tegra210_clockevent *tevt)
131 {
132         tevt->evt.set_mode(CLOCK_EVT_MODE_UNUSED, &tevt->evt);
133         free_irq(tevt->evt.irq, tevt);
134 }
135
136 static int tegra210_timer_cpu_notify(struct notifier_block *self,
137                                      unsigned long action, void *hcpu)
138 {
139         switch (action & ~CPU_TASKS_FROZEN) {
140         case CPU_STARTING:
141                 tegra210_timer_setup(this_cpu_ptr(&tegra210_evt));
142                 break;
143         case CPU_DYING:
144                 tegra210_timer_stop(this_cpu_ptr(&tegra210_evt));
145                 break;
146         }
147
148         return NOTIFY_OK;
149 }
150
151 static struct notifier_block tegra210_timer_cpu_nb = {
152         .notifier_call = tegra210_timer_cpu_notify,
153 };
154
155 u32 notrace tegra_read_usec_raw(void)
156 {
157         return __raw_readl(tegra210_timer_reg_base + TIMERUS_CNTR_1US);
158 }
159
160 static int tegra_timer_suspend(void)
161 {
162         usec_config = __raw_readl(tegra210_timer_reg_base + TIMERUS_USEC_CFG);
163         return 0;
164 }
165
166 static void tegra_timer_resume(void)
167 {
168         __raw_writel(usec_config, tegra210_timer_reg_base + TIMERUS_USEC_CFG);
169 }
170
171 static struct syscore_ops tegra_timer_syscore_ops = {
172         .suspend = tegra_timer_suspend,
173         .resume = tegra_timer_resume,
174         .save = tegra_timer_suspend,
175         .restore = tegra_timer_resume,
176 };
177
178 static void __init tegra210_timer_init(struct device_node *np)
179 {
180         int cpu;
181         struct tegra210_clockevent *tevt;
182         int ret;
183
184         tegra210_timer_reg_base = of_iomap(np, 0);
185         if (!tegra210_timer_reg_base) {
186                 pr_err("%s: can't map timer registers\n", __func__);
187                 BUG();
188         }
189
190         if (of_property_read_u32(np, "clock-frequency",
191                                  &tegra210_timer_freq)) {
192                 pr_err("%s: can't read clock frequency\n", __func__);
193                 BUG();
194         }
195
196         for (cpu = 0; cpu < 4; ++cpu) {
197                 tevt = &per_cpu(tegra210_evt, cpu);
198                 tevt->reg_base = tegra210_timer_reg_base + TIMER_FOR_CPU(cpu);
199                 tevt->evt.irq = irq_of_parse_and_map(np, cpu);
200                 if (!tevt->evt.irq) {
201                         pr_err("%s: can't map IRQ for CPU%d\n",
202                                __func__, cpu);
203                         BUG();
204                 }
205         }
206
207         /*
208          * Configure microsecond timers to have 1MHz clock
209          * Config register is 0xqqww, where qq is "dividend", ww is "divisor"
210          * Uses n+1 scheme
211          */
212         switch (tegra210_timer_freq) {
213         case 12000000:
214                 __raw_writel(0x000b, /* (11+1)/(0+1) */
215                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
216                 break;
217         case 13000000:
218                 __raw_writel(0x000c, /* (12+1)/(0+1) */
219                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
220                 break;
221         case 19200000:
222                 __raw_writel(0x045f, /* (95+1)/(4+1) */
223                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
224                 break;
225         case 26000000:
226                 __raw_writel(0x0019, /* (25+1)/(0+1) */
227                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
228                 break;
229         case 16800000:
230                 __raw_writel(0x0453, /* (83+1)/(4+1) */
231                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
232                 break;
233         case 38400000:
234                 __raw_writel(0x04bf, /* (191+1)/(4+1) */
235                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
236                 break;
237         case 48000000:
238                 __raw_writel(0x002f, /* (47+1)/(0+1) */
239                              tegra210_timer_reg_base + TIMERUS_USEC_CFG);
240                 break;
241         default:
242                 BUG();
243         }
244
245         /* boot cpu is online */
246         tevt = &per_cpu(tegra210_evt, 0);
247         ret = irq_set_affinity(tevt->evt.irq, cpumask_of(0));
248         if (ret) {
249                 pr_err("%s: set timer IRQ affinity to CPU0: %d\n",
250                        __func__, ret);
251                 BUG();
252         }
253         tegra210_timer_setup(tevt);
254
255         if (register_cpu_notifier(&tegra210_timer_cpu_nb)) {
256                 pr_err("%s: cannot setup CPU notifier\n", __func__);
257                 BUG();
258         }
259
260         register_syscore_ops(&tegra_timer_syscore_ops);
261
262         of_node_put(np);
263 }
264
265 CLOCKSOURCE_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer",
266                        tegra210_timer_init);