diff options
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
| -rw-r--r-- | drivers/acpi/cppc_acpi.c | 44 | 
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index d155a86a8614..4bfbe55553f4 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -166,6 +166,13 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_freq);  show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, reference_perf);  show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time); +/* Check for valid access_width, otherwise, fallback to using bit_width */ +#define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width) + +/* Shift and apply the mask for CPC reads/writes */ +#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset & 			\ +					GENMASK(((reg)->bit_width), 0))) +  static ssize_t show_feedback_ctrs(struct kobject *kobj,  		struct kobj_attribute *attr, char *buf)  { @@ -780,6 +787,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)  			} else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {  				if (gas_t->address) {  					void __iomem *addr; +					size_t access_width;  					if (!osc_cpc_flexible_adr_space_confirmed) {  						pr_debug("Flexible address space capability not supported\n"); @@ -787,7 +795,8 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)  							goto out_free;  					} -					addr = ioremap(gas_t->address, gas_t->bit_width/8); +					access_width = GET_BIT_WIDTH(gas_t) / 8; +					addr = ioremap(gas_t->address, access_width);  					if (!addr)  						goto out_free;  					cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr; @@ -983,6 +992,7 @@ int __weak cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)  static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)  {  	void __iomem *vaddr = NULL; +	int size;  	int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);  	struct cpc_reg *reg = ®_res->cpc_entry.reg; @@ -994,7 +1004,7 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)  	*val = 0;  	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { -		u32 width = 8 << (reg->access_width - 1); +		u32 width = GET_BIT_WIDTH(reg);  		u32 val_u32;  		acpi_status status; @@ -1018,7 +1028,9 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)  		return acpi_os_read_memory((acpi_physical_address)reg->address,  				val, reg->bit_width); -	switch (reg->bit_width) { +	size = GET_BIT_WIDTH(reg); + +	switch (size) {  	case 8:  		*val = readb_relaxed(vaddr);  		break; @@ -1037,18 +1049,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)  		return -EFAULT;  	} +	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) +		*val = MASK_VAL(reg, *val); +  	return 0;  }  static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)  {  	int ret_val = 0; +	int size;  	void __iomem *vaddr = NULL;  	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_SYSTEM_IO) { -		u32 width = 8 << (reg->access_width - 1); +		u32 width = GET_BIT_WIDTH(reg);  		acpi_status status;  		status = acpi_os_write_port((acpi_io_address)reg->address, @@ -1070,7 +1086,12 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)  		return acpi_os_write_memory((acpi_physical_address)reg->address,  				val, reg->bit_width); -	switch (reg->bit_width) { +	size = GET_BIT_WIDTH(reg); + +	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) +		val = MASK_VAL(reg, val); + +	switch (size) {  	case 8:  		writeb_relaxed(val, vaddr);  		break; @@ -1158,6 +1179,19 @@ int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)  }  /** + * cppc_get_highest_perf - Get the highest performance register value. + * @cpunum: CPU from which to get highest performance. + * @highest_perf: Return address. + * + * Return: 0 for success, -EIO otherwise. + */ +int cppc_get_highest_perf(int cpunum, u64 *highest_perf) +{ +	return cppc_get_perf(cpunum, HIGHEST_PERF, highest_perf); +} +EXPORT_SYMBOL_GPL(cppc_get_highest_perf); + +/**   * cppc_get_epp_perf - Get the epp register value.   * @cpunum: CPU from which to get epp preference value.   * @epp_perf: Return address.  | 
