From patchwork Thu May 5 11:52:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?UmV4LUJDIENoZW4gKOmZs+afj+i+sCk=?= X-Patchwork-Id: 12839460 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 66839C433FE for ; Thu, 5 May 2022 12:06:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8DSby3lreBcDRrR6FexwaAM96iY3j7RN/QeD08KfN7g=; b=R54xHRFfSdzv+U dE1TSUzb1uZKO1srHRa3IUdQod2Ff+nuUFXmre+ylwhllEdIqFDApFHJwC8/vjT9f+xDkasie7pJo agCJSlcXNQKHuvv5Sfw9uTSMqOdp630PSurphCvEeRHBKOhJ2xCOAYLcRQAG4/FEWTW7Vp80mKpET 855cs/gDPoA+w7B1or2Jxry3R8TKfy5PkAFB0EHWTk0SYG8Oq/bBDlD4IOEl/dxg+Ap3NqWM2cr8U pLNBpwGvkQg79HB0DBupYTPSQXxRcBg3jNlnhi4BiyC1sB2+XXEnPkgk9MzK4ZoHcpUTH62IGAPDd rOkbTF1nI9qvfqXb7Vgg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nmaE1-00Ff1v-Jp; Thu, 05 May 2022 12:04:53 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nmaC1-00Fdp1-OU; Thu, 05 May 2022 12:02:51 +0000 X-UUID: 557c941e0cc945aca5f23f25670b92e8-20220505 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.4, REQID:970164bc-2dd3-4328-8aaa-d06f8ddc4cba, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:faefae9, CLOUDID:9ac8b1b2-56b5-4c9e-8d83-0070b288eb6a, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,File:nil,QS:0,BEC:nil X-UUID: 557c941e0cc945aca5f23f25670b92e8-20220505 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 2687588; Thu, 05 May 2022 05:02:38 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 5 May 2022 04:52:36 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 5 May 2022 19:52:34 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 5 May 2022 19:52:34 +0800 From: Rex-BC Chen To: , , , , CC: , , , , , , , , , , , Rex-BC Chen Subject: [PATCH v6 04/10] cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking() Date: Thu, 5 May 2022 19:52:20 +0800 Message-ID: <20220505115226.20130-5-rex-bc.chen@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220505115226.20130-1-rex-bc.chen@mediatek.com> References: <20220505115226.20130-1-rex-bc.chen@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220505_050249_854853_464BEDDD X-CRM114-Status: GOOD ( 21.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Jia-Wei Chang Because the difference of sram and proc should in a range of min_volt_shift and max_volt_shift. We need to adjust the sram and proc step by step. We replace VOLT_TOL (voltage tolerance) with the platform data and update the logic to determine the voltage boundary and invoking regulator_set_voltage. - Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary of sram regulator. - Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the voltage boundary of vproc regulator. Moreover, to prevent infinite loop when tracking voltage, we calculate the maximum value for each platform data. We assume min voltage is 0 and tracking target voltage using min_volt_shift for each iteration. The retry_max is 3 times of expeted iteration count. Signed-off-by: Jia-Wei Chang Signed-off-by: Rex-BC Chen Reviewed-by: AngeloGioacchino Del Regno --- drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++------------------- 1 file changed, 51 insertions(+), 96 deletions(-) diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 0b6c3479c8cc..fe205eca657d 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,8 +16,6 @@ #include #include -#define VOLT_TOL (10000) - struct mtk_cpufreq_platform_data { int min_volt_shift; int max_volt_shift; @@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info { bool need_voltage_tracking; int pre_vproc; const struct mtk_cpufreq_platform_data *soc_data; + int vtrack_max; }; static struct platform_device *cpufreq_pdev; @@ -73,6 +73,7 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, struct regulator *proc_reg = info->proc_reg; struct regulator *sram_reg = info->sram_reg; int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; + int retry = info->vtrack_max; pre_vproc = regulator_get_voltage(proc_reg); if (pre_vproc < 0) { @@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, "invalid Vproc value: %d\n", pre_vproc); return pre_vproc; } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ - new_vsram = min(new_vproc + soc_data->min_volt_shift, - soc_data->sram_max_volt); - - if (pre_vproc < new_vproc) { - /* - * When scaling up voltages, Vsram and Vproc scale up step - * by step. At each step, set Vsram to (Vproc + 200mV) first, - * then set Vproc to (Vsram - 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - pre_vsram = regulator_get_voltage(sram_reg); - if (pre_vsram < 0) { - dev_err(info->cpu_dev, - "invalid Vsram value: %d\n", pre_vsram); - return pre_vsram; - } - pre_vproc = regulator_get_voltage(proc_reg); - if (pre_vproc < 0) { - dev_err(info->cpu_dev, - "invalid Vproc value: %d\n", pre_vproc); - return pre_vproc; - } - - vsram = min(new_vsram, - pre_vproc + soc_data->min_volt_shift); - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { - vsram = soc_data->sram_max_volt; + pre_vsram = regulator_get_voltage(sram_reg); + if (pre_vsram < 0) { + dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram); + return pre_vsram; + } - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); + new_vsram = clamp(new_vproc + soc_data->min_volt_shift, + soc_data->sram_min_volt, soc_data->sram_max_volt); - vproc = new_vproc; - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); + do { + if (pre_vproc <= new_vproc) { + vsram = clamp(pre_vproc + soc_data->max_volt_shift, + soc_data->sram_min_volt, new_vsram); + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); - vproc = vsram - soc_data->min_volt_shift; - } if (ret) return ret; + if (vsram == soc_data->sram_max_volt || + new_vsram == soc_data->sram_min_volt) + vproc = new_vproc; + else + vproc = vsram - soc_data->min_volt_shift; + ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) { regulator_set_voltage(sram_reg, pre_vsram, - pre_vsram); + soc_data->sram_max_volt); return ret; } - } while (vproc < new_vproc || vsram < new_vsram); - } else if (pre_vproc > new_vproc) { - /* - * When scaling down voltages, Vsram and Vproc scale down step - * by step. At each step, set Vproc to (Vsram - 200mV) first, - * then set Vproc to (Vproc + 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - pre_vproc = regulator_get_voltage(proc_reg); - if (pre_vproc < 0) { - dev_err(info->cpu_dev, - "invalid Vproc value: %d\n", pre_vproc); - return pre_vproc; - } - pre_vsram = regulator_get_voltage(sram_reg); - if (pre_vsram < 0) { - dev_err(info->cpu_dev, - "invalid Vsram value: %d\n", pre_vsram); - return pre_vsram; - } - + } else if (pre_vproc > new_vproc) { vproc = max(new_vproc, pre_vsram - soc_data->max_volt_shift); ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) return ret; @@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, vsram = max(new_vsram, vproc + soc_data->min_volt_shift); - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { - vsram = soc_data->sram_max_volt; - - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); - } - + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); if (ret) { regulator_set_voltage(proc_reg, pre_vproc, - pre_vproc); + soc_data->proc_max_volt); return ret; } - } while (vproc > new_vproc + VOLT_TOL || - vsram > new_vsram + VOLT_TOL); - } + } + + pre_vproc = vproc; + pre_vsram = vsram; + + if (--retry < 0) { + dev_err(info->cpu_dev, + "over loop count, failed to set voltage\n"); + return -EINVAL; + } + } while (vproc != new_vproc || vsram != new_vsram); return 0; } @@ -261,8 +207,8 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, * If the new voltage or the intermediate voltage is higher than the * current voltage, scale up voltage first. */ - target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; - if (pre_vproc < target_vproc) { + target_vproc = max(inter_vproc, vproc); + if (pre_vproc <= target_vproc) { ret = mtk_cpufreq_set_voltage(info, target_vproc); if (ret) { dev_err(cpu_dev, @@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) */ info->need_voltage_tracking = (info->sram_reg != NULL); + /* + * We assume min voltage is 0 and tracking target voltage using + * min_volt_shift for each iteration. + * The vtrack_max is 3 times of expeted iteration count. + */ + info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt, + info->soc_data->proc_max_volt), + info->soc_data->min_volt_shift); + return 0; out_disable_inter_clock: