diff options
| author | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
| commit | 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e (patch) | |
| tree | d57f3a63479a07b4e0cece029886e76e04feb984 /drivers/acpi/cppc_acpi.c | |
| parent | 5dc63e56a9cf8df0b59c234a505a1653f1bdf885 (diff) | |
| parent | 53bea86b5712c7491bb3dae12e271666df0a308c (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.4 merge window.
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
| -rw-r--r-- | drivers/acpi/cppc_acpi.c | 71 | 
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 0f17b1c32718..c51d3ccb4cca 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -193,7 +193,7 @@ static struct attribute *cppc_attrs[] = {  };  ATTRIBUTE_GROUPS(cppc); -static struct kobj_type cppc_ktype = { +static const struct kobj_type cppc_ktype = {  	.sysfs_ops = &kobj_sysfs_ops,  	.default_groups = cppc_groups,  }; @@ -595,6 +595,7 @@ bool __weak cpc_supported_by_cpu(void)  /**   * pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace + * @pcc_ss_id: PCC Subspace index as in the PCC client ACPI package.   *   * Check and allocate the cppc_pcc_data memory.   * In some processor configurations it is possible that same subspace @@ -1154,6 +1155,19 @@ int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)  }  /** + * cppc_get_epp_perf - Get the epp register value. + * @cpunum: CPU from which to get epp preference value. + * @epp_perf: Return address. + * + * Return: 0 for success, -EIO otherwise. + */ +int cppc_get_epp_perf(int cpunum, u64 *epp_perf) +{ +	return cppc_get_perf(cpunum, ENERGY_PERF, epp_perf); +} +EXPORT_SYMBOL_GPL(cppc_get_epp_perf); + +/**   * cppc_get_perf_caps - Get a CPU's performance capabilities.   * @cpunum: CPU from which to get capabilities info.   * @perf_caps: ptr to cppc_perf_caps. See cppc_acpi.h @@ -1365,6 +1379,60 @@ out_err:  }  EXPORT_SYMBOL_GPL(cppc_get_perf_ctrs); +/* + * Set Energy Performance Preference Register value through + * Performance Controls Interface + */ +int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable) +{ +	int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); +	struct cpc_register_resource *epp_set_reg; +	struct cpc_register_resource *auto_sel_reg; +	struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu); +	struct cppc_pcc_data *pcc_ss_data = NULL; +	int ret; + +	if (!cpc_desc) { +		pr_debug("No CPC descriptor for CPU:%d\n", cpu); +		return -ENODEV; +	} + +	auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE]; +	epp_set_reg = &cpc_desc->cpc_regs[ENERGY_PERF]; + +	if (CPC_IN_PCC(epp_set_reg) || CPC_IN_PCC(auto_sel_reg)) { +		if (pcc_ss_id < 0) { +			pr_debug("Invalid pcc_ss_id for CPU:%d\n", cpu); +			return -ENODEV; +		} + +		if (CPC_SUPPORTED(auto_sel_reg)) { +			ret = cpc_write(cpu, auto_sel_reg, enable); +			if (ret) +				return ret; +		} + +		if (CPC_SUPPORTED(epp_set_reg)) { +			ret = cpc_write(cpu, epp_set_reg, perf_ctrls->energy_perf); +			if (ret) +				return ret; +		} + +		pcc_ss_data = pcc_data[pcc_ss_id]; + +		down_write(&pcc_ss_data->pcc_lock); +		/* after writing CPC, transfer the ownership of PCC to platform */ +		ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE); +		up_write(&pcc_ss_data->pcc_lock); +	} else { +		ret = -ENOTSUPP; +		pr_debug("_CPC in PCC is not supported\n"); +	} + +	return ret; +} +EXPORT_SYMBOL_GPL(cppc_set_epp_perf); +  /**   * cppc_set_enable - Set to enable CPPC on the processor by writing the   * Continuous Performance Control package EnableRegister field. @@ -1536,6 +1604,7 @@ EXPORT_SYMBOL_GPL(cppc_set_perf);  /**   * cppc_get_transition_latency - returns frequency transition latency in ns + * @cpu_num: CPU number for per_cpu().   *   * ACPI CPPC does not explicitly specify how a platform can specify the   * transition latency for performance change requests. The closest we have  |