Skip to content

Commit 7ded803

Browse files
mansrdlezcano
authored andcommitted
clocksource/drivers/sun5i: Remove duplication of code and data
Move the clocksource and clock_event_device structs into the main struct sun5i_timer, and update the code for the new layout. This removes a lot of duplication of both code and data. 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-2-mans@mansr.com
1 parent bd0f3aa commit 7ded803

File tree

1 file changed

+76
-130
lines changed

1 file changed

+76
-130
lines changed

drivers/clocksource/timer-sun5i.c

Lines changed: 76 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -35,60 +35,55 @@
3535

3636
#define TIMER_SYNC_TICKS 3
3737

38-
struct sun5i_timer {
38+
/* Pointless struct to minimise diff */
39+
struct _sun5i_timer {
3940
void __iomem *base;
4041
struct clk *clk;
4142
struct notifier_block clk_rate_cb;
4243
u32 ticks_per_jiffy;
4344
};
4445

45-
#define to_sun5i_timer(x) \
46-
container_of(x, struct sun5i_timer, clk_rate_cb)
47-
48-
struct sun5i_timer_clksrc {
49-
struct sun5i_timer timer;
46+
struct sun5i_timer {
47+
struct _sun5i_timer timer;
5048
struct clocksource clksrc;
51-
};
52-
53-
#define to_sun5i_timer_clksrc(x) \
54-
container_of(x, struct sun5i_timer_clksrc, clksrc)
55-
56-
struct sun5i_timer_clkevt {
57-
struct sun5i_timer timer;
5849
struct clock_event_device clkevt;
5950
};
6051

61-
#define to_sun5i_timer_clkevt(x) \
62-
container_of(x, struct sun5i_timer_clkevt, clkevt)
52+
#define nb_to_sun5i_timer(x) \
53+
container_of(x, struct sun5i_timer, timer.clk_rate_cb)
54+
#define clksrc_to_sun5i_timer(x) \
55+
container_of(x, struct sun5i_timer, clksrc)
56+
#define clkevt_to_sun5i_timer(x) \
57+
container_of(x, struct sun5i_timer, clkevt)
6358

6459
/*
6560
* When we disable a timer, we need to wait at least for 2 cycles of
6661
* the timer source clock. We will use for that the clocksource timer
6762
* that is already setup and runs at the same frequency than the other
6863
* timers, and we never will be disabled.
6964
*/
70-
static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce)
65+
static void sun5i_clkevt_sync(struct sun5i_timer *ce)
7166
{
7267
u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1));
7368

7469
while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
7570
cpu_relax();
7671
}
7772

78-
static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer)
73+
static void sun5i_clkevt_time_stop(struct sun5i_timer *ce, u8 timer)
7974
{
8075
u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
8176
writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer));
8277

8378
sun5i_clkevt_sync(ce);
8479
}
8580

86-
static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay)
81+
static void sun5i_clkevt_time_setup(struct sun5i_timer *ce, u8 timer, u32 delay)
8782
{
8883
writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer));
8984
}
9085

91-
static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic)
86+
static void sun5i_clkevt_time_start(struct sun5i_timer *ce, u8 timer, bool periodic)
9287
{
9388
u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
9489

@@ -103,15 +98,15 @@ static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, boo
10398

10499
static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt)
105100
{
106-
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
101+
struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt);
107102

108103
sun5i_clkevt_time_stop(ce, 0);
109104
return 0;
110105
}
111106

112107
static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
113108
{
114-
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
109+
struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt);
115110

116111
sun5i_clkevt_time_stop(ce, 0);
117112
sun5i_clkevt_time_start(ce, 0, false);
@@ -120,7 +115,7 @@ static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
120115

121116
static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt)
122117
{
123-
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
118+
struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt);
124119

