mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-23 07:23:12 +02:00
Merge branches 'acpi-processor' and 'acpi-cppc'
Merge ACPI processor driver updates and ACPI CPPC library updates for 6.16-rc1: - Clean up the initialization of CPU data structures in the ACPI processor driver (Zhang Rui). - Remove an obsolete comment regarding the C-states handling in the ACPI processor driver (Giovanni Gherdovich). - Simplify PCC shared memory region handling (Sudeep Holla). - Rework and extend functions for reading CPPC register values and for updating CPPC registers (Lifeng Zheng). - Add three functions related to autonomous CPU performance state selection to the CPPC library (Lifeng Zheng). * acpi-processor: ACPI: processor: idle: Remove redundant pr->power.count assignment ACPI: processor: idle: Set pr->flags.power unconditionally ACPI: processor: idle: Remove obsolete comment * acpi-cppc: ACPI: CPPC: Add three functions related to autonomous selection ACPI: CPPC: Modify cppc_get_auto_sel_caps() to cppc_get_auto_sel() ACPI: CPPC: Refactor register value get and set ABIs ACPI: CPPC: Add cppc_set_reg_val() ACPI: CPPC: Extract cppc_get_reg_val_in_pcc() ACPI: CPPC: Rename cppc_get_perf() to cppc_get_reg_val() ACPI: CPPC: Optimize cppc_get_perf() ACPI: CPPC: Add IS_OPTIONAL_CPC_REG macro to judge if a cpc_reg is optional ACPI: CPPC: Simplify PCC shared memory region handling ACPI: PCC: Simplify PCC shared memory region handling
This commit is contained in:
commit
0a17adc6be
|
@ -31,7 +31,6 @@
|
|||
|
||||
struct pcc_data {
|
||||
struct pcc_mbox_chan *pcc_chan;
|
||||
void __iomem *pcc_comm_addr;
|
||||
struct completion done;
|
||||
struct mbox_client cl;
|
||||
struct acpi_pcc_info ctx;
|
||||
|
@ -81,14 +80,6 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
|
|||
ret = AE_SUPPORT;
|
||||
goto err_free_channel;
|
||||
}
|
||||
data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
|
||||
pcc_chan->shmem_size);
|
||||
if (!data->pcc_comm_addr) {
|
||||
pr_err("Failed to ioremap PCC comm region mem for %d\n",
|
||||
ctx->subspace_id);
|
||||
ret = AE_NO_MEMORY;
|
||||
goto err_free_channel;
|
||||
}
|
||||
|
||||
*region_context = data;
|
||||
return AE_OK;
|
||||
|
@ -113,7 +104,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
|
|||
reinit_completion(&data->done);
|
||||
|
||||
/* Write to Shared Memory */
|
||||
memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length);
|
||||
memcpy_toio(data->pcc_chan->shmem, (void *)value, data->ctx.length);
|
||||
|
||||
ret = mbox_send_message(data->pcc_chan->mchan, NULL);
|
||||
if (ret < 0)
|
||||
|
@ -134,7 +125,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
|
|||
|
||||
mbox_chan_txdone(data->pcc_chan->mchan, ret);
|
||||
|
||||
memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
|
||||
memcpy_fromio(value, data->pcc_chan->shmem, data->ctx.length);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
struct cppc_pcc_data {
|
||||
struct pcc_mbox_chan *pcc_channel;
|
||||
void __iomem *pcc_comm_addr;
|
||||
bool pcc_channel_acquired;
|
||||
unsigned int deadline_us;
|
||||
unsigned int pcc_mpar, pcc_mrtt, pcc_nominal;
|
||||
|
@ -95,7 +94,7 @@ static DEFINE_PER_CPU(int, cpu_pcc_subspace_idx);
|
|||
static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
|
||||
|
||||
/* pcc mapped address + header size + offset within PCC subspace */
|
||||
#define GET_PCC_VADDR(offs, pcc_ss_id) (pcc_data[pcc_ss_id]->pcc_comm_addr + \
|
||||
#define GET_PCC_VADDR(offs, pcc_ss_id) (pcc_data[pcc_ss_id]->pcc_channel->shmem + \
|
||||
0x8 + (offs))
|
||||
|
||||
/* Check if a CPC register is in PCC */
|
||||
|
@ -129,6 +128,20 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
|
|||
#define CPC_SUPPORTED(cpc) ((cpc)->type == ACPI_TYPE_INTEGER ? \
|
||||
!!(cpc)->cpc_entry.int_value : \
|
||||
!IS_NULL_REG(&(cpc)->cpc_entry.reg))
|
||||
|
||||
/*
|
||||
* Each bit indicates the optionality of the register in per-cpu
|
||||
* cpc_regs[] with the corresponding index. 0 means mandatory and 1
|
||||
* means optional.
|
||||
*/
|
||||
#define REG_OPTIONAL (0x1FC7D0)
|
||||
|
||||
/*
|
||||
* Use the index of the register in per-cpu cpc_regs[] to check if
|
||||
* it's an optional one.
|
||||
*/
|
||||
#define IS_OPTIONAL_CPC_REG(reg_idx) (REG_OPTIONAL & (1U << (reg_idx)))
|
||||
|
||||
/*
|
||||
* Arbitrary Retries in case the remote processor is slow to respond
|
||||
* to PCC commands. Keeping it high enough to cover emulators where
|
||||
|
@ -223,7 +236,7 @@ static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit)
|
|||
int ret, status;
|
||||
struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
struct acpi_pcct_shared_memory __iomem *generic_comm_base =
|
||||
pcc_ss_data->pcc_comm_addr;
|
||||
pcc_ss_data->pcc_channel->shmem;
|
||||
|
||||
if (!pcc_ss_data->platform_owns_pcc)
|
||||
return 0;
|
||||
|
@ -258,7 +271,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
|
|||
int ret = -EIO, i;
|
||||
struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id];
|
||||
struct acpi_pcct_shared_memory __iomem *generic_comm_base =
|
||||
pcc_ss_data->pcc_comm_addr;
|
||||
pcc_ss_data->pcc_channel->shmem;
|
||||
unsigned int time_delta;
|
||||
|
||||
/*
|
||||
|
@ -571,15 +584,6 @@ static int register_pcc_channel(int pcc_ss_idx)
|
|||
pcc_data[pcc_ss_idx]->pcc_mpar = pcc_chan->max_access_rate;
|
||||
pcc_data[pcc_ss_idx]->pcc_nominal = pcc_chan->latency;
|
||||
|
||||
pcc_data[pcc_ss_idx]->pcc_comm_addr =
|
||||
acpi_os_ioremap(pcc_chan->shmem_base_addr,
|
||||
pcc_chan->shmem_size);
|
||||
if (!pcc_data[pcc_ss_idx]->pcc_comm_addr) {
|
||||
pr_err("Failed to ioremap PCC comm region mem for %d\n",
|
||||
pcc_ss_idx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set flag so that we don't come here for each CPU. */
|
||||
pcc_data[pcc_ss_idx]->pcc_channel_acquired = true;
|
||||
}
|
||||
|
@ -1175,43 +1179,106 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
|
||||
static int cppc_get_reg_val_in_pcc(int cpu, struct cpc_register_resource *reg, u64 *val)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
int ret;
|
||||
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
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)
|
||||
ret = cpc_read(cpu, reg, val);
|
||||
else
|
||||
ret = -EIO;
|
||||
|
||||
up_write(&pcc_ss_data->pcc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cppc_get_reg_val(int cpu, enum cppc_regs reg_idx, u64 *val)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
|
||||
struct cpc_register_resource *reg;
|
||||
|
||||
if (val == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
reg = &cpc_desc->cpc_regs[reg_idx];
|
||||
|
||||
if (CPC_IN_PCC(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 -EIO;
|
||||
|
||||
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, reg, perf);
|
||||
else
|
||||
ret = -EIO;
|
||||
|
||||
up_write(&pcc_ss_data->pcc_lock);
|
||||
|
||||
return ret;
|
||||
if ((reg->type == ACPI_TYPE_INTEGER && IS_OPTIONAL_CPC_REG(reg_idx) &&
|
||||
!reg->cpc_entry.int_value) || (reg->type != ACPI_TYPE_INTEGER &&
|
||||
IS_NULL_REG(®->cpc_entry.reg))) {
|
||||
pr_debug("CPC register is not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
cpc_read(cpunum, reg, perf);
|
||||
if (CPC_IN_PCC(reg))
|
||||
return cppc_get_reg_val_in_pcc(cpu, reg, val);
|
||||
|
||||
return 0;
|
||||
return cpc_read(cpu, reg, val);
|
||||
}
|
||||
|
||||
static int cppc_set_reg_val_in_pcc(int cpu, struct cpc_register_resource *reg, u64 val)
|
||||
{
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
struct cppc_pcc_data *pcc_ss_data = NULL;
|
||||
int ret;
|
||||
|
||||
if (pcc_ss_id < 0) {
|
||||
pr_debug("Invalid pcc_ss_id\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = cpc_write(cpu, reg, val);
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cppc_set_reg_val(int cpu, enum cppc_regs reg_idx, u64 val)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
|
||||
struct cpc_register_resource *reg;
|
||||
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
reg = &cpc_desc->cpc_regs[reg_idx];
|
||||
|
||||
/* if a register is writeable, it must be a buffer and not null */
|
||||
if ((reg->type != ACPI_TYPE_BUFFER) || IS_NULL_REG(®->cpc_entry.reg)) {
|
||||
pr_debug("CPC register is not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (CPC_IN_PCC(reg))
|
||||
return cppc_set_reg_val_in_pcc(cpu, reg, val);
|
||||
|
||||
return cpc_write(cpu, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1223,7 +1290,7 @@ static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
|
|||
*/
|
||||
int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
{
|
||||
return cppc_get_perf(cpunum, DESIRED_PERF, desired_perf);
|
||||
return cppc_get_reg_val(cpunum, DESIRED_PERF, desired_perf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
|
||||
|
||||
|
@ -1236,7 +1303,7 @@ EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
|
|||
*/
|
||||
int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
|
||||
{
|
||||
return cppc_get_perf(cpunum, NOMINAL_PERF, nominal_perf);
|
||||
return cppc_get_reg_val(cpunum, NOMINAL_PERF, nominal_perf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1248,7 +1315,7 @@ int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
|
|||
*/
|
||||
int cppc_get_highest_perf(int cpunum, u64 *highest_perf)
|
||||
{
|
||||
return cppc_get_perf(cpunum, HIGHEST_PERF, highest_perf);
|
||||
return cppc_get_reg_val(cpunum, HIGHEST_PERF, highest_perf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
|
||||
|
||||
|
@ -1261,7 +1328,7 @@ EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
|
|||
*/
|
||||
int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
|
||||
{
|
||||
return cppc_get_perf(cpunum, ENERGY_PERF, epp_perf);
|
||||
return cppc_get_reg_val(cpunum, ENERGY_PERF, epp_perf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_epp_perf);
|
||||
|
||||
|
@ -1535,53 +1602,110 @@ 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.
|
||||
* cppc_set_epp() - Write the EPP register.
|
||||
* @cpu: CPU on which to write register.
|
||||
* @epp_val: Value to write to the EPP register.
|
||||
*/
|
||||
int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
int cppc_set_epp(int cpu, u64 epp_val)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
|
||||
struct cpc_register_resource *auto_sel_reg;
|
||||
u64 auto_sel;
|
||||
if (epp_val > CPPC_ENERGY_PERF_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cpc_desc) {
|
||||
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
|
||||
return -ENODEV;
|
||||
}
|
||||
return cppc_set_reg_val(cpu, ENERGY_PERF, epp_val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_set_epp);
|
||||
|
||||
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
|
||||
/**
|
||||
* cppc_get_auto_act_window() - Read autonomous activity window register.
|
||||
* @cpu: CPU from which to read register.
|
||||
* @auto_act_window: Return address.
|
||||
*
|
||||
* According to ACPI 6.5, s8.4.6.1.6, the value read from the autonomous
|
||||
* activity window register consists of two parts: a 7 bits value indicate
|
||||
* significand and a 3 bits value indicate exponent.
|
||||
*/
|
||||
int cppc_get_auto_act_window(int cpu, u64 *auto_act_window)
|
||||
{
|
||||
unsigned int exp;
|
||||
u64 val, sig;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
if (auto_act_window == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
ret = cppc_get_reg_val(cpu, AUTO_ACT_WINDOW, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
sig = val & CPPC_AUTO_ACT_WINDOW_MAX_SIG;
|
||||
exp = (val >> CPPC_AUTO_ACT_WINDOW_SIG_BIT_SIZE) & CPPC_AUTO_ACT_WINDOW_MAX_EXP;
|
||||
*auto_act_window = sig * int_pow(10, exp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
|
||||
EXPORT_SYMBOL_GPL(cppc_get_auto_act_window);
|
||||
|
||||
/**
|
||||
* cppc_set_auto_act_window() - Write autonomous activity window register.
|
||||
* @cpu: CPU on which to write register.
|
||||
* @auto_act_window: usec value to write to the autonomous activity window register.
|
||||
*
|
||||
* According to ACPI 6.5, s8.4.6.1.6, the value to write to the autonomous
|
||||
* activity window register consists of two parts: a 7 bits value indicate
|
||||
* significand and a 3 bits value indicate exponent.
|
||||
*/
|
||||
int cppc_set_auto_act_window(int cpu, u64 auto_act_window)
|
||||
{
|
||||
/* The max value to store is 1270000000 */
|
||||
u64 max_val = CPPC_AUTO_ACT_WINDOW_MAX_SIG * int_pow(10, CPPC_AUTO_ACT_WINDOW_MAX_EXP);
|
||||
int exp = 0;
|
||||
u64 val;
|
||||
|
||||
if (auto_act_window > max_val)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The max significand is 127, when auto_act_window is larger than
|
||||
* 129, discard the precision of the last digit and increase the
|
||||
* exponent by 1.
|
||||
*/
|
||||
while (auto_act_window > CPPC_AUTO_ACT_WINDOW_SIG_CARRY_THRESH) {
|
||||
auto_act_window /= 10;
|
||||
exp += 1;
|
||||
}
|
||||
|
||||
/* For 128 and 129, cut it to 127. */
|
||||
if (auto_act_window > CPPC_AUTO_ACT_WINDOW_MAX_SIG)
|
||||
auto_act_window = CPPC_AUTO_ACT_WINDOW_MAX_SIG;
|
||||
|
||||
val = (exp << CPPC_AUTO_ACT_WINDOW_SIG_BIT_SIZE) + auto_act_window;
|
||||
|
||||
return cppc_set_reg_val(cpu, AUTO_ACT_WINDOW, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_set_auto_act_window);
|
||||
|
||||
/**
|
||||
* cppc_get_auto_sel() - Read autonomous selection register.
|
||||
* @cpu: CPU from which to read register.
|
||||
* @enable: Return address.
|
||||
*/
|
||||
int cppc_get_auto_sel(int cpu, bool *enable)
|
||||
{
|
||||
u64 auto_sel;
|
||||
int ret;
|
||||
|
||||
if (enable == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
ret = cppc_get_reg_val(cpu, AUTO_SEL_ENABLE, &auto_sel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*enable = (bool)auto_sel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_auto_sel);
|
||||
|
||||
/**
|
||||
* cppc_set_auto_sel - Write autonomous selection register.
|
||||
|
@ -1590,43 +1714,7 @@ EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
|
|||
*/
|
||||
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;
|
||||
return cppc_set_reg_val(cpu, AUTO_SEL_ENABLE, enable);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
|
||||
|
||||
|
@ -1640,38 +1728,7 @@ EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
|
|||
*/
|
||||
int cppc_set_enable(int cpu, bool enable)
|
||||
{
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
struct cpc_register_resource *enable_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 -EINVAL;
|
||||
}
|
||||
|
||||
enable_reg = &cpc_desc->cpc_regs[ENABLE];
|
||||
|
||||
if (CPC_IN_PCC(enable_reg)) {
|
||||
|
||||
if (pcc_ss_id < 0)
|
||||
return -EIO;
|
||||
|
||||
ret = cpc_write(cpu, enable_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 platfrom */
|
||||
ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
|
||||
up_write(&pcc_ss_data->pcc_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return cpc_write(cpu, enable_reg, enable);
|
||||
return cppc_set_reg_val(cpu, ENABLE, enable);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_set_enable);
|
||||
|
||||
|
|
|
@ -461,10 +461,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
|
|||
|
||||
static int acpi_processor_get_cstate_info(struct acpi_processor *pr)
|
||||
{
|
||||
unsigned int i;
|
||||
int result;
|
||||
|
||||
|
||||
/* NOTE: the idle thread may not be running while calling
|
||||
* this function */
|
||||
|
||||
|
@ -481,17 +479,7 @@ static int acpi_processor_get_cstate_info(struct acpi_processor *pr)
|
|||
acpi_processor_get_power_info_default(pr);
|
||||
|
||||
pr->power.count = acpi_processor_power_verify(pr);
|
||||
|
||||
/*
|
||||
* if one state of type C2 or C3 is available, mark this
|
||||
* CPU as being "idle manageable"
|
||||
*/
|
||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
|
||||
if (pr->power.states[i].valid) {
|
||||
pr->power.count = i;
|
||||
pr->flags.power = 1;
|
||||
}
|
||||
}
|
||||
pr->flags.power = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -417,6 +417,7 @@ static int shmem_init_perf(struct amd_cpudata *cpudata)
|
|||
struct cppc_perf_caps cppc_perf;
|
||||
union perf_cached perf = READ_ONCE(cpudata->perf);
|
||||
u64 numerator;
|
||||
bool auto_sel;
|
||||
|
||||
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
|
||||
if (ret)
|
||||
|
@ -438,7 +439,7 @@ static int shmem_init_perf(struct amd_cpudata *cpudata)
|
|||
if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||
return 0;
|
||||
|
||||
ret = cppc_get_auto_sel_caps(cpudata->cpu, &cppc_perf);
|
||||
ret = cppc_get_auto_sel(cpudata->cpu, &auto_sel);
|
||||
if (ret) {
|
||||
pr_warn("failed to get auto_sel, ret: %d\n", ret);
|
||||
return 0;
|
||||
|
|
|
@ -32,6 +32,15 @@
|
|||
#define CMD_READ 0
|
||||
#define CMD_WRITE 1
|
||||
|
||||
#define CPPC_AUTO_ACT_WINDOW_SIG_BIT_SIZE (7)
|
||||
#define CPPC_AUTO_ACT_WINDOW_EXP_BIT_SIZE (3)
|
||||
#define CPPC_AUTO_ACT_WINDOW_MAX_SIG ((1 << CPPC_AUTO_ACT_WINDOW_SIG_BIT_SIZE) - 1)
|
||||
#define CPPC_AUTO_ACT_WINDOW_MAX_EXP ((1 << CPPC_AUTO_ACT_WINDOW_EXP_BIT_SIZE) - 1)
|
||||
/* CPPC_AUTO_ACT_WINDOW_MAX_SIG is 127, so 128 and 129 will decay to 127 when writing */
|
||||
#define CPPC_AUTO_ACT_WINDOW_SIG_CARRY_THRESH 129
|
||||
|
||||
#define CPPC_ENERGY_PERF_MAX (0xFF)
|
||||
|
||||
/* Each register has the folowing format. */
|
||||
struct cpc_reg {
|
||||
u8 descriptor;
|
||||
|
@ -159,7 +168,10 @@ 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_epp(int cpu, u64 epp_val);
|
||||
extern int cppc_get_auto_act_window(int cpu, u64 *auto_act_window);
|
||||
extern int cppc_set_auto_act_window(int cpu, u64 auto_act_window);
|
||||
extern int cppc_get_auto_sel(int cpu, bool *enable);
|
||||
extern int cppc_set_auto_sel(int cpu, bool enable);
|
||||
extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
|
||||
extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
|
||||
|
@ -229,11 +241,23 @@ static inline int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
|
|||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_auto_sel(int cpu, bool enable)
|
||||
static inline int cppc_set_epp(int cpu, u64 epp_val)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
static inline int cppc_get_auto_act_window(int cpu, u64 *auto_act_window)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_auto_act_window(int cpu, u64 auto_act_window)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_auto_sel(int cpu, bool *enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_auto_sel(int cpu, bool enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user