| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 | /* linux/arch/arm/plat-s3c24xx/cpu-freq.c * * Copyright (c) 2006-2008 Simtec Electronics *	http://armlinux.simtec.co.uk/ *	Ben Dooks <ben@simtec.co.uk> * * S3C24XX CPU Frequency scaling * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation.*/#include <linux/init.h>#include <linux/module.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/cpufreq.h>#include <linux/cpu.h>#include <linux/clk.h>#include <linux/err.h>#include <linux/io.h>#include <linux/device.h>#include <linux/sysfs.h>#include <linux/slab.h>#include <asm/mach/arch.h>#include <asm/mach/map.h>#include <plat/cpu.h>#include <plat/clock.h>#include <plat/cpu-freq-core.h>#include <mach/regs-clock.h>/* note, cpufreq support deals in kHz, no Hz */static struct cpufreq_driver s3c24xx_driver;static struct s3c_cpufreq_config cpu_cur;static struct s3c_iotimings s3c24xx_iotiming;static struct cpufreq_frequency_table *pll_reg;static unsigned int last_target = ~0;static unsigned int ftab_size;static struct cpufreq_frequency_table *ftab;static struct clk *_clk_mpll;static struct clk *_clk_xtal;static struct clk *clk_fclk;static struct clk *clk_hclk;static struct clk *clk_pclk;static struct clk *clk_arm;#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFSstruct s3c_cpufreq_config *s3c_cpufreq_getconfig(void){	return &cpu_cur;}struct s3c_iotimings *s3c_cpufreq_getiotimings(void){	return &s3c24xx_iotiming;}#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg){	unsigned long fclk, pclk, hclk, armclk;	cfg->freq.fclk = fclk = clk_get_rate(clk_fclk);	cfg->freq.hclk = hclk = clk_get_rate(clk_hclk);	cfg->freq.pclk = pclk = clk_get_rate(clk_pclk);	cfg->freq.armclk = armclk = clk_get_rate(clk_arm);	cfg->pll.index = __raw_readl(S3C2410_MPLLCON);	cfg->pll.frequency = fclk;	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);	cfg->divs.h_divisor = fclk / hclk;	cfg->divs.p_divisor = fclk / pclk;}static inline void s3c_cpufreq_calc(struct s3c_cpufreq_config *cfg){	unsigned long pll = cfg->pll.frequency;	cfg->freq.fclk = pll;	cfg->freq.hclk = pll / cfg->divs.h_divisor;	cfg->freq.pclk = pll / cfg->divs.p_divisor;	/* convert hclk into 10ths of nanoseconds for io calcs */	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);}static inline int closer(unsigned int target, unsigned int n, unsigned int c){	int diff_cur = abs(target - c);	int diff_new = abs(target - n);	return (diff_new < diff_cur);}static void s3c_cpufreq_show(const char *pfx,				 struct s3c_cpufreq_config *cfg){	s3c_freq_dbg("%s: Fvco=%u, F=%lu, A=%lu, H=%lu (%u), P=%lu (%u)\n",		     pfx, cfg->pll.frequency, cfg->freq.fclk, cfg->freq.armclk,		     cfg->freq.hclk, cfg->divs.h_divisor,		     cfg->freq.pclk, cfg->divs.p_divisor);}/* functions to wrapper the driver info calls to do the cpu specific work */static void s3c_cpufreq_setio(struct s3c_cpufreq_config *cfg){	if (cfg->info->set_iotiming)		(cfg->info->set_iotiming)(cfg, &s3c24xx_iotiming);}static int s3c_cpufreq_calcio(struct s3c_cpufreq_config *cfg){	if (cfg->info->calc_iotiming)		return (cfg->info->calc_iotiming)(cfg, &s3c24xx_iotiming);	return 0;}static void s3c_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg){	(cfg->info->set_refresh)(cfg);}static void s3c_cpufreq_setdivs(struct s3c_cpufreq_config *cfg){	(cfg->info->set_divs)(cfg);}static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg){	return (cfg->info->calc_divs)(cfg);}static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg){	(cfg->info->set_fvco)(cfg);}static inline void s3c_cpufreq_resume_clocks(void){	cpu_cur.info->resume_clocks();}static inline void s3c_cpufreq_updateclk(struct clk *clk,					 unsigned int freq){	clk_set_rate(clk, freq);}
 |