35
35
36
36
#define TIMER_SYNC_TICKS 3
37
37
38
- struct sun5i_timer {
38
+ /* Pointless struct to minimise diff */
39
+ struct _sun5i_timer {
39
40
void __iomem * base ;
40
41
struct clk * clk ;
41
42
struct notifier_block clk_rate_cb ;
42
43
u32 ticks_per_jiffy ;
43
44
};
44
45
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 ;
50
48
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 ;
58
49
struct clock_event_device clkevt ;
59
50
};
60
51
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)
63
58
64
59
/*
65
60
* When we disable a timer, we need to wait at least for 2 cycles of
66
61
* the timer source clock. We will use for that the clocksource timer
67
62
* that is already setup and runs at the same frequency than the other
68
63
* timers, and we never will be disabled.
69
64
*/
70
- static void sun5i_clkevt_sync (struct sun5i_timer_clkevt * ce )
65
+ static void sun5i_clkevt_sync (struct sun5i_timer * ce )
71
66
{
72
67
u32 old = readl (ce -> timer .base + TIMER_CNTVAL_LO_REG (1 ));
73
68
74
69
while ((old - readl (ce -> timer .base + TIMER_CNTVAL_LO_REG (1 ))) < TIMER_SYNC_TICKS )
75
70
cpu_relax ();
76
71
}
77
72
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 )
79
74
{
80
75
u32 val = readl (ce -> timer .base + TIMER_CTL_REG (timer ));
81
76
writel (val & ~TIMER_CTL_ENABLE , ce -> timer .base + TIMER_CTL_REG (timer ));
82
77
83
78
sun5i_clkevt_sync (ce );
84
79
}
85
80
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 )
87
82
{
88
83
writel (delay , ce -> timer .base + TIMER_INTVAL_LO_REG (timer ));
89
84
}
90
85
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 )
92
87
{
93
88
u32 val = readl (ce -> timer .base + TIMER_CTL_REG (timer ));
94
89
@@ -103,15 +98,15 @@ static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, boo
103
98
104
99
static int sun5i_clkevt_shutdown (struct clock_event_device * clkevt )
105
100
{
106
- struct sun5i_timer_clkevt * ce = to_sun5i_timer_clkevt (clkevt );
101
+ struct sun5i_timer * ce = clkevt_to_sun5i_timer (clkevt );
107
102
108
103
sun5i_clkevt_time_stop (ce , 0 );
109
104
return 0 ;
110
105
}
111
106
112
107
static int sun5i_clkevt_set_oneshot (struct clock_event_device * clkevt )
113
108
{
114
- struct sun5i_timer_clkevt * ce = to_sun5i_timer_clkevt (clkevt );
109
+ struct sun5i_timer * ce = clkevt_to_sun5i_timer (clkevt );
115
110
116
111
sun5i_clkevt_time_stop (ce , 0 );
117
112
sun5i_clkevt_time_start (ce , 0 , false);
@@ -120,7 +115,7 @@ static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
120
115
121
116
static int sun5i_clkevt_set_periodic (struct clock_event_device * clkevt )
122
117
{
123
- struct sun5i_timer_clkevt * ce = to_sun5i_timer_clkevt (clkevt );
118
+ struct sun5i_timer * ce = clkevt_to_sun5i_timer (clkevt );
124
119
125
120
sun5i_clkevt_time_stop (ce , 0 );
126
121
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)
131
126
static int sun5i_clkevt_next_event (unsigned long evt ,
132
127
struct clock_event_device * clkevt )
133
128
{
134
- struct sun5i_timer_clkevt * ce = to_sun5i_timer_clkevt (clkevt );
129
+ struct sun5i_timer * ce = clkevt_to_sun5i_timer (clkevt );
135
130
136
131
sun5i_clkevt_time_stop (ce , 0 );
137
132
sun5i_clkevt_time_setup (ce , 0 , evt - TIMER_SYNC_TICKS );
@@ -142,7 +137,7 @@ static int sun5i_clkevt_next_event(unsigned long evt,
142
137
143
138
static irqreturn_t sun5i_timer_interrupt (int irq , void * dev_id )
144
139
{
145
- struct sun5i_timer_clkevt * ce = dev_id ;
140
+ struct sun5i_timer * ce = dev_id ;
146
141
147
142
writel (0x1 , ce -> timer .base + TIMER_IRQ_ST_REG );
148
143
ce -> clkevt .event_handler (& ce -> clkevt );
@@ -152,17 +147,16 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
152
147
153
148
static u64 sun5i_clksrc_read (struct clocksource * clksrc )
154
149
{
155
- struct sun5i_timer_clksrc * cs = to_sun5i_timer_clksrc (clksrc );
150
+ struct sun5i_timer * cs = clksrc_to_sun5i_timer (clksrc );
156
151
157
152
return ~readl (cs -> timer .base + TIMER_CNTVAL_LO_REG (1 ));
158
153
}
159
154
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 )
162
157
{
163
158
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 );
166
160
167
161
switch (event ) {
168
162
case PRE_RATE_CHANGE :
@@ -171,6 +165,8 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
171
165
172
166
case POST_RATE_CHANGE :
173
167
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 );
174
170
break ;
175
171
176
172
default :
@@ -181,41 +177,12 @@ static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
181
177
}
182
178
183
179
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 )
186
182
{
187
- struct sun5i_timer_clksrc * cs ;
188
- unsigned long rate ;
183
+ void __iomem * base = cs -> timer .base ;
189
184
int ret ;
190
185
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
-
219
186
writel (~0 , base + TIMER_INTVAL_LO_REG (1 ));
220
187
writel (TIMER_CTL_ENABLE | TIMER_CTL_RELOAD ,
221
188
base + TIMER_CTL_REG (1 ));
@@ -229,72 +196,20 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
229
196
ret = clocksource_register_hz (& cs -> clksrc , rate );
230
197
if (ret ) {
231
198
pr_err ("Couldn't register clock source.\n" );
232
- goto err_remove_notifier ;
199
+ return ret ;
233
200
}
234
201
235
202
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 ;
259
203
}
260
204
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 )
263
208
{
264
- struct sun5i_timer_clkevt * ce ;
265
- unsigned long rate ;
209
+ void __iomem * base = ce -> timer .base ;
266
210
int ret ;
267
211
u32 val ;
268
212
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
-
298
213
ce -> clkevt .name = node -> name ;
299
214
ce -> clkevt .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT ;
300
215
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
317
232
"sun5i_timer0" , ce );
318
233
if (ret ) {
319
234
pr_err ("Unable to register interrupt\n" );
320
- goto err_remove_notifier ;
235
+ return ret ;
321
236
}
322
237
323
238
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 ;
332
239
}
333
240
334
241
static int __init sun5i_timer_init (struct device_node * node )
335
242
{
243
+ struct sun5i_timer * st ;
336
244
struct reset_control * rstc ;
337
245
void __iomem * timer_base ;
338
246
struct clk * clk ;
247
+ unsigned long rate ;
339
248
int irq , ret ;
340
249
250
+ st = kzalloc (sizeof (* st ), GFP_KERNEL );
251
+ if (!st )
252
+ return - ENOMEM ;
253
+
341
254
timer_base = of_io_request_and_map (node , 0 , of_node_full_name (node ));
342
255
if (IS_ERR (timer_base )) {
343
256
pr_err ("Can't map registers\n" );
@@ -356,15 +269,48 @@ static int __init sun5i_timer_init(struct device_node *node)
356
269
return PTR_ERR (clk );
357
270
}
358
271
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
+
359
297
rstc = of_reset_control_get (node , NULL );
360
298
if (!IS_ERR (rstc ))
361
299
reset_control_deassert (rstc );
362
300
363
- ret = sun5i_setup_clocksource (node , timer_base , clk , irq );
301
+ ret = sun5i_setup_clocksource (node , st , rate );
364
302
if (ret )
365
- return ret ;
303
+ goto err_remove_notifier ;
366
304
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 ;
368
314
}
369
315
TIMER_OF_DECLARE (sun5i_a13 , "allwinner,sun5i-a13-hstimer" ,
370
316
sun5i_timer_init );
0 commit comments