summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/thermal/msm_lmh_dcvs.c33
-rw-r--r--drivers/thermal/msm_thermal.c58
2 files changed, 51 insertions, 40 deletions
diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c
index 215c37526081..7e141f15a544 100644
--- a/drivers/thermal/msm_lmh_dcvs.c
+++ b/drivers/thermal/msm_lmh_dcvs.c
@@ -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;
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 7beef24035f8..389a75695355 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -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");