All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Jiří Pinkava" <Jiri.Pinkava@vscht.cz>
To: Randy Dunlap <randy.dunlap@oracle.com>
Cc: "kgene.kim@samsung.com" <kgene.kim@samsung.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
	"ben-linux@fluff.org" <ben-linux@fluff.org>,
	"dwmw2@infradead.org" <dwmw2@infradead.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH] nand: Fix S3C NAND clock stop
Date: Mon, 11 Apr 2011 05:15:17 +0200	[thread overview]
Message-ID: <4DA27245.6@vscht.cz> (raw)
In-Reply-To: <4DA261DA.2050404@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 4329 bytes --]

Current implementation of s3c2410_nand_select_chip call
clk_disable every time when chip = -1 (de-select). This happend
multiple times even if chip was already de-selected. This causes
disabling clock even if they are already disabled and due to
nature of clock subsytem implementation this causes nand clock
to be disabled and newer enabled again.

Signed-off-by: Jiri Pinkava <jiri.pinkava@vscht.cz>
---
  drivers/mtd/nand/s3c2410.c |   57 
+++++++++++++++++++++++++++++++------------
  1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..fbc37dc 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -54,8 +54,14 @@ static int hardware_ecc = 1;
  static int hardware_ecc = 0;
  #endif

+#define CLOCK_DISABLE	0
+#define CLOCK_ENABLE	1
+#define CLOCK_SUSPEND	2
+
+static int clock_state = CLOCK_DISABLE;
+
  #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
  #else
  static const int clock_stop = 0;
  #endif
@@ -159,11 +165,33 @@ static struct s3c2410_platform_nand 
*to_nand_plat(struct platform_device *dev)
  	return dev->dev.platform_data;
  }

-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
  {
  	return clock_stop;
  }

+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		int new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (clock_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	clock_state = new_state;
+}
+
  /* timing calculations */

  #define NS_IN_KHZ 1000000
@@ -333,8 +361,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)
  	nmtd = this->priv;
  	info = nmtd->info;

-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	cur = readl(info->sel_reg);

@@ -356,8 +384,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)

  	writel(cur, info->sel_reg);

-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  }

  /* s3c2410_nand_hwcontrol
@@ -694,8 +722,7 @@ static int s3c24xx_nand_remove(struct 
platform_device *pdev)
  	/* free the common resources */

  	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  		clk_put(info->clk);
  	}

@@ -947,7 +974,7 @@ static int s3c24xx_nand_probe(struct platform_device 
*pdev)
  		goto exit_error;
  	}

-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	/* allocate and map the resource */

@@ -1026,9 +1053,9 @@ static int s3c24xx_nand_probe(struct 
platform_device *pdev)
  		goto exit_error;
  	}

-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
  		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	pr_debug("initialised ok\n");
@@ -1059,8 +1086,7 @@ static int s3c24xx_nand_suspend(struct 
platform_device *dev, pm_message_t pm)

  		writel(info->save_sel | info->sel_bit, info->sel_reg);

-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  	}

  	return 0;
@@ -1072,7 +1098,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  	unsigned long sel;

  	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
  		s3c2410_nand_inithw(info);

  		/* Restore the state of the nFCE line. */
@@ -1082,8 +1108,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  		sel |= info->save_sel & info->sel_bit;
  		writel(sel, info->sel_reg);

-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	return 0;
-- 
1.7.4.4



[-- Attachment #2: 0001-nand-Fix-S3C-NAND-clock-stop.patch --]
[-- Type: text/x-patch, Size: 4499 bytes --]

>From 4fd7086f28d6452f1edafa903e7becd5a0f017c6 Mon Sep 17 00:00:00 2001
From: Jiri Pinkava <jiri.pinkava@vscht.cz>
Date: Mon, 11 Apr 2011 03:20:33 +0200
Subject: [PATCH] nand: Fix S3C NAND clock stop

Current implementation of s3c2410_nand_select_chip call
clk_disable every time when chip = -1 (de-select). This happend
multiple times even if chip was already de-selected. This causes
disabling clock even if they are already disabled and due to
nature of clock subsytem implementation this causes nand clock
to be disabled and newer enabled again.

Signed-off-by: Jiri Pinkava <jiri.pinkava@vscht.cz>
---
 drivers/mtd/nand/s3c2410.c |   57 +++++++++++++++++++++++++++++++------------
 1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..fbc37dc 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -54,8 +54,14 @@ static int hardware_ecc = 1;
 static int hardware_ecc = 0;
 #endif
 
+#define CLOCK_DISABLE	0
+#define CLOCK_ENABLE	1
+#define CLOCK_SUSPEND	2
+
+static int clock_state = CLOCK_DISABLE;
+
 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
 #else
 static const int clock_stop = 0;
 #endif
@@ -159,11 +165,33 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
 	return dev->dev.platform_data;
 }
 
