Index: drivers/mtd/nand/s3c2410.c =================================================================== RCS file: /home/cvs/mtd/drivers/mtd/nand/s3c2410.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -p -r1.21 -r1.22 --- drivers/mtd/nand/s3c2410.c 29 Nov 2005 20:01:29 -0000 1.21 +++ drivers/mtd/nand/s3c2410.c 15 Mar 2006 22:32:08 -0000 1.22 @@ -18,8 +18,9 @@ * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug * 08-Jul-2005 BJD Fix OOPS when no platform data supplied * 20-Oct-2005 BJD Fix timing calculation bug + * 14-Jan-2006 BJD Allow clock to be stopped when idle * - * $Id: s3c2410.c,v 1.20 2005/11/29 20:01:29 gleixner Exp $ + * $Id: s3c2410.c,v 1.22 2006/03/15 22:32:08 bjd Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,8 +37,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include +#include #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG #define DEBUG @@ -73,6 +73,13 @@ static int hardware_ecc = 1; static int hardware_ecc = 0; #endif +#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP +static int clock_stop = 1; +#else +static const int clock_stop = 0; +#endif + + /* new oob placement block for use with hardware ecc generation */ @@ -135,6 +142,11 @@ static struct s3c2410_platform_nand *to_ return dev->dev.platform_data; } +static inline int allow_clk_stop(struct s3c2410_nand_info *info) +{ + return clock_stop; +} + /* timing calculations */ #define NS_IN_KHZ 1000000 @@ -231,6 +243,9 @@ static void s3c2410_nand_select_chip(str bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE; reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF); + if (chip != -1 && allow_clk_stop(info)) + clk_enable(info->clk); + cur = readl(reg); if (chip == -1) { @@ -250,6 +265,9 @@ static void s3c2410_nand_select_chip(str } writel(cur, reg); + + if (chip == -1 && allow_clk_stop(info)) + clk_disable(info->clk); } /* command and control functions @@ -459,8 +477,8 @@ static int s3c2410_nand_remove(struct pl /* free the common resources */ if (info->clk != NULL && !IS_ERR(info->clk)) { - clk_disable(info->clk); - clk_unuse(info->clk); + if (!allow_clk_stop(info)) + clk_disable(info->clk); clk_put(info->clk); } @@ -598,7 +616,6 @@ static int s3c24xx_nand_probe(struct pla goto exit_error; } - clk_use(info->clk); clk_enable(info->clk); /* allocate and map the resource */ @@ -672,6 +689,11 @@ static int s3c24xx_nand_probe(struct pla sets++; } + if (allow_clk_stop(info)) { + dev_info(&pdev->dev, "clock idle support enabled\n"); + clk_disable(info->clk); + } + pr_debug("initialised ok\n"); return 0; @@ -683,6 +705,41 @@ static int s3c24xx_nand_probe(struct pla return err; } +/* PM Support */ +#ifdef CONFIG_PM + +static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm) +{ + struct s3c2410_nand_info *info = platform_get_drvdata(dev); + + if (info) { + if (!allow_clk_stop(info)) + clk_disable(info->clk); + } + + return 0; +} + +static int s3c24xx_nand_resume(struct platform_device *dev) +{ + struct s3c2410_nand_info *info = platform_get_drvdata(dev); + + if (info) { + clk_enable(info->clk); + s3c2410_nand_inithw(info, dev); + + if (allow_clk_stop(info)) + clk_disable(info->clk); + } + + return 0; +} + +#else +#define s3c24xx_nand_suspend NULL +#define s3c24xx_nand_resume NULL +#endif + /* driver device registration */ static int s3c2410_nand_probe(struct platform_device *dev) @@ -698,6 +755,8 @@ static int s3c2440_nand_probe(struct pla static struct platform_driver s3c2410_nand_driver = { .probe = s3c2410_nand_probe, .remove = s3c2410_nand_remove, + .suspend = s3c24xx_nand_suspend, + .resume = s3c24xx_nand_resume, .driver = { .name = "s3c2410-nand", .owner = THIS_MODULE, @@ -707,6 +766,8 @@ static struct platform_driver s3c2410_na static struct platform_driver s3c2440_nand_driver = { .probe = s3c2440_nand_probe, .remove = s3c2410_nand_remove, + .suspend = s3c24xx_nand_suspend, + .resume = s3c24xx_nand_resume, .driver = { .name = "s3c2440-nand", .owner = THIS_MODULE,