From patchwork Mon Apr 11 03:15:17 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pinkava X-Patchwork-Id: 90558 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6E5D3B6F15 for ; Mon, 11 Apr 2011 13:16:46 +1000 (EST) Received: from canuck.infradead.org ([2001:4978:20e::1]) by bombadil.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1Q97bO-0006Bi-SL; Mon, 11 Apr 2011 03:15:47 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1Q97bN-0002ij-7N; Mon, 11 Apr 2011 03:15:45 +0000 Received: from ns.vscht.cz ([2001:718:3:15::5]) by canuck.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1Q97bI-0002iN-P4; Mon, 11 Apr 2011 03:15:42 +0000 Received: from SMTPgw.vscht.cz (smtpgw.vscht.cz [147.33.10.26]) by ns.vscht.cz (8.13.8/8.13.8) with ESMTP id p3B3FIY6009354; Mon, 11 Apr 2011 05:15:18 +0200 Received: from [147.33.239.194] (147.33.239.194) by smtp.vscht.cz (147.33.10.110) with Microsoft SMTP Server id 8.2.255.0; Mon, 11 Apr 2011 05:15:19 +0200 Message-ID: <4DA27245.6@vscht.cz> Date: Mon, 11 Apr 2011 05:15:17 +0200 From: =?UTF-8?B?SmnFmcOtIFBpbmthdmE=?= Organization: =?UTF-8?B?VsWgQ0hU?= User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110307 Lanikai/3.1.9 MIME-Version: 1.0 To: Randy Dunlap Subject: Re: [PATCH] nand: Fix S3C NAND clock stop References: <1302485262-8401-1-git-send-email-jiri.pinkava@vscht.cz> <4DA261DA.2050404@oracle.com> In-Reply-To: <4DA261DA.2050404@oracle.com> X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110410_231541_559145_DA703C18 X-CRM114-Status: GOOD ( 19.31 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain Cc: "kgene.kim@samsung.com" , "linux-kernel@vger.kernel.org" , "linux-mtd@lists.infradead.org" , "ben-linux@fluff.org" , "dwmw2@infradead.org" , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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 --- drivers/mtd/nand/s3c2410.c | 57 +++++++++++++++++++++++++++++++------------ 1 files changed, 41 insertions(+), 16 deletions(-) #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; From 4fd7086f28d6452f1edafa903e7becd5a0f017c6 Mon Sep 17 00:00:00 2001 From: Jiri Pinkava 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 --- 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