Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1fef3c5 authored by Ben Dooks's avatar Ben Dooks Committed by David Woodhouse
Browse files

[MTD NAND] s3c24x0 board: Fix clock handling, ensure proper initialisation.

parent 1046d880
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -135,6 +135,16 @@ config MTD_NAND_NDFC
	help
	 NDFC Nand Flash Controllers are integrated in EP44x SoCs

config MTD_NAND_S3C2410_CLKSTOP
	bool "S3C2410 NAND IDLE clock stop"
	depends on MTD_NAND_S3C2410
	default n
	help
	  Stop the clock to the NAND controller when there is no chip
	  selected to save power. This will mean there is a small delay
	  when the is NAND chip selected or released, but will save
	  approximately 5mA of power when there is nothing happening.

config MTD_NAND_DISKONCHIP
	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
	depends on MTD_NAND && EXPERIMENTAL
+71 −5
Original line number Diff line number Diff line
@@ -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/07 11:14:31 gleixner Exp $
 * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 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,9 +37,6 @@
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <config/mtd/nand/s3c2410/hwecc.h>
#include <config/mtd/nand/s3c2410/debug.h>

#ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
#define DEBUG
#endif
@@ -73,6 +71,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
 */

@@ -134,6 +139,11 @@ 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)
{
	return clock_stop;
}

/* timing calculations */

#define NS_IN_KHZ 1000000
@@ -201,6 +211,11 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_d
		cfg = S3C2440_NFCONF_TACLS(tacls - 1);
		cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
		cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);

		/* enable the controller and de-assert nFCE */

		writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE,
		       info->regs + S3C2440_NFCONT);
	}

	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)
	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) {
@@ -245,6 +263,9 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
	}

	writel(cur, reg);

	if (chip == -1 && allow_clk_stop(info))
		clk_disable(info->clk);
}

/* command and control functions
@@ -417,6 +438,7 @@ static int s3c2410_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);
		clk_put(info->clk);
	}
@@ -627,6 +649,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
			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;

@@ -638,6 +665,41 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
	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)
@@ -653,6 +715,8 @@ static int s3c2440_nand_probe(struct platform_device *dev)
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,
@@ -662,6 +726,8 @@ static struct platform_driver s3c2410_nand_driver = {
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,