-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
 {
 	return clock_stop;
 }
 
+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		int new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (clock_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	clock_state = new_state;
+}
+
 /* timing calculations */
 
 #define NS_IN_KHZ 1000000
@@ -333,8 +361,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 	nmtd = this->priv;
 	info = nmtd->info;
 
-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	cur = readl(info->sel_reg);
 
@@ -356,8 +384,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 
 	writel(cur, info->sel_reg);
 
-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 }
 
 /* s3c2410_nand_hwcontrol
@@ -694,8 +722,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 	/* free the common resources */
 
 	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 		clk_put(info->clk);
 	}
 
@@ -947,7 +974,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 		goto exit_error;
 	}
 
-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	/* allocate and map the resource */
 
@@ -1026,9 +1053,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 		goto exit_error;
 	}
 
-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
 		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	pr_debug("initialised ok\n");
@@ -1059,8 +1086,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
 
 		writel(info->save_sel | info->sel_bit, info->sel_reg);
 
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 	}
 
 	return 0;
@@ -1072,7 +1098,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 	unsigned long sel;
 
 	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 		s3c2410_nand_inithw(info);
 
 		/* Restore the state of the nFCE line. */
@@ -1082,8 +1108,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 		sel |= info->save_sel & info->sel_bit;
 		writel(sel, info->sel_reg);
 
-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	return 0;
-- 
1.7.4.4


WARNING: multiple messages have this Message-ID (diff)
From: Jiri.Pinkava@vscht.cz (Jiří Pinkava)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] nand: Fix S3C NAND clock stop
Date: Mon, 11 Apr 2011 05:15:17 +0200	[thread overview]
Message-ID: <4DA27245.6@vscht.cz> (raw)
In-Reply-To: <4DA261DA.2050404@oracle.com>

Current implementation of s3c2410_nand_select_chip call
clk_disable every time when chip = -1 (de-select). This happend
multiple times even if chip was already de-selected. This causes
disabling clock even if they are already disabled and due to
nature of clock subsytem implementation this causes nand clock
to be disabled and newer enabled again.

Signed-off-by: Jiri Pinkava <jiri.pinkava@vscht.cz>
---
  drivers/mtd/nand/s3c2410.c |   57 
+++++++++++++++++++++++++++++++------------
  1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..fbc37dc 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -54,8 +54,14 @@ static int hardware_ecc = 1;
  static int hardware_ecc = 0;
  #endif

+#define CLOCK_DISABLE	0
+#define CLOCK_ENABLE	1
+#define CLOCK_SUSPEND	2
+
+static int clock_state = CLOCK_DISABLE;
+
  #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
  #else
  static const int clock_stop = 0;
  #endif
@@ -159,11 +165,33 @@ static struct s3c2410_platform_nand 
*to_nand_plat(struct platform_device *dev)
  	return dev->dev.platform_data;
  }

-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
  {
  	return clock_stop;
  }

+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		int new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (clock_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	clock_state = new_state;
+}
+
  /* timing calculations */

  #define NS_IN_KHZ 1000000
@@ -333,8 +361,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)
  	nmtd = this->priv;
  	info = nmtd->info;

-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	cur = readl(info->sel_reg);

@@ -356,8 +384,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)

  	writel(cur, info->sel_reg);

-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  }

  /* s3c2410_nand_hwcontrol
@@ -694,8 +722,7 @@ static int s3c24xx_nand_remove(struct 
platform_device *pdev)
  	/* free the common resources */

  	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  		clk_put(info->clk);
  	}

@@ -947,7 +974,7 @@ static int s3c24xx_nand_probe(struct platform_device 
*pdev)
  		goto exit_error;
  	}

-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	/* allocate and map the resource */

@@ -1026,9 +1053,9 @@ static int s3c24xx_nand_probe(struct 
platform_device *pdev)
  		goto exit_error;
  	}

-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
  		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	pr_debug("initialised ok\n");
@@ -1059,8 +1086,7 @@ static int s3c24xx_nand_suspend(struct 
platform_device *dev, pm_message_t pm)

  		writel(info->save_sel | info->sel_bit, info->sel_reg);

