[patch 2/2] CPUFREQ: S3C24XX NAND driver frequency scaling support.

Ben Dooks ben-linux at fluff.org
Thu Jul 10 04:48:59 EDT 2008


On Wed, Jul 09, 2008 at 02:09:21PM +0100, Ben Dooks wrote:
> Add support for CPU frequency scalling to the S3C24XX NAND driver.

please ignore this patch, it has a build error in it.
 
> Signed-off-by: Ben Dooks <ben-linux at fluff.org>
> 
> Index: linux-2.6.26-rc9-quilt1/drivers/mtd/nand/s3c2410.c
> ===================================================================
> --- linux-2.6.26-rc9-quilt1.orig/drivers/mtd/nand/s3c2410.c	2008-07-09 09:28:56.000000000 +0100
> +++ linux-2.6.26-rc9-quilt1/drivers/mtd/nand/s3c2410.c	2008-07-09 09:53:38.000000000 +0100
> @@ -36,6 +36,7 @@
>  #include <linux/err.h>
>  #include <linux/slab.h>
>  #include <linux/clk.h>
> +#include <linux/cpufreq.h>
>  
>  #include <linux/mtd/mtd.h>
>  #include <linux/mtd/nand.h>
> @@ -104,8 +105,13 @@ struct s3c2410_nand_info {
>  	int				sel_bit;
>  	int				mtd_count;
>  	unsigned long			save_sel;
> +	unsigned long			clk_rate;
>  
>  	enum s3c_cpu_type		cpu_type;
> +
> +#ifdef CONFIG_CPU_FREQ
> +	struct notifier_block	freq_transition;
> +#endif
>  };
>  
>  /* conversion functions */
> @@ -163,17 +169,18 @@ static int s3c_nand_calc_rate(int wanted
>  
>  /* controller setup */
>  
> -static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
> -			       struct platform_device *pdev)
> +static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
>  {
> -	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
> -	unsigned long clkrate = clk_get_rate(info->clk);
> +	struct s3c2410_platform_nand *plat = info->platform;
>  	int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
>  	int tacls, twrph0, twrph1;
> -	unsigned long cfg = 0;
> +	unsigned long clkrate = clk_get_rate(info->clk);
> +	unsigned long set, cfg, mask;
> +	unsigned long flags;
>  
>  	/* calculate the timing information for the controller */
>  
> +	info->clk_rate = clkrate;
>  	clkrate /= 1000;	/* turn clock into kHz for ease of use */
>  
>  	if (plat != NULL) {
> @@ -197,26 +204,68 @@ static int s3c2410_nand_inithw(struct s3
>  
>   	switch (info->cpu_type) {
>   	case TYPE_S3C2410:
> -		cfg = S3C2410_NFCONF_EN;
> -		cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
> -		cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
> -		cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
> +		mask = (S3C2410_NFCONF_TACLS(3) |
> +			S3C2410_NFCONF_TWRPH0(7) |
> +			S3C2410_NFCONF_TWRPH1(7));
> +		set = S3C2410_NFCONF_EN;
> +		set |= S3C2410_NFCONF_TACLS(tacls - 1);
> +		set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
> +		set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
>  		break;
>  
>   	case TYPE_S3C2440:
>   	case TYPE_S3C2412:
> -		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 */
> +		mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) |
> +			S3C2410_NFCONF_TWRPH0(7) |
> +			S3C2410_NFCONF_TWRPH1(7));
> +
> +		set = S3C2440_NFCONF_TACLS(tacls - 1);
> +		set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
> +		set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
> +		break;
>  
> -		writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
> +	default:
> +		/* keep compiler happy */
> +		mask = 0;
> +		set = 0;
> +		BUG();
>  	}
>  
>  	dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
>  
> +	local_irq_save(flags);
> +
> +	cfg = readl(info->regs + S3C2410_NFCONF);
> +	cfg &= ~mask;
> +	cfg |= set;
>  	writel(cfg, info->regs + S3C2410_NFCONF);
> +
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
> +{
> +	unsigned long clkrate = clk_get_rate(info->clk);
> +	int ret;
> +
> +	ret = s3c2410_nand_setrate(info, clkrate);
> +	if (ret < 0)
> +		return ret;
> +
> + 	switch (info->cpu_type) {
> + 	case TYPE_S3C2410:
> +	default:
> +		break;
> +
> + 	case TYPE_S3C2440:
> + 	case TYPE_S3C2412:
> +		/* enable the controller and de-assert nFCE */
> +
> +		writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
> +	}
> +
>  	return 0;
>  }
>  
> @@ -497,6 +546,52 @@ static void s3c2440_nand_write_buf(struc
>  	writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
>  }
>  
> +/* cpufreq driver support */
> +
> +#ifdef CONFIG_CPU_FREQ
> +
> +static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
> +					  unsigned long val, void *data)
> +{
> +	struct s3c2410_nand_info *info;
> +	unsigned long newclk = clk_get_rate(info->clk);
> +	long delta;
> +
> +	info = container_of(nb, struct s3c2410_nand_info, freq_transition);
> +
> +	if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
> +	    (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
> +		s3c2410_nand_setrate(info);
> +	}
> +
> +	return 0;
> +}
> +
> +static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
> +{
> +	info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
> +
> +	return cpufreq_register_notifier(&info->freq_transition,
> +					 CPUFREQ_TRANSITION_NOTIFIER);
> +}
> +
> +static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
> +{
> +	cpufreq_unregister_notifier(&info->freq_transition,
> +				    CPUFREQ_TRANSITION_NOTIFIER);
> +}
> +
> +#else
> +static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
> +{
> +	return 0;
> +}
> +
> +static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
> +{
> +}
> +#endif
> +
>  /* device management functions */
>  
>  static int s3c2410_nand_remove(struct platform_device *pdev)
> @@ -508,9 +603,10 @@ static int s3c2410_nand_remove(struct pl
>  	if (info == NULL)
>  		return 0;
>  
> -	/* first thing we need to do is release all our mtds
> -	 * and their partitions, then go through freeing the
> -	 * resources used
> +	s3c2410_nand_cpufreq_deregister(info);
> +
> +	/* Release all our mtds  and their partitions, then go through
> +	 * freeing the resources used
>  	 */
>  
>  	if (info->mtds != NULL) {
> @@ -769,7 +865,7 @@ static int s3c24xx_nand_probe(struct pla
>  
>  	/* initialise the hardware */
>  
> -	err = s3c2410_nand_inithw(info, pdev);
> +	err = s3c2410_nand_inithw(info);
>  	if (err != 0)
>  		goto exit_error;
>  
> @@ -812,6 +908,12 @@ static int s3c24xx_nand_probe(struct pla
>  			sets++;
>  	}
>  
> +	err = s3c2410_nand_cpufreq_register(info);
> +	if (err < 0) {
> +		dev_err(&pdev->dev, "failed to init cpufreq support\n");
> +		goto exit_error;
> +	}
> +
>  	if (allow_clk_stop(info)) {
>  		dev_info(&pdev->dev, "clock idle support enabled\n");
>  		clk_disable(info->clk);
> @@ -859,7 +961,7 @@ static int s3c24xx_nand_resume(struct pl
>  
>  	if (info) {
>  		clk_enable(info->clk);
> -		s3c2410_nand_inithw(info, dev);
> +		s3c2410_nand_inithw(info);
>  
>  		/* Restore the state of the nFCE line. */
>  
> 
> -- 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Ben (ben at fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'



More information about the linux-mtd mailing list