Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751984AbdHBDpb (ORCPT ); Tue, 1 Aug 2017 23:45:31 -0400 Received: from regular1.263xmail.com ([211.150.99.135]:51328 "EHLO regular1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751768AbdHBDpa (ORCPT ); Tue, 1 Aug 2017 23:45:30 -0400 X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-RL-SENDER: zhangqing@rock-chips.com X-FST-TO: xf@rock-chips.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: zhangqing@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 Message-ID: <59814A66.5070500@rock-chips.com> Date: Wed, 02 Aug 2017 11:43:34 +0800 From: Elaine Zhang User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Heiko Stuebner CC: mturquette@baylibre.com, sboyd@codeaurora.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, huangtao@rock-chips.com, cl@rock-chips.com, xxx@rock-chips.com, xf@rock-chips.com Subject: Re: [PATCH 1/2] clk: fractional-divider: allow overriding of approximation References: <1500624187-12165-1-git-send-email-zhangqing@rock-chips.com> <5990882.df1suBpf8V@phil> <5453089.AIzWDZk3ey@phil> In-Reply-To: <5453089.AIzWDZk3ey@phil> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2940 Lines: 87 hi,heiko: This a good solution.And I tested it on RK SOCs.It's work well. On 08/02/2017 12:21 AM, Heiko Stuebner wrote: > From: Elaine Zhang > > Fractional dividers may have special requirements concerning numerator > and denominator selection that differ from just getting the best > approximation. > > For example on Rockchip socs the denominator must be at least 20 times > larger than the numerator to generate precise clock frequencies. > > Therefore add the ability to provide custom approximation functions. > > Signed-off-by: Elaine Zhang > --- > drivers/clk/clk-fractional-divider.c | 28 ++++++++++++++++++++-------- > include/linux/clk-provider.h | 3 +++ > 2 files changed, 23 insertions(+), 8 deletions(-) > > diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c > index aab904618eb6..fdf625fb10fa 100644 > --- a/drivers/clk/clk-fractional-divider.c > +++ b/drivers/clk/clk-fractional-divider.c > @@ -49,16 +49,12 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, > return ret; > } > > -static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, > - unsigned long *parent_rate) > +static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate, > + unsigned long *parent_rate, > + unsigned long *m, unsigned long *n) > { > struct clk_fractional_divider *fd = to_clk_fd(hw); > unsigned long scale; > - unsigned long m, n; > - u64 ret; > - > - if (!rate || rate >= *parent_rate) > - return *parent_rate; > > /* > * Get rate closer to *parent_rate to guarantee there is no overflow > @@ -71,7 +67,23 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, > > rational_best_approximation(rate, *parent_rate, > GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), > - &m, &n); > + m, n); > +} > + > +static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long *parent_rate) > +{ > + struct clk_fractional_divider *fd = to_clk_fd(hw); > + unsigned long m, n; > + u64 ret; > + > + if (!rate || rate >= *parent_rate) > + return *parent_rate; > + > + if (fd->approximation) > + fd->approximation(hw, rate, parent_rate, &m, &n); > + else > + clk_fd_general_approximation(hw, rate, parent_rate, &m, &n); > > ret = (u64)*parent_rate * m; > do_div(ret, n); > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h > index c59c62571e4f..1fc113fbf955 100644 > --- a/include/linux/clk-provider.h > +++ b/include/linux/clk-provider.h > @@ -565,6 +565,9 @@ struct clk_fractional_divider { > u8 nwidth; > u32 nmask; > u8 flags; > + void (*approximation)(struct clk_hw *hw, > + unsigned long rate, unsigned long *parent_rate, > + unsigned long *m, unsigned long *n); > spinlock_t *lock; > }; > > Tested-by: Elaine Zhang