forked from rubenslte/android_kernel_samsung_msm8226
msm: dcvs: Add 'msm-dcvs' cpufreq governor
The 'msm-dcvs' CPUFreq governor interfaces the msm_dcvs driver frequency change requests with the CPUFreq framework. Change-Id: I950e5b09f568412760d9b022f59f208c6bcb54ce Signed-off-by: Praveen Chidambaram <pchidamb@codeaurora.org>
This commit is contained in:
@@ -1777,6 +1777,7 @@ static struct platform_device *common_devices[] __initdata = {
|
||||
&msm_rtb_device,
|
||||
#endif
|
||||
&apq8064_cpu_idle_device,
|
||||
&apq8064_msm_gov_device,
|
||||
};
|
||||
|
||||
static struct platform_device *sim_devices[] __initdata = {
|
||||
|
||||
@@ -1813,6 +1813,7 @@ static struct platform_device *common_devices[] __initdata = {
|
||||
&msm_rtb_device,
|
||||
#endif
|
||||
&msm8930_cpu_idle_device,
|
||||
&msm8930_msm_gov_device,
|
||||
};
|
||||
|
||||
static struct platform_device *cdp_devices[] __initdata = {
|
||||
|
||||
@@ -2191,6 +2191,7 @@ static struct platform_device *common_devices[] __initdata = {
|
||||
&msm_rtb_device,
|
||||
#endif
|
||||
&msm8960_cpu_idle_device,
|
||||
&msm8960_msm_gov_device,
|
||||
};
|
||||
|
||||
static struct platform_device *sim_devices[] __initdata = {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <mach/rpm.h>
|
||||
#include <mach/mdm2.h>
|
||||
#include <mach/msm_smd.h>
|
||||
#include <mach/msm_dcvs.h>
|
||||
#include <linux/ion.h>
|
||||
#include "clock.h"
|
||||
#include "devices.h"
|
||||
@@ -2149,3 +2150,40 @@ struct platform_device apq8064_cpu_idle_device = {
|
||||
.platform_data = &apq8064_LPM_latency,
|
||||
},
|
||||
};
|
||||
|
||||
static struct msm_dcvs_freq_entry apq8064_freq[] = {
|
||||
{ 384000, 166981, 345600},
|
||||
{ 702000, 213049, 632502},
|
||||
{1026000, 285712, 925613},
|
||||
{1242000, 383945, 1176550},
|
||||
{1458000, 419729, 1465478},
|
||||
{1512000, 434116, 1546674},
|
||||
|
||||
};
|
||||
|
||||
static struct msm_dcvs_core_info apq8064_core_info = {
|
||||
.freq_tbl = &apq8064_freq[0],
|
||||
.core_param = {
|
||||
.max_time_us = 100000,
|
||||
.num_freq = ARRAY_SIZE(apq8064_freq),
|
||||
},
|
||||
.algo_param = {
|
||||
.slack_time_us = 58000,
|
||||
.scale_slack_time = 0,
|
||||
.scale_slack_time_pct = 0,
|
||||
.disable_pc_threshold = 1458000,
|
||||
.em_window_size = 100000,
|
||||
.em_max_util_pct = 97,
|
||||
.ss_window_size = 1000000,
|
||||
.ss_util_pct = 95,
|
||||
.ss_iobusy_conv = 100,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device apq8064_msm_gov_device = {
|
||||
.name = "msm_dcvs_gov",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &apq8064_core_info,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/irqs-8930.h>
|
||||
#include <mach/rpm.h>
|
||||
#include <mach/msm_dcvs.h>
|
||||
|
||||
#include "devices.h"
|
||||
#include "rpm_log.h"
|
||||
@@ -284,3 +285,40 @@ struct platform_device msm8930_cpu_idle_device = {
|
||||
.platform_data = &msm8930_LPM_latency,
|
||||
},
|
||||
};
|
||||
|
||||
static struct msm_dcvs_freq_entry msm8930_freq[] = {
|
||||
{ 384000, 166981, 345600},
|
||||
{ 702000, 213049, 632502},
|
||||
{1026000, 285712, 925613},
|
||||
{1242000, 383945, 1176550},
|
||||
{1458000, 419729, 1465478},
|
||||
{1512000, 434116, 1546674},
|
||||
|
||||
};
|
||||
|
||||
static struct msm_dcvs_core_info msm8930_core_info = {
|
||||
.freq_tbl = &msm8930_freq[0],
|
||||
.core_param = {
|
||||
.max_time_us = 100000,
|
||||
.num_freq = ARRAY_SIZE(msm8930_freq),
|
||||
},
|
||||
.algo_param = {
|
||||
.slack_time_us = 58000,
|
||||
.scale_slack_time = 0,
|
||||
.scale_slack_time_pct = 0,
|
||||
.disable_pc_threshold = 1458000,
|
||||
.em_window_size = 100000,
|
||||
.em_max_util_pct = 97,
|
||||
.ss_window_size = 1000000,
|
||||
.ss_util_pct = 95,
|
||||
.ss_iobusy_conv = 100,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm8930_msm_gov_device = {
|
||||
.name = "msm_dcvs_gov",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &msm8930_core_info,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "rpm_stats.h"
|
||||
#include "pil-q6v4.h"
|
||||
#include "scm-pas.h"
|
||||
#include <mach/msm_dcvs.h>
|
||||
|
||||
#ifdef CONFIG_MSM_MPM
|
||||
#include "mpm.h"
|
||||
@@ -3229,3 +3230,40 @@ struct platform_device msm8960_cpu_idle_device = {
|
||||
.platform_data = &msm8960_LPM_latency,
|
||||
},
|
||||
};
|
||||
|
||||
static struct msm_dcvs_freq_entry msm8960_freq[] = {
|
||||
{ 384000, 166981, 345600},
|
||||
{ 702000, 213049, 632502},
|
||||
{1026000, 285712, 925613},
|
||||
{1242000, 383945, 1176550},
|
||||
{1458000, 419729, 1465478},
|
||||
{1512000, 434116, 1546674},
|
||||
|
||||
};
|
||||
|
||||
static struct msm_dcvs_core_info msm8960_core_info = {
|
||||
.freq_tbl = &msm8960_freq[0],
|
||||
.core_param = {
|
||||
.max_time_us = 100000,
|
||||
.num_freq = ARRAY_SIZE(msm8960_freq),
|
||||
},
|
||||
.algo_param = {
|
||||
.slack_time_us = 58000,
|
||||
.scale_slack_time = 0,
|
||||
.scale_slack_time_pct = 0,
|
||||
.disable_pc_threshold = 1458000,
|
||||
.em_window_size = 100000,
|
||||
.em_max_util_pct = 97,
|
||||
.ss_window_size = 1000000,
|
||||
.ss_util_pct = 95,
|
||||
.ss_iobusy_conv = 100,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm8960_msm_gov_device = {
|
||||
.name = "msm_dcvs_gov",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &msm8960_core_info,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -334,3 +334,7 @@ extern int msm_copper_stub_regulator_devices_len;
|
||||
extern struct platform_device msm8960_cpu_idle_device;
|
||||
extern struct platform_device msm8930_cpu_idle_device;
|
||||
extern struct platform_device apq8064_cpu_idle_device;
|
||||
|
||||
extern struct platform_device msm8960_msm_gov_device;
|
||||
extern struct platform_device msm8930_msm_gov_device;
|
||||
extern struct platform_device apq8064_msm_gov_device;
|
||||
|
||||
@@ -42,3 +42,4 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
|
||||
|
||||
# ARM SoC drivers
|
||||
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
|
||||
obj-$(CONFIG_MSM_DCVS) += cpufreq_gov_msm.o
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/msm_dcvs.h>
|
||||
|
||||
struct msm_gov {
|
||||
int cpu;
|
||||
unsigned int cur_freq;
|
||||
unsigned int min_freq;
|
||||
unsigned int max_freq;
|
||||
struct msm_dcvs_freq gov_notifier;
|
||||
struct cpufreq_policy *policy;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU_SHARED_ALIGNED(struct mutex, gov_mutex);
|
||||
static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_gov, msm_gov_info);
|
||||
static char core_name[NR_CPUS][10];
|
||||
|
||||
static void msm_gov_check_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
|
||||
|
||||
if (policy->max < gov->cur_freq)
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
CPUFREQ_RELATION_H);
|
||||
else if (policy->min > gov->min_freq)
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_L);
|
||||
else
|
||||
__cpufreq_driver_target(policy, gov->cur_freq,
|
||||
CPUFREQ_RELATION_L);
|
||||
|
||||
gov->cur_freq = policy->cur;
|
||||
gov->min_freq = policy->min;
|
||||
gov->max_freq = policy->max;
|
||||
}
|
||||
|
||||
static int msm_dcvs_freq_set(struct msm_dcvs_freq *self,
|
||||
unsigned int freq)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct msm_gov *gov =
|
||||
container_of(self, struct msm_gov, gov_notifier);
|
||||
|
||||
mutex_lock(&per_cpu(gov_mutex, gov->cpu));
|
||||
|
||||
if (freq < gov->min_freq)
|
||||
freq = gov->min_freq;
|
||||
if (freq > gov->max_freq)
|
||||
freq = gov->max_freq;
|
||||
|
||||
ret = __cpufreq_driver_target(gov->policy, freq, CPUFREQ_RELATION_L);
|
||||
gov->cur_freq = gov->policy->cur;
|
||||
|
||||
mutex_unlock(&per_cpu(gov_mutex, gov->cpu));
|
||||
|
||||
if (!ret)
|
||||
return gov->cur_freq;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int msm_dcvs_freq_get(struct msm_dcvs_freq *self)
|
||||
{
|
||||
struct msm_gov *gov =
|
||||
container_of(self, struct msm_gov, gov_notifier);
|
||||
|
||||
return gov->cur_freq;
|
||||
}
|
||||
|
||||
static int cpufreq_governor_msm(struct cpufreq_policy *policy,
|
||||
unsigned int event)
|
||||
{
|
||||
unsigned int cpu = policy->cpu;
|
||||
int ret = 0;
|
||||
int handle = 0;
|
||||
struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
|
||||
struct msm_dcvs_freq *dcvs_notifier =
|
||||
&(per_cpu(msm_gov_info, cpu).gov_notifier);
|
||||
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_START:
|
||||
if (!cpu_online(cpu))
|
||||
return -EINVAL;
|
||||
BUG_ON(!policy->cur);
|
||||
mutex_lock(&per_cpu(gov_mutex, cpu));
|
||||
per_cpu(msm_gov_info, cpu).cpu = cpu;
|
||||
gov->policy = policy;
|
||||
dcvs_notifier->core_name = core_name[cpu];
|
||||
dcvs_notifier->set_frequency = msm_dcvs_freq_set;
|
||||
dcvs_notifier->get_frequency = msm_dcvs_freq_get;
|
||||
handle = msm_dcvs_freq_sink_register(dcvs_notifier);
|
||||
BUG_ON(handle < 0);
|
||||
msm_gov_check_limits(policy);
|
||||
mutex_unlock(&per_cpu(gov_mutex, cpu));
|
||||
break;
|
||||
|
||||
case CPUFREQ_GOV_STOP:
|
||||
mutex_lock(&per_cpu(gov_mutex, cpu));
|
||||
msm_dcvs_freq_sink_unregister(dcvs_notifier);
|
||||
mutex_unlock(&per_cpu(gov_mutex, cpu));
|
||||
break;
|
||||
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
mutex_lock(&per_cpu(gov_mutex, cpu));
|
||||
msm_gov_check_limits(policy);
|
||||
mutex_unlock(&per_cpu(gov_mutex, cpu));
|
||||
break;
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct cpufreq_governor cpufreq_gov_msm = {
|
||||
.name = "msm-dcvs",
|
||||
.governor = cpufreq_governor_msm,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __devinit msm_gov_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
int cpu;
|
||||
uint32_t group_id = 0x43505530; /* CPU0 */
|
||||
struct msm_dcvs_core_info *core = NULL;
|
||||
|
||||
core = pdev->dev.platform_data;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
mutex_init(&per_cpu(gov_mutex, cpu));
|
||||
snprintf(core_name[cpu], 10, "cpu%d", cpu);
|
||||
ret = msm_dcvs_register_core(core_name[cpu], group_id, core);
|
||||
if (ret)
|
||||
pr_err("Unable to register core for %d\n", cpu);
|
||||
}
|
||||
|
||||
return cpufreq_register_governor(&cpufreq_gov_msm);
|
||||
}
|
||||
|
||||
static int __devexit msm_gov_remove(struct platform_device *pdev)
|
||||
{
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver msm_gov_driver = {
|
||||
.probe = msm_gov_probe,
|
||||
.remove = __devexit_p(msm_gov_remove),
|
||||
.driver = {
|
||||
.name = "msm_dcvs_gov",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init cpufreq_gov_msm_init(void)
|
||||
{
|
||||
return platform_driver_register(&msm_gov_driver);
|
||||
}
|
||||
late_initcall(cpufreq_gov_msm_init);
|
||||
Reference in New Issue
Block a user