aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clocksource/sh_cmt.c34
-rw-r--r--drivers/sh/intc/chip.c3
2 files changed, 35 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
151static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) 152static 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
182static void sh_cmt_disable(struct sh_cmt_priv *p) 212static void sh_cmt_disable(struct sh_cmt_priv *p)
diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c
index f33e2dd97934..33b2ed451e09 100644
--- a/drivers/sh/intc/chip.c
+++ b/drivers/sh/intc/chip.c
@@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
186 !defined(CONFIG_CPU_SUBTYPE_SH7709) 186 !defined(CONFIG_CPU_SUBTYPE_SH7709)
187 [IRQ_TYPE_LEVEL_HIGH] = VALID(3), 187 [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
188#endif 188#endif
189#if defined(CONFIG_ARCH_SH7372)
190 [IRQ_TYPE_EDGE_BOTH] = VALID(4),
191#endif
189}; 192};
190 193
191static int intc_set_type(struct irq_data *data, unsigned int type) 194static int intc_set_type(struct irq_data *data, unsigned int type)