Merge back earlier 'pm-cpufreq' material.
This commit is contained in:
		
						commit
						51c4c4ce1d
					
				| @ -200,3 +200,27 @@ Description:	address and size of the percpu note. | ||||
| 		note of cpu#. | ||||
| 
 | ||||
| 		crash_notes_size: size of the note of cpu#. | ||||
| 
 | ||||
| 
 | ||||
| What:		/sys/devices/system/cpu/intel_pstate/max_perf_pct | ||||
| 		/sys/devices/system/cpu/intel_pstate/min_perf_pct | ||||
| 		/sys/devices/system/cpu/intel_pstate/no_turbo | ||||
| Date:		February 2013 | ||||
| Contact:	linux-pm@vger.kernel.org | ||||
| Description:	Parameters for the Intel P-state driver | ||||
| 
 | ||||
| 		Logic for selecting the current P-state in Intel | ||||
| 		Sandybridge+ processors. The three knobs control | ||||
| 		limits for the P-state that will be requested by the | ||||
| 		driver. | ||||
| 
 | ||||
| 		max_perf_pct: limits the maximum P state that will be requested by | ||||
| 		the driver stated as a percentage of the available performance. | ||||
| 
 | ||||
| 		min_perf_pct: limits the minimum P state that will be requested by | ||||
| 		the driver stated as a percentage of the available performance. | ||||
| 
 | ||||
| 		no_turbo: limits the driver to selecting P states below the turbo | ||||
| 		frequency range. | ||||
| 
 | ||||
| 		More details can be found in Documentation/cpu-freq/intel-pstate.txt | ||||
|  | ||||
							
								
								
									
										40
									
								
								Documentation/cpu-freq/intel-pstate.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Documentation/cpu-freq/intel-pstate.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| Intel P-state driver | ||||
| -------------------- | ||||
| 
 | ||||
| This driver implements a scaling driver with an internal governor for | ||||
| Intel Core processors.  The driver follows the same model as the | ||||
| Transmeta scaling driver (longrun.c) and implements the setpolicy() | ||||
| instead of target().  Scaling drivers that implement setpolicy() are | ||||
| assumed to implement internal governors by the cpufreq core. All the | ||||
| logic for selecting the current P state is contained within the | ||||
| driver; no external governor is used by the cpufreq core. | ||||
| 
 | ||||
| Intel SandyBridge+ processors are supported. | ||||
| 
 | ||||
| New sysfs files for controlling P state selection have been added to | ||||
| /sys/devices/system/cpu/intel_pstate/ | ||||
| 
 | ||||
|       max_perf_pct: limits the maximum P state that will be requested by | ||||
|       the driver stated as a percentage of the available performance. | ||||
| 
 | ||||
|       min_perf_pct: limits the minimum P state that will be  requested by | ||||
|       the driver stated as a percentage of the available performance. | ||||
| 
 | ||||
|       no_turbo: limits the driver to selecting P states below the turbo | ||||
|       frequency range. | ||||
| 
 | ||||
| For contemporary Intel processors, the frequency is controlled by the | ||||
| processor itself and the P-states exposed to software are related to | ||||
| performance levels.  The idea that frequency can be set to a single | ||||
| frequency is fiction for Intel Core processors. Even if the scaling | ||||
| driver selects a single P state the actual frequency the processor | ||||
| will run at is selected by the processor itself. | ||||
| 
 | ||||
| New debugfs files have also been added to /sys/kernel/debug/pstate_snb/ | ||||
| 
 | ||||
|       deadband | ||||
|       d_gain_pct | ||||
|       i_gain_pct | ||||
|       p_gain_pct | ||||
|       sample_rate_ms | ||||
|       setpoint | ||||
| @ -303,6 +303,11 @@ void __init exynos_cpuidle_init(void) | ||||
| 	platform_device_register(&exynos_cpuidle); | ||||
| } | ||||
| 
 | ||||
| void __init exynos_cpufreq_init(void) | ||||
| { | ||||
| 	platform_device_register_simple("exynos-cpufreq", -1, NULL, 0); | ||||
| } | ||||
| 
 | ||||
| void __init exynos_init_late(void) | ||||
| { | ||||
| 	if (of_machine_is_compatible("samsung,exynos5440")) | ||||
|  | ||||
| @ -22,6 +22,7 @@ void exynos_init_io(void); | ||||
| void exynos4_restart(enum reboot_mode mode, const char *cmd); | ||||
| void exynos5_restart(enum reboot_mode mode, const char *cmd); | ||||
| void exynos_cpuidle_init(void); | ||||
| void exynos_cpufreq_init(void); | ||||
| void exynos_init_late(void); | ||||
| 
 | ||||
| void exynos_firmware_init(void); | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
| static void __init exynos4_dt_machine_init(void) | ||||
| { | ||||
| 	exynos_cpuidle_init(); | ||||
| 	exynos_cpufreq_init(); | ||||
| 
 | ||||
| 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | ||||
| } | ||||
|  | ||||
| @ -44,6 +44,7 @@ static void __init exynos5_dt_machine_init(void) | ||||
| 	} | ||||
| 
 | ||||
| 	exynos_cpuidle_init(); | ||||
| 	exynos_cpufreq_init(); | ||||
| 
 | ||||
| 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | ||||
| } | ||||
|  | ||||
| @ -181,7 +181,8 @@ config CPU_FREQ_GOV_CONSERVATIVE | ||||
| 
 | ||||
| config GENERIC_CPUFREQ_CPU0 | ||||
| 	tristate "Generic CPU0 cpufreq driver" | ||||
| 	depends on HAVE_CLK && REGULATOR && PM_OPP && OF | ||||
| 	depends on HAVE_CLK && REGULATOR && OF | ||||
| 	select PM_OPP | ||||
| 	help | ||||
| 	  This adds a generic cpufreq driver for CPU0 frequency management. | ||||
| 	  It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) | ||||
|  | ||||
| @ -4,7 +4,8 @@ | ||||
| 
 | ||||
| config ARM_BIG_LITTLE_CPUFREQ | ||||
| 	tristate "Generic ARM big LITTLE CPUfreq driver" | ||||
| 	depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK | ||||
| 	depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK | ||||
| 	select PM_OPP | ||||
| 	help | ||||
| 	  This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. | ||||
| 
 | ||||
| @ -54,7 +55,8 @@ config ARM_EXYNOS5250_CPUFREQ | ||||
| config ARM_EXYNOS5440_CPUFREQ | ||||
| 	bool "SAMSUNG EXYNOS5440" | ||||
| 	depends on SOC_EXYNOS5440 | ||||
| 	depends on HAVE_CLK && PM_OPP && OF | ||||
| 	depends on HAVE_CLK && OF | ||||
| 	select PM_OPP | ||||
| 	default y | ||||
| 	help | ||||
| 	  This adds the CPUFreq driver for Samsung EXYNOS5440 | ||||
| @ -79,11 +81,11 @@ config ARM_HIGHBANK_CPUFREQ | ||||
| 	  If in doubt, say N. | ||||
| 
 | ||||
