Received: by 10.223.176.5 with SMTP id f5csp865627wra; Tue, 6 Feb 2018 08:38:30 -0800 (PST) X-Google-Smtp-Source: AH8x2276tbBZ/RT56YgfeR1YO389SEoHXoUixysVosALKfZRXB/MSA98Me1aX75sZEfOrTT+ghS0 X-Received: by 2002:a17:902:b610:: with SMTP id b16-v6mr2957059pls.132.1517935110171; Tue, 06 Feb 2018 08:38:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517935110; cv=none; d=google.com; s=arc-20160816; b=eyfT41tuEVTYMZCmGis4uJwlnVOaRyLsE4xoCK/TwIknBuSTC/B7gVE/+loBhnMuDi TvCRTgE7L9XoDFfXOjkLm6enWeShh5qpjtMoEdNAEf5tP928MhDYfIt3ESOwd7oYZ54a n+x1a+TzwKWr4gedAaObVjuXPfk0HSo8UMGqvOtBp92+QkPQ8pkEK1gPcUD09u3g1iCf gnORfLAlhQaQGibcT8QeROGyF15CnAxc0zU964jnAKEBmpUFBeuy7c/dusA9b7L2m7lL YeGCLGNAWq2IagljfwWKbE5V5Fo0xgzILxHro/b3/o4hj+fTmLTU37C3ThCjF+TA1TP9 5rVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=iN2vaM/47B9XH+FZwasacd1Hb4FHmjOXgy1SGdbnRAY=; b=my3Ti7DB8CZw4OT6uCksDINr1QmZIYYSZ0p7xVS8QT7JKhXnLzJ0NuHVkQjOZMdBIg OFYYUgkqjLHc1So5VOaC7eG4fQg78RTHe8t7Ly096nErCQbO5DMRrfiG+OJkd52mqZdm 2HPXQBpIZJ6TS0yzMcWbcKmI50x83fx7ElYW/TSgMTRio09uAMiKoyLewg7hv+SDpgGW 81CUnKLUKum1R37Gix6bqTd9SxIJ/gUt/NNHlB+QD9qZfXomEANy6nbi0imeNVrFSBPP mJ1zAPqWu1ebhlf6cM/ClnjzsIsMYc5XBvZhGq2kPDGAdQfVtJENEKw2CkAFQ2dmVsP2 1gTw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o7si4017014pgr.390.2018.02.06.08.38.15; Tue, 06 Feb 2018 08:38:30 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752832AbeBFQgz (ORCPT + 99 others); Tue, 6 Feb 2018 11:36:55 -0500 Received: from hqemgate16.nvidia.com ([216.228.121.65]:16157 "EHLO hqemgate16.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752560AbeBFQen (ORCPT ); Tue, 6 Feb 2018 11:34:43 -0500 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate16.nvidia.com id ; Tue, 06 Feb 2018 08:34:53 -0800 Received: from HQMAIL108.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Tue, 06 Feb 2018 08:34:41 -0800 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Tue, 06 Feb 2018 08:34:41 -0800 Received: from UKMAIL101.nvidia.com (10.26.138.13) by HQMAIL108.nvidia.com (172.18.146.13) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 6 Feb 2018 16:34:41 +0000 Received: from tbergstrom-lnx.Nvidia.com (10.21.24.170) by UKMAIL101.nvidia.com (10.26.138.13) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Tue, 6 Feb 2018 16:34:36 +0000 Received: from tbergstrom-lnx.nvidia.com (localhost [127.0.0.1]) by tbergstrom-lnx.Nvidia.com (Postfix) with ESMTP id 86385F811D8; Tue, 6 Feb 2018 18:34:33 +0200 (EET) From: Peter De Schrijver To: , , , , , , , , , CC: Peter De Schrijver Subject: [PATCH v3 05/11] clk: tegra: prepare dfll driver for PWM regulator Date: Tue, 6 Feb 2018 18:34:06 +0200 Message-ID: <1517934852-23255-6-git-send-email-pdeschrijver@nvidia.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1517934852-23255-1-git-send-email-pdeschrijver@nvidia.com> References: <1517934852-23255-1-git-send-email-pdeschrijver@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.21.24.170] X-ClientProxiedBy: UKMAIL102.nvidia.com (10.26.138.15) To UKMAIL101.nvidia.com (10.26.138.13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch prepares the dfll driver to work with PWM regulators. To do this we introduce a new array lut_uv which gives the voltage for a given index generated by the dfll logic. This index will then be translated to a PMIC voltage ID in case of I2C using the i2c_lut. In case of a PWM regulator, it will be used to determine the PWM duty cycle. We also introduce lut_bottom which holds the lowest voltage we will ever need. In case of I2C this can be set to zero because the i2c_lut will be initialized such that entry 0 will be the lowest voltage we will ever need. In case of PWM, the lowest voltage is determined by the regulator hardware so we need this software limit. Note that this is different from lut_min which gives the lowest voltage we allow taking temperature into account. In a future patchset we will update lut_vmin dynamically. Similarly lut_max will be the highest voltage allowed taking temperature into accouint. Also this will be updated dynamically once temperature dependence will be introduced. Signed-off-by: Peter De Schrijver --- drivers/clk/tegra/clk-dfll.c | 62 ++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 0a7deee..fa97763 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -301,9 +301,10 @@ struct tegra_dfll { u32 i2c_slave_addr; /* i2c_lut array entries are regulator framework selectors */ - unsigned i2c_lut[MAX_DFLL_VOLTAGES]; - int i2c_lut_size; - u8 lut_min, lut_max, lut_safe; + unsigned int i2c_lut[MAX_DFLL_VOLTAGES]; + unsigned int lut_uv[MAX_DFLL_VOLTAGES]; + int lut_size; + u8 lut_bottom, lut_min, lut_max, lut_safe; }; #define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw) @@ -531,10 +532,10 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td) u32 val; for (i = 0; i < MAX_DFLL_VOLTAGES; i++) { - if (i < td->lut_min) - lut_index = td->lut_min; - else if (i > td->lut_max) - lut_index = td->lut_max; + if (i < td->lut_bottom) + lut_index = td->lut_bottom; + else if (i > td->lut_size - 1) + lut_index = td->lut_size - 1; else lut_index = i; @@ -594,9 +595,9 @@ static void dfll_init_out_if(struct tegra_dfll *td) { u32 val; - td->lut_min = 0; - td->lut_max = td->i2c_lut_size - 1; - td->lut_safe = td->lut_min + 1; + td->lut_min = td->lut_bottom; + td->lut_max = td->lut_size - 1; + td->lut_safe = td->lut_min + (td->lut_min < td->lut_max ? 1 : 0); dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG); val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) | @@ -619,11 +620,11 @@ static void dfll_init_out_if(struct tegra_dfll *td) */ /** - * find_lut_index_for_rate - determine I2C LUT index for given DFLL rate + * find_lut_index_for_rate - determine LUT index for given DFLL rate * @td: DFLL instance * @rate: clock rate * - * Determines the index of a I2C LUT entry for a voltage that approximately + * Determines the index of a LUT entry for a voltage that approximately * produces the given DFLL clock rate. This is used when forcing a value * to the integrator during rate changes. Returns -ENOENT if a suitable * LUT index is not found. @@ -637,11 +638,11 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate) if (IS_ERR(opp)) return PTR_ERR(opp); - uv = dev_pm_opp_get_voltage(opp); + uv = dev_pm_opp_get_voltage(opp) / td->soc->alignment.step_uv; dev_pm_opp_put(opp); - for (i = 0; i < td->i2c_lut_size; i++) { - if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv) + for (i = td->lut_bottom; i < td->lut_size; i++) { + if ((td->lut_uv[i] / td->soc->alignment.step_uv) >= uv) return i; } @@ -1377,15 +1378,17 @@ static int dfll_init(struct tegra_dfll *td) */ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV) { - int i, n_voltages, reg_uV; + int i, n_voltages, reg_mult, align_mult; + align_mult = uV / td->soc->alignment.step_uv; 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_mult = regulator_list_voltage(td->vdd_reg, i) / + td->soc->alignment.step_uv; + if (reg_mult < 0) break; - if (uV == reg_uV) + if (align_mult == reg_mult) return i; } @@ -1399,15 +1402,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_mult, align_mult; + align_mult = uV / td->soc->alignment.step_uv; 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_mult = regulator_list_voltage(td->vdd_reg, i) / + td->soc->alignment.step_uv; + if (reg_mult < 0) break; - if (uV <= reg_uV) + if (align_mult <= reg_mult) return i; } @@ -1450,8 +1455,10 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) if (lut < 0) goto out; td->i2c_lut[0] = lut; + td->lut_bottom = 0; for (j = 1, rate = 0; ; rate++) { + opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate); if (IS_ERR(opp)) break; @@ -1484,13 +1491,18 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) if (v >= v_max) break; } - td->i2c_lut_size = j; + td->lut_size = j; if (!td->dvco_rate_min) dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", td->soc->cvb->min_millivolts); - else + else { ret = 0; + for (j = 0; j < td->lut_size; j++) + td->lut_uv[j] = + regulator_list_voltage(td->vdd_reg, + td->i2c_lut[j]); + } out: return ret; -- 1.9.1