-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  	}

  	return 0;
@@ -1072,7 +1098,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  	unsigned long sel;

  	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
  		s3c2410_nand_inithw(info);

  		/* Restore the state of the nFCE line. */
@@ -1082,8 +1108,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  		sel |= info->save_sel & info->sel_bit;
  		writel(sel, info->sel_reg);

-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	return 0;
-- 
1.7.4.4

WARNING: multiple messages have this Message-ID (diff)
From: "Jiří Pinkava" <Jiri.Pinkava@vscht.cz>
To: Randy Dunlap <randy.dunlap@oracle.com>
Cc: "ben-linux@fluff.org" <ben-linux@fluff.org>,
	"kgene.kim@samsung.com" <kgene.kim@samsung.com>,
	"dwmw2@infradead.org" <dwmw2@infradead.org>,
	"linux-arm-kernel@lists.infradead.org" 
	<linux-arm-kernel@lists.infradead.org>,
	"linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] nand: Fix S3C NAND clock stop
Date: Mon, 11 Apr 2011 05:15:17 +0200	[thread overview]
Message-ID: <4DA27245.6@vscht.cz> (raw)
In-Reply-To: <4DA261DA.2050404@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 4329 bytes --]

Current implementation of s3c2410_nand_select_chip call
clk_disable every time when chip = -1 (de-select). This happend
multiple times even if chip was already de-selected. This causes
disabling clock even if they are already disabled and due to
nature of clock subsytem implementation this causes nand clock
to be disabled and newer enabled again.

Signed-off-by: Jiri Pinkava <jiri.pinkava@vscht.cz>
---
  drivers/mtd/nand/s3c2410.c |   57 
+++++++++++++++++++++++++++++++------------
  1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..fbc37dc 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -54,8 +54,14 @@ static int hardware_ecc = 1;
  static int hardware_ecc = 0;
  #endif

+#define CLOCK_DISABLE	0
+#define CLOCK_ENABLE	1
+#define CLOCK_SUSPEND	2
+
+static int clock_state = CLOCK_DISABLE;
+
  #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
  #else
  static const int clock_stop = 0;
  #endif
@@ -159,11 +165,33 @@ static struct s3c2410_platform_nand 
*to_nand_plat(struct platform_device *dev)
  	return dev->dev.platform_data;
  }

-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
  {
  	return clock_stop;
  }

+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		int new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (clock_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	clock_state = new_state;
+}
+
  /* timing calculations */

  #define NS_IN_KHZ 1000000
@@ -333,8 +361,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)
  	nmtd = this->priv;
  	info = nmtd->info;

-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	cur = readl(info->sel_reg);

@@ -356,8 +384,8 @@ static void s3c2410_nand_select_chip(struct mtd_info 
*mtd, int chip)

  	writel(cur, info->sel_reg);

-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  }

  /* s3c2410_nand_hwcontrol
@@ -694,8 +722,7 @@ static int s3c24xx_nand_remove(struct 
platform_device *pdev)
  	/* free the common resources */

  	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  		clk_put(info->clk);
  	}

@@ -947,7 +974,7 @@ static int s3c24xx_nand_probe(struct platform_device 
*pdev)
  		goto exit_error;
  	}

-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);

  	/* allocate and map the resource */

@@ -1026,9 +1053,9 @@ static int s3c24xx_nand_probe(struct 
platform_device *pdev)
  		goto exit_error;
  	}

-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
  		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	pr_debug("initialised ok\n");
@@ -1059,8 +1086,7 @@ static int s3c24xx_nand_suspend(struct 
platform_device *dev, pm_message_t pm)

  		writel(info->save_sel | info->sel_bit, info->sel_reg);

-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
  	}

  	return 0;
@@ -1072,7 +1098,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  	unsigned long sel;

  	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
  		s3c2410_nand_inithw(info);

  		/* Restore the state of the nFCE line. */
@@ -1082,8 +1108,7 @@ static int s3c24xx_nand_resume(struct 
platform_device *dev)
  		sel |= info->save_sel & info->sel_bit;
  		writel(sel, info->sel_reg);

-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
  	}

  	return 0;
-- 
1.7.4.4



