Skip to content

Commit a2c8f92

Browse files
Steven Noonanrafaeljw
authored andcommitted
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 <[email protected]> Signed-off-by: Huang Rui <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 89aa94b commit a2c8f92

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

drivers/acpi/cppc_acpi.c

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
118118
*/
119119
#define NUM_RETRIES 500ULL
120120

121+
#define OVER_16BTS_MASK ~0xFFFFULL
122+
121123
#define define_one_cppc_ro(_name) \
122124
static struct kobj_attribute _name = \
123125
__ATTR(_name, 0444, show_##_name, NULL)
@@ -746,9 +748,26 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
746748
goto out_free;
747749
cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
748750
}
751+
} else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
752+
if (gas_t->access_width < 1 || gas_t->access_width > 3) {
753+
/*
754+
* 1 = 8-bit, 2 = 16-bit, and 3 = 32-bit.
755+
* SystemIO doesn't implement 64-bit
756+
* registers.
757+
*/
758+
pr_debug("Invalid access width %d for SystemIO register\n",
759+
gas_t->access_width);
760+
goto out_free;
761+
}
762+
if (gas_t->address & OVER_16BTS_MASK) {
763+
/* SystemIO registers use 16-bit integer addresses */
764+
pr_debug("Invalid IO port %llu for SystemIO register\n",
765+
gas_t->address);
766+
goto out_free;
767+
}
749768
} else {
750769
if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
751-
/* Support only PCC ,SYS MEM and FFH type regs */
770+
/* Support only PCC, SystemMemory, SystemIO, and FFH type regs. */
752771
pr_debug("Unsupported register type: %d\n", gas_t->space_id);
753772
goto out_free;
754773
}
@@ -923,7 +942,21 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
923942
}
924943

925944
*val = 0;
926-
if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
945+
946+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
947+
u32 width = 8 << (reg->access_width - 1);
948+
acpi_status status;
949+
950+
status = acpi_os_read_port((acpi_io_address)reg->address,
951+
(u32 *)val, width);
952+
if (ACPI_FAILURE(status)) {
953+
pr_debug("Error: Failed to read SystemIO port %llx\n",
954+
reg->address);
955+
return -EFAULT;
956+
}
957+
958+
return 0;
959+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
927960
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
928961
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
929962
vaddr = reg_res->sys_mem_vaddr;
@@ -962,7 +995,20 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
962995
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
963996
struct cpc_reg *reg = &reg_res->cpc_entry.reg;
964997

965-
if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
998+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
999+
u32 width = 8 << (reg->access_width - 1);
1000+
acpi_status status;
1001+
1002+
status = acpi_os_write_port((acpi_io_address)reg->address,
1003+
(u32)val, width);
1004+
if (ACPI_FAILURE(status)) {
1005+
pr_debug("Error: Failed to write SystemIO port %llx\n",
1006+
reg->address);
1007+
return -EFAULT;
1008+
}
1009+
1010+
return 0;
1011+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
9661012
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
9671013
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
9681014
vaddr = reg_res->sys_mem_vaddr;

0 commit comments

Comments
 (0)