| config ARM_IMX6Q_CPUFREQ | ||||
| 	tristate "Freescale i.MX6Q cpufreq support" | ||||
| 	depends on SOC_IMX6Q | ||||
| 	tristate "Freescale i.MX6 cpufreq support" | ||||
| 	depends on ARCH_MXC | ||||
| 	depends on REGULATOR_ANATOP | ||||
| 	help | ||||
| 	  This adds cpufreq driver support for Freescale i.MX6Q SOC. | ||||
| 	  This adds cpufreq driver support for Freescale i.MX6 series SoCs. | ||||
| 
 | ||||
| 	  If in doubt, say N. | ||||
| 
 | ||||
|  | ||||
| @ -488,7 +488,8 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) | ||||
| static struct cpufreq_driver bL_cpufreq_driver = { | ||||
| 	.name			= "arm-big-little", | ||||
| 	.flags			= CPUFREQ_STICKY | | ||||
| 					CPUFREQ_HAVE_GOVERNOR_PER_POLICY, | ||||
| 					CPUFREQ_HAVE_GOVERNOR_PER_POLICY | | ||||
| 					CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify			= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index		= bL_cpufreq_set_target, | ||||
| 	.get			= bL_cpufreq_get_rate, | ||||
|  | ||||
| @ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) | ||||
| 	int ret; | ||||
| 
 | ||||
| 	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); | ||||
| 	if (freq_Hz < 0) | ||||
| 	if (freq_Hz <= 0) | ||||
| 		freq_Hz = freq_table[index].frequency * 1000; | ||||
| 
 | ||||
| 	freq_exact = freq_Hz; | ||||
|  | ||||
| @ -39,7 +39,7 @@ static struct cpufreq_driver *cpufreq_driver; | ||||
| static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); | ||||
| static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); | ||||
| static DEFINE_RWLOCK(cpufreq_driver_lock); | ||||
| static DEFINE_MUTEX(cpufreq_governor_lock); | ||||
| DEFINE_MUTEX(cpufreq_governor_lock); | ||||
| static LIST_HEAD(cpufreq_policy_list); | ||||
| 
 | ||||
| #ifdef CONFIG_HOTPLUG_CPU | ||||
| @ -320,6 +320,20 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy, | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cpufreq_notify_transition); | ||||
| 
 | ||||
| /* Do post notifications when there are chances that transition has failed */ | ||||
| void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | ||||
| 		struct cpufreq_freqs *freqs, int transition_failed) | ||||
| { | ||||
| 	cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); | ||||
| 	if (!transition_failed) | ||||
| 		return; | ||||
| 
 | ||||
| 	swap(freqs->old, freqs->new); | ||||
| 	cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); | ||||
| 	cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); | ||||
| 
 | ||||
| 
 | ||||
| /*********************************************************************
 | ||||
|  *                          SYSFS INTERFACE                          * | ||||
| @ -1059,6 +1073,46 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Sometimes boot loaders set CPU frequency to a value outside of | ||||
| 	 * frequency table present with cpufreq core. In such cases CPU might be | ||||
| 	 * unstable if it has to run on that frequency for long duration of time | ||||
| 	 * and so its better to set it to a frequency which is specified in | ||||
| 	 * freq-table. This also makes cpufreq stats inconsistent as | ||||
| 	 * cpufreq-stats would fail to register because current frequency of CPU | ||||
| 	 * isn't found in freq-table. | ||||
| 	 * | ||||
| 	 * Because we don't want this change to effect boot process badly, we go | ||||
| 	 * for the next freq which is >= policy->cur ('cur' must be set by now, | ||||
| 	 * otherwise we will end up setting freq to lowest of the table as 'cur' | ||||
| 	 * is initialized to zero). | ||||
| 	 * | ||||
| 	 * We are passing target-freq as "policy->cur - 1" otherwise | ||||
| 	 * __cpufreq_driver_target() would simply fail, as policy->cur will be | ||||
| 	 * equal to target-freq. | ||||
| 	 */ | ||||
| 	if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK) | ||||
| 	    && has_target()) { | ||||
| 		/* Are we running at unknown frequency ? */ | ||||
| 		ret = cpufreq_frequency_table_get_index(policy, policy->cur); | ||||
| 		if (ret == -EINVAL) { | ||||
| 			/* Warn user and fix it */ | ||||
| 			pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n", | ||||
| 				__func__, policy->cpu, policy->cur); | ||||
| 			ret = __cpufreq_driver_target(policy, policy->cur - 1, | ||||
| 				CPUFREQ_RELATION_L); | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * Reaching here after boot in a few seconds may not | ||||
| 			 * mean that system will remain stable at "unknown" | ||||
| 			 * frequency for longer duration. Hence, a BUG_ON(). | ||||
| 			 */ | ||||
| 			BUG_ON(ret); | ||||
| 			pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n", | ||||
| 				__func__, policy->cpu, policy->cur); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* related cpus should atleast have policy->cpus */ | ||||
| 	cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); | ||||
| 
 | ||||
| @ -1725,17 +1779,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | ||||
| 			pr_err("%s: Failed to change cpu frequency: %d\n", | ||||
| 					__func__, retval); | ||||
| 
 | ||||
