if (event != PSY_EVENT_PROP_CHANGED)
return NOTIFY_OK;
+ /* dynamic actions are only applied while platform profile is in balanced */
+ if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
+ return 0;
+
epp = amd_pstate_get_balanced_epp(policy);
ret = amd_pstate_set_epp(policy, epp);
return NOTIFY_OK;
}
+
+static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
+static int amd_pstate_profile_get(struct device *dev,
+ enum platform_profile_option *profile)
+{
+ struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+
+ *profile = cpudata->current_profile;
+
+ return 0;
+}
+
+static int amd_pstate_profile_set(struct device *dev,
+ enum platform_profile_option profile)
+{
+ struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+ int ret;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_LOW_POWER:
+ ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
+ if (ret)
+ return ret;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ ret = amd_pstate_set_epp(policy,
+ amd_pstate_get_balanced_epp(policy));
+ if (ret)
+ return ret;
+ break;
+ case PLATFORM_PROFILE_PERFORMANCE:
+ ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE);
+ if (ret)
+ return ret;
+ break;
+ default:
+ pr_err("Unknown Platform Profile %d\n", profile);
+ return -EOPNOTSUPP;
+ }
+
+ cpudata->current_profile = profile;
+
+ return 0;
+}
+
+static const struct platform_profile_ops amd_pstate_profile_ops = {
+ .probe = amd_pstate_profile_probe,
+ .profile_set = amd_pstate_profile_set,
+ .profile_get = amd_pstate_profile_get,
+};
+
static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
{
struct amd_cpudata *cpudata = policy->driver_data;
if (cpudata->power_nb.notifier_call)
power_supply_unreg_notifier(&cpudata->power_nb);
+ if (cpudata->ppdev) {
+ platform_profile_remove(cpudata->ppdev);
+ cpudata->ppdev = NULL;
+ }
+ kfree(cpudata->profile_name);
cpudata->dynamic_epp = false;
}
int ret;
u8 epp;
- epp = amd_pstate_get_balanced_epp(policy);
+ switch (cpudata->current_profile) {
+ case PLATFORM_PROFILE_PERFORMANCE:
+ epp = AMD_CPPC_EPP_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_LOW_POWER:
+ epp = AMD_CPPC_EPP_POWERSAVE;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ epp = amd_pstate_get_balanced_epp(policy);
+ break;
+ default:
+ pr_err("Unknown Platform Profile %d\n", cpudata->current_profile);
+ return -EOPNOTSUPP;
+ }
ret = amd_pstate_set_epp(policy, epp);
if (ret)
return ret;
+ cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
+
+ cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
+ cpudata->profile_name,
+ policy->driver_data,
+ &amd_pstate_profile_ops);
+ if (IS_ERR(cpudata->ppdev)) {
+ ret = PTR_ERR(cpudata->ppdev);
+ goto cleanup;
+ }
+
/* only enable notifier if things will actually change */
if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
return offset;
}
-static ssize_t store_energy_performance_preference(
- struct cpufreq_policy *policy, const char *buf, size_t count)
+static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
{
struct amd_cpudata *cpudata = policy->driver_data;
ssize_t ret;
else
epp = amd_pstate_get_balanced_epp(policy);
- if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+ if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
pr_debug("EPP cannot be set under performance policy\n");
return -EBUSY;
}
return ret ? ret : count;
}
-static ssize_t show_energy_performance_preference(
- struct cpufreq_policy *policy, char *buf)
+static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
{
struct amd_cpudata *cpudata = policy->driver_data;
u8 preference, epp;
amd_pstate_acpi_pm_profile_undefined()) {
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
+ cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
} else {
policy->policy = CPUFREQ_POLICY_POWERSAVE;
cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
+ cpudata->current_profile = PLATFORM_PROFILE_BALANCED;
}
if (dynamic_epp)