diff options
Diffstat (limited to 'drivers/cpufreq')
| -rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 5 | ||||
| -rw-r--r-- | drivers/cpufreq/amd_freq_sensitivity.c | 9 | ||||
| -rw-r--r-- | drivers/cpufreq/cppc_cpufreq.c | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq-dt-platdev.c | 6 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq-dt.c | 34 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq_conservative.c | 6 | ||||
| -rw-r--r-- | drivers/cpufreq/imx6q-cpufreq.c | 52 | ||||
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 42 | ||||
| -rw-r--r-- | drivers/cpufreq/mvebu-cpufreq.c | 9 | ||||
| -rw-r--r-- | drivers/cpufreq/s5pv210-cpufreq.c | 4 | ||||
| -rw-r--r-- | drivers/cpufreq/tegra186-cpufreq.c | 2 | 
12 files changed, 122 insertions, 51 deletions
| diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index b61f4ec43e06..d62fd374d5c7 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -61,6 +61,7 @@ enum {  #define INTEL_MSR_RANGE		(0xffff)  #define AMD_MSR_RANGE		(0x7) +#define HYGON_MSR_RANGE		(0x7)  #define MSR_K7_HWCR_CPB_DIS	(1ULL << 25) @@ -95,6 +96,7 @@ static bool boost_state(unsigned int cpu)  		rdmsr_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &lo, &hi);  		msr = lo | ((u64)hi << 32);  		return !(msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE); +	case X86_VENDOR_HYGON:  	case X86_VENDOR_AMD:  		rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);  		msr = lo | ((u64)hi << 32); @@ -113,6 +115,7 @@ static int boost_set_msr(bool enable)  		msr_addr = MSR_IA32_MISC_ENABLE;  		msr_mask = MSR_IA32_MISC_ENABLE_TURBO_DISABLE;  		break; +	case X86_VENDOR_HYGON:  	case X86_VENDOR_AMD:  		msr_addr = MSR_K7_HWCR;  		msr_mask = MSR_K7_HWCR_CPB_DIS; @@ -225,6 +228,8 @@ static unsigned extract_msr(struct cpufreq_policy *policy, u32 msr)  	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)  		msr &= AMD_MSR_RANGE; +	else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) +		msr &= HYGON_MSR_RANGE;  	else  		msr &= INTEL_MSR_RANGE; diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c index be926d9a66e5..4ac7c3cf34be 100644 --- a/drivers/cpufreq/amd_freq_sensitivity.c +++ b/drivers/cpufreq/amd_freq_sensitivity.c @@ -111,11 +111,16 @@ static int __init amd_freq_sensitivity_init(void)  {  	u64 val;  	struct pci_dev *pcidev; +	unsigned int pci_vendor; -	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) +	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) +		pci_vendor = PCI_VENDOR_ID_AMD; +	else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) +		pci_vendor = PCI_VENDOR_ID_HYGON; +	else  		return -ENODEV; -	pcidev = pci_get_device(PCI_VENDOR_ID_AMD, +	pcidev = pci_get_device(pci_vendor,  			PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, NULL);  	if (!pcidev) { diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 30f302149730..fd25c21cee72 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -428,7 +428,7 @@ MODULE_LICENSE("GPL");  late_initcall(cppc_cpufreq_init); -static const struct acpi_device_id cppc_acpi_ids[] = { +static const struct acpi_device_id cppc_acpi_ids[] __used = {  	{ACPI_PROCESSOR_DEVICE_HID, },  	{}  }; diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index fe14c57de6ca..b1c5468dca16 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -58,6 +58,7 @@ static const struct of_device_id whitelist[] __initconst = {  	{ .compatible = "renesas,r8a73a4", },  	{ .compatible = "renesas,r8a7740", },  	{ .compatible = "renesas,r8a7743", }, +	{ .compatible = "renesas,r8a7744", },  	{ .compatible = "renesas,r8a7745", },  	{ .compatible = "renesas,r8a7778", },  	{ .compatible = "renesas,r8a7779", }, @@ -78,7 +79,10 @@ static const struct of_device_id whitelist[] __initconst = {  	{ .compatible = "rockchip,rk3328", },  	{ .compatible = "rockchip,rk3366", },  	{ .compatible = "rockchip,rk3368", }, -	{ .compatible = "rockchip,rk3399", }, +	{ .compatible = "rockchip,rk3399", +	  .data = &(struct cpufreq_dt_platform_data) +		{ .have_governor_per_policy = true, }, +	},  	{ .compatible = "st-ericsson,u8500", },  	{ .compatible = "st-ericsson,u8540", }, diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 0a9ebf00be46..e58bfcb1169e 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -32,6 +32,7 @@ struct private_data {  	struct device *cpu_dev;  	struct thermal_cooling_device *cdev;  	const char *reg_name; +	bool have_static_opps;  };  static struct freq_attr *cpufreq_dt_attr[] = { @@ -204,6 +205,15 @@ static int cpufreq_init(struct cpufreq_policy *policy)  		}  	} +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) { +		ret = -ENOMEM; +		goto out_put_regulator; +	} + +	priv->reg_name = name; +	priv->opp_table = opp_table; +  	/*  	 * Initialize OPP tables for all policy->cpus. They will be shared by  	 * all CPUs which have marked their CPUs shared with OPP bindings. @@ -214,7 +224,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)  	 *  	 * OPPs might be populated at runtime, don't check for error here  	 */ -	dev_pm_opp_of_cpumask_add_table(policy->cpus); +	if (!dev_pm_opp_of_cpumask_add_table(policy->cpus)) +		priv->have_static_opps = true;  	/*  	 * But we need OPP table to function so if it is not there let's @@ -240,19 +251,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)  				__func__, ret);  	} -	priv = kzalloc(sizeof(*priv), GFP_KERNEL); -	if (!priv) { -		ret = -ENOMEM; -		goto out_free_opp; -	} - -	priv->reg_name = name; -	priv->opp_table = opp_table; -  	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);  	if (ret) {  		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); -		goto out_free_priv; +		goto out_free_opp;  	}  	priv->cpu_dev = cpu_dev; @@ -282,10 +284,11 @@ static int cpufreq_init(struct cpufreq_policy *policy)  out_free_cpufreq_table:  	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -out_free_priv: -	kfree(priv);  out_free_opp: -	dev_pm_opp_of_cpumask_remove_table(policy->cpus); +	if (priv->have_static_opps) +		dev_pm_opp_of_cpumask_remove_table(policy->cpus); +	kfree(priv); +out_put_regulator:  	if (name)  		dev_pm_opp_put_regulators(opp_table);  out_put_clk: @@ -300,7 +303,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy)  	cpufreq_cooling_unregister(priv->cdev);  	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); -	dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); +	if (priv->have_static_opps) +		dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);  	if (priv->reg_name)  		dev_pm_opp_put_regulators(priv->opp_table); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f53fb41efb7b..7aa3dcad2175 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -403,7 +403,7 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin);  void cpufreq_freq_transition_end(struct cpufreq_policy *policy,  		struct cpufreq_freqs *freqs, int transition_failed)  { -	if (unlikely(WARN_ON(!policy->transition_ongoing))) +	if (WARN_ON(!policy->transition_ongoing))  		return;  	cpufreq_notify_post_transition(policy, freqs, transition_failed); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index f20f20a77d4d..4268f87e99fc 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -80,8 +80,10 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)  	 * changed in the meantime, so fall back to current frequency in that  	 * case.  	 */ -	if (requested_freq > policy->max || requested_freq < policy->min) +	if (requested_freq > policy->max || requested_freq < policy->min) {  		requested_freq = policy->cur; +		dbs_info->requested_freq = requested_freq; +	}  	freq_step = get_freq_step(cs_tuners, policy); @@ -92,7 +94,7 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)  	if (policy_dbs->idle_periods < UINT_MAX) {  		unsigned int freq_steps = policy_dbs->idle_periods * freq_step; -		if (requested_freq > freq_steps) +		if (requested_freq > policy->min + freq_steps)  			requested_freq -= freq_steps;  		else  			requested_freq = policy->min; diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index b2ff423ad7f8..8cfee0ab804b 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -12,6 +12,7 @@  #include <linux/cpu_cooling.h>  #include <linux/err.h>  #include <linux/module.h> +#include <linux/nvmem-consumer.h>  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/pm_opp.h> @@ -290,20 +291,32 @@ put_node:  #define OCOTP_CFG3_6ULL_SPEED_792MHZ	0x2  #define OCOTP_CFG3_6ULL_SPEED_900MHZ	0x3 -static void imx6ul_opp_check_speed_grading(struct device *dev) +static int imx6ul_opp_check_speed_grading(struct device *dev)  { -	struct device_node *np; -	void __iomem *base;  	u32 val; +	int ret = 0; -	np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp"); -	if (!np) -		return; +	if (of_find_property(dev->of_node, "nvmem-cells", NULL)) { +		ret = nvmem_cell_read_u32(dev, "speed_grade", &val); +		if (ret) +			return ret; +	} else { +		struct device_node *np; +		void __iomem *base; + +		np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp"); +		if (!np) +			return -ENOENT; + +		base = of_iomap(np, 0); +		of_node_put(np); +		if (!base) { +			dev_err(dev, "failed to map ocotp\n"); +			return -EFAULT; +		} -	base = of_iomap(np, 0); -	if (!base) { -		dev_err(dev, "failed to map ocotp\n"); -		goto put_node; +		val = readl_relaxed(base + OCOTP_CFG3); +		iounmap(base);  	}  	/* @@ -314,7 +327,6 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)  	 * 2b'11: 900000000Hz on i.MX6ULL only;  	 * We need to set the max speed of ARM according to fuse map.  	 */ -	val = readl_relaxed(base + OCOTP_CFG3);  	val >>= OCOTP_CFG3_SPEED_SHIFT;  	val &= 0x3; @@ -334,9 +346,7 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)  				dev_warn(dev, "failed to disable 900MHz OPP\n");  	} -	iounmap(base); -put_node: -	of_node_put(np); +	return ret;  }  static int imx6q_cpufreq_probe(struct platform_device *pdev) @@ -394,10 +404,18 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)  	}  	if (of_machine_is_compatible("fsl,imx6ul") || -	    of_machine_is_compatible("fsl,imx6ull")) -		imx6ul_opp_check_speed_grading(cpu_dev); -	else +	    of_machine_is_compatible("fsl,imx6ull")) { +		ret = imx6ul_opp_check_speed_grading(cpu_dev); +		if (ret == -EPROBE_DEFER) +			return ret; +		if (ret) { +			dev_err(cpu_dev, "failed to read ocotp: %d\n", +				ret); +			return ret; +		} +	} else {  		imx6q_opp_check_speed_grading(cpu_dev); +	}  	/* Because we have added the OPPs here, we must free them */  	free_opp = true; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index b6a1aadaff9f..49c0abf2d48f 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -373,10 +373,28 @@ static void intel_pstate_set_itmt_prio(int cpu)  		}  	}  } + +static int intel_pstate_get_cppc_guranteed(int cpu) +{ +	struct cppc_perf_caps cppc_perf; +	int ret; + +	ret = cppc_get_perf_caps(cpu, &cppc_perf); +	if (ret) +		return ret; + +	return cppc_perf.guaranteed_perf; +} +  #else  static void intel_pstate_set_itmt_prio(int cpu)  {  } + +static int intel_pstate_get_cppc_guranteed(int cpu) +{ +	return -ENOTSUPP; +}  #endif  static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) @@ -699,9 +717,29 @@ static ssize_t show_energy_performance_preference(  cpufreq_freq_attr_rw(energy_performance_preference); +static ssize_t show_base_frequency(struct cpufreq_policy *policy, char *buf) +{ +	struct cpudata *cpu; +	u64 cap; +	int ratio; + +	ratio = intel_pstate_get_cppc_guranteed(policy->cpu); +	if (ratio <= 0) { +		rdmsrl_on_cpu(policy->cpu, MSR_HWP_CAPABILITIES, &cap); +		ratio = HWP_GUARANTEED_PERF(cap); +	} + +	cpu = all_cpu_data[policy->cpu]; + +	return sprintf(buf, "%d\n", ratio * cpu->pstate.scaling); +} + +cpufreq_freq_attr_ro(base_frequency); +  static struct freq_attr *hwp_cpufreq_attrs[] = {  	&energy_performance_preference,  	&energy_performance_available_preferences, +	&base_frequency,  	NULL,  }; @@ -1778,7 +1816,7 @@ static const struct pstate_funcs knl_funcs = {  static const struct x86_cpu_id intel_pstate_cpu_ids[] = {  	ICPU(INTEL_FAM6_SANDYBRIDGE, 		core_funcs),  	ICPU(INTEL_FAM6_SANDYBRIDGE_X,		core_funcs), -	ICPU(INTEL_FAM6_ATOM_SILVERMONT1,	silvermont_funcs), +	ICPU(INTEL_FAM6_ATOM_SILVERMONT,	silvermont_funcs),  	ICPU(INTEL_FAM6_IVYBRIDGE,		core_funcs),  	ICPU(INTEL_FAM6_HASWELL_CORE,		core_funcs),  	ICPU(INTEL_FAM6_BROADWELL_CORE,		core_funcs), @@ -1795,7 +1833,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {  	ICPU(INTEL_FAM6_XEON_PHI_KNL,		knl_funcs),  	ICPU(INTEL_FAM6_XEON_PHI_KNM,		knl_funcs),  	ICPU(INTEL_FAM6_ATOM_GOLDMONT,		core_funcs), -	ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE,       core_funcs), +	ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS,     core_funcs),  	ICPU(INTEL_FAM6_SKYLAKE_X,		core_funcs),  	{}  }; diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c index 31513bd42705..6d33a639f902 100644 --- a/drivers/cpufreq/mvebu-cpufreq.c +++ b/drivers/cpufreq/mvebu-cpufreq.c @@ -84,9 +84,10 @@ static int __init armada_xp_pmsu_cpufreq_init(void)  		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);  		if (ret) { +			dev_pm_opp_remove(cpu_dev, clk_get_rate(clk));  			clk_put(clk);  			dev_err(cpu_dev, "Failed to register OPPs\n"); -			goto opp_register_failed; +			return ret;  		}  		ret = dev_pm_opp_set_sharing_cpus(cpu_dev, @@ -99,11 +100,5 @@ static int __init armada_xp_pmsu_cpufreq_init(void)  	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);  	return 0; - -opp_register_failed: -	/* As registering has failed remove all the opp for all cpus */ -	dev_pm_opp_cpumask_remove_table(cpu_possible_mask); - -	return ret;  }  device_initcall(armada_xp_pmsu_cpufreq_init); diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index 5d31c2db12a3..dbecd7667db2 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -611,8 +611,8 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev)  	for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {  		id = of_alias_get_id(np, "dmc");  		if (id < 0 || id >= ARRAY_SIZE(dmc_base)) { -			pr_err("%s: failed to get alias of dmc node '%s'\n", -				__func__, np->name); +			pr_err("%s: failed to get alias of dmc node '%pOFn'\n", +				__func__, np);  			of_node_put(np);  			return id;  		} diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c index 1f59966573aa..f1e09022b819 100644 --- a/drivers/cpufreq/tegra186-cpufreq.c +++ b/drivers/cpufreq/tegra186-cpufreq.c @@ -121,7 +121,7 @@ static struct cpufreq_frequency_table *init_vhint_table(  	void *virt;  	virt = dma_alloc_coherent(bpmp->dev, sizeof(*data), &phys, -				  GFP_KERNEL | GFP_DMA32); +				  GFP_KERNEL);  	if (!virt)  		return ERR_PTR(-ENOMEM); |