| 		if (notify) { | ||||
| 			/*
 | ||||
| 			 * Notify with old freq in case we failed to change | ||||
| 			 * frequency | ||||
| 			 */ | ||||
| 			if (retval) | ||||
| 				freqs.new = freqs.old; | ||||
| 
 | ||||
| 			cpufreq_notify_transition(policy, &freqs, | ||||
| 					CPUFREQ_POSTCHANGE); | ||||
| 		} | ||||
| 		if (notify) | ||||
| 			cpufreq_notify_post_transition(policy, &freqs, retval); | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
|  | ||||
| @ -119,8 +119,9 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	mutex_lock(&cpufreq_governor_lock); | ||||
| 	if (!policy->governor_enabled) | ||||
| 		return; | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
| 	if (!all_cpus) { | ||||
| 		/*
 | ||||
| @ -135,6 +136,9 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, | ||||
| 		for_each_cpu(i, policy->cpus) | ||||
| 			__gov_queue_work(i, dbs_data, delay); | ||||
| 	} | ||||
| 
 | ||||
| out_unlock: | ||||
| 	mutex_unlock(&cpufreq_governor_lock); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(gov_queue_work); | ||||
| 
 | ||||
|  | ||||
| @ -257,6 +257,8 @@ static ssize_t show_sampling_rate_min_gov_pol				\ | ||||
| 	return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);	\ | ||||
| } | ||||
| 
 | ||||
| extern struct mutex cpufreq_governor_lock; | ||||
| 
 | ||||
| void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); | ||||
| bool need_load_eval(struct cpu_dbs_common_info *cdbs, | ||||
| 		unsigned int sampling_rate); | ||||
|  | ||||
| @ -126,7 +126,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver davinci_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= davinci_verify_speed, | ||||
| 	.target_index	= davinci_target, | ||||
| 	.get		= davinci_getspeed, | ||||
|  | ||||
| @ -48,7 +48,8 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver dbx500_cpufreq_driver = { | ||||
| 	.flags  = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS, | ||||
| 	.flags  = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS | | ||||
| 			CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify = cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index = dbx500_cpufreq_target, | ||||
| 	.get    = dbx500_cpufreq_getspeed, | ||||
|  | ||||
| @ -17,6 +17,7 @@ | ||||
| #include <linux/regulator/consumer.h> | ||||
| #include <linux/cpufreq.h> | ||||
| #include <linux/suspend.h> | ||||
| #include <linux/platform_device.h> | ||||
| 
 | ||||
| #include <plat/cpu.h> | ||||
| 
 | ||||
| @ -218,7 +219,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver exynos_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= exynos_target, | ||||
| 	.get		= exynos_getspeed, | ||||
| @ -232,7 +233,7 @@ static struct cpufreq_driver exynos_driver = { | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| static int __init exynos_cpufreq_init(void) | ||||
| static int exynos_cpufreq_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	int ret = -EINVAL; | ||||
| 
 | ||||
| @ -281,4 +282,12 @@ err_vdd_arm: | ||||
| 	kfree(exynos_info); | ||||
| 	return -EINVAL; | ||||
| } | ||||
| late_initcall(exynos_cpufreq_init); | ||||
| 
 | ||||
| static struct platform_driver exynos_cpufreq_platdrv = { | ||||
| 	.driver = { | ||||
| 		.name	= "exynos-cpufreq", | ||||
| 		.owner	= THIS_MODULE, | ||||
| 	}, | ||||
| 	.probe = exynos_cpufreq_probe, | ||||
| }; | ||||
| module_platform_driver(exynos_cpufreq_platdrv); | ||||
|  | ||||
| @ -102,12 +102,12 @@ static void set_clkdiv(unsigned int div_index) | ||||
| 		cpu_relax(); | ||||
| } | ||||
| 
 | ||||
| static void set_apll(unsigned int new_index, | ||||
| 			     unsigned int old_index) | ||||
| static void set_apll(unsigned int index) | ||||
| { | ||||
| 	unsigned int tmp, pdiv; | ||||
| 	unsigned int tmp; | ||||
| 	unsigned int freq = apll_freq_5250[index].freq; | ||||
| 
 | ||||
| 	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ | ||||
| 	/* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ | ||||
| 	clk_set_parent(moutcore, mout_mpll); | ||||
| 
 | ||||
| 	do { | ||||
| @ -116,24 +116,9 @@ static void set_apll(unsigned int new_index, | ||||
| 		tmp &= 0x7; | ||||
| 	} while (tmp != 0x2); | ||||
| 
 | ||||
| 	/* 2. Set APLL Lock time */ | ||||
| 	pdiv = ((apll_freq_5250[new_index].mps >> 8) & 0x3f); | ||||
| 	clk_set_rate(mout_apll, freq * 1000); | ||||
| 
 | ||||
| 	__raw_writel((pdiv * 250), EXYNOS5_APLL_LOCK); | ||||
| 
 | ||||
| 	/* 3. Change PLL PMS values */ | ||||
| 	tmp = __raw_readl(EXYNOS5_APLL_CON0); | ||||
| 	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0)); | ||||
| 	tmp |= apll_freq_5250[new_index].mps; | ||||
| 	__raw_writel(tmp, EXYNOS5_APLL_CON0); | ||||
| 
 | ||||
| 	/* 4. wait_lock_time */ | ||||
| 	do { | ||||
| 		cpu_relax(); | ||||
| 		tmp = __raw_readl(EXYNOS5_APLL_CON0); | ||||
| 	} while (!(tmp & (0x1 << 29))); | ||||
| 
 | ||||
| 	/* 5. MUX_CORE_SEL = APLL */ | ||||
| 	/* MUX_CORE_SEL = APLL */ | ||||
| 	clk_set_parent(moutcore, mout_apll); | ||||
| 
 | ||||
| 	do { | ||||
| @ -141,55 +126,17 @@ static void set_apll(unsigned int new_index, | ||||
| 		tmp = __raw_readl(EXYNOS5_CLKMUX_STATCPU); | ||||
| 		tmp &= (0x7 << 16); | ||||
| 	} while (tmp != (0x1 << 16)); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static bool exynos5250_pms_change(unsigned int old_index, unsigned int new_index) | ||||
| { | ||||
| 	unsigned int old_pm = apll_freq_5250[old_index].mps >> 8; | ||||
| 	unsigned int new_pm = apll_freq_5250[new_index].mps >> 8; | ||||
| 
 | ||||
| 	return (old_pm == new_pm) ? 0 : 1; | ||||
| } | ||||
| 
 | ||||
| static void exynos5250_set_frequency(unsigned int old_index, | ||||
| 				  unsigned int new_index) | ||||
| { | ||||
| 	unsigned int tmp; | ||||
| 
 | ||||
| 	if (old_index > new_index) { | ||||
| 		if (!exynos5250_pms_change(old_index, new_index)) { | ||||
| 			/* 1. Change the system clock divider values */ | ||||
| 			set_clkdiv(new_index); | ||||
| 			/* 2. Change just s value in apll m,p,s value */ | ||||
| 			tmp = __raw_readl(EXYNOS5_APLL_CON0); | ||||
| 			tmp &= ~(0x7 << 0); | ||||
| 			tmp |= apll_freq_5250[new_index].mps & 0x7; | ||||
| 			__raw_writel(tmp, EXYNOS5_APLL_CON0); | ||||
| 
 | ||||
| 		} else { | ||||
| 			/* Clock Configuration Procedure */ | ||||
| 			/* 1. Change the system clock divider values */ | ||||
| 			set_clkdiv(new_index); | ||||
| 			/* 2. Change the apll m,p,s value */ | ||||
| 			set_apll(new_index, old_index); | ||||
| 		} | ||||
| 		set_clkdiv(new_index); | ||||
| 		set_apll(new_index); | ||||
| 	} else if (old_index < new_index) { | ||||
| 		if (!exynos5250_pms_change(old_index, new_index)) { | ||||
| 			/* 1. Change just s value in apll m,p,s value */ | ||||
| 			tmp = __raw_readl(EXYNOS5_APLL_CON0); | ||||
| 			tmp &= ~(0x7 << 0); | ||||
| 			tmp |= apll_freq_5250[new_index].mps & 0x7; | ||||
| 			__raw_writel(tmp, EXYNOS5_APLL_CON0); | ||||
| 			/* 2. Change the system clock divider values */ | ||||
| 			set_clkdiv(new_index); | ||||
| 		} else { | ||||
| 			/* Clock Configuration Procedure */ | ||||
| 			/* 1. Change the apll m,p,s value */ | ||||
| 			set_apll(new_index, old_index); | ||||
| 			/* 2. Change the system clock divider values */ | ||||
| 			set_clkdiv(new_index); | ||||
| 		} | ||||
| 		set_apll(new_index); | ||||
| 		set_clkdiv(new_index); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -222,7 +169,6 @@ int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) | ||||
| 	info->volt_table = exynos5250_volt_table; | ||||
| 	info->freq_table = exynos5250_freq_table; | ||||
| 	info->set_freq = exynos5250_set_frequency; | ||||
| 	info->need_apll_change = exynos5250_pms_change; | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
|  | ||||
| @ -312,7 +312,8 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver exynos_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION | | ||||
| 				CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= exynos_target, | ||||
| 	.get		= exynos_getspeed, | ||||
|  | ||||
| @ -178,7 +178,29 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); | ||||
| 
 | ||||
| int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, | ||||
| 		unsigned int freq) | ||||
| { | ||||
| 	struct cpufreq_frequency_table *table; | ||||
| 	int i; | ||||
| 
 | ||||
| 	table = cpufreq_frequency_get_table(policy->cpu); | ||||
| 	if (unlikely(!table)) { | ||||
| 		pr_debug("%s: Unable to find frequency table\n", __func__); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||||
| 		if (table[i].frequency == freq) | ||||
| 			return i; | ||||
| 	} | ||||
| 
 | ||||
| 	return -EINVAL; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); | ||||
| 
 | ||||
