aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/cppc_acpi.c
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2016-09-01 16:37:10 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-08 17:02:14 -0400
commita6cbcdd5ab5f242d49f511127f0a601b71be2cc4 (patch)
tree6c7b1fad06bc5dfce0d10ffa9c6903959060df8e /drivers/acpi/cppc_acpi.c
parent5448f14698b916e5b04112b104433b90247e01c7 (diff)
ACPI / CPPC: Add support for functional fixed hardware address
The CPPC registers can also be accessed via functional fixed hardware addresse(FFH) in X86. Add support by modifying cpc_read and cpc_write to be able to read/write MSRs on x86 platform on per cpu basis. Also with this change, acpi_cppc_processor_probe doesn't bail out if address space id is not equal to PCC or memory address space and FFH is supported on the system. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
-rw-r--r--drivers/acpi/cppc_acpi.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index ed58883d35ee..715fe8001d59 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -579,6 +579,19 @@ static int register_pcc_channel(int pcc_subspace_idx)
579 return 0; 579 return 0;
580} 580}
581 581
582/**
583 * cpc_ffh_supported() - check if FFH reading supported
584 *
585 * Check if the architecture has support for functional fixed hardware
586 * read/write capability.
587 *
588 * Return: true for supported, false for not supported
589 */
590bool __weak cpc_ffh_supported(void)
591{
592 return false;
593}
594
582/* 595/*
583 * An example CPC table looks like the following. 596 * An example CPC table looks like the following.
584 * 597 *
@@ -728,9 +741,11 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
728 cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr; 741 cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
729 } 742 }
730 } else { 743 } else {
731 /* Support only PCC and SYS MEM type regs */ 744 if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
732 pr_debug("Unsupported register type: %d\n", gas_t->space_id); 745 /* Support only PCC ,SYS MEM and FFH type regs */
733 goto out_free; 746 pr_debug("Unsupported register type: %d\n", gas_t->space_id);
747 goto out_free;
748 }
734 } 749 }
735 750
736 cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_BUFFER; 751 cpc_ptr->cpc_regs[i-2].type = ACPI_TYPE_BUFFER;
@@ -819,13 +834,43 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
819} 834}
820EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit); 835EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);
821 836
837/**
838 * cpc_read_ffh() - Read FFH register
839 * @cpunum: cpu number to read
840 * @reg: cppc register information
841 * @val: place holder for return value
842 *
843 * Read bit_width bits from a specified address and bit_offset
844 *
845 * Return: 0 for success and error code
846 */
847int __weak cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val)
848{
849 return -ENOTSUPP;
850}
851
852/**
853 * cpc_write_ffh() - Write FFH register
854 * @cpunum: cpu number to write
855 * @reg: cppc register information
856 * @val: value to write
857 *
858 * Write value of bit_width bits to a specified address and bit_offset
859 *
860 * Return: 0 for success and error code
861 */
862int __weak cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
863{
864 return -ENOTSUPP;
865}
866
822/* 867/*
823 * Since cpc_read and cpc_write are called while holding pcc_lock, it should be 868 * Since cpc_read and cpc_write are called while holding pcc_lock, it should be
824 * as fast as possible. We have already mapped the PCC subspace during init, so 869 * as fast as possible. We have already mapped the PCC subspace during init, so
825 * we can directly write to it. 870 * we can directly write to it.
826 */ 871 */
827 872
828static int cpc_read(struct cpc_register_resource *reg_res, u64 *val) 873static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
829{ 874{
830 int ret_val = 0; 875 int ret_val = 0;
831 void __iomem *vaddr = 0; 876 void __iomem *vaddr = 0;
@@ -841,6 +886,8 @@ static int cpc_read(struct cpc_register_resource *reg_res, u64 *val)
841 vaddr = GET_PCC_VADDR(reg->address); 886 vaddr = GET_PCC_VADDR(reg->address);
842 else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 887 else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
843 vaddr = reg_res->sys_mem_vaddr; 888 vaddr = reg_res->sys_mem_vaddr;
889 else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
890 return cpc_read_ffh(cpu, reg, val);
844 else 891 else
845 return acpi_os_read_memory((acpi_physical_address)reg->address, 892 return acpi_os_read_memory((acpi_physical_address)reg->address,
846 val, reg->bit_width); 893 val, reg->bit_width);
@@ -867,7 +914,7 @@ static int cpc_read(struct cpc_register_resource *reg_res, u64 *val)
867 return ret_val; 914 return ret_val;
868} 915}
869 916
870static int cpc_write(struct cpc_register_resource *reg_res, u64 val) 917static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
871{ 918{
872 int ret_val = 0; 919 int ret_val = 0;
873 void __iomem *vaddr = 0; 920 void __iomem *vaddr = 0;
@@ -877,6 +924,8 @@ static int cpc_write(struct cpc_register_resource *reg_res, u64 val)
877 vaddr = GET_PCC_VADDR(reg->address); 924 vaddr = GET_PCC_VADDR(reg->address);
878 else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 925 else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
879 vaddr = reg_res->sys_mem_vaddr; 926 vaddr = reg_res->sys_mem_vaddr;
927 else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
928 return cpc_write_ffh(cpu, reg, val);
880 else 929 else
881 return acpi_os_write_memory((acpi_physical_address)reg->address, 930 return acpi_os_write_memory((acpi_physical_address)reg->address,
882 val, reg->bit_width); 931 val, reg->bit_width);
@@ -941,13 +990,13 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
941 } 990 }
942 } 991 }
943 992
944 cpc_read(highest_reg, &high); 993 cpc_read(cpunum, highest_reg, &high);
945 perf_caps->highest_perf = high; 994 perf_caps->highest_perf = high;
946 995
947 cpc_read(lowest_reg, &low); 996 cpc_read(cpunum, lowest_reg, &low);
948 perf_caps->lowest_perf = low; 997 perf_caps->lowest_perf = low;
949 998
950 cpc_read(nom_perf, &nom); 999 cpc_read(cpunum, nom_perf, &nom);
951 perf_caps->nominal_perf = nom; 1000 perf_caps->nominal_perf = nom;
952 1001
953 if (!high || !low || !nom) 1002 if (!high || !low || !nom)
@@ -1004,9 +1053,9 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
1004 } 1053 }
1005 } 1054 }
1006 1055
1007 cpc_read(delivered_reg, &delivered); 1056 cpc_read(cpunum, delivered_reg, &delivered);
1008 cpc_read(reference_reg, &reference); 1057 cpc_read(cpunum, reference_reg, &reference);
1009 cpc_read(ref_perf_reg, &ref_perf); 1058 cpc_read(cpunum, ref_perf_reg, &ref_perf);
1010 1059
1011 /* 1060 /*
1012 * Per spec, if ctr_wrap_time optional register is unsupported, then the 1061 * Per spec, if ctr_wrap_time optional register is unsupported, then the
@@ -1015,7 +1064,7 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
1015 */ 1064 */
1016 ctr_wrap_time = (u64)(~((u64)0)); 1065 ctr_wrap_time = (u64)(~((u64)0));
1017 if (CPC_SUPPORTED(ctr_wrap_reg)) 1066 if (CPC_SUPPORTED(ctr_wrap_reg))
1018 cpc_read(ctr_wrap_reg, &ctr_wrap_time); 1067 cpc_read(cpunum, ctr_wrap_reg, &ctr_wrap_time);
1019 1068
1020 if (!delivered || !reference || !ref_perf) { 1069 if (!delivered || !reference || !ref_perf) {
1021 ret = -EFAULT; 1070 ret = -EFAULT;
@@ -1082,7 +1131,7 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
1082 * Skip writing MIN/MAX until Linux knows how to come up with 1131 * Skip writing MIN/MAX until Linux knows how to come up with
1083 * useful values. 1132 * useful values.
1084 */ 1133 */
1085 cpc_write(desired_reg, perf_ctrls->desired_perf); 1134 cpc_write(cpu, desired_reg, perf_ctrls->desired_perf);
1086 1135
1087 if (CPC_IN_PCC(desired_reg)) 1136 if (CPC_IN_PCC(desired_reg))
1088 up_read(&pcc_data.pcc_lock); /* END Phase-I */ 1137 up_read(&pcc_data.pcc_lock); /* END Phase-I */