mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: dcvs: remove core name.
Currently core_name is used to identify which core the dcvs operates on. Instead use a type and the type num while registration with dcvs and return an id (dcvs_core_id) upon successfull registration. The dcvs_core_id is used by the clients of msm_dcvs to call upon its apis viz. freq_start, freq_stop, msm_dcvs_idle etc. The dcvs inturn uses the type num passed in at registration time to invoke apis on the clients viz. set_freq, get_freq, idle_enable. This further cleans up the internal dcvs add_core and get_core implementation. One need not pass around the core_name and use the type instead. Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org> (cherry picked from commit 1bbc0321a6871e018c17da6f244b9df442faead6) Signed-off-by: Ram Kumar Chakravarthy Chebathini <rcheba@codeaurora.org> (cherry picked from commit 09456d7d7618e6d0fc6b907b7af75268ea08a942) Change-Id: Id27751a8ec8f5d3d386bbe7c7625ed56757b8bd7 Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
This commit is contained in:
parent
e9fe87f613
commit
404a619d85
4 changed files with 217 additions and 346 deletions
|
@ -19,6 +19,10 @@
|
|||
#define CORES_MAX (10)
|
||||
|
||||
#define CPU_OFFSET 1 /* used to notify TZ the core number */
|
||||
#define GPU_OFFSET (CORES_MAX * 2/3) /* there will be more cpus than gpus,
|
||||
* let the GPU be assigned fewer core
|
||||
* elements and start later
|
||||
*/
|
||||
|
||||
enum msm_core_idle_state {
|
||||
MSM_DCVS_IDLE_ENTER,
|
||||
|
@ -32,56 +36,14 @@ enum msm_core_control_event {
|
|||
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_dcvs_idle
|
||||
*
|
||||
* API for idle code to register and send idle enter/exit
|
||||
* notifications to msm_dcvs driver.
|
||||
*/
|
||||
struct msm_dcvs_idle {
|
||||
const char *core_name;
|
||||
};
|
||||
|
||||
struct msm_gov_platform_data {
|
||||
struct msm_dcvs_core_info *info;
|
||||
int latency;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_dcvs_freq
|
||||
*
|
||||
* API for clock driver code to register and receive frequency change
|
||||
* request for the core from the msm_dcvs driver.
|
||||
*/
|
||||
struct msm_dcvs_freq {
|
||||
const char *core_name;
|
||||
/* Callback from msm_dcvs to set the core frequency */
|
||||
};
|
||||
|
||||
/**
|
||||
* msm_dcvs_idle_source_register
|
||||
* @drv: Pointer to the source driver
|
||||
* @return: Handle to be used for sending idle state notifications.
|
||||
*
|
||||
* Register the idle driver with the msm_dcvs driver to send idle
|
||||
* state notifications for the core.
|
||||
*/
|
||||
extern int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv);
|
||||
|
||||
/**
|
||||
* msm_dcvs_idle_source_unregister
|
||||
* @drv: Pointer to the source driver
|
||||
* @return:
|
||||
* 0 on success
|
||||
* -EINVAL
|
||||
*
|
||||
* Description: Unregister the idle driver with the msm_dcvs driver
|
||||
*/
|
||||
extern int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv);
|
||||
|
||||
/**
|
||||
* msm_dcvs_idle
|
||||
* @handle: Handle provided back at registration
|
||||
* @dcvs_core_id: The id returned by msm_dcvs_register_core
|
||||
* @state: The enter/exit idle state the core is in
|
||||
* @iowaited: iowait in us
|
||||
* on iMSM_DCVS_IDLE_EXIT.
|
||||
|
@ -93,7 +55,7 @@ extern int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv);
|
|||
*
|
||||
* Send idle state notifications to the msm_dcvs driver
|
||||
*/
|
||||
int msm_dcvs_idle(int handle, enum msm_core_idle_state state,
|
||||
int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state,
|
||||
uint32_t iowaited);
|
||||
|
||||
/**
|
||||
|
@ -114,7 +76,8 @@ struct msm_dcvs_core_info {
|
|||
|
||||
/**
|
||||
* msm_dcvs_register_core
|
||||
* @core_name: Unique name identifier for the core.
|
||||
* @type: whether this is a CPU or a GPU
|
||||
* @type_core_num: The number of the core for a type
|
||||
* @info: The core specific algorithm parameters.
|
||||
* @sensor: The thermal sensor number of the core in question
|
||||
* @return :
|
||||
|
@ -127,11 +90,12 @@ struct msm_dcvs_core_info {
|
|||
* Cores that need to run synchronously must share the same group id.
|
||||
*/
|
||||
extern int msm_dcvs_register_core(
|
||||
const char *core_name,
|
||||
enum msm_dcvs_core_type type,
|
||||
int type_core_num,
|
||||
struct msm_dcvs_core_info *info,
|
||||
int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq),
|
||||
unsigned int (*get_frequency)(struct msm_dcvs_freq *self),
|
||||
int (*idle_enable)(struct msm_dcvs_idle *self,
|
||||
int (*set_frequency)(int type_core_num, unsigned int freq),
|
||||
unsigned int (*get_frequency)(int type_core_num),
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event),
|
||||
int sensor);
|
||||
|
||||
|
@ -143,7 +107,7 @@ extern int msm_dcvs_register_core(
|
|||
* Register the clock driver code with the msm_dvs driver to get notified about
|
||||
* frequency change requests.
|
||||
*/
|
||||
extern int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv);
|
||||
extern int msm_dcvs_freq_sink_start(int dcvs_core_id);
|
||||
|
||||
/**
|
||||
* msm_dcvs_freq_sink_stop
|
||||
|
@ -155,7 +119,7 @@ extern int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv);
|
|||
* Unregister the sink driver for the core. This will cause the source driver
|
||||
* for the core to stop sending idle pulses.
|
||||
*/
|
||||
extern int msm_dcvs_freq_sink_stop(struct msm_dcvs_freq *drv);
|
||||
extern int msm_dcvs_freq_sink_stop(int dcvs_core_id);
|
||||
|
||||
/**
|
||||
* msm_dcvs_update_limits
|
||||
|
@ -163,5 +127,5 @@ extern int msm_dcvs_freq_sink_stop(struct msm_dcvs_freq *drv);
|
|||
*
|
||||
* Update the frequency known to dcvs when the limits are changed.
|
||||
*/
|
||||
extern void msm_dcvs_update_limits(struct msm_dcvs_freq *drv);
|
||||
extern void msm_dcvs_update_limits(int dcvs_core_id);
|
||||
#endif
|
||||
|
|
|
@ -73,6 +73,9 @@ struct core_attribs {
|
|||
};
|
||||
|
||||
struct dcvs_core {
|
||||
enum msm_dcvs_core_type type;
|
||||
/* this is the number in each type for example cpu 0,1,2 and gpu 0,1 */
|
||||
int type_core_num;
|
||||
char core_name[CORE_NAME_MAX];
|
||||
uint32_t actual_freq;
|
||||
uint32_t freq_change_us;
|
||||
|
@ -81,8 +84,6 @@ struct dcvs_core {
|
|||
|
||||
struct msm_dcvs_algo_param algo_param;
|
||||
struct msm_dcvs_energy_curve_coeffs coeffs;
|
||||
struct msm_dcvs_idle *idle_driver;
|
||||
struct msm_dcvs_freq *freq_driver;
|
||||
|
||||
/* private */
|
||||
int64_t time_start;
|
||||
|
@ -90,16 +91,17 @@ struct dcvs_core {
|
|||
spinlock_t cpu_lock;
|
||||
struct task_struct *task;
|
||||
struct core_attribs attrib;
|
||||
uint32_t handle;
|
||||
uint32_t dcvs_core_id;
|
||||
struct hrtimer timer;
|
||||
int32_t timer_disabled;
|
||||
struct msm_dcvs_core_info *info;
|
||||
int sensor;
|
||||
int pending_freq;
|
||||
wait_queue_head_t wait_q;
|
||||
int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq);
|
||||
unsigned int (*get_frequency)(struct msm_dcvs_freq *self);
|
||||
int (*idle_enable)(struct msm_dcvs_idle *self,
|
||||
|
||||
int (*set_frequency)(int type_core_num, unsigned int freq);
|
||||
unsigned int (*get_frequency)(int type_core_num);
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event);
|
||||
};
|
||||
|
||||
|
@ -110,10 +112,8 @@ module_param_named(enable, msm_dcvs_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP);
|
|||
static struct dentry *debugfs_base;
|
||||
|
||||
static struct dcvs_core core_list[CORES_MAX];
|
||||
static DEFINE_MUTEX(core_list_lock);
|
||||
|
||||
static struct kobject *cores_kobj;
|
||||
static struct dcvs_core *core_handles[CORES_MAX];
|
||||
|
||||
/* Change core frequency, called with core mutex locked */
|
||||
static int __msm_dcvs_change_freq(struct dcvs_core *core)
|
||||
|
@ -127,7 +127,7 @@ static int __msm_dcvs_change_freq(struct dcvs_core *core)
|
|||
uint32_t slack_us = 0;
|
||||
uint32_t ret1 = 0;
|
||||
|
||||
if (!core->freq_driver || !core->set_frequency) {
|
||||
if (!core->set_frequency) {
|
||||
/* Core may have unregistered or hotplugged */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ repeat:
|
|||
* We will need to get back the actual frequency in KHz and
|
||||
* the record the time taken to change it.
|
||||
*/
|
||||
ret = core->set_frequency(core->freq_driver, requested_freq);
|
||||
ret = core->set_frequency(core->type_core_num, requested_freq);
|
||||
if (ret <= 0) {
|
||||
__err("Core %s failed to set freq %u\n",
|
||||
core->core_name, requested_freq);
|
||||
|
@ -177,15 +177,14 @@ repeat:
|
|||
* Disable low power modes if the actual frequency is >
|
||||
* disable_pc_threshold.
|
||||
*/
|
||||
if (core->actual_freq >
|
||||
core->algo_param.disable_pc_threshold) {
|
||||
core->idle_enable(core->idle_driver,
|
||||
if (core->actual_freq > core->algo_param.disable_pc_threshold) {
|
||||
core->idle_enable(core->type_core_num,
|
||||
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES);
|
||||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Disabling LPM for %s\n", core->core_name);
|
||||
} else if (core->actual_freq <=
|
||||
core->algo_param.disable_pc_threshold) {
|
||||
core->idle_enable(core->idle_driver,
|
||||
core->idle_enable(core->type_core_num,
|
||||
MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
|
||||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Enabling LPM for %s\n", core->core_name);
|
||||
|
@ -196,8 +195,10 @@ repeat:
|
|||
* to this frequency and that will get us the new slack
|
||||
* timer
|
||||
*/
|
||||
ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
|
||||
core->actual_freq, (uint32_t)time_end, &slack_us, &ret1);
|
||||
ret = msm_dcvs_scm_event(core->dcvs_core_id,
|
||||
MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
|
||||
core->actual_freq, (uint32_t)time_end,
|
||||
&slack_us, &ret1);
|
||||
if (!ret) {
|
||||
/* Reset the slack timer */
|
||||
if (slack_us) {
|
||||
|
@ -253,7 +254,8 @@ static int __msm_dcvs_report_temp(struct dcvs_core *core)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
|
||||
ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id,
|
||||
&info->power_param,
|
||||
&info->freq_tbl[0], &core->coeffs);
|
||||
return ret;
|
||||
}
|
||||
|
@ -291,7 +293,7 @@ static int msm_dcvs_update_freq(struct dcvs_core *core,
|
|||
uint32_t new_freq = 0;
|
||||
|
||||
spin_lock_irqsave(&core->cpu_lock, flags);
|
||||
ret = msm_dcvs_scm_event(core->handle, event, param0,
|
||||
ret = msm_dcvs_scm_event(core->dcvs_core_id, event, param0,
|
||||
core->actual_freq, &new_freq, ret1);
|
||||
if (ret) {
|
||||
if (ret == -13)
|
||||
|
@ -374,7 +376,7 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \
|
|||
} else { \
|
||||
uint32_t old_val = core->algo_param._name; \
|
||||
core->algo_param._name = val; \
|
||||
ret = msm_dcvs_scm_set_algo_params(core->handle, \
|
||||
ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id, \
|
||||
&core->algo_param); \
|
||||
if (ret) { \
|
||||
core->algo_param._name = old_val; \
|
||||
|
@ -406,7 +408,7 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \
|
|||
} else { \
|
||||
int32_t old_val = core->coeffs._name; \
|
||||
core->coeffs._name = val; \
|
||||
ret = msm_dcvs_scm_set_power_params(core->handle, \
|
||||
ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, \
|
||||
&core->info->power_param, &core->info->freq_tbl[0], \
|
||||
&core->coeffs); \
|
||||
if (ret) { \
|
||||
|
@ -437,9 +439,9 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \
|
|||
* Function declarations for different attributes.
|
||||
* Gets used when setting the attribute show and store parameters.
|
||||
*/
|
||||
DCVS_PARAM_SHOW(core_id, core->handle)
|
||||
DCVS_PARAM_SHOW(idle_enabled, (core->idle_driver != NULL))
|
||||
DCVS_PARAM_SHOW(freq_change_enabled, (core->freq_driver != NULL))
|
||||
DCVS_PARAM_SHOW(core_id, core->dcvs_core_id)
|
||||
DCVS_PARAM_SHOW(idle_enabled, (core->idle_enable != NULL))
|
||||
DCVS_PARAM_SHOW(freq_change_enabled, (core->set_frequency != NULL))
|
||||
DCVS_PARAM_SHOW(actual_freq, (core->actual_freq))
|
||||
DCVS_PARAM_SHOW(freq_change_us, (core->freq_change_us))
|
||||
|
||||
|
@ -535,107 +537,71 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Return the core if found or add to list if @add_to_list is true */
|
||||
static struct dcvs_core *msm_dcvs_add_core(const char *name, int *pos)
|
||||
/* Return the core and initialize non platform data specific numbers in it */
|
||||
static struct dcvs_core *msm_dcvs_add_core(enum msm_dcvs_core_type type,
|
||||
int num)
|
||||
{
|
||||
struct dcvs_core *core = NULL;
|
||||
int i;
|
||||
int empty = -1;
|
||||
char name[CORE_NAME_MAX];
|
||||
|
||||
if (!name[0] ||
|
||||
(strnlen(name, CORE_NAME_MAX - 1) == CORE_NAME_MAX - 1))
|
||||
return core;
|
||||
switch (type) {
|
||||
case MSM_DCVS_CORE_TYPE_CPU:
|
||||
i = CPU_OFFSET + num;
|
||||
BUG_ON(i >= GPU_OFFSET);
|
||||
snprintf(name, CORE_NAME_MAX, "cpu%d", num);
|
||||
break;
|
||||
case MSM_DCVS_CORE_TYPE_GPU:
|
||||
i = GPU_OFFSET + num;
|
||||
BUG_ON(i >= CORES_MAX);
|
||||
snprintf(name, CORE_NAME_MAX, "gpu%d", num);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mutex_lock(&core_list_lock);
|
||||
for (i = 0; i < CORES_MAX; i++) {
|
||||
core = &core_list[i];
|
||||
if ((empty < 0) && !core->core_name[0]) {
|
||||
empty = i;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(name, core->core_name, CORE_NAME_MAX)) {
|
||||
if (pos != NULL)
|
||||
*pos = i;
|
||||
/*
|
||||
* found a core with the same name, return NULL and
|
||||
* set pos
|
||||
*/
|
||||
core = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for core_list full */
|
||||
if (empty < 0) {
|
||||
*pos = 0;
|
||||
core = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
core = &core_list[empty];
|
||||
core->dcvs_core_id = i;
|
||||
strlcpy(core->core_name, name, CORE_NAME_MAX);
|
||||
mutex_init(&core->lock);
|
||||
spin_lock_init(&core->cpu_lock);
|
||||
core->handle = empty + CORE_HANDLE_OFFSET;
|
||||
hrtimer_init(&core->timer,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
|
||||
hrtimer_init(&core->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
|
||||
core->timer.function = msm_dcvs_core_slack_timer;
|
||||
if (pos != NULL)
|
||||
*pos = empty;
|
||||
|
||||
out:
|
||||
mutex_unlock(&core_list_lock);
|
||||
return core;
|
||||
}
|
||||
|
||||
/* Return the core if found or add to list if @add_to_list is true */
|
||||
static struct dcvs_core *msm_dcvs_get_core(const char *name, int *pos)
|
||||
static struct dcvs_core *msm_dcvs_get_core(int offset)
|
||||
{
|
||||
struct dcvs_core *core = NULL;
|
||||
int i;
|
||||
|
||||
if (!name[0] ||
|
||||
(strnlen(name, CORE_NAME_MAX - 1) == CORE_NAME_MAX - 1))
|
||||
return core;
|
||||
|
||||
mutex_lock(&core_list_lock);
|
||||
for (i = 0; i < CORES_MAX; i++) {
|
||||
core = &core_list[i];
|
||||
if (!strncmp(name, core->core_name, CORE_NAME_MAX)) {
|
||||
if (pos != NULL)
|
||||
*pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&core_list_lock);
|
||||
|
||||
return core;
|
||||
/* if the handle is still not set bug */
|
||||
BUG_ON(core_list[offset].dcvs_core_id == -1);
|
||||
return &core_list[offset];
|
||||
}
|
||||
|
||||
int msm_dcvs_register_core(const char *core_name,
|
||||
|
||||
int msm_dcvs_register_core(
|
||||
enum msm_dcvs_core_type type,
|
||||
int type_core_num,
|
||||
struct msm_dcvs_core_info *info,
|
||||
int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq),
|
||||
unsigned int (*get_frequency)(struct msm_dcvs_freq *self),
|
||||
int (*idle_enable)(struct msm_dcvs_idle *self,
|
||||
int (*set_frequency)(int type_core_num, unsigned int freq),
|
||||
unsigned int (*get_frequency)(int type_core_num),
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event),
|
||||
int sensor)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int pos = 0;
|
||||
struct dcvs_core *core = NULL;
|
||||
uint32_t ret1;
|
||||
uint32_t ret2;
|
||||
|
||||
if (!core_name || !core_name[0])
|
||||
return ret;
|
||||
|
||||
core = msm_dcvs_add_core(core_name, &pos);
|
||||
core = msm_dcvs_add_core(type, type_core_num);
|
||||
if (!core)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
|
||||
core->type = type;
|
||||
core->type_core_num = type_core_num;
|
||||
core->set_frequency = set_frequency;
|
||||
core->get_frequency = get_frequency;
|
||||
core->idle_enable = idle_enable;
|
||||
|
@ -647,24 +613,39 @@ int msm_dcvs_register_core(const char *core_name,
|
|||
memcpy(&core->coeffs, &info->energy_coeffs,
|
||||
sizeof(struct msm_dcvs_energy_curve_coeffs));
|
||||
|
||||
info->core_param.core_bitmask_id = 1 << pos;
|
||||
pr_debug("registering core with sensor %d\n", sensor);
|
||||
/*
|
||||
* The tz expects cpu0 to represent bit 0 in the mask, however the
|
||||
* dcvs_core_id needs to start from 1, dcvs_core_id = 0 is used to
|
||||
* indicate that this request is not associated with any core.
|
||||
* mpdecision
|
||||
*/
|
||||
info->core_param.core_bitmask_id
|
||||
= 1 << (core->dcvs_core_id - CPU_OFFSET);
|
||||
core->sensor = sensor;
|
||||
|
||||
ret = msm_dcvs_scm_register_core(core->handle, &info->core_param);
|
||||
if (ret)
|
||||
ret = msm_dcvs_scm_register_core(core->dcvs_core_id, &info->core_param);
|
||||
if (ret) {
|
||||
__err("%s: scm register core fail handle = %d ret = %d\n",
|
||||
__func__, core->dcvs_core_id, ret);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ret = msm_dcvs_scm_set_algo_params(core->handle, &info->algo_param);
|
||||
if (ret)
|
||||
ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id,
|
||||
&info->algo_param);
|
||||
if (ret) {
|
||||
__err("%s: scm algo params failed ret = %d\n", __func__, ret);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
|
||||
ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id,
|
||||
&info->power_param,
|
||||
&info->freq_tbl[0], &core->coeffs);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
__err("%s: scm power params failed ret = %d\n", __func__, ret);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CORE_ONLINE,
|
||||
ret = msm_dcvs_scm_event(core->dcvs_core_id, MSM_DCVS_SCM_CORE_ONLINE,
|
||||
core->actual_freq, 0, &ret1, &ret2);
|
||||
if (ret)
|
||||
goto bail;
|
||||
|
@ -672,48 +653,53 @@ int msm_dcvs_register_core(const char *core_name,
|
|||
ret = msm_dcvs_setup_core_sysfs(core);
|
||||
if (ret) {
|
||||
__err("Unable to setup core %s sysfs\n", core->core_name);
|
||||
core_handles[core->handle - CORE_HANDLE_OFFSET] = NULL;
|
||||
goto bail;
|
||||
}
|
||||
init_waitqueue_head(&core->wait_q);
|
||||
core->task = kthread_run(msm_dcvs_do_freq, (void *)core,
|
||||
"msm_dcvs/%d", core->handle);
|
||||
bail:
|
||||
"msm_dcvs/%d", core->dcvs_core_id);
|
||||
ret = core->dcvs_core_id;
|
||||
mutex_unlock(&core->lock);
|
||||
return ret;
|
||||
bail:
|
||||
mutex_unlock(&core->lock);
|
||||
core->dcvs_core_id = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_dcvs_register_core);
|
||||
|
||||
void msm_dcvs_update_limits(struct msm_dcvs_freq *drv)
|
||||
void msm_dcvs_update_limits(int dcvs_core_id)
|
||||
{
|
||||
struct dcvs_core *core;
|
||||
|
||||
if (!drv || !drv->core_name)
|
||||
if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
|
||||
__err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
|
||||
__func__, dcvs_core_id);
|
||||
return;
|
||||
}
|
||||
|
||||
core = msm_dcvs_get_core(drv->core_name, NULL);
|
||||
core->actual_freq = core->get_frequency(drv);
|
||||
core = msm_dcvs_get_core(dcvs_core_id);
|
||||
core->actual_freq = core->get_frequency(core->type_core_num);
|
||||
}
|
||||
|
||||
int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv)
|
||||
int msm_dcvs_freq_sink_start(int dcvs_core_id)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dcvs_core *core = NULL;
|
||||
uint32_t ret1;
|
||||
uint32_t ret2;
|
||||
|
||||
if (!drv || !drv->core_name)
|
||||
return ret;
|
||||
if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
|
||||
__err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
|
||||
__func__, dcvs_core_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = msm_dcvs_get_core(drv->core_name, NULL);
|
||||
core = msm_dcvs_get_core(dcvs_core_id);
|
||||
if (!core)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
if (core->freq_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER))
|
||||
__info("Frequency notifier for %s being replaced\n",
|
||||
core->core_name);
|
||||
core->freq_driver = drv;
|
||||
if (IS_ERR(core->task)) {
|
||||
mutex_unlock(&core->lock);
|
||||
return -EFAULT;
|
||||
|
@ -722,101 +708,56 @@ int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv)
|
|||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Enabling idle pulse for %s\n", core->core_name);
|
||||
|
||||
if (core->idle_driver) {
|
||||
core->actual_freq = core->get_frequency(drv);
|
||||
core->actual_freq = core->get_frequency(core->type_core_num);
|
||||
/* Notify TZ to start receiving idle info for the core */
|
||||
ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
|
||||
&ret1, &ret2);
|
||||
core->idle_enable(core->idle_driver,
|
||||
MSM_DCVS_ENABLE_IDLE_PULSE);
|
||||
}
|
||||
core->idle_enable(core->type_core_num, MSM_DCVS_ENABLE_IDLE_PULSE);
|
||||
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
return core->handle;
|
||||
return core->dcvs_core_id;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_dcvs_freq_sink_start);
|
||||
|
||||
int msm_dcvs_freq_sink_stop(struct msm_dcvs_freq *drv)
|
||||
int msm_dcvs_freq_sink_stop(int dcvs_core_id)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dcvs_core *core = NULL;
|
||||
uint32_t ret1;
|
||||
uint32_t ret2;
|
||||
|
||||
if (!drv || !drv->core_name)
|
||||
return ret;
|
||||
if (dcvs_core_id < 0 || dcvs_core_id > CORES_MAX) {
|
||||
pr_err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
|
||||
__func__, dcvs_core_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = msm_dcvs_get_core(drv->core_name, NULL);
|
||||
core = msm_dcvs_get_core(dcvs_core_id);
|
||||
if (!core)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Disabling idle pulse for %s\n", core->core_name);
|
||||
if (core->idle_driver) {
|
||||
core->idle_enable(core->idle_driver,
|
||||
MSM_DCVS_DISABLE_IDLE_PULSE);
|
||||
|
||||
core->idle_enable(core->type_core_num, MSM_DCVS_DISABLE_IDLE_PULSE);
|
||||
/* Notify TZ to stop receiving idle info for the core */
|
||||
ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
|
||||
&ret1, &ret2);
|
||||
hrtimer_cancel(&core->timer);
|
||||
core->idle_enable(core->idle_driver,
|
||||
core->idle_enable(core->type_core_num,
|
||||
MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
|
||||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Enabling LPM for %s\n", core->core_name);
|
||||
}
|
||||
core->freq_driver = NULL;
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_dcvs_freq_sink_stop);
|
||||
|
||||
int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dcvs_core *core = NULL;
|
||||
|
||||
if (!drv || !drv->core_name)
|
||||
return ret;
|
||||
|
||||
core = msm_dcvs_get_core(drv->core_name, NULL);
|
||||
if (!core)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
if (core->idle_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER))
|
||||
__info("Idle notifier for %s being replaced\n",
|
||||
core->core_name);
|
||||
core->idle_driver = drv;
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
return core->handle;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_dcvs_idle_source_register);
|
||||
|
||||
int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct dcvs_core *core = NULL;
|
||||
|
||||
if (!drv || !drv->core_name)
|
||||
return ret;
|
||||
|
||||
core = msm_dcvs_get_core(drv->core_name, NULL);
|
||||
if (!core)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
core->idle_driver = NULL;
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_dcvs_idle_source_unregister);
|
||||
|
||||
int msm_dcvs_idle(int handle, enum msm_core_idle_state state, uint32_t iowaited)
|
||||
int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state,
|
||||
uint32_t iowaited)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dcvs_core *core = NULL;
|
||||
|
@ -824,11 +765,12 @@ int msm_dcvs_idle(int handle, enum msm_core_idle_state state, uint32_t iowaited)
|
|||
uint32_t r0, r1;
|
||||
uint32_t freq_changed = 0;
|
||||
|
||||
if (handle >= CORE_HANDLE_OFFSET &&
|
||||
(handle - CORE_HANDLE_OFFSET) < CORES_MAX)
|
||||
core = &core_list[handle - CORE_HANDLE_OFFSET];
|
||||
if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
|
||||
pr_err("invalid dcvs_core_id = %d ret -EINVAL\n", dcvs_core_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BUG_ON(!core);
|
||||
core = msm_dcvs_get_core(dcvs_core_id);
|
||||
|
||||
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
|
||||
__info("Core %s idle state %d\n", core->core_name, state);
|
||||
|
@ -836,7 +778,7 @@ int msm_dcvs_idle(int handle, enum msm_core_idle_state state, uint32_t iowaited)
|
|||
switch (state) {
|
||||
case MSM_DCVS_IDLE_ENTER:
|
||||
hrtimer_cancel(&core->timer);
|
||||
ret = msm_dcvs_scm_event(core->handle,
|
||||
ret = msm_dcvs_scm_event(core->dcvs_core_id,
|
||||
MSM_DCVS_SCM_IDLE_ENTER, 0, 0, &r0, &r1);
|
||||
if (ret)
|
||||
__err("Error (%d) sending idle enter for %s\n",
|
||||
|
@ -917,6 +859,7 @@ late_initcall(msm_dcvs_late_init);
|
|||
static int __init msm_dcvs_early_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (!msm_dcvs_enabled) {
|
||||
__info("Not enabled (%d)\n", msm_dcvs_enabled);
|
||||
|
@ -927,6 +870,8 @@ static int __init msm_dcvs_early_init(void)
|
|||
if (ret)
|
||||
__err("Unable to initialize DCVS err=%d\n", ret);
|
||||
|
||||
for (i = 0; i < CORES_MAX; i++)
|
||||
core_list[i].dcvs_core_id = -1;
|
||||
return ret;
|
||||
}
|
||||
postcore_initcall(msm_dcvs_early_init);
|
||||
|
|
|
@ -25,23 +25,19 @@
|
|||
#include <mach/msm_dcvs.h>
|
||||
|
||||
struct cpu_idle_info {
|
||||
int cpu;
|
||||
int enabled;
|
||||
int handle;
|
||||
struct msm_dcvs_idle dcvs_notifier;
|
||||
int dcvs_core_id;
|
||||
struct pm_qos_request pm_qos_req;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_idle_info, cpu_idle_info);
|
||||
static DEFINE_PER_CPU_SHARED_ALIGNED(u64, iowait_on_cpu);
|
||||
static char core_name[NR_CPUS][10];
|
||||
static uint32_t latency;
|
||||
|
||||
static int msm_dcvs_idle_notifier(struct msm_dcvs_idle *self,
|
||||
static int msm_dcvs_idle_notifier(int core_num,
|
||||
enum msm_core_control_event event)
|
||||
{
|
||||
struct cpu_idle_info *info = container_of(self,
|
||||
struct cpu_idle_info, dcvs_notifier);
|
||||
struct cpu_idle_info *info = &per_cpu(cpu_idle_info, core_num);
|
||||
|
||||
switch (event) {
|
||||
case MSM_DCVS_ENABLE_IDLE_PULSE:
|
||||
|
@ -86,7 +82,7 @@ static int msm_cpuidle_notifier(struct notifier_block *self, unsigned long cmd,
|
|||
if (val == (u64)-1)
|
||||
val = 0;
|
||||
per_cpu(iowait_on_cpu, smp_processor_id()) = val;
|
||||
msm_dcvs_idle(info->handle, MSM_DCVS_IDLE_ENTER, 0);
|
||||
msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0);
|
||||
break;
|
||||
|
||||
case CPU_PM_EXIT:
|
||||
|
@ -97,7 +93,7 @@ static int msm_cpuidle_notifier(struct notifier_block *self, unsigned long cmd,
|
|||
val = 0;
|
||||
io_wait_us = val;
|
||||
iowaited = (io_wait_us - prev_io_wait_us);
|
||||
msm_dcvs_idle(info->handle, MSM_DCVS_IDLE_EXIT, iowaited);
|
||||
msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_EXIT, iowaited);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -108,52 +104,32 @@ static struct notifier_block idle_nb = {
|
|||
.notifier_call = msm_cpuidle_notifier,
|
||||
};
|
||||
|
||||
static void msm_gov_idle_source_init(int cpu)
|
||||
static void msm_gov_idle_source_init(int cpu, int dcvs_core_id)
|
||||
{
|
||||
struct cpu_idle_info *info = NULL;
|
||||
struct msm_dcvs_idle *inotify = NULL;
|
||||
|
||||
info = &per_cpu(cpu_idle_info, cpu);
|
||||
info->cpu = cpu;
|
||||
inotify = &info->dcvs_notifier;
|
||||
snprintf(core_name[cpu], 10, "cpu%d", cpu);
|
||||
inotify->core_name = core_name[cpu];
|
||||
info->handle = msm_dcvs_idle_source_register(inotify);
|
||||
BUG_ON(info->handle < 0);
|
||||
info->dcvs_core_id = dcvs_core_id;
|
||||
|
||||
pm_qos_add_request(&info->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
|
||||
PM_QOS_DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
static int msm_gov_idle_source_uninit(int cpu)
|
||||
{
|
||||
struct cpu_idle_info *info = NULL;
|
||||
struct msm_dcvs_idle *inotify = NULL;
|
||||
|
||||
info = &per_cpu(cpu_idle_info, cpu);
|
||||
info->cpu = cpu;
|
||||
inotify = &info->dcvs_notifier;
|
||||
return msm_dcvs_idle_source_unregister(inotify);
|
||||
}
|
||||
|
||||
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;
|
||||
int dcvs_core_id;
|
||||
};
|
||||
|
||||
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);
|
||||
struct msm_dcvs_freq *dcvs_notifier =
|
||||
&(per_cpu(msm_gov_info, policy->cpu).gov_notifier);
|
||||
|
||||
if (policy->max < gov->cur_freq)
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
|
@ -168,15 +144,14 @@ static void msm_gov_check_limits(struct cpufreq_policy *policy)
|
|||
gov->cur_freq = policy->cur;
|
||||
gov->min_freq = policy->min;
|
||||
gov->max_freq = policy->max;
|
||||
msm_dcvs_update_limits(dcvs_notifier);
|
||||
msm_dcvs_update_limits(gov->dcvs_core_id);
|
||||
}
|
||||
|
||||
static int msm_dcvs_freq_set(struct msm_dcvs_freq *self,
|
||||
static int msm_dcvs_freq_set(int core_num,
|
||||
unsigned int freq)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct msm_gov *gov =
|
||||
container_of(self, struct msm_gov, gov_notifier);
|
||||
struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
|
||||
|
||||
mutex_lock(&per_cpu(gov_mutex, gov->cpu));
|
||||
|
||||
|
@ -200,11 +175,9 @@ static int msm_dcvs_freq_set(struct msm_dcvs_freq *self,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int msm_dcvs_freq_get(struct msm_dcvs_freq *self)
|
||||
static unsigned int msm_dcvs_freq_get(int core_num)
|
||||
{
|
||||
struct msm_gov *gov =
|
||||
container_of(self, struct msm_gov, gov_notifier);
|
||||
|
||||
struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
|
||||
/*
|
||||
* the rw_sem in cpufreq is always held when this is called.
|
||||
* The policy->cur won't be updated in this case - so it is safe to
|
||||
|
@ -220,8 +193,6 @@ static int cpufreq_governor_msm(struct cpufreq_policy *policy,
|
|||
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:
|
||||
|
@ -231,15 +202,14 @@ static int cpufreq_governor_msm(struct cpufreq_policy *policy,
|
|||
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];
|
||||
handle = msm_dcvs_freq_sink_start(dcvs_notifier);
|
||||
handle = msm_dcvs_freq_sink_start(gov->dcvs_core_id);
|
||||
BUG_ON(handle < 0);
|
||||
msm_gov_check_limits(policy);
|
||||
mutex_unlock(&per_cpu(gov_mutex, cpu));
|
||||
break;
|
||||
|
||||
case CPUFREQ_GOV_STOP:
|
||||
msm_dcvs_freq_sink_stop(dcvs_notifier);
|
||||
msm_dcvs_freq_sink_stop(gov->dcvs_core_id);
|
||||
break;
|
||||
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
|
@ -260,7 +230,6 @@ struct cpufreq_governor cpufreq_gov_msm = {
|
|||
|
||||
static int __devinit msm_gov_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
int cpu;
|
||||
struct msm_dcvs_core_info *core = NULL;
|
||||
struct msm_dcvs_core_info *core_info = NULL;
|
||||
|
@ -272,19 +241,25 @@ static int __devinit msm_gov_probe(struct platform_device *pdev)
|
|||
latency = pdata->latency;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct msm_gov *gov = &per_cpu(msm_gov_info, cpu);
|
||||
|
||||
mutex_init(&per_cpu(gov_mutex, cpu));
|
||||
snprintf(core_name[cpu], 10, "cpu%d", cpu);
|
||||
if (cpu < core->num_cores)
|
||||
sensor = core_info->sensors[cpu];
|
||||
ret = msm_dcvs_register_core(core_name[cpu], core_info,
|
||||
gov->dcvs_core_id = msm_dcvs_register_core(
|
||||
MSM_DCVS_CORE_TYPE_CPU,
|
||||
cpu,
|
||||
core_info,
|
||||
msm_dcvs_freq_set,
|
||||
msm_dcvs_freq_get,
|
||||
msm_dcvs_idle_notifier,
|
||||
sensor);
|
||||
if (ret)
|
||||
if (gov->dcvs_core_id < 0) {
|
||||
pr_err("Unable to register core for %d\n", cpu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msm_gov_idle_source_init(cpu);
|
||||
msm_gov_idle_source_init(cpu, gov->dcvs_core_id);
|
||||
}
|
||||
|
||||
cpu_pm_register_notifier(&idle_nb);
|
||||
|
@ -294,11 +269,6 @@ static int __devinit msm_gov_probe(struct platform_device *pdev)
|
|||
|
||||
static int __devexit msm_gov_remove(struct platform_device *pdev)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
msm_gov_idle_source_uninit(cpu);
|
||||
}
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,19 +22,19 @@
|
|||
struct msm_priv {
|
||||
struct kgsl_device *device;
|
||||
int enabled;
|
||||
int handle;
|
||||
unsigned int cur_freq;
|
||||
struct msm_dcvs_idle idle_source;
|
||||
struct msm_dcvs_freq freq_sink;
|
||||
struct msm_dcvs_core_info *core_info;
|
||||
int gpu_busy;
|
||||
int dcvs_core_id;
|
||||
};
|
||||
|
||||
static int msm_idle_enable(struct msm_dcvs_idle *self,
|
||||
/* reference to be used in idle and freq callbacks */
|
||||
static struct msm_priv *the_msm_priv;
|
||||
|
||||
static int msm_idle_enable(int type_core_num,
|
||||
enum msm_core_control_event event)
|
||||
{
|
||||
struct msm_priv *priv = container_of(self, struct msm_priv,
|
||||
idle_source);
|
||||
struct msm_priv *priv = the_msm_priv;
|
||||
|
||||
switch (event) {
|
||||
case MSM_DCVS_ENABLE_IDLE_PULSE:
|
||||
|
@ -53,12 +53,10 @@ static int msm_idle_enable(struct msm_dcvs_idle *self,
|
|||
/* Set the requested frequency if it is within 5MHz (delta) of a
|
||||
* supported frequency.
|
||||
*/
|
||||
static int msm_set_freq(struct msm_dcvs_freq *self,
|
||||
unsigned int freq)
|
||||
static int msm_set_freq(int core_num, unsigned int freq)
|
||||
{
|
||||
int i, delta = 5000000;
|
||||
struct msm_priv *priv = container_of(self, struct msm_priv,
|
||||
freq_sink);
|
||||
struct msm_priv *priv = the_msm_priv;
|
||||
struct kgsl_device *device = priv->device;
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
|
||||
|
@ -79,10 +77,10 @@ static int msm_set_freq(struct msm_dcvs_freq *self,
|
|||
return priv->cur_freq / 1000;
|
||||
}
|
||||
|
||||
static unsigned int msm_get_freq(struct msm_dcvs_freq *self)
|
||||
static unsigned int msm_get_freq(int core_num)
|
||||
{
|
||||
struct msm_priv *priv = container_of(self, struct msm_priv,
|
||||
freq_sink);
|
||||
struct msm_priv *priv = the_msm_priv;
|
||||
|
||||
/* return current frequency in kHz */
|
||||
return priv->cur_freq / 1000;
|
||||
}
|
||||
|
@ -92,7 +90,7 @@ static void msm_busy(struct kgsl_device *device,
|
|||
{
|
||||
struct msm_priv *priv = pwrscale->priv;
|
||||
if (priv->enabled && !priv->gpu_busy) {
|
||||
msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_EXIT, 0);
|
||||
msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_EXIT, 0);
|
||||
trace_kgsl_mpdcvs(device, 1);
|
||||
priv->gpu_busy = 1;
|
||||
}
|
||||
|
@ -106,7 +104,8 @@ static void msm_idle(struct kgsl_device *device,
|
|||
|
||||
if (priv->enabled && priv->gpu_busy)
|
||||
if (device->ftbl->isidle(device)) {
|
||||
msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
|
||||
msm_dcvs_idle(priv->dcvs_core_id,
|
||||
MSM_DCVS_IDLE_ENTER, 0);
|
||||
trace_kgsl_mpdcvs(device, 0);
|
||||
priv->gpu_busy = 0;
|
||||
}
|
||||
|
@ -119,7 +118,7 @@ static void msm_sleep(struct kgsl_device *device,
|
|||
struct msm_priv *priv = pwrscale->priv;
|
||||
|
||||
if (priv->enabled && priv->gpu_busy) {
|
||||
msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
|
||||
msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0);
|
||||
trace_kgsl_mpdcvs(device, 0);
|
||||
priv->gpu_busy = 0;
|
||||
}
|
||||
|
@ -132,7 +131,7 @@ static int msm_init(struct kgsl_device *device,
|
|||
{
|
||||
struct msm_priv *priv;
|
||||
struct msm_dcvs_freq_entry *tbl;
|
||||
int i, ret, low_level;
|
||||
int i, ret = -EINVAL, low_level;
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
struct platform_device *pdev =
|
||||
container_of(device->parentdev, struct platform_device, dev);
|
||||
|
@ -149,29 +148,24 @@ static int msm_init(struct kgsl_device *device,
|
|||
low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
|
||||
for (i = 0; i <= low_level; i++)
|
||||
tbl[i].freq = pwr->pwrlevels[low_level - i].gpu_freq / 1000;
|
||||
ret = msm_dcvs_register_core(device->name, priv->core_info,
|
||||
priv->dcvs_core_id = msm_dcvs_register_core(MSM_DCVS_CORE_TYPE_GPU, 0,
|
||||
priv->core_info,
|
||||
msm_set_freq, msm_get_freq, msm_idle_enable,
|
||||
priv->core_info->sensors[0]);
|
||||
if (ret) {
|
||||
if (priv->dcvs_core_id < 0) {
|
||||
KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->device = device;
|
||||
priv->idle_source.core_name = device->name;
|
||||
priv->handle = msm_dcvs_idle_source_register(&priv->idle_source);
|
||||
if (priv->handle < 0) {
|
||||
ret = priv->handle;
|
||||
KGSL_PWR_ERR(device, "msm_dcvs_idle_source_register failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->freq_sink.core_name = device->name;
|
||||
ret = msm_dcvs_freq_sink_start(&priv->freq_sink);
|
||||
the_msm_priv = priv;
|
||||
ret = msm_dcvs_freq_sink_start(priv->dcvs_core_id);
|
||||
if (ret >= 0) {
|
||||
if (device->ftbl->isidle(device)) {
|
||||
priv->gpu_busy = 0;
|
||||
msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
|
||||
msm_dcvs_idle(priv->dcvs_core_id,
|
||||
MSM_DCVS_IDLE_ENTER, 0);
|
||||
} else {
|
||||
priv->gpu_busy = 1;
|
||||
}
|
||||
|
@ -179,7 +173,6 @@ static int msm_init(struct kgsl_device *device,
|
|||
}
|
||||
|
||||
KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n");
|
||||
msm_dcvs_idle_source_unregister(&priv->idle_source);
|
||||
|
||||
err:
|
||||
kfree(pwrscale->priv);
|
||||
|
@ -195,8 +188,7 @@ static void msm_close(struct kgsl_device *device,
|
|||
|
||||
if (pwrscale->priv == NULL)
|
||||
return;
|
||||
msm_dcvs_idle_source_unregister(&priv->idle_source);
|
||||
msm_dcvs_freq_sink_stop(&priv->freq_sink);
|
||||
msm_dcvs_freq_sink_stop(priv->dcvs_core_id);
|
||||
kfree(pwrscale->priv);
|
||||
pwrscale->priv = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue