mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
ACPI: CPPC: Add auto select register read/write support
For some AMD shared memory based systems, the autonomous selection bit needed to be set explicitly. Add autonomous selection register related APIs to acpi driver, which amd_pstate driver uses later. Acked-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> Signed-off-by: Wyes Karny <wyes.karny@amd.com> [ rjw: Fixed up kerneldoc comments, white space adjustment, subject edits ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
76531df5e1
commit
c984f5d5d4
@ -1433,6 +1433,102 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_set_epp_perf);
|
||||
|
||||
/**
|
||||
* cppc_get_auto_sel_caps - Read autonomous selection register.
|
||||
* @cpunum : CPU from which to read register.
|
||||
* @perf_caps : struct where autonomous selection register value is updated.
|
||||
*/
|
||||
int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
|
||||
struct cpc_register_resource *auto_sel_reg;
|
||||
u64 auto_sel;
|
||||
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
|
||||
|
||||
if (!CPC_SUPPORTED(auto_sel_reg))
|
||||
pr_warn_once("Autonomous mode is not unsupported!\n");
|
||||
|
||||
if (CPC_IN_PCC(auto_sel_reg)) {
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (pcc_ss_id < 0)
|
||||
return -ENODEV;
|
||||
|
||||
pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
|
||||
down_write(&pcc_ss_data->pcc_lock);
|
||||
|
||||
if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0) {
|
||||
cpc_read(cpunum, auto_sel_reg, &auto_sel);
|
||||
perf_caps->auto_sel = (bool)auto_sel;
|
||||
} else {
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
up_write(&pcc_ss_data->pcc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
|
||||
|
||||
/**
|
||||
* cppc_set_auto_sel - Write autonomous selection register.
|
||||
* @cpu : CPU to which to write register.
|
||||
* @enable : the desired value of autonomous selection resiter to be updated.
|
||||
*/
|
||||
int cppc_set_auto_sel(int cpu, bool enable)
|
||||
{
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
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 = -EINVAL;
|
||||
|
||||
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];
|
||||
|
||||
if (CPC_IN_PCC(auto_sel_reg)) {
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (CPC_SUPPORTED(auto_sel_reg)) {
|
||||
ret = cpc_write(cpu, auto_sel_reg, enable);
|
||||
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_auto_sel);
|
||||
|
||||
/**
|
||||
* cppc_set_enable - Set to enable CPPC on the processor by writing the
|
||||
* Continuous Performance Control package EnableRegister field.
|
||||
|
@ -109,6 +109,7 @@ struct cppc_perf_caps {
|
||||
u32 lowest_freq;
|
||||
u32 nominal_freq;
|
||||
u32 energy_perf;
|
||||
bool auto_sel;
|
||||
};
|
||||
|
||||
struct cppc_perf_ctrls {
|
||||
@ -153,6 +154,8 @@ extern int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val);
|
||||
extern int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val);
|
||||
extern int cppc_get_epp_perf(int cpunum, u64 *epp_perf);
|
||||
extern int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable);
|
||||
extern int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps);
|
||||
extern int cppc_set_auto_sel(int cpu, bool enable);
|
||||
#else /* !CONFIG_ACPI_CPPC_LIB */
|
||||
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
{
|
||||
@ -214,6 +217,14 @@ static inline int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_auto_sel(int cpu, bool enable)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#endif /* !CONFIG_ACPI_CPPC_LIB */
|
||||
|
||||
#endif /* _CPPC_ACPI_H*/
|
||||
|
Loading…
Reference in New Issue
Block a user