| static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table); | ||||
| 
 | ||||
| /**
 | ||||
|  * show_available_freqs - show available frequencies for the specified CPU | ||||
|  */ | ||||
|  | ||||
| @ -35,6 +35,9 @@ static struct device *cpu_dev; | ||||
| static struct cpufreq_frequency_table *freq_table; | ||||
| static unsigned int transition_latency; | ||||
| 
 | ||||
| static u32 *imx6_soc_volt; | ||||
| static u32 soc_opp_count; | ||||
| 
 | ||||
| static unsigned int imx6q_get_speed(unsigned int cpu) | ||||
| { | ||||
| 	return clk_get_rate(arm_clk) / 1000; | ||||
| @ -69,23 +72,22 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) | ||||
| 
 | ||||
| 	/* scaling up?  scale voltage before frequency */ | ||||
| 	if (new_freq > old_freq) { | ||||
| 		ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); | ||||
| 		if (ret) { | ||||
| 			dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); | ||||
| 		if (ret) { | ||||
| 			dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		ret = regulator_set_voltage_tol(arm_reg, volt, 0); | ||||
| 		if (ret) { | ||||
| 			dev_err(cpu_dev, | ||||
| 				"failed to scale vddarm up: %d\n", ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Need to increase vddpu and vddsoc for safety | ||||
| 		 * if we are about to run at 1.2 GHz. | ||||
| 		 */ | ||||
| 		if (new_freq == FREQ_1P2_GHZ / 1000) { | ||||
| 			regulator_set_voltage_tol(pu_reg, | ||||
| 					PU_SOC_VOLTAGE_HIGH, 0); | ||||
| 			regulator_set_voltage_tol(soc_reg, | ||||
| 					PU_SOC_VOLTAGE_HIGH, 0); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -120,12 +122,15 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) | ||||
| 				 "failed to scale vddarm down: %d\n", ret); | ||||
| 			ret = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		if (old_freq == FREQ_1P2_GHZ / 1000) { | ||||
| 			regulator_set_voltage_tol(pu_reg, | ||||
| 					PU_SOC_VOLTAGE_NORMAL, 0); | ||||
| 			regulator_set_voltage_tol(soc_reg, | ||||
| 					PU_SOC_VOLTAGE_NORMAL, 0); | ||||
| 		ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); | ||||
| 		if (ret) { | ||||
| 			dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); | ||||
| 			ret = 0; | ||||
| 		} | ||||
| 		ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); | ||||
| 		if (ret) { | ||||
| 			dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); | ||||
| 			ret = 0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -138,6 +143,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver imx6q_cpufreq_driver = { | ||||
| 	.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify = cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index = imx6q_set_target, | ||||
| 	.get = imx6q_get_speed, | ||||
| @ -153,6 +159,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | ||||
| 	struct dev_pm_opp *opp; | ||||
| 	unsigned long min_volt, max_volt; | ||||
| 	int num, ret; | ||||
| 	const struct property *prop; | ||||
| 	const __be32 *val; | ||||
| 	u32 nr, i, j; | ||||
| 
 | ||||
| 	cpu_dev = get_cpu_device(0); | ||||
| 	if (!cpu_dev) { | ||||
| @ -187,12 +196,25 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | ||||
| 		goto put_node; | ||||
| 	} | ||||
| 
 | ||||
| 	/* We expect an OPP table supplied by platform */ | ||||
| 	/*
 | ||||
| 	 * We expect an OPP table supplied by platform. | ||||
| 	 * Just, incase the platform did not supply the OPP | ||||
| 	 * table, it will try to get it. | ||||
| 	 */ | ||||
| 	num = dev_pm_opp_get_opp_count(cpu_dev); | ||||
| 	if (num < 0) { | ||||
| 		ret = num; | ||||
| 		dev_err(cpu_dev, "no OPP table is found: %d\n", ret); | ||||
| 		goto put_node; | ||||
| 		ret = of_init_opp_table(cpu_dev); | ||||
| 		if (ret < 0) { | ||||
| 			dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); | ||||
| 			goto put_node; | ||||
| 		} | ||||
| 
 | ||||
| 		num = dev_pm_opp_get_opp_count(cpu_dev); | ||||
| 		if (num < 0) { | ||||
| 			ret = num; | ||||
| 			dev_err(cpu_dev, "no OPP table is found: %d\n", ret); | ||||
| 			goto put_node; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); | ||||
| @ -201,9 +223,61 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | ||||
| 		goto put_node; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Make imx6_soc_volt array's size same as arm opp number */ | ||||
| 	imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); | ||||
| 	if (imx6_soc_volt == NULL) { | ||||
| 		ret = -ENOMEM; | ||||
| 		goto free_freq_table; | ||||
| 	} | ||||
| 
 | ||||
| 	prop = of_find_property(np, "fsl,soc-operating-points", NULL); | ||||
| 	if (!prop || !prop->value) | ||||
| 		goto soc_opp_out; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Each OPP is a set of tuples consisting of frequency and | ||||
| 	 * voltage like <freq-kHz vol-uV>. | ||||
| 	 */ | ||||
| 	nr = prop->length / sizeof(u32); | ||||
| 	if (nr % 2 || (nr / 2) < num) | ||||
| 		goto soc_opp_out; | ||||
| 
 | ||||
