16
16
#include <linux/irqreturn.h>
17
17
#include <linux/reset.h>
18
18
#include <linux/slab.h>
19
- #include <linux/of.h>
20
- #include <linux/of_address.h>
21
- #include <linux/of_irq.h>
19
+ #include <linux/platform_device.h>
22
20
23
21
#define TIMER_IRQ_EN_REG 0x00
24
22
#define TIMER_IRQ_EN (val ) BIT(val)
@@ -171,41 +169,42 @@ static int sun5i_rate_cb(struct notifier_block *nb,
171
169
return NOTIFY_DONE ;
172
170
}
173
171
174
- static int __init sun5i_setup_clocksource (struct device_node * node ,
175
- struct sun5i_timer * cs ,
176
- unsigned long rate )
172
+ static int sun5i_setup_clocksource (struct platform_device * pdev ,
173
+ unsigned long rate )
177
174
{
175
+ struct sun5i_timer * cs = platform_get_drvdata (pdev );
178
176
void __iomem * base = cs -> base ;
179
177
int ret ;
180
178
181
179
writel (~0 , base + TIMER_INTVAL_LO_REG (1 ));
182
180
writel (TIMER_CTL_ENABLE | TIMER_CTL_RELOAD ,
183
181
base + TIMER_CTL_REG (1 ));
184
182
185
- cs -> clksrc .name = node -> name ;
183
+ cs -> clksrc .name = pdev -> dev . of_node -> name ;
186
184
cs -> clksrc .rating = 340 ;
187
185
cs -> clksrc .read = sun5i_clksrc_read ;
188
186
cs -> clksrc .mask = CLOCKSOURCE_MASK (32 );
189
187
cs -> clksrc .flags = CLOCK_SOURCE_IS_CONTINUOUS ;
190
188
191
189
ret = clocksource_register_hz (& cs -> clksrc , rate );
192
190
if (ret ) {
193
- pr_err ( "Couldn't register clock source.\n" );
191
+ dev_err ( & pdev -> dev , "Couldn't register clock source.\n" );
194
192
return ret ;
195
193
}
196
194
197
195
return 0 ;
198
196
}
199
197
200
- static int __init sun5i_setup_clockevent (struct device_node * node ,
201
- struct sun5i_timer * ce ,
202
- unsigned long rate , int irq )
198
+ static int sun5i_setup_clockevent (struct platform_device * pdev ,
199
+ unsigned long rate , int irq )
203
200
{
201
+ struct device * dev = & pdev -> dev ;
202
+ struct sun5i_timer * ce = platform_get_drvdata (pdev );
204
203
void __iomem * base = ce -> base ;
205
204
int ret ;
206
205
u32 val ;
207
206
208
- ce -> clkevt .name = node -> name ;
207
+ ce -> clkevt .name = dev -> of_node -> name ;
209
208
ce -> clkevt .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT ;
210
209
ce -> clkevt .set_next_event = sun5i_clkevt_next_event ;
211
210
ce -> clkevt .set_state_shutdown = sun5i_clkevt_shutdown ;
@@ -223,58 +222,55 @@ static int __init sun5i_setup_clockevent(struct device_node *node,
223
222
clockevents_config_and_register (& ce -> clkevt , rate ,
224
223
TIMER_SYNC_TICKS , 0xffffffff );
225
224
226
- ret = request_irq (irq , sun5i_timer_interrupt , IRQF_TIMER | IRQF_IRQPOLL ,
227
- "sun5i_timer0" , ce );
225
+ ret = devm_request_irq (dev , irq , sun5i_timer_interrupt ,
226
+ IRQF_TIMER | IRQF_IRQPOLL ,
227
+ "sun5i_timer0" , ce );
228
228
if (ret ) {
229
- pr_err ( "Unable to register interrupt\n" );
229
+ dev_err ( dev , "Unable to register interrupt\n" );
230
230
return ret ;
231
231
}
232
232
233
233
return 0 ;
234
234
}
235
235
236
- static int __init sun5i_timer_init (struct device_node * node )
236
+ static int sun5i_timer_probe (struct platform_device * pdev )
237
237
{
238
+ struct device * dev = & pdev -> dev ;
238
239
struct sun5i_timer * st ;
239
240
struct reset_control * rstc ;
240
241
void __iomem * timer_base ;
241
242
struct clk * clk ;
242
243
unsigned long rate ;
243
244
int irq , ret ;
244
245
245
- st = kzalloc ( sizeof (* st ), GFP_KERNEL );
246
+ st = devm_kzalloc ( dev , sizeof (* st ), GFP_KERNEL );
246
247
if (!st )
247
248
return - ENOMEM ;
248
249
249
- timer_base = of_io_request_and_map (node , 0 , of_node_full_name (node ));
250
+ platform_set_drvdata (pdev , st );
251
+
252
+ timer_base = devm_platform_ioremap_resource (pdev , 0 );
250
253
if (IS_ERR (timer_base )) {
251
- pr_err ( "Can't map registers\n" );
254
+ dev_err ( dev , "Can't map registers\n" );
252
255
return PTR_ERR (timer_base );
253
256
}
254
257
255
- irq = irq_of_parse_and_map ( node , 0 );
256
- if (irq <= 0 ) {
257
- pr_err ( "Can't parse IRQ\n" );
258
- return - EINVAL ;
258
+ irq = platform_get_irq ( pdev , 0 );
259
+ if (irq < 0 ) {
260
+ dev_err ( dev , "Can't get IRQ\n" );
261
+ return irq ;
259
262
}
260
263
261
- clk = of_clk_get ( node , 0 );
264
+ clk = devm_clk_get_enabled ( dev , NULL );
262
265
if (IS_ERR (clk )) {
263
- pr_err ( "Can't get timer clock\n" );
266
+ dev_err ( dev , "Can't get timer clock\n" );
264
267
return PTR_ERR (clk );
265
268
}
266
269
267
- ret = clk_prepare_enable (clk );
268
- if (ret ) {
269
- pr_err ("Couldn't enable parent clock\n" );
270
- goto err_free ;
271
- }
272
-
273
270
rate = clk_get_rate (clk );
274
271
if (!rate ) {
275
- pr_err ("Couldn't get parent clock rate\n" );
276
- ret = - EINVAL ;
277
- goto err_disable_clk ;
272
+ dev_err (dev , "Couldn't get parent clock rate\n" );
273
+ return - EINVAL ;
278
274
}
279
275
280
276
st -> base = timer_base ;
@@ -283,31 +279,52 @@ static int __init sun5i_timer_init(struct device_node *node)
283
279
st -> clk_rate_cb .notifier_call = sun5i_rate_cb ;
284
280
st -> clk_rate_cb .next = NULL ;
285
281
286
- ret = clk_notifier_register ( clk , & st -> clk_rate_cb );
282
+ ret = devm_clk_notifier_register ( dev , clk , & st -> clk_rate_cb );
287
283
if (ret ) {
288
- pr_err ( "Unable to register clock notifier.\n" );
289
- goto err_disable_clk ;
284
+ dev_err ( dev , "Unable to register clock notifier.\n" );
285
+ return ret ;
290
286
}
291
287
292
- rstc = of_reset_control_get ( node , NULL );
293
- if (! IS_ERR ( rstc ) )
288
+ rstc = devm_reset_control_get_optional_exclusive ( dev , NULL );
289
+ if (rstc )
294
290
reset_control_deassert (rstc );
295
291
296
- ret = sun5i_setup_clocksource (node , st , rate );
292
+ ret = sun5i_setup_clocksource (pdev , rate );
293
+ if (ret )
294
+ return ret ;
295
+
296
+ ret = sun5i_setup_clockevent (pdev , rate , irq );
297
297
if (ret )
298
- goto err_remove_notifier ;
298
+ goto err_unreg_clocksource ;
299
299
300
- return sun5i_setup_clockevent ( node , st , rate , irq ) ;
300
+ return 0 ;
301
301
302
- err_remove_notifier :
303
- clk_notifier_unregister (clk , & st -> clk_rate_cb );
304
- err_disable_clk :
305
- clk_disable_unprepare (clk );
306
- err_free :
307
- kfree (st );
302
+ err_unreg_clocksource :
303
+ clocksource_unregister (& st -> clksrc );
308
304
return ret ;
309
305
}
310
- TIMER_OF_DECLARE (sun5i_a13 , "allwinner,sun5i-a13-hstimer" ,
311
- sun5i_timer_init );
312
- TIMER_OF_DECLARE (sun7i_a20 , "allwinner,sun7i-a20-hstimer" ,
313
- sun5i_timer_init );
306
+
307
+ static void sun5i_timer_remove (struct platform_device * pdev )
308
+ {
309
+ struct sun5i_timer * st = platform_get_drvdata (pdev );
310
+
311
+ clocksource_unregister (& st -> clksrc );
312
+ }
313
+
314
+ static const struct of_device_id sun5i_timer_of_match [] = {
315
+ { .compatible = "allwinner,sun5i-a13-hstimer" },
316
+ { .compatible = "allwinner,sun7i-a20-hstimer" },
317
+ {},
318
+ };
319
+ MODULE_DEVICE_TABLE (of , sun5i_timer_of_match );
320
+
321
+ static struct platform_driver sun5i_timer_driver = {
322
+ .probe = sun5i_timer_probe ,
323
+ .remove_new = sun5i_timer_remove ,
324
+ .driver = {
325
+ .name = "sun5i-timer" ,
326
+ .of_match_table = sun5i_timer_of_match ,
327
+ .suppress_bind_attrs = true,
328
+ },
329
+ };
330
+ module_platform_driver (sun5i_timer_driver );
0 commit comments