Skip to content

Commit 7e5bac6

Browse files
mansrdlezcano
authored andcommitted
clocksource/drivers/sun5i: Convert to platform device driver
Convert the sun5i hstimer driver to a platform device driver. This makes it work again on A20 and other systems where the clock is provided by a platform device driver. Fixes: 7ec03b5 ("clk: sunxi-ng: Convert early providers to platform drivers") Signed-off-by: Mans Rullgard <mans@mansr.com> Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> Acked-by: Maxime Ripard <mripard@kernel.org> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20230630201800.16501-4-mans@mansr.com
1 parent 0b38dd1 commit 7e5bac6

File tree

1 file changed

+69
-52
lines changed

1 file changed

+69
-52
lines changed

drivers/clocksource/timer-sun5i.c

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
#include <linux/irqreturn.h>
1717
#include <linux/reset.h>
1818
#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>
2220

2321
#define TIMER_IRQ_EN_REG 0x00
2422
#define TIMER_IRQ_EN(val) BIT(val)
@@ -171,41 +169,42 @@ static int sun5i_rate_cb(struct notifier_block *nb,
171169
return NOTIFY_DONE;
172170
}
173171

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)
177174
{
175+
struct sun5i_timer *cs = platform_get_drvdata(pdev);
178176
void __iomem *base = cs->base;
179177
int ret;
180178

181179
writel(~0, base + TIMER_INTVAL_LO_REG(1));
182180
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
183181
base + TIMER_CTL_REG(1));
184182

185-
cs->clksrc.name = node->name;
183+
cs->clksrc.name = pdev->dev.of_node->name;
186184
cs->clksrc.rating = 340;
187185
cs->clksrc.read = sun5i_clksrc_read;
188186
cs->clksrc.mask = CLOCKSOURCE_MASK(32);
189187
cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
190188

191189
ret = clocksource_register_hz(&cs->clksrc, rate);
192190
if (ret) {
193-
pr_err("Couldn't register clock source.\n");
191+
dev_err(&pdev->dev, "Couldn't register clock source.\n");
194192
return ret;
195193
}
196194

197195
return 0;
198196
}
199197

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)
203200
{
201+
struct device *dev = &pdev->dev;
202+
struct sun5i_timer *ce = platform_get_drvdata(pdev);
204203
void __iomem *base = ce->base;
205204
int ret;
206205
u32 val;
207206

208-
ce->clkevt.name = node->name;
207+
ce->clkevt.name = dev->of_node->name;
209208
ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
210209
ce->clkevt.set_next_event = sun5i_clkevt_next_event;
211210
ce->clkevt.set_state_shutdown = sun5i_clkevt_shutdown;
@@ -223,58 +222,55 @@ static int __init sun5i_setup_clockevent(struct device_node *node,
223222
clockevents_config_and_register(&ce->clkevt, rate,
224223
TIMER_SYNC_TICKS, 0xffffffff);
225224

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);
228228
if (ret) {
229-
pr_err("Unable to register interrupt\n");
229+
dev_err(dev, "Unable to register interrupt\n");
230230
return ret;
231231
}
232232

233233
return 0;
234234
}
235235

236-
static int __init sun5i_timer_init(struct device_node *node)
236+
static int sun5i_timer_probe(struct platform_device *pdev)
237237
{
238+
struct device *dev = &pdev->dev;
238239
struct sun5i_timer *st;
239240
struct reset_control *rstc;
240241
void __iomem *timer_base;
241242
struct clk *clk;
242243
unsigned long rate;
243244
int irq, ret;
244245

245-
st = kzalloc(sizeof(*st), GFP_KERNEL);
246+
st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
246247
if (!st)
247248
return -ENOMEM;
248249

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);
250253
if (IS_ERR(timer_base)) {
251-
pr_err("Can't map registers\n");
254+
dev_err(dev, "Can't map registers\n");
252255
return PTR_ERR(timer_base);
253256
}
254257

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;
259262
}
260263

261-
clk = of_clk_get(node, 0);
264+
clk = devm_clk_get_enabled(dev, NULL);
262265
if (IS_ERR(clk)) {
263-
pr_err("Can't get timer clock\n");
266+
dev_err(dev, "Can't get timer clock\n");
264267
return PTR_ERR(clk);
265268
}
266269

267-
ret = clk_prepare_enable(clk);
268-
if (ret) {
269-
pr_err("Couldn't enable parent clock\n");
270-
goto err_free;
271-
}
272-
273270
rate = clk_get_rate(clk);
274271
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;
278274
}
279275

280276
st->base = timer_base;
@@ -283,31 +279,52 @@ static int __init sun5i_timer_init(struct device_node *node)
283279
st->clk_rate_cb.notifier_call = sun5i_rate_cb;
284280
st->clk_rate_cb.next = NULL;
285281

286-
ret = clk_notifier_register(clk, &st->clk_rate_cb);
282+
ret = devm_clk_notifier_register(dev, clk, &st->clk_rate_cb);
287283
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;
290286
}
291287

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)
294290
reset_control_deassert(rstc);
295291

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);
297297
if (ret)
298-
goto err_remove_notifier;
298+
goto err_unreg_clocksource;
299299

300-
return sun5i_setup_clockevent(node, st, rate, irq);
300+
return 0;
301301

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);
308304
return ret;
309305
}
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

Comments
 (0)