Merge "drivers: thermal: Use FCAP scm call instead of DMAX in LMH DCVSh"

This commit is contained in:
Linux Build Service Account 2019-06-29 15:41:44 -07:00 committed by Gerrit - the friendly Code Review server
commit 54d23a97a0
2 changed files with 51 additions and 40 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 2019 The Linux Foundation. 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
@ -54,7 +54,7 @@
#define MSM_LIMITS_CLUSTER_0 0x6370302D
#define MSM_LIMITS_CLUSTER_1 0x6370312D
#define MSM_LIMITS_DOMAIN_MAX 0x444D4158
#define MSM_LIMIT_FREQ_CAP 0x46434150
#define MSM_LIMITS_HIGH_THRESHOLD_VAL 95000
#define MSM_LIMITS_ARM_THRESHOLD_VAL 65000
@ -194,34 +194,40 @@ static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data)
}
static int msm_lmh_dcvs_write(uint32_t node_id, uint32_t fn,
uint32_t setting, uint32_t val)
uint32_t setting, uint32_t val, uint32_t val1,
bool enable_val1)
{
int ret;
struct scm_desc desc_arg;
uint32_t *payload = NULL;
uint32_t payload_len;
payload = kzalloc(sizeof(uint32_t) * 5, GFP_KERNEL);
payload_len = ((enable_val1) ? 6 : 5) * sizeof(uint32_t);
payload = kcalloc((enable_val1) ? 6 : 5, sizeof(uint32_t), GFP_KERNEL);
if (!payload)
return -ENOMEM;
payload[0] = fn; /* algorithm */
payload[1] = 0; /* unused sub-algorithm */
payload[2] = setting;
payload[3] = 1; /* number of values */
payload[3] = enable_val1 ? 2 : 1; /* number of values */
payload[4] = val;
if (enable_val1)
payload[5] = val1;
desc_arg.args[0] = SCM_BUFFER_PHYS(payload);
desc_arg.args[1] = sizeof(uint32_t) * 5;
desc_arg.args[1] = payload_len;
desc_arg.args[2] = MSM_LIMITS_NODE_DCVS;
desc_arg.args[3] = node_id;
desc_arg.args[4] = 0; /* version */
desc_arg.arginfo = SCM_ARGS(5, SCM_RO, SCM_VAL, SCM_VAL,
SCM_VAL, SCM_VAL);
dmac_flush_range(payload, (void *)payload + 5 * (sizeof(uint32_t)));
dmac_flush_range(payload, (void *)payload + payload_len);
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_LMH, MSM_LIMITS_DCVSH), &desc_arg);
kfree(payload);
return ret;
}
@ -265,7 +271,7 @@ static int lmh_activate_trip(struct thermal_zone_device *dev,
case LIMITS_TRIP_LO:
ret = msm_lmh_dcvs_write(hw->affinity,
MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMITS_ARM_THRESHOLD, temp);
MSM_LIMITS_ARM_THRESHOLD, temp, 0, 0);
break;
case LIMITS_TRIP_HI:
/*
@ -276,13 +282,13 @@ static int lmh_activate_trip(struct thermal_zone_device *dev,
return -EINVAL;
ret = msm_lmh_dcvs_write(hw->affinity,
MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMITS_HI_THRESHOLD, temp);
MSM_LIMITS_HI_THRESHOLD, temp, 0, 0);
if (ret)
break;
ret = msm_lmh_dcvs_write(hw->affinity,
MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMITS_LOW_THRESHOLD, temp -
MSM_LIMITS_LOW_THRESHOLD_OFFSET);
MSM_LIMITS_LOW_THRESHOLD_OFFSET, 0, 0);
break;
default:
return -EINVAL;
@ -347,8 +353,9 @@ static int lmh_set_max_limit(int cpu, u32 freq)
if (!hw)
return -EINVAL;
return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_GENERAL,
MSM_LIMITS_DOMAIN_MAX, freq);
return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMIT_FREQ_CAP, freq,
freq >= hw->max_freq ? 0 : 1, 1);
}
static int lmh_get_cur_limit(int cpu, unsigned long *freq)
@ -457,7 +464,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
/* Enable the thermal algorithm early */
ret = msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
return ret;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. 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
@ -59,11 +59,11 @@
#define MSM_LIMITS_DCVSH 0x10
#define MSM_LIMITS_NODE_DCVS 0x44435653
#define MSM_LIMITS_SUB_FN_THERMAL 0x54484D4C
#define MSM_LIMITS_SUB_FN_GENERAL 0x47454E00
#define MSM_LIMITS_SUB_FN_CRNT 0x43524E54
#define MSM_LIMITS_SUB_FN_REL 0x52454C00
#define MSM_LIMITS_DOMAIN_MAX 0x444D4158
#define MSM_LIMITS_DOMAIN_MIN 0x444D494E
#define MSM_LIMITS_FREQ_CAP 0x46434150
#define MSM_LIMITS_CLUSTER_0 0x6370302D
#define MSM_LIMITS_CLUSTER_1 0x6370312D
#define MSM_LIMITS_ALGO_MODE_ENABLE 0x454E424C
@ -1018,55 +1018,58 @@ static struct notifier_block msm_thermal_cpufreq_notifier = {
.notifier_call = msm_thermal_cpufreq_callback,
};
static int msm_lmh_dcvs_write(uint32_t node_id, uint32_t fn, uint32_t setting,
uint32_t val)
static int msm_lmh_dcvs_write(uint32_t node_id, uint32_t fn,
uint32_t setting, uint32_t val, uint32_t val1,
bool enable_val1)
{
int ret;
struct scm_desc desc_arg;
uint32_t *payload = NULL;
uint32_t payload_len;
payload = kzalloc(sizeof(uint32_t) * 5, GFP_KERNEL);
payload_len = ((enable_val1) ? 6 : 5) * sizeof(uint32_t);
payload = kcalloc((enable_val1) ? 6 : 5, sizeof(uint32_t), GFP_KERNEL);
if (!payload)
return -ENOMEM;
payload[0] = fn;
payload[0] = fn; /* algorithm */
payload[1] = 0; /* unused sub-algorithm */
payload[2] = setting;
payload[3] = 1; /* number of values */
payload[3] = enable_val1 ? 2 : 1; /* number of values */
payload[4] = val;
if (enable_val1)
payload[5] = val1;
desc_arg.args[0] = SCM_BUFFER_PHYS(payload);
desc_arg.args[1] = sizeof(uint32_t) * 5;
desc_arg.args[1] = payload_len;
desc_arg.args[2] = MSM_LIMITS_NODE_DCVS;
desc_arg.args[3] = node_id;
desc_arg.args[4] = 0; /* version */
desc_arg.arginfo = SCM_ARGS(5, SCM_RO, SCM_VAL, SCM_VAL,
SCM_VAL, SCM_VAL);
dmac_flush_range(payload, (void *)payload + 5 * (sizeof(uint32_t)));
dmac_flush_range(payload, (void *)payload + payload_len);
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_LMH, MSM_LIMITS_DCVSH), &desc_arg);
kfree(payload);
return ret;
}
static int msm_lmh_dcvs_update(int cpu)
{
uint32_t id = cpus[cpu].parent_ptr->cluster_id;
uint32_t max_freq = cpus[cpu].limited_max_freq;
uint32_t min_freq = cpus[cpu].limited_min_freq;
uint32_t max_freq = cpus[cpu].limited_max_freq, hw_max_freq = U32_MAX;
uint32_t affinity;
int ret;
/*
* It is better to use max/min limits of cluster for given
* It is better to use max limits of cluster for given
* cpu if cluster mitigation is supported. It ensures that it
* requests aggregated max/min limits of all cpus in that cluster.
* requests aggregated max limits of all cpus in that cluster.
*/
if (core_ptr) {
if (core_ptr)
max_freq = cpus[cpu].parent_ptr->limited_max_freq;
min_freq = cpus[cpu].parent_ptr->limited_min_freq;
}
switch (id) {
case 0:
@ -1080,13 +1083,14 @@ static int msm_lmh_dcvs_update(int cpu)
return -EINVAL;
};
ret = msm_lmh_dcvs_write(affinity, MSM_LIMITS_SUB_FN_GENERAL,
MSM_LIMITS_DOMAIN_MAX, max_freq);
if (ret)
return ret;
if (cpus[cpu].parent_ptr->freq_table)
hw_max_freq =
cpus[cpu].parent_ptr->freq_table[
cpus[cpu].parent_ptr->freq_idx_high].frequency;
ret = msm_lmh_dcvs_write(affinity, MSM_LIMITS_SUB_FN_GENERAL,
MSM_LIMITS_DOMAIN_MIN, min_freq);
ret = msm_lmh_dcvs_write(affinity, MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMITS_FREQ_CAP, max_freq,
max_freq >= hw_max_freq ? 0 : 1, 1);
if (ret)
return ret;
/*
@ -1729,23 +1733,23 @@ static int msm_thermal_lmh_dcvs_init(struct platform_device *pdev)
*/
ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_0,
MSM_LIMITS_SUB_FN_REL,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
pr_err("Unable to enable REL algo for cluster0\n");
ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_1,
MSM_LIMITS_SUB_FN_REL,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
pr_err("Unable to enable REL algo for cluster1\n");
ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_0,
MSM_LIMITS_SUB_FN_CRNT,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
pr_err("Unable enable CRNT algo for cluster0\n");
ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_1,
MSM_LIMITS_SUB_FN_CRNT,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
pr_err("Unable enable CRNT algo for cluster1\n");