hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
commit | author | age
a07526 1 // SPDX-License-Identifier: GPL-2.0-only
H 2 /*
3  *  linux/arch/arm/kernel/smp_twd.c
4  *
5  *  Copyright (C) 2002 ARM Ltd.
6  *  All Rights Reserved
7  */
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <linux/cpu.h>
12 #include <linux/delay.h>
13 #include <linux/device.h>
14 #include <linux/err.h>
15 #include <linux/smp.h>
16 #include <linux/jiffies.h>
17 #include <linux/clockchips.h>
18 #include <linux/interrupt.h>
19 #include <linux/io.h>
20 #include <linux/of_irq.h>
21 #include <linux/of_address.h>
22
23 #include <asm/smp_twd.h>
24
25 /* set up by the platform code */
26 static void __iomem *twd_base;
27
28 static struct clk *twd_clk;
29 static unsigned long twd_timer_rate;
30 static DEFINE_PER_CPU(bool, percpu_setup_called);
31
32 static struct clock_event_device __percpu *twd_evt;
33 static unsigned int twd_features =
2f529f 34        CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PIPELINE;
a07526 35 static int twd_ppi;
H 36
37 static int twd_shutdown(struct clock_event_device *clk)
38 {
39    writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
40    return 0;
41 }
42
43 static int twd_set_oneshot(struct clock_event_device *clk)
44 {
45    /* period set, and timer enabled in 'next_event' hook */
46    writel_relaxed(TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT,
47               twd_base + TWD_TIMER_CONTROL);
48    return 0;
49 }
50
51 static int twd_set_periodic(struct clock_event_device *clk)
52 {
53    unsigned long ctrl = TWD_TIMER_CONTROL_ENABLE |
54                 TWD_TIMER_CONTROL_IT_ENABLE |
55                 TWD_TIMER_CONTROL_PERIODIC;
56
57    writel_relaxed(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
58               twd_base + TWD_TIMER_LOAD);
59    writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
60    return 0;
61 }
62
63 static int twd_set_next_event(unsigned long evt,
64            struct clock_event_device *unused)
65 {
66    unsigned long ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL);
67
68    ctrl |= TWD_TIMER_CONTROL_ENABLE;
69
70    writel_relaxed(evt, twd_base + TWD_TIMER_COUNTER);
71    writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
72
73    return 0;
74 }
75
76 /*
77  * local_timer_ack: checks for a local timer interrupt.
78  *
79  * If a local timer interrupt has occurred, acknowledge and return 1.
80  * Otherwise, return 0.
81  */
82 static int twd_timer_ack(void)
83 {
84    if (readl_relaxed(twd_base + TWD_TIMER_INTSTAT)) {
85        writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT);
86        return 1;
87    }
88
89    return 0;
90 }
91
92 static void twd_timer_stop(void)
93 {
94    struct clock_event_device *clk = raw_cpu_ptr(twd_evt);
95
96    twd_shutdown(clk);
97    disable_percpu_irq(clk->irq);
98 }
99
100 /*
101  * Updates clockevent frequency when the cpu frequency changes.
102  * Called on the cpu that is changing frequency with interrupts disabled.
103  */
104 static void twd_update_frequency(void *new_rate)
105 {
106    twd_timer_rate = *((unsigned long *) new_rate);
107
108    clockevents_update_freq(raw_cpu_ptr(twd_evt), twd_timer_rate);
109 }
110
111 static int twd_rate_change(struct notifier_block *nb,
112    unsigned long flags, void *data)
113 {
114    struct clk_notifier_data *cnd = data;
115
116    /*
117     * The twd clock events must be reprogrammed to account for the new
118     * frequency.  The timer is local to a cpu, so cross-call to the
119     * changing cpu.
120     */
121    if (flags == POST_RATE_CHANGE)
122        on_each_cpu(twd_update_frequency,
123                  (void *)&cnd->new_rate, 1);
124
125    return NOTIFY_OK;
126 }
127
128 static struct notifier_block twd_clk_nb = {
129    .notifier_call = twd_rate_change,
130 };
131
132 static int twd_clk_init(void)
133 {
134    if (twd_evt && raw_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
135        return clk_notifier_register(twd_clk, &twd_clk_nb);
136
137    return 0;
138 }
139 core_initcall(twd_clk_init);
140
141 static void twd_calibrate_rate(void)
142 {
143    unsigned long count;
144    u64 waitjiffies;
145
146    /*
147     * If this is the first time round, we need to work out how fast
148     * the timer ticks
149     */
150    if (twd_timer_rate == 0) {
151        pr_info("Calibrating local timer... ");
152
153        /* Wait for a tick to start */
154        waitjiffies = get_jiffies_64() + 1;
155
156        while (get_jiffies_64() < waitjiffies)
157            udelay(10);
158
159        /* OK, now the tick has started, let's get the timer going */
160        waitjiffies += 5;
161
162                 /* enable, no interrupt or reload */
163        writel_relaxed(0x1, twd_base + TWD_TIMER_CONTROL);
164
165                 /* maximum value */
166        writel_relaxed(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
167
168        while (get_jiffies_64() < waitjiffies)
169            udelay(10);
170
171        count = readl_relaxed(twd_base + TWD_TIMER_COUNTER);
172
173        twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
174
175        pr_cont("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
176            (twd_timer_rate / 10000) % 100);
177    }
178 }
179
180 static irqreturn_t twd_handler(int irq, void *dev_id)
181 {
182    struct clock_event_device *evt = dev_id;
183
184    if (twd_timer_ack()) {
2f529f 185        clockevents_handle_event(evt);
a07526 186        return IRQ_HANDLED;
H 187    }
188
189    return IRQ_NONE;
190 }
191
192 static void twd_get_clock(struct device_node *np)
193 {
194    int err;
195
196    if (np)
197        twd_clk = of_clk_get(np, 0);
198    else
199        twd_clk = clk_get_sys("smp_twd", NULL);
200
201    if (IS_ERR(twd_clk)) {
202        pr_err("smp_twd: clock not found %d\n", (int) PTR_ERR(twd_clk));
203        return;
204    }
205
206    err = clk_prepare_enable(twd_clk);
207    if (err) {
208        pr_err("smp_twd: clock failed to prepare+enable: %d\n", err);
209        clk_put(twd_clk);
210        return;
211    }
212
213    twd_timer_rate = clk_get_rate(twd_clk);
214 }
215
216 /*
217  * Setup the local clock events for a CPU.
218  */
219 static void twd_timer_setup(void)
220 {
221    struct clock_event_device *clk = raw_cpu_ptr(twd_evt);
222    int cpu = smp_processor_id();
223
224    /*
225     * If the basic setup for this CPU has been done before don't
226     * bother with the below.
227     */
228    if (per_cpu(percpu_setup_called, cpu)) {
229        writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
230        clockevents_register_device(clk);
231        enable_percpu_irq(clk->irq, 0);
232        return;
233    }
234    per_cpu(percpu_setup_called, cpu) = true;
235
236    twd_calibrate_rate();
237
238    /*
239     * The following is done once per CPU the first time .setup() is
240     * called.
241     */
242    writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
243
244    clk->name = "local_timer";
245    clk->features = twd_features;
246    clk->rating = 350;
247    clk->set_state_shutdown = twd_shutdown;
248    clk->set_state_periodic = twd_set_periodic;
249    clk->set_state_oneshot = twd_set_oneshot;
250    clk->tick_resume = twd_shutdown;
251    clk->set_next_event = twd_set_next_event;
252    clk->irq = twd_ppi;
253    clk->cpumask = cpumask_of(cpu);
254
255    clockevents_config_and_register(clk, twd_timer_rate,
256                    0xf, 0xffffffff);
257    enable_percpu_irq(clk->irq, 0);
258 }
259
260 static int twd_timer_starting_cpu(unsigned int cpu)
261 {
262    twd_timer_setup();
263    return 0;
264 }
265
266 static int twd_timer_dying_cpu(unsigned int cpu)
267 {
268    twd_timer_stop();
269    return 0;
270 }
271
272 static int __init twd_local_timer_common_register(struct device_node *np)
273 {
274    int err;
275
276    twd_evt = alloc_percpu(struct clock_event_device);
277    if (!twd_evt) {
278        err = -ENOMEM;
279        goto out_free;
280    }
281
2f529f 282    err = __request_percpu_irq(twd_ppi, twd_handler,
H 283                   IRQF_TIMER, "twd", twd_evt);
a07526 284    if (err) {
H 285        pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err);
286        goto out_free;
287    }
288
289    cpuhp_setup_state_nocalls(CPUHP_AP_ARM_TWD_STARTING,
290                  "arm/timer/twd:starting",
291                  twd_timer_starting_cpu, twd_timer_dying_cpu);
292
293    twd_get_clock(np);
294    if (!of_property_read_bool(np, "always-on"))
295        twd_features |= CLOCK_EVT_FEAT_C3STOP;
296
297    /*
298     * Immediately configure the timer on the boot CPU, unless we need
299     * jiffies to be incrementing to calibrate the rate in which case
300     * setup the timer in late_time_init.
301     */
302    if (twd_timer_rate)
303        twd_timer_setup();
304    else
305        late_time_init = twd_timer_setup;
306
307    return 0;
308
309 out_free:
310    iounmap(twd_base);
311    twd_base = NULL;
312    free_percpu(twd_evt);
313
314    return err;
315 }
316
317 static int __init twd_local_timer_of_register(struct device_node *np)
318 {
319    int err;
320
321    twd_ppi = irq_of_parse_and_map(np, 0);
322    if (!twd_ppi) {
323        err = -EINVAL;
324        goto out;
325    }
326
327    twd_base = of_iomap(np, 0);
328    if (!twd_base) {
329        err = -ENOMEM;
330        goto out;
331    }
332
333    err = twd_local_timer_common_register(np);
334
335 out:
336    WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
337    return err;
338 }
339 TIMER_OF_DECLARE(arm_twd_a9, "arm,cortex-a9-twd-timer", twd_local_timer_of_register);
340 TIMER_OF_DECLARE(arm_twd_a5, "arm,cortex-a5-twd-timer", twd_local_timer_of_register);
341 TIMER_OF_DECLARE(arm_twd_11mp, "arm,arm11mp-twd-timer", twd_local_timer_of_register);