| 	for (j = 0; j < num; j++) { | ||||
| 		val = prop->value; | ||||
| 		for (i = 0; i < nr / 2; i++) { | ||||
| 			unsigned long freq = be32_to_cpup(val++); | ||||
| 			unsigned long volt = be32_to_cpup(val++); | ||||
| 			if (freq_table[j].frequency == freq) { | ||||
| 				imx6_soc_volt[soc_opp_count++] = volt; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| soc_opp_out: | ||||
| 	/* use fixed soc opp volt if no valid soc opp info found in dtb */ | ||||
| 	if (soc_opp_count != num) { | ||||
| 		dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); | ||||
| 		for (j = 0; j < num; j++) | ||||
| 			imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; | ||||
| 		if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) | ||||
| 			imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; | ||||
| 	} | ||||
| 
 | ||||
| 	if (of_property_read_u32(np, "clock-latency", &transition_latency)) | ||||
| 		transition_latency = CPUFREQ_ETERNAL; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Calculate the ramp time for max voltage change in the | ||||
| 	 * VDDSOC and VDDPU regulators. | ||||
| 	 */ | ||||
| 	ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); | ||||
| 	if (ret > 0) | ||||
| 		transition_latency += ret * 1000; | ||||
| 	ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); | ||||
| 	if (ret > 0) | ||||
| 		transition_latency += ret * 1000; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * OPP is maintained in order of increasing frequency, and | ||||
| 	 * freq_table initialised from OPP is therefore sorted in the | ||||
| @ -221,18 +295,6 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) | ||||
| 	if (ret > 0) | ||||
| 		transition_latency += ret * 1000; | ||||
| 
 | ||||
| 	/* Count vddpu and vddsoc latency in for 1.2 GHz support */ | ||||
| 	if (freq_table[num].frequency == FREQ_1P2_GHZ / 1000) { | ||||
| 		ret = regulator_set_voltage_time(pu_reg, PU_SOC_VOLTAGE_NORMAL, | ||||
| 						 PU_SOC_VOLTAGE_HIGH); | ||||
| 		if (ret > 0) | ||||
| 			transition_latency += ret * 1000; | ||||
| 		ret = regulator_set_voltage_time(soc_reg, PU_SOC_VOLTAGE_NORMAL, | ||||
| 						 PU_SOC_VOLTAGE_HIGH); | ||||
| 		if (ret > 0) | ||||
| 			transition_latency += ret * 1000; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = cpufreq_register_driver(&imx6q_cpufreq_driver); | ||||
| 	if (ret) { | ||||
| 		dev_err(cpu_dev, "failed register driver: %d\n", ret); | ||||
|  | ||||
| @ -190,6 +190,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver integrator_driver = { | ||||
| 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= integrator_verify_policy, | ||||
| 	.target		= integrator_set_target, | ||||
| 	.get		= integrator_get, | ||||
|  | ||||
| @ -35,6 +35,7 @@ | ||||
| #define SAMPLE_COUNT		3 | ||||
| 
 | ||||
| #define BYT_RATIOS	0x66a | ||||
| #define BYT_VIDS        0x66b | ||||
| 
 | ||||
| #define FRAC_BITS 8 | ||||
| #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) | ||||
| @ -64,6 +65,12 @@ struct pstate_data { | ||||
| 	int	turbo_pstate; | ||||
| }; | ||||
| 
 | ||||
| struct vid_data { | ||||
| 	int32_t min; | ||||
| 	int32_t max; | ||||
| 	int32_t ratio; | ||||
| }; | ||||
| 
 | ||||
| struct _pid { | ||||
| 	int setpoint; | ||||
| 	int32_t integral; | ||||
| @ -82,10 +89,9 @@ struct cpudata { | ||||
| 	struct timer_list timer; | ||||
| 
 | ||||
| 	struct pstate_data pstate; | ||||
| 	struct vid_data vid; | ||||
| 	struct _pid pid; | ||||
| 
 | ||||
| 	int min_pstate_count; | ||||
| 
 | ||||
| 	u64	prev_aperf; | ||||
| 	u64	prev_mperf; | ||||
| 	int	sample_ptr; | ||||
| @ -106,7 +112,8 @@ struct pstate_funcs { | ||||
| 	int (*get_max)(void); | ||||
| 	int (*get_min)(void); | ||||
| 	int (*get_turbo)(void); | ||||
| 	void (*set)(int pstate); | ||||
| 	void (*set)(struct cpudata*, int pstate); | ||||
| 	void (*get_vid)(struct cpudata *); | ||||
| }; | ||||
| 
 | ||||
| struct cpu_defaults { | ||||
| @ -358,6 +365,42 @@ static int byt_get_max_pstate(void) | ||||
| 	return (value >> 16) & 0xFF; | ||||
| } | ||||
| 
 | ||||
| static void byt_set_pstate(struct cpudata *cpudata, int pstate) | ||||
| { | ||||
| 	u64 val; | ||||
| 	int32_t vid_fp; | ||||
| 	u32 vid; | ||||
| 
 | ||||
| 	val = pstate << 8; | ||||
| 	if (limits.no_turbo) | ||||
| 		val |= (u64)1 << 32; | ||||
| 
 | ||||
| 	vid_fp = cpudata->vid.min + mul_fp( | ||||
| 		int_tofp(pstate - cpudata->pstate.min_pstate), | ||||
| 		cpudata->vid.ratio); | ||||
| 
 | ||||
| 	vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); | ||||
| 	vid = fp_toint(vid_fp); | ||||
| 
 | ||||
| 	val |= vid; | ||||
| 
 | ||||
| 	wrmsrl(MSR_IA32_PERF_CTL, val); | ||||
| } | ||||
| 
 | ||||
| static void byt_get_vid(struct cpudata *cpudata) | ||||
| { | ||||
| 	u64 value; | ||||
| 
 | ||||
| 	rdmsrl(BYT_VIDS, value); | ||||
| 	cpudata->vid.min = int_tofp((value >> 8) & 0x7f); | ||||
| 	cpudata->vid.max = int_tofp((value >> 16) & 0x7f); | ||||
| 	cpudata->vid.ratio = div_fp( | ||||
| 		cpudata->vid.max - cpudata->vid.min, | ||||
| 		int_tofp(cpudata->pstate.max_pstate - | ||||
| 			cpudata->pstate.min_pstate)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int core_get_min_pstate(void) | ||||
| { | ||||
| 	u64 value; | ||||
| @ -384,7 +427,7 @@ static int core_get_turbo_pstate(void) | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static void core_set_pstate(int pstate) | ||||
| static void core_set_pstate(struct cpudata *cpudata, int pstate) | ||||
| { | ||||
| 	u64 val; | ||||
| 
 | ||||
| @ -425,7 +468,8 @@ static struct cpu_defaults byt_params = { | ||||
| 		.get_max = byt_get_max_pstate, | ||||
| 		.get_min = byt_get_min_pstate, | ||||
| 		.get_turbo = byt_get_max_pstate, | ||||
| 		.set = core_set_pstate, | ||||
| 		.set = byt_set_pstate, | ||||
| 		.get_vid = byt_get_vid, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| @ -462,7 +506,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | ||||
| 
 | ||||
| 	cpu->pstate.current_pstate = pstate; | ||||
| 
 | ||||
| 	pstate_funcs.set(pstate); | ||||
| 	pstate_funcs.set(cpu, pstate); | ||||
| } | ||||
| 
 | ||||
| static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) | ||||
| @ -488,6 +532,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | ||||
| 	cpu->pstate.max_pstate = pstate_funcs.get_max(); | ||||
| 	cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); | ||||
| 
 | ||||
| 	if (pstate_funcs.get_vid) | ||||
| 		pstate_funcs.get_vid(cpu); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * goto max pstate so we don't slow up boot if we are built-in if we are | ||||
| 	 * a module we will take care of it during normal operation | ||||
| @ -568,15 +615,6 @@ static void intel_pstate_timer_func(unsigned long __data) | ||||
| 
 | ||||
| 	intel_pstate_sample(cpu); | ||||
| 	intel_pstate_adjust_busy_pstate(cpu); | ||||
| 
 | ||||
| 	if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) { | ||||
| 		cpu->min_pstate_count++; | ||||
| 		if (!(cpu->min_pstate_count % 5)) { | ||||
| 			intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); | ||||
| 		} | ||||
| 	} else | ||||
| 		cpu->min_pstate_count = 0; | ||||
| 
 | ||||
| 	intel_pstate_set_sample_time(cpu); | ||||
| } | ||||
| 
 | ||||
| @ -782,6 +820,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | ||||
| 	pstate_funcs.get_min   = funcs->get_min; | ||||
| 	pstate_funcs.get_turbo = funcs->get_turbo; | ||||
| 	pstate_funcs.set       = funcs->set; | ||||
| 	pstate_funcs.get_vid   = funcs->get_vid; | ||||
| } | ||||
| 
 | ||||
| #if IS_ENABLED(CONFIG_ACPI) | ||||
|  | ||||
| @ -97,6 +97,7 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver kirkwood_cpufreq_driver = { | ||||
| 	.flags	= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.get	= kirkwood_cpufreq_get_cpu_frequency, | ||||
| 	.verify	= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index = kirkwood_cpufreq_target, | ||||
|  | ||||
| @ -162,7 +162,7 @@ static int omap_cpu_exit(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver omap_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= omap_target, | ||||
| 	.get		= omap_getspeed, | ||||
|  | ||||
| @ -213,6 +213,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, | ||||
| 		cpu, target_freq, | ||||
| 		(pcch_virt_addr + pcc_cpu_data->input_offset)); | ||||
| 
 | ||||
| 	freqs.old = policy->cur; | ||||
| 	freqs.new = target_freq; | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||||
| 
 | ||||
| @ -228,25 +229,20 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, | ||||
| 	memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ); | ||||
| 
 | ||||
| 	status = ioread16(&pcch_hdr->status); | ||||
| 	iowrite16(0, &pcch_hdr->status); | ||||
| 
 | ||||
| 	cpufreq_notify_post_transition(policy, &freqs, status != CMD_COMPLETE); | ||||
| 	spin_unlock(&pcc_lock); | ||||
| 
 | ||||
| 	if (status != CMD_COMPLETE) { | ||||
| 		pr_debug("target: FAILED for cpu %d, with status: 0x%x\n", | ||||
| 			cpu, status); | ||||
| 		goto cmd_incomplete; | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	iowrite16(0, &pcch_hdr->status); | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||||
| 	pr_debug("target: was SUCCESSFUL for cpu %d\n", cpu); | ||||
| 	spin_unlock(&pcc_lock); | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| cmd_incomplete: | ||||
| 	freqs.new = freqs.old; | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||||
| 	iowrite16(0, &pcch_hdr->status); | ||||
| 	spin_unlock(&pcc_lock); | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static int pcc_get_offset(int cpu) | ||||
|  | ||||
| @ -26,41 +26,108 @@ | ||||
| static unsigned int                     busfreq;   /* FSB, in 10 kHz */ | ||||
| static unsigned int                     max_multiplier; | ||||
| 
 | ||||
| static unsigned int			param_busfreq = 0; | ||||
| static unsigned int			param_max_multiplier = 0; | ||||
| 
 | ||||
| module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO); | ||||
| MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)"); | ||||
| 
 | ||||
| module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO); | ||||
| MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz"); | ||||
| 
 | ||||
