aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig1
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c13
-rw-r--r--drivers/clocksource/time-armada-370-xp.c55
-rw-r--r--drivers/clocksource/timer-atmel-pit.c32
-rw-r--r--drivers/clocksource/timer-integrator-ap.c210
-rw-r--r--drivers/clocksource/timer-marco.c23
7 files changed, 288 insertions, 47 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 90420600e1eb..f657a48d20eb 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -32,6 +32,7 @@ config ARMADA_370_XP_TIMER
32 32
33config MESON6_TIMER 33config MESON6_TIMER
34 bool 34 bool
35 select CLKSRC_MMIO
35 36
36config ORION_TIMER 37config ORION_TIMER
37 select CLKSRC_OF 38 select CLKSRC_OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 756f6f10efa0..fae0435cc23d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -45,4 +45,5 @@ obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
45obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o 45obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
46obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o 46obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
47obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o 47obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
48obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o
48obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o 49obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 43005d4d3348..6a79fc4f900c 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -462,7 +462,10 @@ static void __init arch_counter_register(unsigned type)
462 462
463 /* Register the CP15 based counter if we have one */ 463 /* Register the CP15 based counter if we have one */
464 if (type & ARCH_CP15_TIMER) { 464 if (type & ARCH_CP15_TIMER) {
465 arch_timer_read_counter = arch_counter_get_cntvct; 465 if (arch_timer_use_virtual)
466 arch_timer_read_counter = arch_counter_get_cntvct;
467 else
468 arch_timer_read_counter = arch_counter_get_cntpct;
466 } else { 469 } else {
467 arch_timer_read_counter = arch_counter_get_cntvct_mem; 470 arch_timer_read_counter = arch_counter_get_cntvct_mem;
468 471
@@ -702,6 +705,14 @@ static void __init arch_timer_init(struct device_node *np)
702 arch_timer_detect_rate(NULL, np); 705 arch_timer_detect_rate(NULL, np);
703 706
704 /* 707 /*
708 * If we cannot rely on firmware initializing the timer registers then
709 * we should use the physical timers instead.
710 */
711 if (IS_ENABLED(CONFIG_ARM) &&
712 of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
713 arch_timer_use_virtual = false;
714
715 /*
705 * If HYP mode is available, we know that the physical timer 716 * If HYP mode is available, we know that the physical timer
706 * has been configured to be accessible from PL1. Use it, so 717 * has been configured to be accessible from PL1. Use it, so
707 * that a guest can use the virtual timer instead. 718 * that a guest can use the virtual timer instead.
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 0451e62fac7a..0c8c5e337540 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -43,6 +43,7 @@
43#include <linux/module.h> 43#include <linux/module.h>
44#include <linux/sched_clock.h> 44#include <linux/sched_clock.h>
45#include <linux/percpu.h> 45#include <linux/percpu.h>
46#include <linux/syscore_ops.h>
46 47
47/* 48/*
48 * Timer block registers. 49 * Timer block registers.
@@ -223,6 +224,28 @@ static struct notifier_block armada_370_xp_timer_cpu_nb = {
223 .notifier_call = armada_370_xp_timer_cpu_notify, 224 .notifier_call = armada_370_xp_timer_cpu_notify,
224}; 225};
225 226
227static u32 timer0_ctrl_reg, timer0_local_ctrl_reg;
228
229static int armada_370_xp_timer_suspend(void)
230{
231 timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF);
232 timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF);
233 return 0;
234}
235
236static void armada_370_xp_timer_resume(void)
237{
238 writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
239 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
240 writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF);
241 writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF);
242}
243
244struct syscore_ops armada_370_xp_timer_syscore_ops = {
245 .suspend = armada_370_xp_timer_suspend,
246 .resume = armada_370_xp_timer_resume,
247};
248
226static void __init armada_370_xp_timer_common_init(struct device_node *np) 249static void __init armada_370_xp_timer_common_init(struct device_node *np)
227{ 250{
228 u32 clr = 0, set = 0; 251 u32 clr = 0, set = 0;
@@ -285,6 +308,8 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
285 /* Immediately configure the timer on the boot CPU */ 308 /* Immediately configure the timer on the boot CPU */
286 if (!res) 309 if (!res)
287 armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); 310 armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
311
312 register_syscore_ops(&armada_370_xp_timer_syscore_ops);
288} 313}
289 314
290static void __init armada_xp_timer_init(struct device_node *np) 315static void __init armada_xp_timer_init(struct device_node *np)
@@ -293,6 +318,7 @@ static void __init armada_xp_timer_init(struct device_node *np)
293 318
294 /* The 25Mhz fixed clock is mandatory, and must always be available */ 319 /* The 25Mhz fixed clock is mandatory, and must always be available */
295 BUG_ON(IS_ERR(clk)); 320 BUG_ON(IS_ERR(clk));
321 clk_prepare_enable(clk);
296 timer_clk = clk_get_rate(clk); 322 timer_clk = clk_get_rate(clk);
297 323
298 armada_370_xp_timer_common_init(np); 324 armada_370_xp_timer_common_init(np);
@@ -300,11 +326,40 @@ static void __init armada_xp_timer_init(struct device_node *np)
300CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", 326CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
301 armada_xp_timer_init); 327 armada_xp_timer_init);
302 328
329static void __init armada_375_timer_init(struct device_node *np)
330{
331 struct clk *clk;
332
333 clk = of_clk_get_by_name(np, "fixed");
334 if (!IS_ERR(clk)) {
335 clk_prepare_enable(clk);
336 timer_clk = clk_get_rate(clk);
337 } else {
338
339 /*
340 * This fallback is required in order to retain proper
341 * devicetree backwards compatibility.
342 */
343 clk = of_clk_get(np, 0);
344
345 /* Must have at least a clock */
346 BUG_ON(IS_ERR(clk));
347 clk_prepare_enable(clk);
348 timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
349 timer25Mhz = false;
350 }
351
352 armada_370_xp_timer_common_init(np);
353}
354CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
355 armada_375_timer_init);
356
303static void __init armada_370_timer_init(struct device_node *np) 357static void __init armada_370_timer_init(struct device_node *np)
304{ 358{
305 struct clk *clk = of_clk_get(np, 0); 359 struct clk *clk = of_clk_get(np, 0);
306 360
307 BUG_ON(IS_ERR(clk)); 361 BUG_ON(IS_ERR(clk));
362 clk_prepare_enable(clk);
308 timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; 363 timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
309 timer25Mhz = false; 364 timer25Mhz = false;
310 365
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index d5289098b3df..b5b4d4585c9a 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -262,35 +262,3 @@ static void __init at91sam926x_pit_dt_init(struct device_node *node)
262} 262}
263CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", 263CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
264 at91sam926x_pit_dt_init); 264 at91sam926x_pit_dt_init);
265
266static void __iomem *pit_base_addr;
267
268void __init at91sam926x_pit_init(int irq)
269{
270 struct pit_data *data;
271
272 data = kzalloc(sizeof(*data), GFP_KERNEL);
273 if (!data)
274 panic(pr_fmt("Unable to allocate memory\n"));
275
276 data->base = pit_base_addr;
277
278 data->mck = clk_get(NULL, "mck");
279 if (IS_ERR(data->mck))
280 panic(pr_fmt("Unable to get mck clk\n"));
281
282 data->irq = irq;
283
284 at91sam926x_pit_common_init(data);
285}
286
287void __init at91sam926x_ioremap_pit(u32 addr)
288{
289 if (of_have_populated_dt())
290 return;
291
292 pit_base_addr = ioremap(addr, 16);
293
294 if (!pit_base_addr)
295 panic(pr_fmt("Impossible to ioremap PIT\n"));
296}
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
new file mode 100644
index 000000000000..b9efd30513d5
--- /dev/null
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -0,0 +1,210 @@
1/*
2 * Integrator/AP timer driver
3 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
4 * Copyright (c) 2014, Linaro Limited
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/clk.h>
22#include <linux/clocksource.h>
23#include <linux/of_irq.h>
24#include <linux/of_address.h>
25#include <linux/of_platform.h>
26#include <linux/clockchips.h>
27#include <linux/interrupt.h>
28#include <linux/sched_clock.h>
29#include <asm/hardware/arm_timer.h>
30
31static void __iomem * sched_clk_base;
32
33static u64 notrace integrator_read_sched_clock(void)
34{
35 return -readl(sched_clk_base + TIMER_VALUE);
36}
37
38static void integrator_clocksource_init(unsigned long inrate,
39 void __iomem *base)
40{
41 u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
42 unsigned long rate = inrate;
43
44 if (rate >= 1500000) {
45 rate /= 16;
46 ctrl |= TIMER_CTRL_DIV16;
47 }
48
49 writel(0xffff, base + TIMER_LOAD);
50 writel(ctrl, base + TIMER_CTRL);
51
52 clocksource_mmio_init(base + TIMER_VALUE, "timer2",
53 rate, 200, 16, clocksource_mmio_readl_down);
54
55 sched_clk_base = base;
56 sched_clock_register(integrator_read_sched_clock, 16, rate);
57}
58
59static unsigned long timer_reload;
60static void __iomem * clkevt_base;
61
62/*
63 * IRQ handler for the timer
64 */
65static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
66{
67 struct clock_event_device *evt = dev_id;
68
69 /* clear the interrupt */
70 writel(1, clkevt_base + TIMER_INTCLR);
71
72 evt->event_handler(evt);
73
74 return IRQ_HANDLED;
75}
76
77static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
78{
79 u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
80
81 /* Disable timer */
82 writel(ctrl, clkevt_base + TIMER_CTRL);
83
84 switch (mode) {
85 case CLOCK_EVT_MODE_PERIODIC:
86 /* Enable the timer and start the periodic tick */
87 writel(timer_reload, clkevt_base + TIMER_LOAD);
88 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
89 writel(ctrl, clkevt_base + TIMER_CTRL);
90 break;
91 case CLOCK_EVT_MODE_ONESHOT:
92 /* Leave the timer disabled, .set_next_event will enable it */
93 ctrl &= ~TIMER_CTRL_PERIODIC;
94 writel(ctrl, clkevt_base + TIMER_CTRL);
95 break;
96 case CLOCK_EVT_MODE_UNUSED:
97 case CLOCK_EVT_MODE_SHUTDOWN:
98 case CLOCK_EVT_MODE_RESUME:
99 default:
100 /* Just leave in disabled state */
101 break;
102 }
103
104}
105
106static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
107{
108 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
109
110 writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
111 writel(next, clkevt_base + TIMER_LOAD);
112 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
113
114 return 0;
115}
116
117static struct clock_event_device integrator_clockevent = {
118 .name = "timer1",
119 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
120 .set_mode = clkevt_set_mode,
121 .set_next_event = clkevt_set_next_event,
122 .rating = 300,
123};
124
125static struct irqaction integrator_timer_irq = {
126 .name = "timer",
127 .flags = IRQF_TIMER | IRQF_IRQPOLL,
128 .handler = integrator_timer_interrupt,
129 .dev_id = &integrator_clockevent,
130};
131
132static void integrator_clockevent_init(unsigned long inrate,
133 void __iomem *base, int irq)
134{
135 unsigned long rate = inrate;
136 unsigned int ctrl = 0;
137
138 clkevt_base = base;
139 /* Calculate and program a divisor */
140 if (rate > 0x100000 * HZ) {
141 rate /= 256;
142 ctrl |= TIMER_CTRL_DIV256;
143 } else if (rate > 0x10000 * HZ) {
144 rate /= 16;
145 ctrl |= TIMER_CTRL_DIV16;
146 }
147 timer_reload = rate / HZ;
148 writel(ctrl, clkevt_base + TIMER_CTRL);
149
150 setup_irq(irq, &integrator_timer_irq);
151 clockevents_config_and_register(&integrator_clockevent,
152 rate,
153 1,
154 0xffffU);
155}
156
157static void __init integrator_ap_timer_init_of(struct device_node *node)
158{
159 const char *path;
160 void __iomem *base;
161 int err;
162 int irq;
163 struct clk *clk;
164 unsigned long rate;
165 struct device_node *pri_node;
166 struct device_node *sec_node;
167
168 base = of_io_request_and_map(node, 0, "integrator-timer");
169 if (!base)
170 return;
171
172 clk = of_clk_get(node, 0);
173 if (IS_ERR(clk)) {
174 pr_err("No clock for %s\n", node->name);
175 return;
176 }
177 clk_prepare_enable(clk);
178 rate = clk_get_rate(clk);
179 writel(0, base + TIMER_CTRL);
180
181 err = of_property_read_string(of_aliases,
182 "arm,timer-primary", &path);
183 if (WARN_ON(err))
184 return;
185 pri_node = of_find_node_by_path(path);
186 err = of_property_read_string(of_aliases,
187 "arm,timer-secondary", &path);
188 if (WARN_ON(err))
189 return;
190 sec_node = of_find_node_by_path(path);
191
192 if (node == pri_node) {
193 /* The primary timer lacks IRQ, use as clocksource */
194 integrator_clocksource_init(rate, base);
195 return;
196 }
197
198 if (node == sec_node) {
199 /* The secondary timer will drive the clock event */
200 irq = irq_of_parse_and_map(node, 0);
201 integrator_clockevent_init(rate, base, irq);
202 return;
203 }
204
205 pr_info("Timer @%p unused\n", base);
206 clk_disable_unprepare(clk);
207}
208
209CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
210 integrator_ap_timer_init_of);
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index caf7a2030461..361a789d4bee 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -20,8 +20,6 @@
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/sched_clock.h> 21#include <linux/sched_clock.h>
22 22
23#define MARCO_CLOCK_FREQ 1000000
24
25#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 23#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
26#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 24#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004
27#define SIRFSOC_TIMER_MATCH_0 0x0018 25#define SIRFSOC_TIMER_MATCH_0 0x0018
@@ -40,6 +38,8 @@
40 38
41#define SIRFSOC_TIMER_REG_CNT 6 39#define SIRFSOC_TIMER_REG_CNT 6
42 40
41static unsigned long marco_timer_rate;
42
43static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { 43static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
44 SIRFSOC_TIMER_WATCHDOG_EN, 44 SIRFSOC_TIMER_WATCHDOG_EN,
45 SIRFSOC_TIMER_32COUNTER_0_CTRL, 45 SIRFSOC_TIMER_32COUNTER_0_CTRL,
@@ -195,7 +195,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
195 ce->rating = 200; 195 ce->rating = 200;
196 ce->set_mode = sirfsoc_timer_set_mode; 196 ce->set_mode = sirfsoc_timer_set_mode;
197 ce->set_next_event = sirfsoc_timer_set_next_event; 197 ce->set_next_event = sirfsoc_timer_set_next_event;
198 clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60); 198 clockevents_calc_mult_shift(ce, marco_timer_rate, 60);
199 ce->max_delta_ns = clockevent_delta2ns(-2, ce); 199 ce->max_delta_ns = clockevent_delta2ns(-2, ce);
200 ce->min_delta_ns = clockevent_delta2ns(2, ce); 200 ce->min_delta_ns = clockevent_delta2ns(2, ce);
201 ce->cpumask = cpumask_of(cpu); 201 ce->cpumask = cpumask_of(cpu);
@@ -257,7 +257,6 @@ static void __init sirfsoc_clockevent_init(void)
257/* initialize the kernel jiffy timer source */ 257/* initialize the kernel jiffy timer source */
258static void __init sirfsoc_marco_timer_init(struct device_node *np) 258static void __init sirfsoc_marco_timer_init(struct device_node *np)
259{ 259{
260 unsigned long rate;
261 u32 timer_div; 260 u32 timer_div;
262 struct clk *clk; 261 struct clk *clk;
263 262
@@ -266,16 +265,12 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
266 265
267 BUG_ON(clk_prepare_enable(clk)); 266 BUG_ON(clk_prepare_enable(clk));
268 267
269 rate = clk_get_rate(clk); 268 marco_timer_rate = clk_get_rate(clk);
270
271 BUG_ON(rate < MARCO_CLOCK_FREQ);
272 BUG_ON(rate % MARCO_CLOCK_FREQ);
273 269
274 /* Initialize the timer dividers */ 270 /* timer dividers: 0, not divided */
275 timer_div = rate / MARCO_CLOCK_FREQ - 1; 271 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
276 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); 272 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
277 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); 273 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
278 writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
279 274
280 /* Initialize timer counters to 0 */ 275 /* Initialize timer counters to 0 */
281 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); 276 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
@@ -288,7 +283,7 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
288 /* Clear all interrupts */ 283 /* Clear all interrupts */
289 writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); 284 writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
290 285
291 BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, MARCO_CLOCK_FREQ)); 286 BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate));
292 287
293 sirfsoc_clockevent_init(); 288 sirfsoc_clockevent_init();
294} 289}