hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/clocksource/timer-sp804.c
....@@ -1,22 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * linux/drivers/clocksource/timer-sp.c
34 *
45 * Copyright (C) 1999 - 2003 ARM Limited
56 * Copyright (C) 2000 Deep Blue Solutions Ltd
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
207 */
218 #include <linux/clk.h>
229 #include <linux/clocksource.h>
....@@ -31,14 +18,56 @@
3118 #include <linux/of_irq.h>
3219 #include <linux/sched_clock.h>
3320
34
-#include <clocksource/timer-sp804.h>
35
-
3621 #include "timer-sp.h"
3722
38
-static long __init sp804_get_clock_rate(struct clk *clk)
23
+/* Hisilicon 64-bit timer(a variant of ARM SP804) */
24
+#define HISI_TIMER_1_BASE 0x00
25
+#define HISI_TIMER_2_BASE 0x40
26
+#define HISI_TIMER_LOAD 0x00
27
+#define HISI_TIMER_LOAD_H 0x04
28
+#define HISI_TIMER_VALUE 0x08
29
+#define HISI_TIMER_VALUE_H 0x0c
30
+#define HISI_TIMER_CTRL 0x10
31
+#define HISI_TIMER_INTCLR 0x14
32
+#define HISI_TIMER_RIS 0x18
33
+#define HISI_TIMER_MIS 0x1c
34
+#define HISI_TIMER_BGLOAD 0x20
35
+#define HISI_TIMER_BGLOAD_H 0x24
36
+
37
+
38
+struct sp804_timer __initdata arm_sp804_timer = {
39
+ .load = TIMER_LOAD,
40
+ .value = TIMER_VALUE,
41
+ .ctrl = TIMER_CTRL,
42
+ .intclr = TIMER_INTCLR,
43
+ .timer_base = {TIMER_1_BASE, TIMER_2_BASE},
44
+ .width = 32,
45
+};
46
+
47
+struct sp804_timer __initdata hisi_sp804_timer = {
48
+ .load = HISI_TIMER_LOAD,
49
+ .load_h = HISI_TIMER_LOAD_H,
50
+ .value = HISI_TIMER_VALUE,
51
+ .value_h = HISI_TIMER_VALUE_H,
52
+ .ctrl = HISI_TIMER_CTRL,
53
+ .intclr = HISI_TIMER_INTCLR,
54
+ .timer_base = {HISI_TIMER_1_BASE, HISI_TIMER_2_BASE},
55
+ .width = 64,
56
+};
57
+
58
+static struct sp804_clkevt sp804_clkevt[NR_TIMERS];
59
+
60
+static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
3961 {
4062 long rate;
4163 int err;
64
+
65
+ if (!clk)
66
+ clk = clk_get_sys("sp804", name);
67
+ if (IS_ERR(clk)) {
68
+ pr_err("sp804: %s clock not found: %ld\n", name, PTR_ERR(clk));
69
+ return PTR_ERR(clk);
70
+ }
4271
4372 err = clk_prepare(clk);
4473 if (err) {
....@@ -66,50 +95,57 @@
6695 return rate;
6796 }
6897
69
-static void __iomem *sched_clock_base;
98
+static struct sp804_clkevt * __init sp804_clkevt_get(void __iomem *base)
99
+{
100
+ int i;
101
+
102
+ for (i = 0; i < NR_TIMERS; i++) {
103
+ if (sp804_clkevt[i].base == base)
104
+ return &sp804_clkevt[i];
105
+ }
106
+
107
+ /* It's impossible to reach here */
108
+ WARN_ON(1);
109
+
110
+ return NULL;
111
+}
112
+
113
+static struct sp804_clkevt *sched_clkevt;
70114
71115 static u64 notrace sp804_read(void)
72116 {
73
- return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
117
+ return ~readl_relaxed(sched_clkevt->value);
74118 }
75119
76
-void __init sp804_timer_disable(void __iomem *base)
77
-{
78
- writel(0, base + TIMER_CTRL);
79
-}
80
-
81
-int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
82
- const char *name,
83
- struct clk *clk,
84
- int use_sched_clock)
120
+int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
121
+ const char *name,
122
+ struct clk *clk,
123
+ int use_sched_clock)
85124 {
86125 long rate;
126
+ struct sp804_clkevt *clkevt;
87127
88
- if (!clk) {
89
- clk = clk_get_sys("sp804", name);
90
- if (IS_ERR(clk)) {
91
- pr_err("sp804: clock not found: %d\n",
92
- (int)PTR_ERR(clk));
93
- return PTR_ERR(clk);
94
- }
95
- }
96
-
97
- rate = sp804_get_clock_rate(clk);
128
+ rate = sp804_get_clock_rate(clk, name);
98129 if (rate < 0)
99130 return -EINVAL;
100131
101
- /* setup timer 0 as free-running clocksource */
102
- writel(0, base + TIMER_CTRL);
103
- writel(0xffffffff, base + TIMER_LOAD);
104
- writel(0xffffffff, base + TIMER_VALUE);
105
- writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
106
- base + TIMER_CTRL);
132
+ clkevt = sp804_clkevt_get(base);
107133
108
- clocksource_mmio_init(base + TIMER_VALUE, name,
134
+ writel(0, clkevt->ctrl);
135
+ writel(0xffffffff, clkevt->load);
136
+ writel(0xffffffff, clkevt->value);
137
+ if (clkevt->width == 64) {
138
+ writel(0xffffffff, clkevt->load_h);
139
+ writel(0xffffffff, clkevt->value_h);
140
+ }
141
+ writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
142
+ clkevt->ctrl);
143
+
144
+ clocksource_mmio_init(clkevt->value, name,
109145 rate, 200, 32, clocksource_mmio_readl_down);
110146
111147 if (use_sched_clock) {
112
- sched_clock_base = base;
148
+ sched_clkevt = clkevt;
113149 sched_clock_register(sp804_read, 32, rate);
114150 }
115151
....@@ -117,8 +153,7 @@
117153 }
118154
119155
120
-static void __iomem *clkevt_base;
121
-static unsigned long clkevt_reload;
156
+static struct sp804_clkevt *common_clkevt;
122157
123158 /*
124159 * IRQ handler for the timer
....@@ -128,7 +163,7 @@
128163 struct clock_event_device *evt = dev_id;
129164
130165 /* clear the interrupt */
131
- writel(1, clkevt_base + TIMER_INTCLR);
166
+ writel(1, common_clkevt->intclr);
132167
133168 evt->event_handler(evt);
134169
....@@ -137,7 +172,7 @@
137172
138173 static inline void timer_shutdown(struct clock_event_device *evt)
139174 {
140
- writel(0, clkevt_base + TIMER_CTRL);
175
+ writel(0, common_clkevt->ctrl);
141176 }
142177
143178 static int sp804_shutdown(struct clock_event_device *evt)
....@@ -152,8 +187,8 @@
152187 TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
153188
154189 timer_shutdown(evt);
155
- writel(clkevt_reload, clkevt_base + TIMER_LOAD);
156
- writel(ctrl, clkevt_base + TIMER_CTRL);
190
+ writel(common_clkevt->reload, common_clkevt->load);
191
+ writel(ctrl, common_clkevt->ctrl);
157192 return 0;
158193 }
159194
....@@ -163,8 +198,8 @@
163198 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
164199 TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE;
165200
166
- writel(next, clkevt_base + TIMER_LOAD);
167
- writel(ctrl, clkevt_base + TIMER_CTRL);
201
+ writel(next, common_clkevt->load);
202
+ writel(ctrl, common_clkevt->ctrl);
168203
169204 return 0;
170205 }
....@@ -181,65 +216,79 @@
181216 .rating = 300,
182217 };
183218
184
-static struct irqaction sp804_timer_irq = {
185
- .name = "timer",
186
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
187
- .handler = sp804_timer_interrupt,
188
- .dev_id = &sp804_clockevent,
189
-};
190
-
191
-int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
219
+int __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
220
+ struct clk *clk, const char *name)
192221 {
193222 struct clock_event_device *evt = &sp804_clockevent;
194223 long rate;
195224
196
- if (!clk)
197
- clk = clk_get_sys("sp804", name);
198
- if (IS_ERR(clk)) {
199
- pr_err("sp804: %s clock not found: %d\n", name,
200
- (int)PTR_ERR(clk));
201
- return PTR_ERR(clk);
202
- }
203
-
204
- rate = sp804_get_clock_rate(clk);
225
+ rate = sp804_get_clock_rate(clk, name);
205226 if (rate < 0)
206227 return -EINVAL;
207228
208
- clkevt_base = base;
209
- clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
229
+ common_clkevt = sp804_clkevt_get(base);
230
+ common_clkevt->reload = DIV_ROUND_CLOSEST(rate, HZ);
210231 evt->name = name;
211232 evt->irq = irq;
212233 evt->cpumask = cpu_possible_mask;
213234
214
- writel(0, base + TIMER_CTRL);
235
+ writel(0, common_clkevt->ctrl);
215236
216
- setup_irq(irq, &sp804_timer_irq);
237
+ if (request_irq(irq, sp804_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
238
+ "timer", &sp804_clockevent))
239
+ pr_err("%s: request_irq() failed\n", "timer");
217240 clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
218241
219242 return 0;
220243 }
221244
222
-static int __init sp804_of_init(struct device_node *np)
245
+static void __init sp804_clkevt_init(struct sp804_timer *timer, void __iomem *base)
246
+{
247
+ int i;
248
+
249
+ for (i = 0; i < NR_TIMERS; i++) {
250
+ void __iomem *timer_base;
251
+ struct sp804_clkevt *clkevt;
252
+
253
+ timer_base = base + timer->timer_base[i];
254
+ clkevt = &sp804_clkevt[i];
255
+ clkevt->base = timer_base;
256
+ clkevt->load = timer_base + timer->load;
257
+ clkevt->load_h = timer_base + timer->load_h;
258
+ clkevt->value = timer_base + timer->value;
259
+ clkevt->value_h = timer_base + timer->value_h;
260
+ clkevt->ctrl = timer_base + timer->ctrl;
261
+ clkevt->intclr = timer_base + timer->intclr;
262
+ clkevt->width = timer->width;
263
+ }
264
+}
265
+
266
+static int __init sp804_of_init(struct device_node *np, struct sp804_timer *timer)
223267 {
224268 static bool initialized = false;
225269 void __iomem *base;
270
+ void __iomem *timer1_base;
271
+ void __iomem *timer2_base;
226272 int irq, ret = -EINVAL;
227273 u32 irq_num = 0;
228274 struct clk *clk1, *clk2;
229275 const char *name = of_get_property(np, "compatible", NULL);
230276
277
+ if (initialized) {
278
+ pr_debug("%pOF: skipping further SP804 timer device\n", np);
279
+ return 0;
280
+ }
281
+
231282 base = of_iomap(np, 0);
232283 if (!base)
233284 return -ENXIO;
234285
235
- /* Ensure timers are disabled */
236
- writel(0, base + TIMER_CTRL);
237
- writel(0, base + TIMER_2_BASE + TIMER_CTRL);
286
+ timer1_base = base + timer->timer_base[0];
287
+ timer2_base = base + timer->timer_base[1];
238288
239
- if (initialized || !of_device_is_available(np)) {
240
- ret = -EINVAL;
241
- goto err;
242
- }
289
+ /* Ensure timers are disabled */
290
+ writel(0, timer1_base + timer->ctrl);
291
+ writel(0, timer2_base + timer->ctrl);
243292
244293 clk1 = of_clk_get(np, 0);
245294 if (IS_ERR(clk1))
....@@ -249,7 +298,7 @@
249298 if (of_clk_get_parent_count(np) == 3) {
250299 clk2 = of_clk_get(np, 1);
251300 if (IS_ERR(clk2)) {
252
- pr_err("sp804: %s clock not found: %d\n", np->name,
301
+ pr_err("sp804: %pOFn clock not found: %d\n", np,
253302 (int)PTR_ERR(clk2));
254303 clk2 = NULL;
255304 }
....@@ -260,24 +309,27 @@
260309 if (irq <= 0)
261310 goto err;
262311
312
+ sp804_clkevt_init(timer, base);
313
+
263314 of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
264315 if (irq_num == 2) {
265316
266
- ret = __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
317
+ ret = sp804_clockevents_init(timer2_base, irq, clk2, name);
267318 if (ret)
268319 goto err;
269320
270
- ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
321
+ ret = sp804_clocksource_and_sched_clock_init(timer1_base,
322
+ name, clk1, 1);
271323 if (ret)
272324 goto err;
273325 } else {
274326
275
- ret = __sp804_clockevents_init(base, irq, clk1 , name);
327
+ ret = sp804_clockevents_init(timer1_base, irq, clk1, name);
276328 if (ret)
277329 goto err;
278330
279
- ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
280
- name, clk2, 1);
331
+ ret = sp804_clocksource_and_sched_clock_init(timer2_base,
332
+ name, clk2, 1);
281333 if (ret)
282334 goto err;
283335 }
....@@ -288,7 +340,18 @@
288340 iounmap(base);
289341 return ret;
290342 }
291
-TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
343
+
344
+static int __init arm_sp804_of_init(struct device_node *np)
345
+{
346
+ return sp804_of_init(np, &arm_sp804_timer);
347
+}
348
+TIMER_OF_DECLARE(sp804, "arm,sp804", arm_sp804_of_init);
349
+
350
+static int __init hisi_sp804_of_init(struct device_node *np)
351
+{
352
+ return sp804_of_init(np, &hisi_sp804_timer);
353
+}
354
+TIMER_OF_DECLARE(hisi_sp804, "hisilicon,sp804", hisi_sp804_of_init);
292355
293356 static int __init integrator_cp_of_init(struct device_node *np)
294357 {
....@@ -311,13 +374,16 @@
311374 }
312375
313376 /* Ensure timer is disabled */
314
- writel(0, base + TIMER_CTRL);
377
+ writel(0, base + arm_sp804_timer.ctrl);
315378
316379 if (init_count == 2 || !of_device_is_available(np))
317380 goto err;
318381
382
+ sp804_clkevt_init(&arm_sp804_timer, base);
383
+
319384 if (!init_count) {
320
- ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
385
+ ret = sp804_clocksource_and_sched_clock_init(base,
386
+ name, clk, 0);
321387 if (ret)
322388 goto err;
323389 } else {
....@@ -325,7 +391,7 @@
325391 if (irq <= 0)
326392 goto err;
327393
328
- ret = __sp804_clockevents_init(base, irq, clk, name);
394
+ ret = sp804_clockevents_init(base, irq, clk, name);
329395 if (ret)
330396 goto err;
331397 }