All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] clocksource: sh_cmt: wait for CMCNT on init
@ 2011-06-30  9:12 Magnus Damm
  2011-07-13  7:59 ` [PATCH] clocksource: sh_cmt: wait for CMCNT on init V2 Magnus Damm
  2011-07-21  7:54 ` Paul Mundt
  0 siblings, 2 replies; 3+ messages in thread
From: Magnus Damm @ 2011-06-30  9:12 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

Add code to the CMT driver to wait for CMCNT to settle before
starting the timer channel. Makes the driver more robust.

Needed for CMT2 on sh7372 and certain CMT channels on sh73a0.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 drivers/clocksource/sh_cmt.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

--- 0001/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c	2011-06-29 20:41:22.000000000 +0900
@@ -174,6 +174,20 @@ static int sh_cmt_enable(struct sh_cmt_p
 	sh_cmt_write(p, CMCOR, 0xffffffff);
 	sh_cmt_write(p, CMCNT, 0);
 
+	/*
+	 * According to the user's manual, as CMCNT can be operated only
+	 * by the RCLK (Pseudo 32 KHz), there's one restrictions on
+	 * modifying CMCNT register; two RCLK cycles are necessary before
+	 * this register is either read or any modification of the value
+	 * it holds is reflected in the LSI's actual operation.
+	 *
+	 * While at it, we're supposed to clear out the CMCNT as of this
+	 * moment, so make sure it's processed properly here.  This will
+	 * take RCLKx2 at maximum.
+	 */
+	while (sh_cmt_read(p, CMCNT) != 0)
+		cpu_relax();
+
 	/* enable channel */
 	sh_cmt_start_stop_ch(p, 1);
 	return 0;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] clocksource: sh_cmt: wait for CMCNT on init V2
  2011-06-30  9:12 [PATCH] clocksource: sh_cmt: wait for CMCNT on init Magnus Damm
@ 2011-07-13  7:59 ` Magnus Damm
  2011-07-21  7:54 ` Paul Mundt
  1 sibling, 0 replies; 3+ messages in thread
From: Magnus Damm @ 2011-07-13  7:59 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

Add code to the CMT driver to wait for CMCNT V2. This to let
the register value settle before starting the timer channel.
Makes the driver more robust.

Needed for CMT2 on sh7372 and certain CMT channels on sh73a0.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 Changes since V1:
 - added timeout
 - updated comment

 drivers/clocksource/sh_cmt.c |   35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

--- 0001/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c	2011-07-13 16:47:34.000000000 +0900
@@ -26,6 +26,7 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
@@ -150,13 +151,13 @@ static void sh_cmt_start_stop_ch(struct
 
 static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 {
-	int ret;
+	int k, ret;
 
 	/* enable clock */
 	ret = clk_enable(p->clk);
 	if (ret) {
 		dev_err(&p->pdev->dev, "cannot enable clock\n");
-		return ret;
+		goto err0;
 	}
 
 	/* make sure channel is disabled */
@@ -174,9 +175,39 @@ static int sh_cmt_enable(struct sh_cmt_p
 	sh_cmt_write(p, CMCOR, 0xffffffff);
 	sh_cmt_write(p, CMCNT, 0);
 
+	/*
+	 * According to the sh73a0 user's manual, as CMCNT can be operated
+	 * only by the RCLK (Pseudo 32 KHz), there's one restriction on
+	 * modifying CMCNT register; two RCLK cycles are necessary before
+	 * this register is either read or any modification of the value
+	 * it holds is reflected in the LSI's actual operation.
+	 *
+	 * While at it, we're supposed to clear out the CMCNT as of this
+	 * moment, so make sure it's processed properly here.  This will
+	 * take RCLKx2 at maximum.
+	 */
+
+	for (k = 0; k < 100; k++) {
+		if (!sh_cmt_read(p, CMCNT))
+			break;
+		udelay(1);
+	}
+
+	if (sh_cmt_read(p, CMCNT)) {
+		dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
+		ret = -ETIMEDOUT;
+		goto err1;
+	}
+
 	/* enable channel */
 	sh_cmt_start_stop_ch(p, 1);
 	return 0;
+ err1:
+	/* stop clock */
+	clk_disable(p->clk);
+
+ err0:
+	return ret;
 }
 
 static void sh_cmt_disable(struct sh_cmt_priv *p)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] clocksource: sh_cmt: wait for CMCNT on init V2
  2011-06-30  9:12 [PATCH] clocksource: sh_cmt: wait for CMCNT on init Magnus Damm
  2011-07-13  7:59 ` [PATCH] clocksource: sh_cmt: wait for CMCNT on init V2 Magnus Damm
@ 2011-07-21  7:54 ` Paul Mundt
  1 sibling, 0 replies; 3+ messages in thread
From: Paul Mundt @ 2011-07-21  7:54 UTC (permalink / raw)
  To: linux-sh

On Wed, Jul 13, 2011 at 04:59:48PM +0900, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
> 
> Add code to the CMT driver to wait for CMCNT V2. This to let
> the register value settle before starting the timer channel.
> Makes the driver more robust.
> 
> Needed for CMT2 on sh7372 and certain CMT channels on sh73a0.
> 
> Signed-off-by: Magnus Damm <damm@opensource.se>

Applied, thanks.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-07-21  7:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-30  9:12 [PATCH] clocksource: sh_cmt: wait for CMCNT on init Magnus Damm
2011-07-13  7:59 ` [PATCH] clocksource: sh_cmt: wait for CMCNT on init V2 Magnus Damm
2011-07-21  7:54 ` Paul Mundt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.