125120
sun5i_clkevt_time_stop(ce, 0);
126121
sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
@@ -131,7 +126,7 @@ static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt)
131126
static int sun5i_clkevt_next_event(unsigned long evt,
132127
struct clock_event_device *clkevt)
133128
{
134-
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
129+
struct sun5i_timer *ce = clkevt_to_sun5i_timer(clkevt);
135130

136131
sun5i_clkevt_time_stop(ce, 0);
137132
sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS);
@@ -142,7 +137,7 @@ static int sun5i_clkevt_next_event(unsigned long evt,
142137

143138
static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
144139
{
145-
struct sun5i_timer_clkevt *ce = dev_id;
140+
struct sun5i_timer *ce = dev_id;
146141

147142
writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG);
148143
ce->clkevt.event_handler(&ce->clkevt);
@@ -152,17 +147,16 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
152147

153148
static u64 sun5i_clksrc_read(struct clocksource *clksrc)
154149
{
155-
struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
150+
struct sun5i_timer *cs = clksrc_to_sun5i_timer(clksrc);
156151

157152
return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
158153
}
159154

160-
static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
161-
unsigned long event, void *data)
155+
static int sun5i_rate_cb(struct notifier_block *nb,
156+
unsigned long event, void *data)
162157
{
163158
struct clk_notifier_data *ndata = data;
164-
struct sun5i_timer *timer = to_sun5i_timer(nb);
165-
struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer);
159+
struct sun5i_timer *cs = nb_to_sun5i_timer(nb);
166160

167161
switch (event) {
168162
case PRE_RATE_CHANGE:
@@ -171,6 +165,8 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
171165

172166
case POST_RATE_CHANGE:
173167
clocksource_register_hz(&cs->clksrc, ndata->new_rate);
168+
clockevents_update_freq(&cs->clkevt, ndata->new_rate);
169+
cs->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ);
174170
break;
175171

176172
default:
@@ -181,41 +177,12 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
181177
}
182178

183179
static int __init sun5i_setup_clocksource(struct device_node *node,
184-
void __iomem *base,
185-
struct clk *clk, int irq)
180+
struct sun5i_timer *cs,
181+
unsigned long rate)
186182
{
187-
struct sun5i_timer_clksrc *cs;
188-
unsigned long rate;
183+
void __iomem *base = cs->timer.base;
189184
int ret;
190185

191-
cs = kzalloc(sizeof(*cs), GFP_KERNEL);
192-
if (!cs)
193-
return -ENOMEM;
194-
195-
ret = clk_prepare_enable(clk);
196-
if (ret) {
197-
pr_err("Couldn't enable parent clock\n");
198-
goto err_free;
199-
}
200-
201-
rate = clk_get_rate(clk);
202-
if (!rate) {
203-
pr_err("Couldn't get parent clock rate\n");
204-
ret = -EINVAL;
205-
goto err_disable_clk;
206-
}
207-
208-
cs->timer.base = base;
209-
cs->timer.clk = clk;
210-
cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc;
211-
cs->timer.clk_rate_cb.next = NULL;
212-
213-
ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb);
214-
if (ret) {
215-
pr_err("Unable to register clock notifier.\n");
216-
goto err_disable_clk;
217-
}
218-
219186
writel(~0, base + TIMER_INTVAL_LO_REG(1));
220187
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
221188
base + TIMER_CTL_REG(1));
@@ -229,72 +196,20 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
229196
ret = clocksource_register_hz(&cs->clksrc, rate);
230197
if (ret) {
231198
pr_err("Couldn't register clock source.\n");
232-
goto err_remove_notifier;
199+
return ret;
233200
}
234201

235202
return 0;
236-
237-
err_remove_notifier:
238-
clk_notifier_unregister(clk, &cs->timer.clk_rate_cb);
239-
err_disable_clk:
240-
clk_disable_unprepare(clk);
241-
err_free:
242-
kfree(cs);
243-
return ret;
244-
}
245-
246-
static int sun5i_rate_cb_clkevt(struct notifier_block *nb,
247-
unsigned long event, void *data)
248-
{
249-
struct clk_notifier_data *ndata = data;
250-
struct sun5i_timer *timer = to_sun5i_timer(nb);
251-
struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer);
252-
253-
if (event == POST_RATE_CHANGE) {
254-
clockevents_update_freq(&ce->clkevt, ndata->new_rate);
255-
ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ);
256-
}
257-
258-
return NOTIFY_DONE;
259203
}
260204

