From patchwork Fri Apr 22 10:31:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Penny Chiu X-Patchwork-Id: 8909421 Return-Path: X-Original-To: patchwork-linux-clk@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 820CC9F1C1 for ; Fri, 22 Apr 2016 10:35:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 48C2B20256 for ; Fri, 22 Apr 2016 10:35:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C6ED120221 for ; Fri, 22 Apr 2016 10:35:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752097AbcDVKcL (ORCPT ); Fri, 22 Apr 2016 06:32:11 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:5885 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751172AbcDVKcH (ORCPT ); Fri, 22 Apr 2016 06:32:07 -0400 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com id ; Fri, 22 Apr 2016 03:32:06 -0700 Received: from HQMAIL105.nvidia.com ([172.20.187.12]) by hqnvupgp07.nvidia.com (PGP Universal service); Fri, 22 Apr 2016 03:31:56 -0700 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Fri, 22 Apr 2016 03:31:56 -0700 Received: from HQMAIL102.nvidia.com (172.18.146.10) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Fri, 22 Apr 2016 10:32:05 +0000 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQMAIL102.nvidia.com (172.18.146.10) with Microsoft SMTP Server id 15.0.1130.7 via Frontend Transport; Fri, 22 Apr 2016 10:32:05 +0000 Received: from pchiu-i7.nvidia.com (Not Verified[10.19.120.104]) by hqnvemgw02.nvidia.com with Trustwave SEG (v7, 5, 5, 8150) id ; Fri, 22 Apr 2016 03:32:05 -0700 From: Penny Chiu To: , , , , , , CC: , , , , , , , , Penny Chiu Subject: [PATCH 01/11] clk: tegra: dfll: Fix voltage comparison Date: Fri, 22 Apr 2016 18:31:01 +0800 Message-ID: <1461321071-6431-2-git-send-email-pchiu@nvidia.com> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1461321071-6431-1-git-send-email-pchiu@nvidia.com> References: <1461321071-6431-1-git-send-email-pchiu@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When generating opp table, the voltage is round down based on the alignment in cvb table. This alignment should be also applied on all voltage comparison. By the way, the alignment voltage values should depend on regulator device specification, so these values should not be hard code in cvb table. To Move these values into devicetree will be more independent for different platforms using the same SoC. Signed-off-by: Penny Chiu --- .../bindings/clock/nvidia,tegra124-dfll.txt | 9 ++++++++ drivers/clk/tegra/clk-dfll.c | 27 +++++++++++++--------- drivers/clk/tegra/clk-dfll.h | 1 + drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 23 ++++++++++++++---- drivers/clk/tegra/cvb.c | 12 ++++++---- drivers/clk/tegra/cvb.h | 8 ++++--- 6 files changed, 58 insertions(+), 22 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt index ee7e5fd..84080a8 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt @@ -34,6 +34,14 @@ Required properties: hardware will start controlling. The regulator will be queried for the I2C register, control values and supported voltages. +Reguired properties for build voltage table: +- nvidia,align-step-uv: Step uV of regulator for CPU voltage rail. This + value will be applied when building frequency-voltage table to ensure + all calculated voltages will be aligned to voltages regulator supplied. + +Optional properties for build voltage table: +- nvidia,align-offset-uv: Offset uV for calculating DFLL output voltage. + Required properties for the control loop parameters: - nvidia,sample-rate: Sample rate of the DFLL control loop. - nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM. @@ -68,6 +76,7 @@ clock@0,70110000 { vdd-cpu-supply = <&vdd_cpu>; status = "okay"; + nvidia,align-step-uv = <10000>; /* 10mv */ nvidia,sample-rate = <12500>; nvidia,droop-ctrl = <0x00000f00>; nvidia,force-mode = <1>; diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 19bfa07..a279467 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -630,7 +630,7 @@ static void dfll_init_out_if(struct tegra_dfll *td) static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate) { struct dev_pm_opp *opp; - int i, uv; + int i, align_volt; rcu_read_lock(); @@ -639,12 +639,13 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate) rcu_read_unlock(); return PTR_ERR(opp); } - uv = dev_pm_opp_get_voltage(opp); + align_volt = dev_pm_opp_get_voltage(opp) / td->soc->alignment; rcu_read_unlock(); for (i = 0; i < td->i2c_lut_size; i++) { - if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv) + if ((regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) / + td->soc->alignment) == align_volt) return i; } @@ -1380,15 +1381,17 @@ di_err1: */ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV) { - int i, n_voltages, reg_uV; + int i, n_voltages, reg_volt, align_volt; + align_volt = uV / td->soc->alignment; n_voltages = regulator_count_voltages(td->vdd_reg); for (i = 0; i < n_voltages; i++) { - reg_uV = regulator_list_voltage(td->vdd_reg, i); - if (reg_uV < 0) + reg_volt = regulator_list_voltage(td->vdd_reg, i) / + td->soc->alignment; + if (reg_volt < 0) break; - if (uV == reg_uV) + if (align_volt == reg_volt) return i; } @@ -1402,15 +1405,17 @@ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV) * */ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV) { - int i, n_voltages, reg_uV; + int i, n_voltages, reg_volt, align_volt; + align_volt = uV / td->soc->alignment; n_voltages = regulator_count_voltages(td->vdd_reg); for (i = 0; i < n_voltages; i++) { - reg_uV = regulator_list_voltage(td->vdd_reg, i); - if (reg_uV < 0) + reg_volt = regulator_list_voltage(td->vdd_reg, i) / + td->soc->alignment; + if (reg_volt < 0) break; - if (uV <= reg_uV) + if (align_volt <= reg_volt) return i; } diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index 2e4c077..5714691 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h @@ -37,6 +37,7 @@ struct tegra_dfll_soc_data { struct device *dev; unsigned int min_millivolts; + unsigned int alignment; u32 tune0_low; u32 tune0_high; u32 tune1; diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index 6125333..5e5958e 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -42,9 +42,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { .process_id = -1, .min_millivolts = 900, .max_millivolts = 1260, - .alignment = { - .step_uv = 10000, /* 10mV */ - }, .speedo_scale = 100, .voltage_scale = 1000, .cvb_table = { @@ -84,7 +81,8 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) { - int process_id, speedo_id, speedo_value; + int process_id, speedo_id, speedo_value, ret; + struct rail_alignment align; struct tegra_dfll_soc_data *soc; const struct cvb_table *cvb; @@ -108,8 +106,24 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) return -ENODEV; } + ret = of_property_read_u32(pdev->dev.of_node, "nvidia,align-offset-uv", + &align.offset_uv); + if (ret < 0) { + dev_dbg(&pdev->dev, + "offset uv not found, the default value will be 0\n"); + align.offset_uv = 0; + } + + ret = of_property_read_u32(pdev->dev.of_node, "nvidia,align-step-uv", + &align.step_uv); + if (ret < 0) { + dev_err(&pdev->dev, "missing step uv\n"); + return -EINVAL; + } + cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables, ARRAY_SIZE(tegra124_cpu_cvb_tables), + &align, process_id, speedo_id, speedo_value, cpu_max_freq_table[speedo_id], soc->dev); @@ -120,6 +134,7 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) } soc->min_millivolts = cvb->min_millivolts; + soc->alignment = align.step_uv; soc->tune0_low = cvb->cpu_dfll_data.tune0_low; soc->tune0_high = cvb->cpu_dfll_data.tune0_high; soc->tune1 = cvb->cpu_dfll_data.tune1; diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c index 69c74ee..a3be166 100644 --- a/drivers/clk/tegra/cvb.c +++ b/drivers/clk/tegra/cvb.c @@ -62,13 +62,13 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up) } static int build_opp_table(const struct cvb_table *d, + const struct rail_alignment *align, int speedo_value, unsigned long max_freq, struct device *opp_dev) { int i, ret, dfll_mv, min_mv, max_mv; const struct cvb_table_freq_entry *table = NULL; - const struct rail_alignment *align = &d->alignment; min_mv = round_voltage(d->min_millivolts, align, UP); max_mv = round_voltage(d->max_millivolts, align, DOWN); @@ -110,8 +110,11 @@ static int build_opp_table(const struct cvb_table *d, */ const struct cvb_table *tegra_cvb_build_opp_table( const struct cvb_table *cvb_tables, - size_t sz, int process_id, - int speedo_id, int speedo_value, + size_t sz, + const struct rail_alignment *align, + int process_id, + int speedo_id, + int speedo_value, unsigned long max_rate, struct device *opp_dev) { @@ -125,7 +128,8 @@ const struct cvb_table *tegra_cvb_build_opp_table( if (d->process_id != -1 && d->process_id != process_id) continue; - ret = build_opp_table(d, speedo_value, max_rate, opp_dev); + ret = build_opp_table( + d, align, speedo_value, max_rate, opp_dev); return ret ? ERR_PTR(ret) : d; } diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h index f62cdc4..4964c49 100644 --- a/drivers/clk/tegra/cvb.h +++ b/drivers/clk/tegra/cvb.h @@ -49,7 +49,6 @@ struct cvb_table { int min_millivolts; int max_millivolts; - struct rail_alignment alignment; int speedo_scale; int voltage_scale; @@ -59,8 +58,11 @@ struct cvb_table { const struct cvb_table *tegra_cvb_build_opp_table( const struct cvb_table *cvb_tables, - size_t sz, int process_id, - int speedo_id, int speedo_value, + size_t sz, + const struct rail_alignment *align, + int process_id, + int speedo_id, + int speedo_value, unsigned long max_rate, struct device *opp_dev);