| /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ | ||||
| static struct cpufreq_frequency_table clock_ratio[] = { | ||||
| 	{45,  /* 000 -> 4.5x */ 0}, | ||||
| 	{50,  /* 001 -> 5.0x */ 0}, | ||||
| 	{40,  /* 010 -> 4.0x */ 0}, | ||||
| 	{55,  /* 011 -> 5.5x */ 0}, | ||||
| 	{20,  /* 100 -> 2.0x */ 0}, | ||||
| 	{30,  /* 101 -> 3.0x */ 0}, | ||||
| 	{60,  /* 110 -> 6.0x */ 0}, | ||||
| 	{55,  /* 011 -> 5.5x */ 0}, | ||||
| 	{50,  /* 001 -> 5.0x */ 0}, | ||||
| 	{45,  /* 000 -> 4.5x */ 0}, | ||||
| 	{40,  /* 010 -> 4.0x */ 0}, | ||||
| 	{35,  /* 111 -> 3.5x */ 0}, | ||||
| 	{30,  /* 101 -> 3.0x */ 0}, | ||||
| 	{20,  /* 100 -> 2.0x */ 0}, | ||||
| 	{0, CPUFREQ_TABLE_END} | ||||
| }; | ||||
| 
 | ||||
| static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 }; | ||||
| static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 }; | ||||
| 
 | ||||
| static const struct { | ||||
| 	unsigned freq; | ||||
| 	unsigned mult; | ||||
| } usual_frequency_table[] = { | ||||
| 	{ 400000, 40 },	// 100   * 4
 | ||||
| 	{ 450000, 45 }, // 100   * 4.5
 | ||||
| 	{ 475000, 50 }, //  95   * 5
 | ||||
| 	{ 500000, 50 }, // 100   * 5
 | ||||
| 	{ 506250, 45 }, // 112.5 * 4.5
 | ||||
| 	{ 533500, 55 }, //  97   * 5.5
 | ||||
| 	{ 550000, 55 }, // 100   * 5.5
 | ||||
| 	{ 562500, 50 }, // 112.5 * 5
 | ||||
| 	{ 570000, 60 }, //  95   * 6
 | ||||
| 	{ 600000, 60 }, // 100   * 6
 | ||||
| 	{ 618750, 55 }, // 112.5 * 5.5
 | ||||
| 	{ 660000, 55 }, // 120   * 5.5
 | ||||
| 	{ 675000, 60 }, // 112.5 * 6
 | ||||
| 	{ 720000, 60 }, // 120   * 6
 | ||||
| }; | ||||
| 
 | ||||
| #define FREQ_RANGE		3000 | ||||
| 
 | ||||
