Blame view
drivers/clocksource/timer-atmel-st.c
6.19 KB
1a59d1b8e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
73a59c1c4 [ARM] 3240/2: AT9... |
2 |
/* |
9d0412680 [ARM] 4124/1: Ren... |
3 |
* linux/arch/arm/mach-at91/at91rm9200_time.c |
73a59c1c4 [ARM] 3240/2: AT9... |
4 5 6 |
* * Copyright (C) 2003 SAN People * Copyright (C) 2003 ATMEL |
73a59c1c4 [ARM] 3240/2: AT9... |
7 |
*/ |
5e802dfab [ARM] 4539/1: clo... |
8 |
#include <linux/kernel.h> |
73a59c1c4 [ARM] 3240/2: AT9... |
9 |
#include <linux/interrupt.h> |
07d265dd5 [ARM] 3683/2: AR... |
10 |
#include <linux/irq.h> |
216ab8f15 clocksource: atme... |
11 |
#include <linux/clk.h> |
5e802dfab [ARM] 4539/1: clo... |
12 |
#include <linux/clockchips.h> |
9fce85c7e ARM: at91: Export... |
13 |
#include <linux/export.h> |
adf2edfd6 clocksource: atme... |
14 15 |
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon/atmel-st.h> |
454c46df8 ARM: AT91: Add DT... |
16 |
#include <linux/of_irq.h> |
adf2edfd6 clocksource: atme... |
17 |
#include <linux/regmap.h> |
73a59c1c4 [ARM] 3240/2: AT9... |
18 |
|
963151f24 [ARM] 3579/1: AT9... |
19 |
static unsigned long last_crtr; |
5e802dfab [ARM] 4539/1: clo... |
20 21 |
static u32 irqmask; static struct clock_event_device clkevt; |
adf2edfd6 clocksource: atme... |
22 |
static struct regmap *regmap_st; |
216ab8f15 clocksource: atme... |
23 |
static int timer_latch; |
2f5893cf4 ARM: at91: define... |
24 |
|
73a59c1c4 [ARM] 3240/2: AT9... |
25 |
/* |
5e802dfab [ARM] 4539/1: clo... |
26 27 28 |
* The ST_CRTR is updated asynchronously to the master clock ... but * the updates as seen by the CPU don't seem to be strictly monotonic. * Waiting until we read the same value twice avoids glitching. |
73a59c1c4 [ARM] 3240/2: AT9... |
29 |
*/ |
5e802dfab [ARM] 4539/1: clo... |
30 31 |
static inline unsigned long read_CRTR(void) { |
adf2edfd6 clocksource: atme... |
32 |
unsigned int x1, x2; |
73a59c1c4 [ARM] 3240/2: AT9... |
33 |
|
adf2edfd6 clocksource: atme... |
34 |
regmap_read(regmap_st, AT91_ST_CRTR, &x1); |
73a59c1c4 [ARM] 3240/2: AT9... |
35 |
do { |
adf2edfd6 clocksource: atme... |
36 |
regmap_read(regmap_st, AT91_ST_CRTR, &x2); |
5e802dfab [ARM] 4539/1: clo... |
37 38 39 40 |
if (x1 == x2) break; x1 = x2; } while (1); |
73a59c1c4 [ARM] 3240/2: AT9... |
41 42 43 44 |
return x1; } /* |
73a59c1c4 [ARM] 3240/2: AT9... |
45 46 |
* IRQ handler for the timer. */ |
0cd61b68c Initial blind fix... |
47 |
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id) |
73a59c1c4 [ARM] 3240/2: AT9... |
48 |
{ |
adf2edfd6 clocksource: atme... |
49 50 51 52 |
u32 sr; regmap_read(regmap_st, AT91_ST_SR, &sr); sr &= irqmask; |
73a59c1c4 [ARM] 3240/2: AT9... |
53 |
|
501d70383 arm/at91: Don't d... |
54 55 56 57 58 |
/* * irqs should be disabled here, but as the irq is shared they are only * guaranteed to be off if the timer irq is registered first. */ WARN_ON_ONCE(!irqs_disabled()); |
5e802dfab [ARM] 4539/1: clo... |
59 60 61 62 63 |
/* simulate "oneshot" timer with alarm */ if (sr & AT91_ST_ALMS) { clkevt.event_handler(&clkevt); return IRQ_HANDLED; } |
73a59c1c4 [ARM] 3240/2: AT9... |
64 |
|
5e802dfab [ARM] 4539/1: clo... |
65 66 67 |
/* periodic mode should handle delayed ticks */ if (sr & AT91_ST_PITS) { u32 crtr = read_CRTR(); |
73a59c1c4 [ARM] 3240/2: AT9... |
68 |
|
216ab8f15 clocksource: atme... |
69 70 |
while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) { last_crtr += timer_latch; |
5e802dfab [ARM] 4539/1: clo... |
71 72 |
clkevt.event_handler(&clkevt); } |
73a59c1c4 [ARM] 3240/2: AT9... |
73 74 |
return IRQ_HANDLED; } |
5e802dfab [ARM] 4539/1: clo... |
75 76 77 |
/* this irq is shared ... */ return IRQ_NONE; |
73a59c1c4 [ARM] 3240/2: AT9... |
78 |
} |
a5a1d1c29 clocksource: Use ... |
79 |
static u64 read_clk32k(struct clocksource *cs) |
2a6f9902c [ARM] 3580/1: AT9... |
80 |
{ |
5e802dfab [ARM] 4539/1: clo... |
81 82 |
return read_CRTR(); } |
2a6f9902c [ARM] 3580/1: AT9... |
83 |
|
5e802dfab [ARM] 4539/1: clo... |
84 85 86 87 88 |
static struct clocksource clk32k = { .name = "32k_counter", .rating = 150, .read = read_clk32k, .mask = CLOCKSOURCE_MASK(20), |
5e802dfab [ARM] 4539/1: clo... |
89 90 |
.flags = CLOCK_SOURCE_IS_CONTINUOUS, }; |
8ab282305 clockevents/drive... |
91 |
static void clkdev32k_disable_and_flush_irq(void) |
5e802dfab [ARM] 4539/1: clo... |
92 |
{ |
adf2edfd6 clocksource: atme... |
93 |
unsigned int val; |
5e802dfab [ARM] 4539/1: clo... |
94 |
/* Disable and flush pending timer interrupts */ |
adf2edfd6 clocksource: atme... |
95 96 |
regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); regmap_read(regmap_st, AT91_ST_SR, &val); |
5e802dfab [ARM] 4539/1: clo... |
97 |
last_crtr = read_CRTR(); |
8ab282305 clockevents/drive... |
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
} static int clkevt32k_shutdown(struct clock_event_device *evt) { clkdev32k_disable_and_flush_irq(); irqmask = 0; regmap_write(regmap_st, AT91_ST_IER, irqmask); return 0; } static int clkevt32k_set_oneshot(struct clock_event_device *dev) { clkdev32k_disable_and_flush_irq(); /* * ALM for oneshot irqs, set by next_event() * before 32 seconds have passed. */ irqmask = AT91_ST_ALMS; regmap_write(regmap_st, AT91_ST_RTAR, last_crtr); |
adf2edfd6 clocksource: atme... |
118 |
regmap_write(regmap_st, AT91_ST_IER, irqmask); |
8ab282305 clockevents/drive... |
119 120 121 122 123 124 125 126 127 |
return 0; } static int clkevt32k_set_periodic(struct clock_event_device *dev) { clkdev32k_disable_and_flush_irq(); /* PIT for periodic irqs; fixed rate of 1/HZ */ irqmask = AT91_ST_PITS; |
216ab8f15 clocksource: atme... |
128 |
regmap_write(regmap_st, AT91_ST_PIMR, timer_latch); |
8ab282305 clockevents/drive... |
129 130 |
regmap_write(regmap_st, AT91_ST_IER, irqmask); return 0; |
5e802dfab [ARM] 4539/1: clo... |
131 |
} |
2a6f9902c [ARM] 3580/1: AT9... |
132 |
|
5e802dfab [ARM] 4539/1: clo... |
133 134 135 |
static int clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) { |
5e802dfab [ARM] 4539/1: clo... |
136 137 |
u32 alm; int status = 0; |
adf2edfd6 clocksource: atme... |
138 |
unsigned int val; |
5e802dfab [ARM] 4539/1: clo... |
139 140 |
BUG_ON(delta < 2); |
5e802dfab [ARM] 4539/1: clo... |
141 142 143 144 145 146 147 148 149 150 151 152 |
/* The alarm IRQ uses absolute time (now+delta), not the relative * time (delta) in our calling convention. Like all clockevents * using such "match" hardware, we have a race to defend against. * * Our defense here is to have set up the clockevent device so the * delta is at least two. That way we never end up writing RTAR * with the value then held in CRTR ... which would mean the match * wouldn't trigger until 32 seconds later, after CRTR wraps. */ alm = read_CRTR(); /* Cancel any pending alarm; flush any pending IRQ */ |
adf2edfd6 clocksource: atme... |
153 154 |
regmap_write(regmap_st, AT91_ST_RTAR, alm); regmap_read(regmap_st, AT91_ST_SR, &val); |
d100f2595 [ARM] 3955/1: AT9... |
155 |
|
5e802dfab [ARM] 4539/1: clo... |
156 157 |
/* Schedule alarm by writing RTAR. */ alm += delta; |
adf2edfd6 clocksource: atme... |
158 |
regmap_write(regmap_st, AT91_ST_RTAR, alm); |
5e802dfab [ARM] 4539/1: clo... |
159 |
|
5e802dfab [ARM] 4539/1: clo... |
160 |
return status; |
2a6f9902c [ARM] 3580/1: AT9... |
161 |
} |
5e802dfab [ARM] 4539/1: clo... |
162 |
static struct clock_event_device clkevt = { |
8ab282305 clockevents/drive... |
163 164 165 166 167 168 169 170 171 |
.name = "at91_tick", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 150, .set_next_event = clkevt32k_next_event, .set_state_shutdown = clkevt32k_shutdown, .set_state_periodic = clkevt32k_set_periodic, .set_state_oneshot = clkevt32k_set_oneshot, .tick_resume = clkevt32k_shutdown, |
5e802dfab [ARM] 4539/1: clo... |
172 |
}; |
73a59c1c4 [ARM] 3240/2: AT9... |
173 |
/* |
5e802dfab [ARM] 4539/1: clo... |
174 |
* ST (system timer) module supports both clockevents and clocksource. |
73a59c1c4 [ARM] 3240/2: AT9... |
175 |
*/ |
adbaf5254 clocksource/drive... |
176 |
static int __init atmel_st_timer_init(struct device_node *node) |
73a59c1c4 [ARM] 3240/2: AT9... |
177 |
{ |
216ab8f15 clocksource: atme... |
178 179 |
struct clk *sclk; unsigned int sclk_rate, val; |
0afb46b24 clocksource: atme... |
180 |
int irq, ret; |
adf2edfd6 clocksource: atme... |
181 182 |
regmap_st = syscon_node_to_regmap(node); |
adbaf5254 clocksource/drive... |
183 184 185 186 187 |
if (IS_ERR(regmap_st)) { pr_err("Unable to get regmap "); return PTR_ERR(regmap_st); } |
454c46df8 ARM: AT91: Add DT... |
188 |
|
5e802dfab [ARM] 4539/1: clo... |
189 |
/* Disable all timer interrupts, and clear any pending ones */ |
adf2edfd6 clocksource: atme... |
190 |
regmap_write(regmap_st, AT91_ST_IDR, |
5e802dfab [ARM] 4539/1: clo... |
191 |
AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); |
adf2edfd6 clocksource: atme... |
192 193 194 |
regmap_read(regmap_st, AT91_ST_SR, &val); /* Get the interrupts property */ |
0afb46b24 clocksource: atme... |
195 |
irq = irq_of_parse_and_map(node, 0); |
adbaf5254 clocksource/drive... |
196 197 198 199 200 |
if (!irq) { pr_err("Unable to get IRQ from DT "); return -EINVAL; } |
73a59c1c4 [ARM] 3240/2: AT9... |
201 |
|
2a6f9902c [ARM] 3580/1: AT9... |
202 |
/* Make IRQs happen for the system timer */ |
0afb46b24 clocksource: atme... |
203 204 205 |
ret = request_irq(irq, at91rm9200_timer_interrupt, IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL, "at91_tick", regmap_st); |
adbaf5254 clocksource/drive... |
206 207 208 209 210 |
if (ret) { pr_err("Unable to setup IRQ "); return ret; } |
73a59c1c4 [ARM] 3240/2: AT9... |
211 |
|
216ab8f15 clocksource: atme... |
212 |
sclk = of_clk_get(node, 0); |
adbaf5254 clocksource/drive... |
213 214 215 216 217 |
if (IS_ERR(sclk)) { pr_err("Unable to get slow clock "); return PTR_ERR(sclk); } |
216ab8f15 clocksource: atme... |
218 |
|
adbaf5254 clocksource/drive... |
219 220 221 222 223 224 |
ret = clk_prepare_enable(sclk); if (ret) { pr_err("Could not enable slow clock "); return ret; } |
216ab8f15 clocksource: atme... |
225 226 |
sclk_rate = clk_get_rate(sclk); |
adbaf5254 clocksource/drive... |
227 228 229 230 231 |
if (!sclk_rate) { pr_err("Invalid slow clock rate "); return -EINVAL; } |
216ab8f15 clocksource: atme... |
232 |
timer_latch = (sclk_rate + HZ / 2) / HZ; |
5e802dfab [ARM] 4539/1: clo... |
233 234 235 236 |
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used * directly for the clocksource and all clockevents, after adjusting * its prescaler from the 1 Hz default. */ |
adf2edfd6 clocksource: atme... |
237 |
regmap_write(regmap_st, AT91_ST_RTMR, 1); |
73a59c1c4 [ARM] 3240/2: AT9... |
238 |
|
5e802dfab [ARM] 4539/1: clo... |
239 |
/* Setup timer clockevent, with minimum of two ticks (important!!) */ |
320ab2b0b cpumask: convert ... |
240 |
clkevt.cpumask = cpumask_of(0); |
216ab8f15 clocksource: atme... |
241 |
clockevents_config_and_register(&clkevt, sclk_rate, |
1c2835311 ARM: at91: rm9200... |
242 |
2, AT91_ST_ALMV); |
2a6f9902c [ARM] 3580/1: AT9... |
243 |
|
5e802dfab [ARM] 4539/1: clo... |
244 |
/* register clocksource */ |
adbaf5254 clocksource/drive... |
245 |
return clocksource_register_hz(&clk32k, sclk_rate); |
73a59c1c4 [ARM] 3240/2: AT9... |
246 |
} |
172733959 clocksource/drive... |
247 |
TIMER_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st", |
bbfc97e1b ARM: at91: proper... |
248 |
atmel_st_timer_init); |