xref: /linux/arch/hexagon/kernel/time.c (revision 021bc4b9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Time related functions for Hexagon architecture
4  *
5  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
6  */
7 
8 #include <linux/init.h>
9 #include <linux/clockchips.h>
10 #include <linux/clocksource.h>
11 #include <linux/interrupt.h>
12 #include <linux/err.h>
13 #include <linux/platform_device.h>
14 #include <linux/ioport.h>
15 #include <linux/of.h>
16 #include <linux/of_address.h>
17 #include <linux/of_irq.h>
18 #include <linux/module.h>
19 
20 #include <asm/delay.h>
21 #include <asm/hexagon_vm.h>
22 #include <asm/time.h>
23 
24 #define TIMER_ENABLE		BIT(0)
25 
26 /*
27  * For the clocksource we need:
28  *	pcycle frequency (600MHz)
29  * For the loops_per_jiffy we need:
30  *	thread/cpu frequency (100MHz)
31  * And for the timer, we need:
32  *	sleep clock rate
33  */
34 
35 cycles_t	pcycle_freq_mhz;
36 cycles_t	thread_freq_mhz;
37 cycles_t	sleep_clk_freq;
38 
39 /*
40  * 8x50 HDD Specs 5-8.  Simulator co-sim not fixed until
41  * release 1.1, and then it's "adjustable" and probably not defaulted.
42  */
43 #define RTOS_TIMER_INT		3
44 #define RTOS_TIMER_REGS_ADDR	0xAB000000UL
45 
46 static struct resource rtos_timer_resources[] = {
47 	{
48 		.start	= RTOS_TIMER_REGS_ADDR,
49 		.end	= RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
50 		.flags	= IORESOURCE_MEM,
51 	},
52 };
53 
54 static struct platform_device rtos_timer_device = {
55 	.name		= "rtos_timer",
56 	.id		= -1,
57 	.num_resources	= ARRAY_SIZE(rtos_timer_resources),
58 	.resource	= rtos_timer_resources,
59 };
60 
61 /*  A lot of this stuff should move into a platform specific section.  */
62 struct adsp_hw_timer_struct {
63 	u32 match;   /*  Match value  */
64 	u32 count;
65 	u32 enable;  /*  [1] - CLR_ON_MATCH_EN, [0] - EN  */
66 	u32 clear;   /*  one-shot register that clears the count  */
67 };
68 
69 /*  Look for "TCX0" for related constants.  */
70 static __iomem struct adsp_hw_timer_struct *rtos_timer;
71 
72 static u64 timer_get_cycles(struct clocksource *cs)
73 {
74 	return (u64) __vmgettime();
75 }
76 
77 static struct clocksource hexagon_clocksource = {
78 	.name		= "pcycles",
79 	.rating		= 250,
80 	.read		= timer_get_cycles,
81 	.mask		= CLOCKSOURCE_MASK(64),
82 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
83 };
84 
85 static int set_next_event(unsigned long delta, struct clock_event_device *evt)
86 {
87 	/*  Assuming the timer will be disabled when we enter here.  */
88 
89 	iowrite32(1, &rtos_timer->clear);
90 	iowrite32(0, &rtos_timer->clear);
91 
92 	iowrite32(delta, &rtos_timer->match);
93 	iowrite32(TIMER_ENABLE, &rtos_timer->enable);
94 	return 0;
95 }
96 
97 #ifdef CONFIG_SMP
98 /*  Broadcast mechanism  */
99 static void broadcast(const struct cpumask *mask)
100 {
101 	send_ipi(mask, IPI_TIMER);
102 }
103 #endif
104 
105 /* XXX Implement set_state_shutdown() */
106 static struct clock_event_device hexagon_clockevent_dev = {
107 	.name		= "clockevent",
108 	.features	= CLOCK_EVT_FEAT_ONESHOT,
109 	.rating		= 400,
110 	.irq		= RTOS_TIMER_INT,
111 	.set_next_event = set_next_event,
112 #ifdef CONFIG_SMP
113 	.broadcast	= broadcast,
114 #endif
115 };
116 
117 #ifdef CONFIG_SMP
118 static DEFINE_PER_CPU(struct clock_event_device, clock_events);
119 
120 void setup_percpu_clockdev(void)
121 {
122 	int cpu = smp_processor_id();
123 	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
124 	struct clock_event_device *dummy_clock_dev =
125 		&per_cpu(clock_events, cpu);
126 
127 	memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
128 	INIT_LIST_HEAD(&dummy_clock_dev->list);
129 
130 	dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
131 	dummy_clock_dev->cpumask = cpumask_of(cpu);
132 
133 	clockevents_register_device(dummy_clock_dev);
134 }
135 
136 /*  Called from smp.c for each CPU's timer ipi call  */
137 void ipi_timer(void)
138 {
139 	int cpu = smp_processor_id();
140 	struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
141 
142 	ce_dev->event_handler(ce_dev);
143 }
144 #endif /* CONFIG_SMP */
145 
146 static irqreturn_t timer_interrupt(int irq, void *devid)
147 {
148 	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
149 
150 	iowrite32(0, &rtos_timer->enable);
151 	ce_dev->event_handler(ce_dev);
152 
153 	return IRQ_HANDLED;
154 }
155 
156 /*
157  * time_init_deferred - called by start_kernel to set up timer/clock source
158  *
159  * Install the IRQ handler for the clock, setup timers.
160  * This is done late, as that way, we can use ioremap().
161  *
162  * This runs just before the delay loop is calibrated, and
163  * is used for delay calibration.
164  */
165 static void __init time_init_deferred(void)
166 {
167 	struct resource *resource = NULL;
168 	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
169 	unsigned long flag = IRQF_TIMER | IRQF_TRIGGER_RISING;
170 
171 	ce_dev->cpumask = cpu_all_mask;
172 
173 	if (!resource)
174 		resource = rtos_timer_device.resource;
175 
176 	/*  ioremap here means this has to run later, after paging init  */
177 	rtos_timer = ioremap(resource->start, resource_size(resource));
178 
179 	if (!rtos_timer) {
180 		release_mem_region(resource->start, resource_size(resource));
181 	}
182 	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
183 
184 	/*  Note: the sim generic RTOS clock is apparently really 18750Hz  */
185 
186 	/*
187 	 * Last arg is some guaranteed seconds for which the conversion will
188 	 * work without overflow.
189 	 */
190 	clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
191 
192 	ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
193 	ce_dev->max_delta_ticks = 0x7fffffff;
194 	ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
195 	ce_dev->min_delta_ticks = 0xf;
196 
197 #ifdef CONFIG_SMP
198 	setup_percpu_clockdev();
199 #endif
200 
201 	clockevents_register_device(ce_dev);
202 	if (request_irq(ce_dev->irq, timer_interrupt, flag, "rtos_timer", NULL))
203 		pr_err("Failed to register rtos_timer interrupt\n");
204 }
205 
206 void __init time_init(void)
207 {
208 	late_time_init = time_init_deferred;
209 }
210 
211 void __delay(unsigned long cycles)
212 {
213 	unsigned long long start = __vmgettime();
214 
215 	while ((__vmgettime() - start) < cycles)
216 		cpu_relax();
217 }
218 EXPORT_SYMBOL(__delay);
219 
220 /*
221  * This could become parametric or perhaps even computed at run-time,
222  * but for now we take the observed simulator jitter.
223  */
224 static long long fudgefactor = 350;  /* Maybe lower if kernel optimized. */
225 
226 void __udelay(unsigned long usecs)
227 {
228 	unsigned long long start = __vmgettime();
229 	unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
230 
231 	while ((__vmgettime() - start) < finish)
232 		cpu_relax(); /*  not sure how this improves readability  */
233 }
234 EXPORT_SYMBOL(__udelay);
235