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");