From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linuxfoundation.org ([140.211.169.12]:52930 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2436559AbeHATSi (ORCPT ); Wed, 1 Aug 2018 15:18:38 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mike Looijmans , Stephen Boyd , Sasha Levin Subject: [PATCH 4.17 056/336] clk-si544: Properly round requested frequency to nearest match Date: Wed, 1 Aug 2018 18:46:31 +0200 Message-Id: <20180801165031.218891845@linuxfoundation.org> In-Reply-To: <20180801165028.930831994@linuxfoundation.org> References: <20180801165028.930831994@linuxfoundation.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: stable-owner@vger.kernel.org List-ID: 4.17-stable review patch. If anyone has any objections, please let me know. ------------------ From: Mike Looijmans [ Upstream commit 4d3f36c5e9ca0f947eed71660239c529c501141a ] The si544 driver had a rounding problem that using the result of clk_round_rate may set the clock to yet another rate, for example: clk_round_rate(195000000) = 194999999 clk_round_rate(194999999) = 194999998 Clients would expect that after clk_set_rate(clk, freq2=clk_round_rate(clk, freq)) the chip will be running at exactly freq2. The problem was in the calculation of the feedback divider, it was always rounded down instead of to the nearest possible VCO value. After this change, the following holds true for any supported frequency: actual_freq = clk_round_rate(clk, freq); clk_set_rate(clk, actual_freq); clk_round_rate(clk, actual_freq) == actual_freq && clk_get_rate(clk) == actual_freq Signed-off-by: Mike Looijmans Fixes: 953cc3e81170 ("clk: Add driver for the si544 clock generator chip") Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/clk/clk-si544.c | 1 + 1 file changed, 1 insertion(+) --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -207,6 +207,7 @@ static int si544_calc_muldiv(struct clk_ /* And the fractional bits using the remainder */ vco = (u64)tmp << 32; + vco += FXO / 2; /* Round to nearest multiple */ do_div(vco, FXO); settings->fb_div_frac = vco;