Source
173
173
int ret;
174
174
struct pit_data *data;
175
175
176
176
data = kzalloc(sizeof(*data), GFP_KERNEL);
177
177
if (!data)
178
178
return -ENOMEM;
179
179
180
180
data->base = of_iomap(node, 0);
181
181
if (!data->base) {
182
182
pr_err("Could not map PIT address\n");
183
-
return -ENXIO;
183
+
ret = -ENXIO;
184
+
goto exit;
184
185
}
185
186
186
187
data->mck = of_clk_get(node, 0);
187
188
if (IS_ERR(data->mck)) {
188
189
pr_err("Unable to get mck clk\n");
189
-
return PTR_ERR(data->mck);
190
+
ret = PTR_ERR(data->mck);
191
+
goto exit;
190
192
}
191
193
192
194
ret = clk_prepare_enable(data->mck);
193
195
if (ret) {
194
196
pr_err("Unable to enable mck\n");
195
-
return ret;
197
+
goto exit;
196
198
}
197
199
198
200
/* Get the interrupts property */
199
201
data->irq = irq_of_parse_and_map(node, 0);
200
202
if (!data->irq) {
201
203
pr_err("Unable to get IRQ from DT\n");
202
-
return -EINVAL;
204
+
ret = -EINVAL;
205
+
goto exit;
203
206
}
204
207
205
208
/*
206
209
* Use our actual MCK to figure out how many MCK/16 ticks per
207
210
* 1/HZ period (instead of a compile-time constant LATCH).
208
211
*/
209
212
pit_rate = clk_get_rate(data->mck) / 16;
210
213
data->cycle = DIV_ROUND_CLOSEST(pit_rate, HZ);
211
214
WARN_ON(((data->cycle - 1) & ~AT91_PIT_PIV) != 0);
212
215
220
223
bits = 12 /* PICNT */ + ilog2(data->cycle) /* PIV */;
221
224
data->clksrc.mask = CLOCKSOURCE_MASK(bits);
222
225
data->clksrc.name = "pit";
223
226
data->clksrc.rating = 175;
224
227
data->clksrc.read = read_pit_clk;
225
228
data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
226
229
227
230
ret = clocksource_register_hz(&data->clksrc, pit_rate);
228
231
if (ret) {
229
232
pr_err("Failed to register clocksource\n");
230
-
return ret;
233
+
goto exit;
231
234
}
232
235
233
236
/* Set up irq handler */
234
237
ret = request_irq(data->irq, at91sam926x_pit_interrupt,
235
238
IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
236
239
"at91_tick", data);
237
240
if (ret) {
238
241
pr_err("Unable to setup IRQ\n");
239
-
return ret;
242
+
clocksource_unregister(&data->clksrc);
243
+
goto exit;
240
244
}
241
245
242
246
/* Set up and register clockevents */
243
247
data->clkevt.name = "pit";
244
248
data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
245
249
data->clkevt.shift = 32;
246
250
data->clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, data->clkevt.shift);
247
251
data->clkevt.rating = 100;
248
252
data->clkevt.cpumask = cpumask_of(0);
249
253
250
254
data->clkevt.set_state_shutdown = pit_clkevt_shutdown;
251
255
data->clkevt.set_state_periodic = pit_clkevt_set_periodic;
252
256
data->clkevt.resume = at91sam926x_pit_resume;
253
257
data->clkevt.suspend = at91sam926x_pit_suspend;
254
258
clockevents_register_device(&data->clkevt);
255
259
256
260
return 0;
261
+
262
+
exit:
263
+
kfree(data);
264
+
return ret;
257
265
}
258
266
TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
259
267
at91sam926x_pit_dt_init);