Linux Audio

Check our new training course

Loading...
v5.9
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 *  linux/arch/arm/kernel/arch_timer.c
 4 *
 5 *  Copyright (C) 2011 ARM Ltd.
 6 *  All Rights Reserved
 
 
 
 
 7 */
 8#include <linux/init.h>
 9#include <linux/types.h>
10#include <linux/errno.h>
 
 
 
 
 
 
 
 
11
12#include <asm/delay.h>
 
13#include <asm/arch_timer.h>
 
 
 
 
 
 
 
 
 
 
 
 
14
15#include <clocksource/arm_arch_timer.h>
 
 
16
17static unsigned long arch_timer_read_counter_long(void)
 
 
 
 
18{
19	return arch_timer_read_counter();
 
 
 
 
 
 
 
 
 
20}
21
22static struct delay_timer arch_delay_timer;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24static void __init arch_timer_delay_timer_register(void)
25{
26	/* Use the architected timer for the delay loop. */
27	arch_delay_timer.read_current_timer = arch_timer_read_counter_long;
28	arch_delay_timer.freq = arch_timer_get_rate();
29	register_current_timer_delay(&arch_delay_timer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30}
31
32int __init arch_timer_arch_init(void)
 
33{
34        u32 arch_timer_rate = arch_timer_get_rate();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36	if (arch_timer_rate == 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37		return -ENXIO;
38
39	arch_timer_delay_timer_register();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41	return 0;
42}
v3.5.6
 
  1/*
  2 *  linux/arch/arm/kernel/arch_timer.c
  3 *
  4 *  Copyright (C) 2011 ARM Ltd.
  5 *  All Rights Reserved
  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 version 2 as
  9 * published by the Free Software Foundation.
 10 */
 11#include <linux/init.h>
 12#include <linux/kernel.h>
 13#include <linux/delay.h>
 14#include <linux/device.h>
 15#include <linux/smp.h>
 16#include <linux/cpu.h>
 17#include <linux/jiffies.h>
 18#include <linux/clockchips.h>
 19#include <linux/interrupt.h>
 20#include <linux/of_irq.h>
 21#include <linux/io.h>
 22
 23#include <asm/cputype.h>
 24#include <asm/localtimer.h>
 25#include <asm/arch_timer.h>
 26#include <asm/system_info.h>
 27#include <asm/sched_clock.h>
 28
 29static unsigned long arch_timer_rate;
 30static int arch_timer_ppi;
 31static int arch_timer_ppi2;
 32
 33static struct clock_event_device __percpu **arch_timer_evt;
 34
 35/*
 36 * Architected system timer support.
 37 */
 38
 39#define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
 40#define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
 41#define ARCH_TIMER_CTRL_IT_STAT		(1 << 2)
 42
 43#define ARCH_TIMER_REG_CTRL		0
 44#define ARCH_TIMER_REG_FREQ		1
 45#define ARCH_TIMER_REG_TVAL		2
 46
 47static void arch_timer_reg_write(int reg, u32 val)
 48{
 49	switch (reg) {
 50	case ARCH_TIMER_REG_CTRL:
 51		asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
 52		break;
 53	case ARCH_TIMER_REG_TVAL:
 54		asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
 55		break;
 56	}
 57
 58	isb();
 59}
 60
 61static u32 arch_timer_reg_read(int reg)
 62{
 63	u32 val;
 64
 65	switch (reg) {
 66	case ARCH_TIMER_REG_CTRL:
 67		asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
 68		break;
 69	case ARCH_TIMER_REG_FREQ:
 70		asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
 71		break;
 72	case ARCH_TIMER_REG_TVAL:
 73		asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
 74		break;
 75	default:
 76		BUG();
 77	}
 78
 79	return val;
 80}
 81
 82static irqreturn_t arch_timer_handler(int irq, void *dev_id)
 83{
 84	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
 85	unsigned long ctrl;
 86
 87	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
 88	if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
 89		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
 90		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
 91		evt->event_handler(evt);
 92		return IRQ_HANDLED;
 93	}
 94
 95	return IRQ_NONE;
 96}
 97
 98static void arch_timer_disable(void)
 99{
100	unsigned long ctrl;
101
102	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
103	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
104	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
105}
106
107static void arch_timer_set_mode(enum clock_event_mode mode,
108				struct clock_event_device *clk)
109{
110	switch (mode) {
111	case CLOCK_EVT_MODE_UNUSED:
112	case CLOCK_EVT_MODE_SHUTDOWN:
113		arch_timer_disable();
114		break;
115	default:
116		break;
117	}
118}
119
120static int arch_timer_set_next_event(unsigned long evt,
121				     struct clock_event_device *unused)
122{
123	unsigned long ctrl;
124
125	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
126	ctrl |= ARCH_TIMER_CTRL_ENABLE;
127	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
128
129	arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
130	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
131
132	return 0;
133}
134
135static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
136{
137	/* Be safe... */
138	arch_timer_disable();
139
140	clk->features = CLOCK_EVT_FEAT_ONESHOT;
141	clk->name = "arch_sys_timer";
142	clk->rating = 450;
143	clk->set_mode = arch_timer_set_mode;
144	clk->set_next_event = arch_timer_set_next_event;
145	clk->irq = arch_timer_ppi;
146
147	clockevents_config_and_register(clk, arch_timer_rate,
148					0xf, 0x7fffffff);
149
150	*__this_cpu_ptr(arch_timer_evt) = clk;
151
152	enable_percpu_irq(clk->irq, 0);
153	if (arch_timer_ppi2)
154		enable_percpu_irq(arch_timer_ppi2, 0);
155
156	return 0;
157}
158
159/* Is the optional system timer available? */
160static int local_timer_is_architected(void)
161{
162	return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
163	       ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
164}
165
166static int arch_timer_available(void)
167{
168	unsigned long freq;
169
170	if (!local_timer_is_architected())
171		return -ENXIO;
172
173	if (arch_timer_rate == 0) {
174		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
175		freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
176
177		/* Check the timer frequency. */
178		if (freq == 0) {
179			pr_warn("Architected timer frequency not available\n");
180			return -EINVAL;
181		}
182
183		arch_timer_rate = freq;
184	}
185
186	pr_info_once("Architected local timer running at %lu.%02luMHz.\n",
187		     arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100);
188	return 0;
189}
190
191static inline cycle_t arch_counter_get_cntpct(void)
192{
193	u32 cvall, cvalh;
194
195	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
196
197	return ((cycle_t) cvalh << 32) | cvall;
198}
199
200static inline cycle_t arch_counter_get_cntvct(void)
201{
202	u32 cvall, cvalh;
203
204	asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
205
206	return ((cycle_t) cvalh << 32) | cvall;
207}
208
209static u32 notrace arch_counter_get_cntvct32(void)
210{
211	cycle_t cntvct = arch_counter_get_cntvct();
212
213	/*
214	 * The sched_clock infrastructure only knows about counters
215	 * with at most 32bits. Forget about the upper 24 bits for the
216	 * time being...
217	 */
218	return (u32)(cntvct & (u32)~0);
219}
220
221static cycle_t arch_counter_read(struct clocksource *cs)
222{
223	return arch_counter_get_cntpct();
224}
225
226static struct clocksource clocksource_counter = {
227	.name	= "arch_sys_counter",
228	.rating	= 400,
229	.read	= arch_counter_read,
230	.mask	= CLOCKSOURCE_MASK(56),
231	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
232};
233
234static void __cpuinit arch_timer_stop(struct clock_event_device *clk)
235{
236	pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
237		 clk->irq, smp_processor_id());
238	disable_percpu_irq(clk->irq);
239	if (arch_timer_ppi2)
240		disable_percpu_irq(arch_timer_ppi2);
241	arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
242}
243
244static struct local_timer_ops arch_timer_ops __cpuinitdata = {
245	.setup	= arch_timer_setup,
246	.stop	= arch_timer_stop,
247};
248
249static struct clock_event_device arch_timer_global_evt;
250
251static int __init arch_timer_register(void)
252{
253	int err;
254
255	err = arch_timer_available();
256	if (err)
257		return err;
258
259	arch_timer_evt = alloc_percpu(struct clock_event_device *);
260	if (!arch_timer_evt)
261		return -ENOMEM;
262
263	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
264
265	err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
266				 "arch_timer", arch_timer_evt);
267	if (err) {
268		pr_err("arch_timer: can't register interrupt %d (%d)\n",
269		       arch_timer_ppi, err);
270		goto out_free;
271	}
272
273	if (arch_timer_ppi2) {
274		err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
275					 "arch_timer", arch_timer_evt);
276		if (err) {
277			pr_err("arch_timer: can't register interrupt %d (%d)\n",
278			       arch_timer_ppi2, err);
279			arch_timer_ppi2 = 0;
280			goto out_free_irq;
281		}
282	}
283
284	err = local_timer_register(&arch_timer_ops);
285	if (err) {
286		/*
287		 * We couldn't register as a local timer (could be
288		 * because we're on a UP platform, or because some
289		 * other local timer is already present...). Try as a
290		 * global timer instead.
291		 */
292		arch_timer_global_evt.cpumask = cpumask_of(0);
293		err = arch_timer_setup(&arch_timer_global_evt);
294	}
295
296	if (err)
297		goto out_free_irq;
298
299	return 0;
300
301out_free_irq:
302	free_percpu_irq(arch_timer_ppi, arch_timer_evt);
303	if (arch_timer_ppi2)
304		free_percpu_irq(arch_timer_ppi2, arch_timer_evt);
305
306out_free:
307	free_percpu(arch_timer_evt);
308
309	return err;
310}
311
312static const struct of_device_id arch_timer_of_match[] __initconst = {
313	{ .compatible	= "arm,armv7-timer",	},
314	{},
315};
316
317int __init arch_timer_of_register(void)
318{
319	struct device_node *np;
320	u32 freq;
321
322	np = of_find_matching_node(NULL, arch_timer_of_match);
323	if (!np) {
324		pr_err("arch_timer: can't find DT node\n");
325		return -ENODEV;
326	}
327
328	/* Try to determine the frequency from the device tree or CNTFRQ */
329	if (!of_property_read_u32(np, "clock-frequency", &freq))
330		arch_timer_rate = freq;
331
332	arch_timer_ppi = irq_of_parse_and_map(np, 0);
333	arch_timer_ppi2 = irq_of_parse_and_map(np, 1);
334	pr_info("arch_timer: found %s irqs %d %d\n",
335		np->name, arch_timer_ppi, arch_timer_ppi2);
336
337	return arch_timer_register();
338}
339
340int __init arch_timer_sched_clock_init(void)
341{
342	int err;
343
344	err = arch_timer_available();
345	if (err)
346		return err;
347
348	setup_sched_clock(arch_counter_get_cntvct32, 32, arch_timer_rate);
349	return 0;
350}