From f6ee0c2bb45db2737a186315bbe1e448a1f19d38 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 25 Jun 2019 18:02:20 +0530 Subject: [PATCH 1/2] drivers: thermal: Use FCAP scm call instead of DMAX in KTM KTM driver right now achieves the software mitigation by using the domain max scm call. But this could have some delays in clearing the mitigation. To avoid the delay, use the frequency cap scm call to place the mitigation. Change-Id: If357a57836fe0be13977a56a1f20567715908f25 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/thermal/msm_thermal.c | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) 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"); From 03f0af3c211e72d559dabe8486c60a6454d167a7 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 25 Jun 2019 18:06:17 +0530 Subject: [PATCH 2/2] drivers: thermal: Use FCAP scm call instead of DMAX in LMH DCVSh LMH-DCVSh driver right now achieves the software mitigation by using the domain max scm call. But this could have some delays in clearing the mitigation. To avoid the delay, use the frequency cap scm call to place the mitigation. Change-Id: I00f1b2534505e02c8e66f6ce8088c37bfbb98198 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/thermal/msm_lmh_dcvs.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 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;