261-
static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base,
262-
struct clk *clk, int irq)
205+
static int __init sun5i_setup_clockevent(struct device_node *node,
206+
struct sun5i_timer *ce,
207+
unsigned long rate, int irq)
263208
{
264-
struct sun5i_timer_clkevt *ce;
265-
unsigned long rate;
209+
void __iomem *base = ce->timer.base;
266210
int ret;
267211
u32 val;
268212

269-
ce = kzalloc(sizeof(*ce), GFP_KERNEL);
270-
if (!ce)
271-
return -ENOMEM;
272-
273-
ret = clk_prepare_enable(clk);
274-
if (ret) {
275-
pr_err("Couldn't enable parent clock\n");
276-
goto err_free;
277-
}
278-
279-
rate = clk_get_rate(clk);
280-
if (!rate) {
281-
pr_err("Couldn't get parent clock rate\n");
282-
ret = -EINVAL;
283-
goto err_disable_clk;
284-
}
285-
286-
ce->timer.base = base;
287-
ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
288-
ce->timer.clk = clk;
289-
ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt;
290-
ce->timer.clk_rate_cb.next = NULL;
291-
292-
ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb);
293-
if (ret) {
294-
pr_err("Unable to register clock notifier.\n");
295-
goto err_disable_clk;
296-
}
297-
298213
ce->clkevt.name = node->name;
299214
ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
300215
ce->clkevt.set_next_event = sun5i_clkevt_next_event;
@@ -317,27 +232,25 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem
317232
"sun5i_timer0", ce);
318233
if (ret) {
319234
pr_err("Unable to register interrupt\n");
320-
goto err_remove_notifier;
235+
return ret;
321236
}
322237

323238
return 0;
324-
325-
err_remove_notifier:
326-
clk_notifier_unregister(clk, &ce->timer.clk_rate_cb);
327-
err_disable_clk:
328-
clk_disable_unprepare(clk);
329-
err_free:
330-
kfree(ce);
331-
return ret;
332239
}
333240

334241
static int __init sun5i_timer_init(struct device_node *node)
335242
{
243+
struct sun5i_timer *st;
336244
struct reset_control *rstc;
337245
void __iomem *timer_base;
338246
struct clk *clk;
247+
unsigned long rate;
339248
int irq, ret;
340249

250+
st = kzalloc(sizeof(*st), GFP_KERNEL);
251+
if (!st)
252+
return -ENOMEM;
253+
341254
timer_base = of_io_request_and_map(node, 0, of_node_full_name(node));
342255
if (IS_ERR(timer_base)) {
343256
pr_err("Can't map registers\n");
@@ -356,15 +269,48 @@ static int __init sun5i_timer_init(struct device_node *node)
356269
return PTR_ERR(clk);
357270
}
358271

272+
ret = clk_prepare_enable(clk);
273+
if (ret) {
274+
pr_err("Couldn't enable parent clock\n");
275+
goto err_free;
276+
}
277+
278+
rate = clk_get_rate(clk);
279+
if (!rate) {
280+
pr_err("Couldn't get parent clock rate\n");
281+
ret = -EINVAL;
282+
goto err_disable_clk;
283+
}
284+
285+
st->timer.base = timer_base;
286+
st->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
287+
st->timer.clk = clk;
288+
st->timer.clk_rate_cb.notifier_call = sun5i_rate_cb;
289+
st->timer.clk_rate_cb.next = NULL;
290+
291+
ret = clk_notifier_register(clk, &st->timer.clk_rate_cb);
292+
if (ret) {
293+
pr_err("Unable to register clock notifier.\n");
294+
goto err_disable_clk;
295+
}
296+
359297
rstc = of_reset_control_get(node, NULL);
360298
if (!IS_ERR(rstc))
361299
reset_control_deassert(rstc);
362300

363-
ret = sun5i_setup_clocksource(node, timer_base, clk, irq);
301+
ret = sun5i_setup_clocksource(node, st, rate);
364302
if (ret)
365-
return ret;
303+
goto err_remove_notifier;
366304

367-
return sun5i_setup_clockevent(node, timer_base, clk, irq);
305+
return sun5i_setup_clockevent(node, st, rate, irq);
306+
307+
err_remove_notifier:
308+
clk_notifier_unregister(clk, &st->timer.clk_rate_cb);
309+
err_disable_clk:
310+
clk_disable_unprepare(clk);
311+
err_free:
312+
kfree(st);
313+
return ret;
368314
}
369315
TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
370316
sun5i_timer_init);

0 commit comments

Comments
 (0)