mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-14 06:24:53 +08:00
ACPI: CPPC: Implement support for SystemIO registers
According to the ACPI v6.2 (and later) specification, SystemIO can be used for _CPC registers. This teaches cppc_acpi how to handle such registers. This patch was tested using the amd_pstate driver on my Zephyrus G15 (model GA503QS) using the current version 410 BIOS, which uses a SystemIO register for the HighestPerformance element in _CPC. Signed-off-by: Steven Noonan <steven@valvesoftware.com> Signed-off-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
89aa94b4a2
commit
a2c8f92bea
@ -118,6 +118,8 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
|
|||||||
*/
|
*/
|
||||||
#define NUM_RETRIES 500ULL
|
#define NUM_RETRIES 500ULL
|
||||||
|
|
||||||
|
#define OVER_16BTS_MASK ~0xFFFFULL
|
||||||
|
|
||||||
#define define_one_cppc_ro(_name) \
|
#define define_one_cppc_ro(_name) \
|
||||||
static struct kobj_attribute _name = \
|
static struct kobj_attribute _name = \
|
||||||
__ATTR(_name, 0444, show_##_name, NULL)
|
__ATTR(_name, 0444, show_##_name, NULL)
|
||||||
@ -746,9 +748,26 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
|
cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
|
||||||
}
|
}
|
||||||
|
} else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||||
|
if (gas_t->access_width < 1 || gas_t->access_width > 3) {
|
||||||
|
/*
|
||||||
|
* 1 = 8-bit, 2 = 16-bit, and 3 = 32-bit.
|
||||||
|
* SystemIO doesn't implement 64-bit
|
||||||
|
* registers.
|
||||||
|
*/
|
||||||
|
pr_debug("Invalid access width %d for SystemIO register\n",
|
||||||
|
gas_t->access_width);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
if (gas_t->address & OVER_16BTS_MASK) {
|
||||||
|
/* SystemIO registers use 16-bit integer addresses */
|
||||||
|
pr_debug("Invalid IO port %llu for SystemIO register\n",
|
||||||
|
gas_t->address);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
|
if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
|
||||||
/* Support only PCC ,SYS MEM and FFH type regs */
|
/* Support only PCC, SystemMemory, SystemIO, and FFH type regs. */
|
||||||
pr_debug("Unsupported register type: %d\n", gas_t->space_id);
|
pr_debug("Unsupported register type: %d\n", gas_t->space_id);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
@ -923,7 +942,21 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*val = 0;
|
*val = 0;
|
||||||
if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
|
|
||||||
|
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||||
|
u32 width = 8 << (reg->access_width - 1);
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_os_read_port((acpi_io_address)reg->address,
|
||||||
|
(u32 *)val, width);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
pr_debug("Error: Failed to read SystemIO port %llx\n",
|
||||||
|
reg->address);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
|
||||||
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
|
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
|
||||||
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||||
vaddr = reg_res->sys_mem_vaddr;
|
vaddr = reg_res->sys_mem_vaddr;
|
||||||
@ -962,7 +995,20 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
|||||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||||
struct cpc_reg *reg = ®_res->cpc_entry.reg;
|
struct cpc_reg *reg = ®_res->cpc_entry.reg;
|
||||||
|
|
||||||
if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
|
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||||
|
u32 width = 8 << (reg->access_width - 1);
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_os_write_port((acpi_io_address)reg->address,
|
||||||
|
(u32)val, width);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
pr_debug("Error: Failed to write SystemIO port %llx\n",
|
||||||
|
reg->address);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
|
||||||
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
|
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
|
||||||
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||||
vaddr = reg_res->sys_mem_vaddr;
|
vaddr = reg_res->sys_mem_vaddr;
|
||||||
|
Loading…
Reference in New Issue
Block a user