Skip to content

Commit c984f5d

Browse files
wkarnyrafaeljw
authored andcommitted
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>
1 parent 76531df commit c984f5d

2 files changed

Lines changed: 107 additions & 0 deletions

File tree

drivers/acpi/cppc_acpi.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,102 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
14331433
}
14341434
EXPORT_SYMBOL_GPL(cppc_set_epp_perf);
14351435

1436+
/**
1437+
* cppc_get_auto_sel_caps - Read autonomous selection register.
1438+
* @cpunum : CPU from which to read register.
1439+
* @perf_caps : struct where autonomous selection register value is updated.
1440+
*/
1441+
int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
1442+
{
1443+
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
1444+
struct cpc_register_resource *auto_sel_reg;
1445+
u64 auto_sel;
1446+
1447+
if (!cpc_desc) {
1448+
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
1449+
return -ENODEV;
1450+
}
1451+
1452+
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
1453+
1454+
if (!CPC_SUPPORTED(auto_sel_reg))
1455+
pr_warn_once("Autonomous mode is not unsupported!\n");
1456+
1457+
if (CPC_IN_PCC(auto_sel_reg)) {
1458+
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
1459+
struct cppc_pcc_data *pcc_ss_data = NULL;
1460+
int ret = 0;
1461+
1462+
if (pcc_ss_id < 0)
1463+
return -ENODEV;
1464+
1465+
pcc_ss_data = pcc_data[pcc_ss_id];
1466+
1467+
down_write(&pcc_ss_data->pcc_lock);
1468+
1469+
if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0) {
1470+
cpc_read(cpunum, auto_sel_reg, &auto_sel);
1471+
perf_caps->auto_sel = (bool)auto_sel;
1472+
} else {
1473+
ret = -EIO;
1474+
}
1475+
1476+
up_write(&pcc_ss_data->pcc_lock);
1477+
1478+
return ret;
1479+
}
1480+
1481+
return 0;
1482+
}
1483+
EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
1484+
1485+
/**
1486+
* cppc_set_auto_sel - Write autonomous selection register.
1487+
* @cpu : CPU to which to write register.
1488+
* @enable : the desired value of autonomous selection resiter to be updated.
1489+
*/
1490+
int cppc_set_auto_sel(int cpu, bool enable)
1491+
{
1492+
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
1493+
struct cpc_register_resource *auto_sel_reg;
1494+
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
1495+
struct cppc_pcc_data *pcc_ss_data = NULL;
1496+
int ret = -EINVAL;
1497+
1498+
if (!cpc_desc) {
1499+
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
1500+
return -ENODEV;
1501+
}
1502+
1503+
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
1504+
1505+
if (CPC_IN_PCC(auto_sel_reg)) {
1506+
if (pcc_ss_id < 0) {
1507+
pr_debug("Invalid pcc_ss_id\n");
1508+
return -ENODEV;
1509+
}
1510+
1511+
if (CPC_SUPPORTED(auto_sel_reg)) {
1512+
ret = cpc_write(cpu, auto_sel_reg, enable);
1513+
if (ret)
1514+
return ret;
1515+
}
1516+
1517+
pcc_ss_data = pcc_data[pcc_ss_id];
1518+
1519+
down_write(&pcc_ss_data->pcc_lock);
1520+
/* after writing CPC, transfer the ownership of PCC to platform */
1521+
ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
1522+
up_write(&pcc_ss_data->pcc_lock);
1523+
} else {
1524+
ret = -ENOTSUPP;
1525+
pr_debug("_CPC in PCC is not supported\n");
1526+
}
1527+
1528+
return ret;
1529+
}
1530+
EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
1531+
14361532
/**
14371533
* cppc_set_enable - Set to enable CPPC on the processor by writing the
14381534
* Continuous Performance Control package EnableRegister field.

include/acpi/cppc_acpi.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ struct cppc_perf_caps {
109109
u32 lowest_freq;
110110
u32 nominal_freq;
111111
u32 energy_perf;
112+
bool auto_sel;
112113
};
113114

114115
struct cppc_perf_ctrls {
@@ -153,6 +154,8 @@ extern int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val);
153154
extern int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val);
154155
extern int cppc_get_epp_perf(int cpunum, u64 *epp_perf);
155156
extern int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable);
157+
extern int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps);
158+
extern int cppc_set_auto_sel(int cpu, bool enable);
156159
#else /* !CONFIG_ACPI_CPPC_LIB */
157160
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
158161
{
@@ -214,6 +217,14 @@ static inline int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
214217
{
215218
return -ENOTSUPP;
216219
}
220+
static inline int cppc_set_auto_sel(int cpu, bool enable)
221+
{
222+
return -ENOTSUPP;
223+
}
224+
static inline int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
225+
{
226+
return -ENOTSUPP;
227+
}
217228
#endif /* !CONFIG_ACPI_CPPC_LIB */
218229

219230
#endif /* _CPPC_ACPI_H*/

0 commit comments

Comments
 (0)