diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2016-09-01 16:37:10 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-08 17:02:14 -0400 |
commit | a6cbcdd5ab5f242d49f511127f0a601b71be2cc4 (patch) | |
tree | 6c7b1fad06bc5dfce0d10ffa9c6903959060df8e /drivers/acpi/cppc_acpi.c | |
parent | 5448f14698b916e5b04112b104433b90247e01c7 (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.c | 75 |
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 | */ | ||
590 | bool __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 | } |
820 | EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit); | 835 | EXPORT_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 | */ | ||
847 | int __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 | */ | ||
862 | int __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 | ||
828 | static int cpc_read(struct cpc_register_resource *reg_res, u64 *val) | 873 | static 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 | ||
870 | static int cpc_write(struct cpc_register_resource *reg_res, u64 val) | 917 | static 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 */ |