[-- Attachment #2: 0001-nand-Fix-S3C-NAND-clock-stop.patch --]
[-- Type: text/x-patch, Size: 4499 bytes --]

>From 4fd7086f28d6452f1edafa903e7becd5a0f017c6 Mon Sep 17 00:00:00 2001
From: Jiri Pinkava <jiri.pinkava@vscht.cz>
Date: Mon, 11 Apr 2011 03:20:33 +0200
Subject: [PATCH] nand: Fix S3C NAND clock stop

Current implementation of s3c2410_nand_select_chip call
clk_disable every time when chip = -1 (de-select). This happend
multiple times even if chip was already de-selected. This causes
disabling clock even if they are already disabled and due to
nature of clock subsytem implementation this causes nand clock
to be disabled and newer enabled again.

Signed-off-by: Jiri Pinkava <jiri.pinkava@vscht.cz>
---
 drivers/mtd/nand/s3c2410.c |   57 +++++++++++++++++++++++++++++++------------
 1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..fbc37dc 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -54,8 +54,14 @@ static int hardware_ecc = 1;
 static int hardware_ecc = 0;
 #endif
 
+#define CLOCK_DISABLE	0
+#define CLOCK_ENABLE	1
+#define CLOCK_SUSPEND	2
+
+static int clock_state = CLOCK_DISABLE;
+
 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
 #else
 static const int clock_stop = 0;
 #endif
@@ -159,11 +165,33 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
 	return dev->dev.platform_data;
 }
 
-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
 {
 	return clock_stop;
 }
 
+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		int new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (clock_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	clock_state = new_state;
+}
+
 /* timing calculations */
 
 #define NS_IN_KHZ 1000000
@@ -333,8 +361,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 	nmtd = this->priv;
 	info = nmtd->info;
 
-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	cur = readl(info->sel_reg);
 
@@ -356,8 +384,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 
 	writel(cur, info->sel_reg);
 
-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 }
 
 /* s3c2410_nand_hwcontrol
@@ -694,8 +722,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 	/* free the common resources */
 
 	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 		clk_put(info->clk);
 	}
 
@@ -947,7 +974,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 		goto exit_error;
 	}
 
-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	/* allocate and map the resource */
 
@@ -1026,9 +1053,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 		goto exit_error;
 	}
 
-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
 		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	pr_debug("initialised ok\n");
@@ -1059,8 +1086,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
 
 		writel(info->save_sel | info->sel_bit, info->sel_reg);
 
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 	}
 
 	return 0;
@@ -1072,7 +1098,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 	unsigned long sel;
 
 	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 		s3c2410_nand_inithw(info);
 
 		/* Restore the state of the nFCE line. */
@@ -1082,8 +1108,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
 		sel |= info->save_sel & info->sel_bit;
 		writel(sel, info->sel_reg);
 
-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	return 0;
-- 
1.7.4.4


  reply	other threads:[~2011-04-11  3:15 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-11  1:27 [PATCH] nand: Fix S3C NAND clock stop Jiri Pinkava
2011-04-11  1:27 ` Jiri Pinkava
2011-04-11  1:27 ` Jiri Pinkava
2011-04-11  2:05 ` Randy Dunlap
2011-04-11  2:05   ` Randy Dunlap
2011-04-11  2:05   ` Randy Dunlap
2011-04-11  3:15   ` Jiří Pinkava [this message]
2011-04-11  3:15     ` Jiří Pinkava
2011-04-11  3:15     ` Jiří Pinkava
2011-04-11 14:48     ` Jiri Pinkava
2011-04-11 14:48       ` Jiri Pinkava
2011-04-13  3:36       ` Artem Bityutskiy
2011-04-13  3:36         ` Artem Bityutskiy
2011-04-13  9:59         ` [PATCH 1/2] " Jiri Pinkava
2011-04-13  9:59           ` Jiri Pinkava
2011-04-13  9:59           ` [PATCH 2/2] nand: Remove unnecessary variable Jiri Pinkava
2011-04-13  9:59             ` Jiri Pinkava
2011-04-14 12:17             ` Artem Bityutskiy
2011-04-14 12:17               ` Artem Bityutskiy
2011-04-14 12:16           ` [PATCH 1/2] nand: Fix S3C NAND clock stop Artem Bityutskiy
2011-04-14 12:16             ` Artem Bityutskiy
  -- strict thread matches above, loose matches on Subject: below --
2011-04-11  1:20 [PATCH] " Jiri Pinkava
2011-04-11  1:20 Jiri Pinkava

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DA27245.6@vscht.cz \
    --to=jiri.pinkava@vscht.cz \
    --cc=ben-linux@fluff.org \
    --cc=dwmw2@infradead.org \
    --cc=kgene.kim@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=randy.dunlap@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.