| /**
 | ||||
|  * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier | ||||
|  * | ||||
|  *   Returns the current setting of the frequency multiplier. Core clock | ||||
|  * Returns the current setting of the frequency multiplier. Core clock | ||||
|  * speed is frequency of the Front-Side Bus multiplied with this value. | ||||
|  */ | ||||
| static int powernow_k6_get_cpu_multiplier(void) | ||||
| { | ||||
| 	u64 invalue = 0; | ||||
| 	unsigned long invalue = 0; | ||||
| 	u32 msrval; | ||||
| 
 | ||||
| 	local_irq_disable(); | ||||
| 
 | ||||
| 	msrval = POWERNOW_IOPORT + 0x1; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ | ||||
| 	invalue = inl(POWERNOW_IOPORT + 0x8); | ||||
| 	msrval = POWERNOW_IOPORT + 0x0; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ | ||||
| 
 | ||||
| 	return clock_ratio[(invalue >> 5)&7].driver_data; | ||||
| 	local_irq_enable(); | ||||
| 
 | ||||
| 	return clock_ratio[register_to_index[(invalue >> 5)&7]].driver_data; | ||||
| } | ||||
| 
 | ||||
| static void powernow_k6_set_cpu_multiplier(unsigned int best_i) | ||||
| { | ||||
| 	unsigned long outvalue, invalue; | ||||
| 	unsigned long msrval; | ||||
| 	unsigned long cr0; | ||||
| 
 | ||||
| 	/* we now need to transform best_i to the BVC format, see AMD#23446 */ | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The processor doesn't respond to inquiry cycles while changing the | ||||
| 	 * frequency, so we must disable cache. | ||||
| 	 */ | ||||
| 	local_irq_disable(); | ||||
| 	cr0 = read_cr0(); | ||||
| 	write_cr0(cr0 | X86_CR0_CD); | ||||
| 	wbinvd(); | ||||
| 
 | ||||
| 	outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5); | ||||
| 
 | ||||
| 	msrval = POWERNOW_IOPORT + 0x1; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ | ||||
| 	invalue = inl(POWERNOW_IOPORT + 0x8); | ||||
| 	invalue = invalue & 0x1f; | ||||
| 	outvalue = outvalue | invalue; | ||||
| 	outl(outvalue, (POWERNOW_IOPORT + 0x8)); | ||||
| 	msrval = POWERNOW_IOPORT + 0x0; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ | ||||
| 
 | ||||
