mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02: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
					
				
					 1 changed files with 49 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -118,6 +118,8 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
 | 
			
		|||
 */
 | 
			
		||||
#define NUM_RETRIES 500ULL
 | 
			
		||||
 | 
			
		||||
#define OVER_16BTS_MASK ~0xFFFFULL
 | 
			
		||||
 | 
			
		||||
#define define_one_cppc_ro(_name)		\
 | 
			
		||||
static struct kobj_attribute _name =		\
 | 
			
		||||
__ATTR(_name, 0444, show_##_name, NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -746,9 +748,26 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 | 
			
		|||
						goto out_free;
 | 
			
		||||
					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 {
 | 
			
		||||
				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);
 | 
			
		||||
					goto out_free;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -923,7 +942,21 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	*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);
 | 
			
		||||
	else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 | 
			
		||||
		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);
 | 
			
		||||
	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);
 | 
			
		||||
	else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 | 
			
		||||
		vaddr = reg_res->sys_mem_vaddr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue