diff options
Diffstat (limited to 'drivers/clocksource/timer-atmel-pit.c')
-rw-r--r-- | drivers/clocksource/timer-atmel-pit.c | 96 |
1 files changed, 37 insertions, 59 deletions
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index 7f0f5b26d8c5..6555821bbdae 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c | |||
@@ -149,24 +149,13 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) | |||
149 | { | 149 | { |
150 | struct pit_data *data = dev_id; | 150 | struct pit_data *data = dev_id; |
151 | 151 | ||
152 | /* | ||
153 | * irqs should be disabled here, but as the irq is shared they are only | ||
154 | * guaranteed to be off if the timer irq is registered first. | ||
155 | */ | ||
156 | WARN_ON_ONCE(!irqs_disabled()); | ||
157 | |||
158 | /* The PIT interrupt may be disabled, and is shared */ | 152 | /* The PIT interrupt may be disabled, and is shared */ |
159 | if (clockevent_state_periodic(&data->clkevt) && | 153 | if (clockevent_state_periodic(&data->clkevt) && |
160 | (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) { | 154 | (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) { |
161 | unsigned nr_ticks; | ||
162 | |||
163 | /* Get number of ticks performed before irq, and ack it */ | 155 | /* Get number of ticks performed before irq, and ack it */ |
164 | nr_ticks = PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR)); | 156 | data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, |
165 | do { | 157 | AT91_PIT_PIVR)); |
166 | data->cnt += data->cycle; | 158 | data->clkevt.event_handler(&data->clkevt); |
167 | data->clkevt.event_handler(&data->clkevt); | ||
168 | nr_ticks--; | ||
169 | } while (nr_ticks); | ||
170 | 159 | ||
171 | return IRQ_HANDLED; | 160 | return IRQ_HANDLED; |
172 | } | 161 | } |
@@ -177,11 +166,41 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) | |||
177 | /* | 166 | /* |
178 | * Set up both clocksource and clockevent support. | 167 | * Set up both clocksource and clockevent support. |
179 | */ | 168 | */ |
180 | static int __init at91sam926x_pit_common_init(struct pit_data *data) | 169 | static int __init at91sam926x_pit_dt_init(struct device_node *node) |
181 | { | 170 | { |
182 | unsigned long pit_rate; | 171 | unsigned long pit_rate; |
183 | unsigned bits; | 172 | unsigned bits; |
184 | int ret; | 173 | int ret; |
174 | struct pit_data *data; | ||
175 | |||
176 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
177 | if (!data) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | data->base = of_iomap(node, 0); | ||
181 | if (!data->base) { | ||
182 | pr_err("Could not map PIT address\n"); | ||
183 | return -ENXIO; | ||
184 | } | ||
185 | |||
186 | data->mck = of_clk_get(node, 0); | ||
187 | if (IS_ERR(data->mck)) { | ||
188 | pr_err("Unable to get mck clk\n"); | ||
189 | return PTR_ERR(data->mck); | ||
190 | } | ||
191 | |||
192 | ret = clk_prepare_enable(data->mck); | ||
193 | if (ret) { | ||
194 | pr_err("Unable to enable mck\n"); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | /* Get the interrupts property */ | ||
199 | data->irq = irq_of_parse_and_map(node, 0); | ||
200 | if (!data->irq) { | ||
201 | pr_err("Unable to get IRQ from DT\n"); | ||
202 | return -EINVAL; | ||
203 | } | ||
185 | 204 | ||
186 | /* | 205 | /* |
187 | * Use our actual MCK to figure out how many MCK/16 ticks per | 206 | * Use our actual MCK to figure out how many MCK/16 ticks per |
@@ -236,46 +255,5 @@ static int __init at91sam926x_pit_common_init(struct pit_data *data) | |||
236 | 255 | ||
237 | return 0; | 256 | return 0; |
238 | } | 257 | } |
239 | |||
240 | static int __init at91sam926x_pit_dt_init(struct device_node *node) | ||
241 | { | ||
242 | struct pit_data *data; | ||
243 | int ret; | ||
244 | |||
245 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
246 | if (!data) | ||
247 | return -ENOMEM; | ||
248 | |||
249 | data->base = of_iomap(node, 0); | ||
250 | if (!data->base) { | ||
251 | pr_err("Could not map PIT address\n"); | ||
252 | return -ENXIO; | ||
253 | } | ||
254 | |||
255 | data->mck = of_clk_get(node, 0); | ||
256 | if (IS_ERR(data->mck)) | ||
257 | /* Fallback on clkdev for !CCF-based boards */ | ||
258 | data->mck = clk_get(NULL, "mck"); | ||
259 | |||
260 | if (IS_ERR(data->mck)) { | ||
261 | pr_err("Unable to get mck clk\n"); | ||
262 | return PTR_ERR(data->mck); | ||
263 | } | ||
264 | |||
265 | ret = clk_prepare_enable(data->mck); | ||
266 | if (ret) { | ||
267 | pr_err("Unable to enable mck\n"); | ||
268 | return ret; | ||
269 | } | ||
270 | |||
271 | /* Get the interrupts property */ | ||
272 | data->irq = irq_of_parse_and_map(node, 0); | ||
273 | if (!data->irq) { | ||
274 | pr_err("Unable to get IRQ from DT\n"); | ||
275 | return -EINVAL; | ||
276 | } | ||
277 | |||
278 | return at91sam926x_pit_common_init(data); | ||
279 | } | ||
280 | CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", | 258 | CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", |
281 | at91sam926x_pit_dt_init); | 259 | at91sam926x_pit_dt_init); |