|
25 | 25 | #ifdef CONFIG_CPU_FREQ
|
26 | 26 | #include <linux/cpufreq.h>
|
27 | 27 | #endif /* CONFIG_CPU_FREQ */
|
| 28 | +#ifdef CONFIG_PM_OPP |
| 29 | +#include <linux/pm_opp.h> |
| 30 | +#endif /* CONFIG_PM_OPP */ |
28 | 31 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
29 | 32 | #include <linux/sched/signal.h>
|
30 | 33 | #endif /* KERNEL_VERSION(4, 11, 0) */
|
@@ -2021,6 +2024,62 @@ static void Query_DeviceTree(unsigned int cpu)
|
2021 | 2024 | Core->Boost[BOOST(TGT)] = cur_freq / UNIT_KHz(PRECISION);
|
2022 | 2025 | }
|
2023 | 2026 |
|
| 2027 | +#ifdef CONFIG_PM_OPP |
| 2028 | +static unsigned long GetVoltage_From_OPP(unsigned int cpu, |
| 2029 | + unsigned long freq_hz) |
| 2030 | +{ |
| 2031 | + unsigned long u_volt = 0; |
| 2032 | + struct device *cpu_dev = get_cpu_device(cpu); |
| 2033 | + if (cpu_dev != NULL) { |
| 2034 | + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) |
| 2035 | + struct dev_pm_opp *opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); |
| 2036 | + #else |
| 2037 | + struct opp *opp_find_freq_ceil(cpu_dev, &freq_hz); |
| 2038 | + #endif |
| 2039 | + if (!IS_ERR(opp)) { |
| 2040 | + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) |
| 2041 | + u_volt = dev_pm_opp_get_voltage(opp); |
| 2042 | + dev_pm_opp_put(opp); |
| 2043 | + #else |
| 2044 | + u_volt = opp_get_voltage(opp); |
| 2045 | + #endif |
| 2046 | + } |
| 2047 | + } |
| 2048 | + return u_volt; |
| 2049 | +} |
| 2050 | + |
| 2051 | +static void Query_Voltage_From_OPP(void) |
| 2052 | +{ |
| 2053 | + unsigned int cpu; |
| 2054 | + for (cpu = 0; cpu < PUBLIC(RO(Proc))->CPU.Count; cpu++) { |
| 2055 | + enum RATIO_BOOST boost; |
| 2056 | + for (boost = BOOST(MIN); boost < BOOST(SIZE) - BOOST(18C); boost++) |
| 2057 | + { |
| 2058 | + unsigned long freq_hz = PUBLIC(RO(Proc))->Features.Factory.Clock.Hz |
| 2059 | + * PUBLIC(RO(Core, AT(cpu)))->Boost[BOOST(18C) + boost], |
| 2060 | + |
| 2061 | + u_volt = GetVoltage_From_OPP(cpu, freq_hz); |
| 2062 | + u_volt = u_volt >> 5; |
| 2063 | + |
| 2064 | + PRIVATE(OF(Core, AT(cpu)))->OPP[boost].VID = (signed int) u_volt; |
| 2065 | + } |
| 2066 | + } |
| 2067 | +} |
| 2068 | + |
| 2069 | +inline enum RATIO_BOOST Find_OPP_From_Ratio(CORE_RO *Core, unsigned int ratio) |
| 2070 | +{ |
| 2071 | + enum RATIO_BOOST boost, last = BOOST(MIN); |
| 2072 | + for (boost = BOOST(MIN); boost < BOOST(SIZE) - BOOST(18C); boost++) { |
| 2073 | + if (Core->Boost[BOOST(18C) + boost] <= ratio) { |
| 2074 | + last = boost; |
| 2075 | + continue; |
| 2076 | + } |
| 2077 | + break; |
| 2078 | + } |
| 2079 | + return last; |
| 2080 | +} |
| 2081 | +#endif /* CONFIG_PM_OPP */ |
| 2082 | + |
2024 | 2083 | static void Compute_ACPI_CPPC_Bounds(unsigned int cpu)
|
2025 | 2084 | {
|
2026 | 2085 | CORE_RO *Core = (CORE_RO *) PUBLIC(RO(Core, AT(cpu)));
|
@@ -3307,6 +3366,39 @@ static enum hrtimer_restart Cycle_GenericMachine(struct hrtimer *pTimer)
|
3307 | 3366 | #endif
|
3308 | 3367 | PUBLIC(RO(Core, AT(cpu)))->Boost[BOOST(TGT)] = Core->Ratio.COF.Q;
|
3309 | 3368 |
|
| 3369 | + #ifdef CONFIG_PM_OPP |
| 3370 | + { |
| 3371 | + enum RATIO_BOOST index = Find_OPP_From_Ratio(Core, Core->Ratio.COF.Q); |
| 3372 | + |
| 3373 | + switch (SCOPE_OF_FORMULA(PUBLIC(RO(Proc))->voltageFormula)) { |
| 3374 | + case FORMULA_SCOPE_CORE: |
| 3375 | + if (!((Core->T.ThreadID == 0) || (Core->T.ThreadID == -1))) |
| 3376 | + { |
| 3377 | + break; |
| 3378 | + } |
| 3379 | + fallthrough; |
| 3380 | + case FORMULA_SCOPE_SMT: |
| 3381 | + Core->PowerThermal.VID = \ |
| 3382 | + PRIVATE(OF(Core, AT(Core->Bind)))->OPP[index].VID; |
| 3383 | + break; |
| 3384 | + case FORMULA_SCOPE_PKG: |
| 3385 | + if (Core->Bind == PUBLIC(RO(Proc))->Service.Core) { |
| 3386 | + Core->PowerThermal.VID = \ |
| 3387 | + PRIVATE(OF(Core, AT(Core->Bind)))->OPP[index].VID; |
| 3388 | + } |
| 3389 | + break; |
| 3390 | + case FORMULA_SCOPE_NONE: |
| 3391 | + break; |
| 3392 | + } |
| 3393 | + if (((PUBLIC(RO(Proc))->Features.Hybrid) |
| 3394 | + && (Core->Bind == PUBLIC(RO(Proc))->Service.Hybrid)) |
| 3395 | + || (Core->Bind == PUBLIC(RO(Proc))->Service.Core)) |
| 3396 | + { |
| 3397 | + PUBLIC(RO(Proc))->PowerThermal.VID.CPU = \ |
| 3398 | + PRIVATE(OF(Core, AT(Core->Bind)))->OPP[index].VID; |
| 3399 | + } |
| 3400 | + } |
| 3401 | + #endif /* CONFIG_PM_OPP */ |
3310 | 3402 | BITSET(LOCKLESS, PUBLIC(RW(Core, AT(cpu)))->Sync.V, NTFY);
|
3311 | 3403 |
|
3312 | 3404 | return HRTIMER_RESTART;
|
@@ -5922,6 +6014,10 @@ static int CoreFreqK_Ignition_Level_Up(INIT_ARG *pArg)
|
5922 | 6014 |
|
5923 | 6015 | Controller_Start(0);
|
5924 | 6016 |
|
| 6017 | +#ifdef CONFIG_PM_OPP |
| 6018 | + Query_Voltage_From_OPP(); |
| 6019 | +#endif /* CONFIG_PM_OPP */ |
| 6020 | + |
5925 | 6021 | #ifdef CONFIG_HOTPLUG_CPU
|
5926 | 6022 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
|
5927 | 6023 | /* Always returns zero (kernel/notifier.c) */
|
|
0 commit comments