diff options
Diffstat (limited to 'drivers/clocksource/sh_cmt.c')
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index dc7c033ef587..32a77becc098 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/delay.h> | ||
29 | #include <linux/clocksource.h> | 30 | #include <linux/clocksource.h> |
30 | #include <linux/clockchips.h> | 31 | #include <linux/clockchips.h> |
31 | #include <linux/sh_timer.h> | 32 | #include <linux/sh_timer.h> |
@@ -150,13 +151,13 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
150 | 151 | ||
151 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | 152 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) |
152 | { | 153 | { |
153 | int ret; | 154 | int k, ret; |
154 | 155 | ||
155 | /* enable clock */ | 156 | /* enable clock */ |
156 | ret = clk_enable(p->clk); | 157 | ret = clk_enable(p->clk); |
157 | if (ret) { | 158 | if (ret) { |
158 | dev_err(&p->pdev->dev, "cannot enable clock\n"); | 159 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
159 | return ret; | 160 | goto err0; |
160 | } | 161 | } |
161 | 162 | ||
162 | /* make sure channel is disabled */ | 163 | /* make sure channel is disabled */ |
@@ -174,9 +175,38 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
174 | sh_cmt_write(p, CMCOR, 0xffffffff); | 175 | sh_cmt_write(p, CMCOR, 0xffffffff); |
175 | sh_cmt_write(p, CMCNT, 0); | 176 | sh_cmt_write(p, CMCNT, 0); |
176 | 177 | ||
178 | /* | ||
179 | * According to the sh73a0 user's manual, as CMCNT can be operated | ||
180 | * only by the RCLK (Pseudo 32 KHz), there's one restriction on | ||
181 | * modifying CMCNT register; two RCLK cycles are necessary before | ||
182 | * this register is either read or any modification of the value | ||
183 | * it holds is reflected in the LSI's actual operation. | ||
184 | * | ||
185 | * While at it, we're supposed to clear out the CMCNT as of this | ||
186 | * moment, so make sure it's processed properly here. This will | ||
187 | * take RCLKx2 at maximum. | ||
188 | */ | ||
189 | for (k = 0; k < 100; k++) { | ||
190 | if (!sh_cmt_read(p, CMCNT)) | ||
191 | break; | ||
192 | udelay(1); | ||
193 | } | ||
194 | |||
195 | if (sh_cmt_read(p, CMCNT)) { | ||
196 | dev_err(&p->pdev->dev, "cannot clear CMCNT\n"); | ||
197 | ret = -ETIMEDOUT; | ||
198 | goto err1; | ||
199 | } | ||
200 | |||
177 | /* enable channel */ | 201 | /* enable channel */ |
178 | sh_cmt_start_stop_ch(p, 1); | 202 | sh_cmt_start_stop_ch(p, 1); |
179 | return 0; | 203 | return 0; |
204 | err1: | ||
205 | /* stop clock */ | ||
206 | clk_disable(p->clk); | ||
207 | |||
208 | err0: | ||
209 | return ret; | ||
180 | } | 210 | } |
181 | 211 | ||
182 | static void sh_cmt_disable(struct sh_cmt_priv *p) | 212 | static void sh_cmt_disable(struct sh_cmt_priv *p) |