From patchwork Wed Jan 29 16:24:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime COQUELIN X-Patchwork-Id: 23882 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f199.google.com (mail-ie0-f199.google.com [209.85.223.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id A00A6202FA for ; Wed, 29 Jan 2014 16:27:57 +0000 (UTC) Received: by mail-ie0-f199.google.com with SMTP id x13sf6659036ief.10 for ; Wed, 29 Jan 2014 08:27:56 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=N/IG6Kzit9KbG7OpEjNub7k0OzuKjgBlQvvVjDxotbI=; b=VU9L6D3UTWMzlE5tbKl1TvjANqDIU+uoDjMr3wuAOYtHPLbNfbqf1Yy17ezEsuo0UF Tt663JpcFJ46bZQAFwAanbr52PNdDbzpjbe2T0vzwDYnwwfApeLCyVIBu9NaS6PauxwM HrDaYZbSa6n+jMqfABY832uxyVbnk5Pq0P/kEDGYgPWzch2wEOmtoZwO6IwZE6EOqlrX vaMHx1ZB+SFS7fMAZl/N2Uf3Kai43dbt4KgOgTx5kI98A+7jiF8MVU0FVUhsk0p+w5sb 317WN8aZUuqTtDoATA/Cp0oJdaVYBNDmJpiaidM4DPN0u9gU+mS6fK4E8LqU+cA0s0sA 04xg== X-Gm-Message-State: ALoCoQlXpdi7RNJdGtmlIetsY+Or3pjYNUBaZXuLzClsb6eCzJlbiT4ypcxGVDwyPc0u960oS22B X-Received: by 10.43.92.73 with SMTP id bp9mr2319110icc.26.1391012876586; Wed, 29 Jan 2014 08:27:56 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.93.199 with SMTP id d65ls150231qge.12.gmail; Wed, 29 Jan 2014 08:27:56 -0800 (PST) X-Received: by 10.221.34.211 with SMTP id st19mr7339076vcb.5.1391012876448; Wed, 29 Jan 2014 08:27:56 -0800 (PST) Received: from mail-vc0-f174.google.com (mail-vc0-f174.google.com [209.85.220.174]) by mx.google.com with ESMTPS id sg4si942807vdc.66.2014.01.29.08.27.56 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 29 Jan 2014 08:27:56 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.174; Received: by mail-vc0-f174.google.com with SMTP id im17so1298816vcb.33 for ; Wed, 29 Jan 2014 08:27:56 -0800 (PST) X-Received: by 10.220.191.134 with SMTP id dm6mr7443781vcb.16.1391012876250; Wed, 29 Jan 2014 08:27:56 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp126180vcz; Wed, 29 Jan 2014 08:27:55 -0800 (PST) X-Received: by 10.180.219.44 with SMTP id pl12mr6448643wic.12.1391012875314; Wed, 29 Jan 2014 08:27:55 -0800 (PST) Received: from casper.infradead.org (casper.infradead.org. [2001:770:15f::2]) by mx.google.com with ESMTPS id ea9si1723811wib.21.2014.01.29.08.27.54 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Jan 2014 08:27:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:770:15f::2 as permitted sender) client-ip=2001:770:15f::2; Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W8Xxr-00029m-1x; Wed, 29 Jan 2014 16:26:12 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1W8XxW-0000d8-O8; Wed, 29 Jan 2014 16:25:50 +0000 Received: from eu1sys200aog103.obsmtp.com ([207.126.144.115]) by merlin.infradead.org with smtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W8Xww-0000ZW-OY for linux-arm-kernel@lists.infradead.org; Wed, 29 Jan 2014 16:25:16 +0000 Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob103.postini.com ([207.126.147.11]) with SMTP ID DSNKUukrU6kAX2faFwHocbZkoOfmMlbtEDYF@postini.com; Wed, 29 Jan 2014 16:25:14 UTC Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id B87A410A; Wed, 29 Jan 2014 16:23:33 +0000 (GMT) Received: from mail7.sgp.st.com (unknown [164.129.223.81]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 991152C66A; Wed, 29 Jan 2014 16:24:21 +0000 (GMT) Received: from lmenx29l.st.com (lmenx29l.lme.st.com [10.201.23.80]) by mail7.sgp.st.com (MOS 4.3.3-GA) with ESMTP id BWY31345 (AUTH lme00137); Wed, 29 Jan 2014 17:24:18 +0100 From: Maxime COQUELIN To: Mike Turquette , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/3] clk: divider: Fix best div calculation for power-of-two and table dividers Date: Wed, 29 Jan 2014 17:24:06 +0100 Message-Id: <1391012648-12481-2-git-send-email-maxime.coquelin@st.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1391012648-12481-1-git-send-email-maxime.coquelin@st.com> References: <1391012648-12481-1-git-send-email-maxime.coquelin@st.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140129_112515_048791_7217EC63 X-CRM114-Status: GOOD ( 16.23 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [207.126.144.115 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: kernel@stlinux.com, maxime.coquelin@st.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: maxime.coquelin@st.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 The divider returned by clk_divider_bestdiv() is likely to be invalid in case of power-of-two and table dividers when CLK_SET_RATE_PARENT flag isn't set. Signed-off-by: Maxime Coquelin --- drivers/clk/clk-divider.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 5543b7d..2137d58 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -144,6 +144,37 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div) return true; } +static int _round_up_table(const struct clk_div_table *table, int div) +{ + const struct clk_div_table *clkt; + int up = _get_table_maxdiv(table); + + for (clkt = table; clkt->div; clkt++) { + if (clkt->div == div) + return clkt->div; + else if (clkt->div < div) + continue; + + if ((clkt->div - div) < (up - div)) + up = clkt->div; + } + + return up; +} + +static int _div_round_up(struct clk_divider *divider, + unsigned long parent_rate, unsigned long rate) +{ + int div = DIV_ROUND_UP(parent_rate, rate); + + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + div = __roundup_pow_of_two(div); + if (divider->table) + div = _round_up_table(divider->table, div); + + return div; +} + static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate) { @@ -159,7 +190,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { parent_rate = *best_parent_rate; - bestdiv = DIV_ROUND_UP(parent_rate, rate); + bestdiv = _div_round_up(divider, parent_rate, rate); bestdiv = bestdiv == 0 ? 1 : bestdiv; bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; return bestdiv; @@ -219,6 +250,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, u32 val; div = parent_rate / rate; + + if (!_is_valid_div(divider, div)) + return -EINVAL; + value = _get_val(divider, div); if (value > div_mask(divider))