diff options
| -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) |
