@@ -126,6 +126,7 @@ static struct clocksource clksrc = {
126
126
struct tc_clkevt_device {
127
127
struct clock_event_device clkevt ;
128
128
struct clk * clk ;
129
+ bool clk_enabled ;
129
130
void __iomem * regs ;
130
131
};
131
132
@@ -143,15 +144,39 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
143
144
*/
144
145
static u32 timer_clock ;
145
146
147
+ static void tc_clk_disable (struct clock_event_device * d )
148
+ {
149
+ struct tc_clkevt_device * tcd = to_tc_clkevt (d );
150
+
151
+ clk_disable (tcd -> clk );
152
+ tcd -> clk_enabled = false;
153
+ }
154
+
155
+ static void tc_clk_enable (struct clock_event_device * d )
156
+ {
157
+ struct tc_clkevt_device * tcd = to_tc_clkevt (d );
158
+
159
+ if (tcd -> clk_enabled )
160
+ return ;
161
+ clk_enable (tcd -> clk );
162
+ tcd -> clk_enabled = true;
163
+ }
164
+
146
165
static int tc_shutdown (struct clock_event_device * d )
147
166
{
148
167
struct tc_clkevt_device * tcd = to_tc_clkevt (d );
149
168
void __iomem * regs = tcd -> regs ;
150
169
151
170
writel (0xff , regs + ATMEL_TC_REG (2 , IDR ));
152
171
writel (ATMEL_TC_CLKDIS , regs + ATMEL_TC_REG (2 , CCR ));
172
+ return 0 ;
173
+ }
174
+
175
+ static int tc_shutdown_clk_off (struct clock_event_device * d )
176
+ {
177
+ tc_shutdown (d );
153
178
if (!clockevent_state_detached (d ))
154
- clk_disable ( tcd -> clk );
179
+ tc_clk_disable ( d );
155
180
156
181
return 0 ;
157
182
}
@@ -164,7 +189,7 @@ static int tc_set_oneshot(struct clock_event_device *d)
164
189
if (clockevent_state_oneshot (d ) || clockevent_state_periodic (d ))
165
190
tc_shutdown (d );
166
191
167
- clk_enable ( tcd -> clk );
192
+ tc_clk_enable ( d );
168
193
169
194
/* slow clock, count up to RC, then irq and stop */
170
195
writel (timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
@@ -186,7 +211,7 @@ static int tc_set_periodic(struct clock_event_device *d)
186
211
/* By not making the gentime core emulate periodic mode on top
187
212
* of oneshot, we get lower overhead and improved accuracy.
188
213
*/
189
- clk_enable ( tcd -> clk );
214
+ tc_clk_enable ( d );
190
215
191
216
/* slow clock, count up to RC, then irq and restart */
192
217
writel (timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO ,
@@ -220,7 +245,7 @@ static struct tc_clkevt_device clkevt = {
220
245
/* Should be lower than at91rm9200's system timer */
221
246
.rating = 125 ,
222
247
.set_next_event = tc_next_event ,
223
- .set_state_shutdown = tc_shutdown ,
248
+ .set_state_shutdown = tc_shutdown_clk_off ,
224
249
.set_state_periodic = tc_set_periodic ,
225
250
.set_state_oneshot = tc_set_oneshot ,
226
251
},
0 commit comments