aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig10
-rw-r--r--drivers/mtd/nand/s3c2410.c76
2 files changed, 81 insertions, 5 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 203f90a024db..3db77eec0ed2 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -135,6 +135,16 @@ config MTD_NAND_NDFC
135 help 135 help
136 NDFC Nand Flash Controllers are integrated in EP44x SoCs 136 NDFC Nand Flash Controllers are integrated in EP44x SoCs
137 137
138config MTD_NAND_S3C2410_CLKSTOP
139 bool "S3C2410 NAND IDLE clock stop"
140 depends on MTD_NAND_S3C2410
141 default n
142 help
143 Stop the clock to the NAND controller when there is no chip
144 selected to save power. This will mean there is a small delay
145 when the is NAND chip selected or released, but will save
146 approximately 5mA of power when there is nothing happening.
147
138config MTD_NAND_DISKONCHIP 148config MTD_NAND_DISKONCHIP
139 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" 149 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
140 depends on MTD_NAND && EXPERIMENTAL 150 depends on MTD_NAND && EXPERIMENTAL
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d6365a668874..fd78fb83549e 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -18,8 +18,9 @@
18 * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug 18 * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug
19 * 08-Jul-2005 BJD Fix OOPS when no platform data supplied 19 * 08-Jul-2005 BJD Fix OOPS when no platform data supplied
20 * 20-Oct-2005 BJD Fix timing calculation bug 20 * 20-Oct-2005 BJD Fix timing calculation bug
21 * 14-Jan-2006 BJD Allow clock to be stopped when idle
21 * 22 *
22 * $Id: s3c2410.c,v 1.20 2005/11/07 11:14:31 gleixner Exp $ 23 * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 bjd Exp $
23 * 24 *
24 * This program is free software; you can redistribute it and/or modify 25 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by 26 * it under the terms of the GNU General Public License as published by
@@ -36,9 +37,6 @@
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37*/ 38*/
38 39
39#include <config/mtd/nand/s3c2410/hwecc.h>
40#include <config/mtd/nand/s3c2410/debug.h>
41
42#ifdef CONFIG_MTD_NAND_S3C2410_DEBUG 40#ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
43#define DEBUG 41#define DEBUG
44#endif 42#endif
@@ -73,6 +71,13 @@ static int hardware_ecc = 1;
73static int hardware_ecc = 0; 71static int hardware_ecc = 0;
74#endif 72#endif
75 73
74#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
75static int clock_stop = 1;
76#else
77static const int clock_stop = 0;
78#endif
79
80
76/* new oob placement block for use with hardware ecc generation 81/* new oob placement block for use with hardware ecc generation
77 */ 82 */
78 83
@@ -134,6 +139,11 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
134 return dev->dev.platform_data; 139 return dev->dev.platform_data;
135} 140}
136 141
142static inline int allow_clk_stop(struct s3c2410_nand_info *info)
143{
144 return clock_stop;
145}
146
137/* timing calculations */ 147/* timing calculations */
138 148
139#define NS_IN_KHZ 1000000 149#define NS_IN_KHZ 1000000
@@ -201,6 +211,11 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_d
201 cfg = S3C2440_NFCONF_TACLS(tacls - 1); 211 cfg = S3C2440_NFCONF_TACLS(tacls - 1);
202 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); 212 cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
203 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1); 213 cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
214
215 /* enable the controller and de-assert nFCE */
216
217 writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE,
218 info->regs + S3C2440_NFCONT);
204 } 219 }
205 220
206 pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); 221 pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
@@ -226,6 +241,9 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
226 bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE; 241 bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;
227 reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF); 242 reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF);
228 243
244 if (chip != -1 && allow_clk_stop(info))
245 clk_enable(info->clk);
246
229 cur = readl(reg); 247 cur = readl(reg);
230 248
231 if (chip == -1) { 249 if (chip == -1) {
@@ -245,6 +263,9 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
245 } 263 }
246 264
247 writel(cur, reg); 265 writel(cur, reg);
266
267 if (chip == -1 && allow_clk_stop(info))
268 clk_disable(info->clk);
248} 269}
249 270
250/* command and control functions 271/* command and control functions
@@ -417,7 +438,8 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
417 /* free the common resources */ 438 /* free the common resources */
418 439
419 if (info->clk != NULL && !IS_ERR(info->clk)) { 440 if (info->clk != NULL && !IS_ERR(info->clk)) {
420 clk_disable(info->clk); 441 if (!allow_clk_stop(info))
442 clk_disable(info->clk);
421 clk_put(info->clk); 443 clk_put(info->clk);
422 } 444 }
423 445
@@ -627,6 +649,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
627 sets++; 649 sets++;
628 } 650 }
629 651
652 if (allow_clk_stop(info)) {
653 dev_info(&pdev->dev, "clock idle support enabled\n");
654 clk_disable(info->clk);
655 }
656
630 pr_debug("initialised ok\n"); 657 pr_debug("initialised ok\n");
631 return 0; 658 return 0;
632 659
@@ -638,6 +665,41 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
638 return err; 665 return err;
639} 666}
640 667
668/* PM Support */
669#ifdef CONFIG_PM
670
671static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
672{
673 struct s3c2410_nand_info *info = platform_get_drvdata(dev);
674
675 if (info) {
676 if (!allow_clk_stop(info))
677 clk_disable(info->clk);
678 }
679
680 return 0;
681}
682
683static int s3c24xx_nand_resume(struct platform_device *dev)
684{
685 struct s3c2410_nand_info *info = platform_get_drvdata(dev);
686
687 if (info) {
688 clk_enable(info->clk);
689 s3c2410_nand_inithw(info, dev);
690
691 if (allow_clk_stop(info))
692 clk_disable(info->clk);
693 }
694
695 return 0;
696}
697
698#else
699#define s3c24xx_nand_suspend NULL
700#define s3c24xx_nand_resume NULL
701#endif
702
641/* driver device registration */ 703/* driver device registration */
642 704
643static int s3c2410_nand_probe(struct platform_device *dev) 705static int s3c2410_nand_probe(struct platform_device *dev)
@@ -653,6 +715,8 @@ static int s3c2440_nand_probe(struct platform_device *dev)
653static struct platform_driver s3c2410_nand_driver = { 715static struct platform_driver s3c2410_nand_driver = {
654 .probe = s3c2410_nand_probe, 716 .probe = s3c2410_nand_probe,
655 .remove = s3c2410_nand_remove, 717 .remove = s3c2410_nand_remove,
718 .suspend = s3c24xx_nand_suspend,
719 .resume = s3c24xx_nand_resume,
656 .driver = { 720 .driver = {
657 .name = "s3c2410-nand", 721 .name = "s3c2410-nand",
658 .owner = THIS_MODULE, 722 .owner = THIS_MODULE,
@@ -662,6 +726,8 @@ static struct platform_driver s3c2410_nand_driver = {
662static struct platform_driver s3c2440_nand_driver = { 726static struct platform_driver s3c2440_nand_driver = {
663 .probe = s3c2440_nand_probe, 727 .probe = s3c2440_nand_probe,
664 .remove = s3c2410_nand_remove, 728 .remove = s3c2410_nand_remove,
729 .suspend = s3c24xx_nand_suspend,
730 .resume = s3c24xx_nand_resume,
665 .driver = { 731 .driver = {
666 .name = "s3c2440-nand", 732 .name = "s3c2440-nand",
667 .owner = THIS_MODULE, 733 .owner = THIS_MODULE,