| 	write_cr0(cr0); | ||||
| 	local_irq_enable(); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * powernow_k6_target - set the PowerNow! multiplier | ||||
| @ -71,8 +138,6 @@ static int powernow_k6_get_cpu_multiplier(void) | ||||
| static int powernow_k6_target(struct cpufreq_policy *policy, | ||||
| 		unsigned int best_i) | ||||
| { | ||||
| 	unsigned long outvalue = 0, invalue = 0; | ||||
| 	unsigned long msrval; | ||||
| 	struct cpufreq_freqs freqs; | ||||
| 
 | ||||
| 	if (clock_ratio[best_i].driver_data > max_multiplier) { | ||||
| @ -85,35 +150,63 @@ static int powernow_k6_target(struct cpufreq_policy *policy, | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||||
| 
 | ||||
| 	/* we now need to transform best_i to the BVC format, see AMD#23446 */ | ||||
| 
 | ||||
| 	outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); | ||||
| 
 | ||||
| 	msrval = POWERNOW_IOPORT + 0x1; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ | ||||
| 	invalue = inl(POWERNOW_IOPORT + 0x8); | ||||
| 	invalue = invalue & 0xf; | ||||
| 	outvalue = outvalue | invalue; | ||||
| 	outl(outvalue , (POWERNOW_IOPORT + 0x8)); | ||||
| 	msrval = POWERNOW_IOPORT + 0x0; | ||||
| 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ | ||||
| 	powernow_k6_set_cpu_multiplier(best_i); | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | ||||
| { | ||||
| 	unsigned int i, f; | ||||
| 	unsigned khz; | ||||
| 
 | ||||
| 	if (policy->cpu != 0) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	/* get frequencies */ | ||||
| 	max_multiplier = powernow_k6_get_cpu_multiplier(); | ||||
| 	busfreq = cpu_khz / max_multiplier; | ||||
| 	max_multiplier = 0; | ||||
| 	khz = cpu_khz; | ||||
| 	for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) { | ||||
| 		if (khz >= usual_frequency_table[i].freq - FREQ_RANGE && | ||||
| 		    khz <= usual_frequency_table[i].freq + FREQ_RANGE) { | ||||
| 			khz = usual_frequency_table[i].freq; | ||||
| 			max_multiplier = usual_frequency_table[i].mult; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (param_max_multiplier) { | ||||
| 		for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { | ||||
| 			if (clock_ratio[i].driver_data == param_max_multiplier) { | ||||
| 				max_multiplier = param_max_multiplier; | ||||
| 				goto have_max_multiplier; | ||||
| 			} | ||||
| 		} | ||||
| 		printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!max_multiplier) { | ||||
| 		printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz); | ||||
| 		printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n"); | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| 
 | ||||
| have_max_multiplier: | ||||
| 	param_max_multiplier = max_multiplier; | ||||
| 
 | ||||
| 	if (param_busfreq) { | ||||
| 		if (param_busfreq >= 50000 && param_busfreq <= 150000) { | ||||
| 			busfreq = param_busfreq / 10; | ||||
| 			goto have_busfreq; | ||||
| 		} | ||||
| 		printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	busfreq = khz / max_multiplier; | ||||
| have_busfreq: | ||||
| 	param_busfreq = busfreq * 10; | ||||
| 
 | ||||
| 	/* table init */ | ||||
| 	for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { | ||||
| @ -125,7 +218,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | ||||
| 	} | ||||
| 
 | ||||
| 	/* cpuinfo and default policy values */ | ||||
| 	policy->cpuinfo.transition_latency = 200000; | ||||
| 	policy->cpuinfo.transition_latency = 500000; | ||||
| 
 | ||||
| 	return cpufreq_table_validate_and_show(policy, clock_ratio); | ||||
| } | ||||
|  | ||||
| @ -964,14 +964,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, | ||||
| 	cpufreq_cpu_put(policy); | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||||
| 
 | ||||
| 	res = transition_fid_vid(data, fid, vid); | ||||
| 	if (res) | ||||
| 		freqs.new = freqs.old; | ||||
| 	else | ||||
| 		freqs.new = find_khz_freq_from_fid(data->currfid); | ||||
| 	cpufreq_notify_post_transition(policy, &freqs, res); | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -423,6 +423,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver pxa_cpufreq_driver = { | ||||
| 	.flags	= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify	= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index = pxa_set_target, | ||||
| 	.init	= pxa_cpufreq_init, | ||||
|  | ||||
| @ -201,6 +201,7 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver pxa3xx_cpufreq_driver = { | ||||
| 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= pxa3xx_cpufreq_set, | ||||
| 	.init		= pxa3xx_cpufreq_init, | ||||
|  | ||||
| @ -481,7 +481,7 @@ err_hclk: | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver s3c2416_cpufreq_driver = { | ||||
| 	.flags          = 0, | ||||
| 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= s3c2416_cpufreq_set_target, | ||||
| 	.get		= s3c2416_cpufreq_get_speed, | ||||
|  | ||||
| @ -22,8 +22,6 @@ | ||||
| #include <linux/err.h> | ||||
| #include <linux/io.h> | ||||
| 
 | ||||
| #include <mach/hardware.h> | ||||
| 
 | ||||
| #include <asm/mach/arch.h> | ||||
| #include <asm/mach/map.h> | ||||
| 
 | ||||
| @ -55,7 +53,7 @@ static inline int within_khz(unsigned long a, unsigned long b) | ||||
|  * specified in @cfg. The values are stored in @cfg for later use | ||||
|  * by the relevant set routine if the request settings can be reached. | ||||
|  */ | ||||
| int s3c2440_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) | ||||
| static int s3c2440_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) | ||||
| { | ||||
| 	unsigned int hdiv, pdiv; | ||||
| 	unsigned long hclk, fclk, armclk; | ||||
| @ -242,7 +240,7 @@ static int s3c2440_cpufreq_calctable(struct s3c_cpufreq_config *cfg, | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| struct s3c_cpufreq_info s3c2440_cpufreq_info = { | ||||
| static struct s3c_cpufreq_info s3c2440_cpufreq_info = { | ||||
| 	.max		= { | ||||
| 		.fclk	= 400000000, | ||||
| 		.hclk	= 133333333, | ||||
|  | ||||
| @ -448,7 +448,7 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy) | ||||
| #endif | ||||
| 
 | ||||
| static struct cpufreq_driver s3c24xx_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.target		= s3c_cpufreq_target, | ||||
| 	.get		= s3c_cpufreq_get, | ||||
| 	.init		= s3c_cpufreq_init, | ||||
| @ -509,7 +509,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int __init s3c_cpufreq_auto_io(void) | ||||
| static int __init s3c_cpufreq_auto_io(void) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
|  | ||||
| @ -226,7 +226,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver s3c64xx_cpufreq_driver = { | ||||
| 	.flags          = 0, | ||||
| 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= s3c64xx_cpufreq_set_target, | ||||
| 	.get		= s3c64xx_cpufreq_get_speed, | ||||
|  | ||||
| @ -560,7 +560,7 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver s5pv210_driver = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= s5pv210_target, | ||||
| 	.get		= s5pv210_getspeed, | ||||
|  | ||||
| @ -201,7 +201,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver sa1100_driver __refdata = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= sa1100_target, | ||||
| 	.get		= sa11x0_getspeed, | ||||
|  | ||||
| @ -312,7 +312,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) | ||||
| /* sa1110_driver needs __refdata because it must remain after init registers
 | ||||
|  * it with cpufreq_register_driver() */ | ||||
| static struct cpufreq_driver sa1110_driver __refdata = { | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= sa1110_target, | ||||
| 	.get		= sa11x0_getspeed, | ||||
|  | ||||
| @ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, | ||||
| 	} | ||||
| 
 | ||||
| 	newfreq = clk_round_rate(srcclk, newfreq * mult); | ||||
| 	if (newfreq < 0) { | ||||
| 	if (newfreq <= 0) { | ||||
| 		pr_err("clk_round_rate failed for cpu src clock\n"); | ||||
| 		return newfreq; | ||||
| 	} | ||||
| @ -162,7 +162,7 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy) | ||||
| 
 | ||||
| static struct cpufreq_driver spear_cpufreq_driver = { | ||||
| 	.name		= "cpufreq-spear", | ||||
| 	.flags		= CPUFREQ_STICKY, | ||||
| 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= spear_cpufreq_target, | ||||
| 	.get		= spear_cpufreq_get, | ||||
|  | ||||
| @ -214,6 +214,7 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy) | ||||
| } | ||||
| 
 | ||||
| static struct cpufreq_driver tegra_cpufreq_driver = { | ||||
| 	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK, | ||||
| 	.verify		= cpufreq_generic_frequency_table_verify, | ||||
| 	.target_index	= tegra_target, | ||||
| 	.get		= tegra_getspeed, | ||||
|  | ||||
| @ -46,20 +46,18 @@ static int ucv2_target(struct cpufreq_policy *policy, | ||||
| 			 unsigned int target_freq, | ||||
| 			 unsigned int relation) | ||||
| { | ||||
| 	unsigned int cur = ucv2_getspeed(0); | ||||
| 	struct cpufreq_freqs freqs; | ||||
| 	struct clk *mclk = clk_get(NULL, "MAIN_CLK"); | ||||
| 	int ret; | ||||
| 
 | ||||
| 	freqs.old = policy->cur; | ||||
| 	freqs.new = target_freq; | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||||
| 	ret = clk_set_rate(mclk, target_freq * 1000); | ||||
| 	cpufreq_notify_post_transition(policy, &freqs, ret); | ||||
| 
 | ||||
| 	if (!clk_set_rate(mclk, target_freq * 1000)) { | ||||
| 		freqs.old = cur; | ||||
| 		freqs.new = target_freq; | ||||
| 	} | ||||
| 
 | ||||
| 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||||
| 
 | ||||
| 	return 0; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int __init ucv2_cpu_init(struct cpufreq_policy *policy) | ||||
|  | ||||
| @ -252,6 +252,15 @@ struct cpufreq_driver { | ||||
|  */ | ||||
| #define CPUFREQ_ASYNC_NOTIFICATION  (1 << 4) | ||||
| 
 | ||||
| /*
 | ||||
|  * Set by drivers which want cpufreq core to check if CPU is running at a | ||||
|  * frequency present in freq-table exposed by the driver. For these drivers if | ||||
|  * CPU is found running at an out of table freq, we will try to set it to a freq | ||||
|  * from the table. And if that fails, we will stop further boot process by | ||||
|  * issuing a BUG_ON(). | ||||
|  */ | ||||
| #define CPUFREQ_NEED_INITIAL_FREQ_CHECK	(1 << 5) | ||||
| 
 | ||||
| int cpufreq_register_driver(struct cpufreq_driver *driver_data); | ||||
| int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); | ||||
| 
 | ||||
| @ -306,6 +315,8 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); | ||||
| 
 | ||||
| void cpufreq_notify_transition(struct cpufreq_policy *policy, | ||||
| 		struct cpufreq_freqs *freqs, unsigned int state); | ||||
| void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | ||||
| 		struct cpufreq_freqs *freqs, int transition_failed); | ||||
| 
 | ||||
| #else /* CONFIG_CPU_FREQ */ | ||||
| static inline int cpufreq_register_notifier(struct notifier_block *nb, | ||||
| @ -439,6 +450,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, | ||||
| 				   unsigned int target_freq, | ||||
| 				   unsigned int relation, | ||||
| 				   unsigned int *index); | ||||
| int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, | ||||
| 		unsigned int freq); | ||||
| 
 | ||||
| void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); | ||||
| ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user