Message ID | 20230702-pll-mipi_set_rate_parent-v3-5-46dcb8aa9cbc@oltmanns.dev |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9f45:0:b0:3ea:f831:8777 with SMTP id v5csp88447vqx; Sun, 2 Jul 2023 11:23:32 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5GjwL93U9dg27RbZ72o7ASxkoILuuY6YsbzzdxwMYon0DC48Y4ssGQsVsulMVS4tdI1i/4 X-Received: by 2002:a05:6a20:8e01:b0:123:149b:a34f with SMTP id y1-20020a056a208e0100b00123149ba34fmr12125814pzj.1.1688322211993; Sun, 02 Jul 2023 11:23:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688322211; cv=none; d=google.com; s=arc-20160816; b=wj05Q0zJBrSr81ARX/jVkULe/JnffwPm8Y4x4jommMXbMD+rM3HGzZvT6IyyZrT79+ grEmTzfCTiaWjBTyU1eGYRaK8yvzYGOmo/qfjrMrvHGtvxPvenibAq8mkyDzOWmWrs+s 1SWkIBCeMevDUQDVvWUV7Bs0jdz5efqwcCq/kXkSLdCKi9rtO3TsQ9JMSHaV5L42O/i4 H0YnlL2dxeO+bp7r8yi78HROf3KWZbNwGvxMc8NQgcIpTDOAsYcD8u7cdX6daQNWR9NA wBBhlqBEkiAYkr5NTsASUnAn6wLkXKuFNjHMa039rfih10QJ/38MATfeBHsYB0tGyLGv 449w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=aq590HVBEwg50wkxos7ahgh1JLWFQV+J8aVVvHi0a4Y=; fh=qochKExQAM0bhcnc+r+ZD43ZS//6TaZetJnkaAgsyOw=; b=NksO4l5KHbpGKWvX881P9Y4FSEMuMHodHTRkMZLyGuR2vJFGt+1zSFDAumcb0HlOuZ toNkyd9Zn9tBoerhHaXsOOPe+vU3U8U/6TE+QwfQ7Gjo5zqWyHrulm1YWUqGmIuMSdR5 ia5HeNNTPuzQueodibfnBed5oY3R+txR0i1rtX5O5Y9m8ndsXzjLqYY/VpX7rzacidXy vkb5k95EupQcnYo50zKMC0UtfFe/Kx3toGNtTLSwfLJ+PmRFVYkDJhuQ1ACHMDwyueId CxWJrrVd96cJFkCzYRuSp0eoyDboc61zmW4OaVwBAMxf1TzDkohjHxzo/tlcrvldJhih gC0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@oltmanns.dev header.s=MBO0001 header.b="sp5J/ikk"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oltmanns.dev Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j16-20020a63e750000000b0053eeed3d26asi16565237pgk.688.2023.07.02.11.23.17; Sun, 02 Jul 2023 11:23:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@oltmanns.dev header.s=MBO0001 header.b="sp5J/ikk"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oltmanns.dev Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230102AbjGBR4N (ORCPT <rfc822;ivan.orlov0322@gmail.com> + 99 others); Sun, 2 Jul 2023 13:56:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229947AbjGBRz6 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sun, 2 Jul 2023 13:55:58 -0400 Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [IPv6:2001:67c:2050:0:465::201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B2650E61; Sun, 2 Jul 2023 10:55:55 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4QvGty2ygmz9sjH; Sun, 2 Jul 2023 19:55:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oltmanns.dev; s=MBO0001; t=1688320554; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aq590HVBEwg50wkxos7ahgh1JLWFQV+J8aVVvHi0a4Y=; b=sp5J/ikkFc4sG/tZVmx7vim/b4tes2DMOeGREJ0+Am3L/iIpglGd451ODGeccWD/oSayT2 KIghBJLi6i4mEH5MnomDsDC4kMHhZiwAIBfNp25zrxRy9AwKCnNbtCNCkWpaPfbdf3p/YN J+Vxj18uxXlEzKUNOmKn6Xo4hQCdjBSo78WUm8OjNzbgbn0cA4NU8obdpMyYy1ASPygTqM L04KLs/3m3Y04whldj3CEi+idzvlflpbDMTdOgS+HPhnghtVl88iP563MAf0MSu17BX8Tj sX0vWVd/YrVs9xHIczgD26PHK3fySe1QFOURUAbLsL/t7YvbJ0oFDJ/GnGlwBA== From: Frank Oltmanns <frank@oltmanns.dev> Date: Sun, 02 Jul 2023 19:55:24 +0200 Subject: [PATCH v3 5/8] clk: sunxi-ng: nkm: Support finding closest rate MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230702-pll-mipi_set_rate_parent-v3-5-46dcb8aa9cbc@oltmanns.dev> References: <20230702-pll-mipi_set_rate_parent-v3-0-46dcb8aa9cbc@oltmanns.dev> In-Reply-To: <20230702-pll-mipi_set_rate_parent-v3-0-46dcb8aa9cbc@oltmanns.dev> To: Maxime Ripard <maxime@cerno.tech>, Michael Turquette <mturquette@baylibre.com>, Stephen Boyd <sboyd@kernel.org>, Chen-Yu Tsai <wens@csie.org>, Jernej Skrabec <jernej.skrabec@gmail.com>, Samuel Holland <samuel@sholland.org>, Andre Przywara <andre.przywara@arm.com>, Roman Beranek <me@crly.cz> Cc: linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Frank Oltmanns <frank@oltmanns.dev> X-Developer-Signature: v=1; a=openpgp-sha256; l=5689; i=frank@oltmanns.dev; h=from:subject:message-id; bh=01TYbYHSpWpEljajLcjLJtavTtPY0wbp20arNVgfXdk=; b=owEB7QES/pANAwAIAZppogiUStPHAcsmYgBkobocbibhLaXOZS9QFPeBBunCc7/+EdaOJX2Bx Kw/P870HFKJAbMEAAEIAB0WIQQC/SV7f5DmuaVET5aaaaIIlErTxwUCZKG6HAAKCRCaaaIIlErT x5LsDACBuood8TCghOul1h0Z0uWTsL+qOFEbf5SrDXrAA8Gh3TxAAkDJNuwr+P3qiTYHJTl4V81 1f1IJ5VDj+osn/SZfCADWNn0ii+hXFJekCxeykaZaJmFtudM8USZskZ2z1bowms9Kcm4+jRC53g JYg0iDOO7Mnj8DH8S/ip+Di2+ugxWwzi95t9lf7kxL9vhVhTP8J7S4tQYSjBNSlOvKaKvTzHO53 4nbF4wnU5zwncRPP9KCIlmito4mOSArUyZQAml1/M4y8YwyGgR6fMnavq9swFAd3uS3SmEP48xU 6NQFWBnpBZrWXcySWmPOdATDfw80yeTzUVSqZtVQeSLx9bpl+DGxtMI6WTljKDUxEptUFn/kmzs SAAg1mHka5vwnou+4rd0zXw8gWu1bp6h5mstTNU4kq3nTNz4G2hQrT73YsYNzuTdMk7jaOHJmvq zUojXNqeOdFFHN9HUnZVQGtK9EeoeCuGYSWtiaYXVUeebtwKgAUC5oFYzfxaWIWgjF+Bs= X-Developer-Key: i=frank@oltmanns.dev; a=openpgp; fpr=02FD257B7F90E6B9A5444F969A69A208944AD3C7 X-Rspamd-Queue-Id: 4QvGty2ygmz9sjH X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1770334151644426110?= X-GMAIL-MSGID: =?utf-8?q?1770334151644426110?= |
Series |
clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate
|
|
Commit Message
Frank Oltmanns
July 2, 2023, 5:55 p.m. UTC
When finding the best rate for a NKM clock, consider rates that are
higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is
set.
Accommodate ccu_mux_helper_determine_rate to this change.
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++-----
drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++-----------
2 files changed, 54 insertions(+), 17 deletions(-)
Comments
Hi Frank, kernel test robot noticed the following build warnings: [auto build test WARNING on 6995e2de6891c724bfeb2db33d7b87775f913ad1] url: https://github.com/intel-lab-lkp/linux/commits/Frank-Oltmanns/clk-sunxi-ng-nkm-consider-alternative-parent-rates-when-determining-rate/20230703-015726 base: 6995e2de6891c724bfeb2db33d7b87775f913ad1 patch link: https://lore.kernel.org/r/20230702-pll-mipi_set_rate_parent-v3-5-46dcb8aa9cbc%40oltmanns.dev patch subject: [PATCH v3 5/8] clk: sunxi-ng: nkm: Support finding closest rate config: riscv-rv32_defconfig (https://download.01.org/0day-ci/archive/20230703/202307030302.s1bheEun-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a) reproduce: (https://download.01.org/0day-ci/archive/20230703/202307030302.s1bheEun-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202307030302.s1bheEun-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/clk/sunxi-ng/ccu_nkm.c:46:24: warning: variable 'tmp_diff' is uninitialized when used here [-Wuninitialized] 46 | tmp_diff = rate - tmp_diff; | ^~~~~~~~ drivers/clk/sunxi-ng/ccu_nkm.c:33:27: note: initialize the variable 'tmp_diff' to silence this warning 33 | unsigned long tmp_diff; | ^ | = 0 drivers/clk/sunxi-ng/ccu_nkm.c:93:24: warning: variable 'tmp_diff' is uninitialized when used here [-Wuninitialized] 93 | tmp_diff = rate - tmp_diff; | ^~~~~~~~ drivers/clk/sunxi-ng/ccu_nkm.c:82:27: note: initialize the variable 'tmp_diff' to silence this warning 82 | unsigned long tmp_diff; | ^ | = 0 2 warnings generated. vim +/tmp_diff +46 drivers/clk/sunxi-ng/ccu_nkm.c 19 20 static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, 21 struct _ccu_nkm *nkm, struct clk_hw *phw, 22 unsigned long features) 23 { 24 unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; 25 unsigned long best_diff = ULONG_MAX; 26 unsigned long best_n = 0, best_k = 0, best_m = 0; 27 unsigned long _n, _k, _m; 28 29 for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { 30 for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { 31 for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { 32 unsigned long tmp_rate; 33 unsigned long tmp_diff; 34 35 tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); 36 37 tmp_rate = tmp_parent * _n * _k / _m; 38 39 if (features & CCU_FEATURE_CLOSEST_RATE) { 40 tmp_diff = rate > tmp_rate ? 41 rate - tmp_rate : 42 tmp_rate - rate; 43 } else { 44 if (tmp_rate > rate) 45 continue; > 46 tmp_diff = rate - tmp_diff; 47 } 48 49 if (tmp_diff < best_diff) { 50 best_rate = tmp_rate; 51 best_parent_rate = tmp_parent; 52 best_diff = tmp_diff; 53 best_n = _n; 54 best_k = _k; 55 best_m = _m; 56 } 57 } 58 } 59 } 60 61 nkm->n = best_n; 62 nkm->k = best_k; 63 nkm->m = best_m; 64 65 *parent = best_parent_rate; 66 67 return best_rate; 68 } 69
On 2023-07-02 at 19:55:24 +0200, Frank Oltmanns <frank@oltmanns.dev> wrote: > When finding the best rate for a NKM clock, consider rates that are > higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is > set. > > Accommodate ccu_mux_helper_determine_rate to this change. > > Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> > --- > drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++----- > drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++----------- > 2 files changed, 54 insertions(+), 17 deletions(-) > > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c > index 1d557e323169..8594d6a4addd 100644 > --- a/drivers/clk/sunxi-ng/ccu_mux.c > +++ b/drivers/clk/sunxi-ng/ccu_mux.c > @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > } > > for (i = 0; i < clk_hw_get_num_parents(hw); i++) { > - unsigned long tmp_rate, parent_rate; > + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; > struct clk_hw *parent; > > parent = clk_hw_get_parent_by_index(hw, i); > @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > goto out; > } > > - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > - best_rate = tmp_rate; > - best_parent_rate = parent_rate; > - best_parent = parent; > + if (common->features & CCU_FEATURE_CLOSEST_RATE) { > + unsigned long tmp_diff = req->rate > tmp_rate ? > + req->rate - tmp_rate : > + tmp_rate - req->rate; > + > + if (tmp_diff < best_diff) { > + best_rate = tmp_rate; > + best_parent_rate = parent_rate; > + best_parent = parent; > + best_diff = tmp_diff; > + } > + } else { > + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > + best_rate = tmp_rate; > + best_parent_rate = parent_rate; > + best_parent = parent; > + } > } > } > > diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c > index d83843e69c25..36d9e987e4d8 100644 > --- a/drivers/clk/sunxi-ng/ccu_nkm.c > +++ b/drivers/clk/sunxi-ng/ccu_nkm.c > @@ -18,9 +18,11 @@ struct _ccu_nkm { > }; > > static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, > - struct _ccu_nkm *nkm, struct clk_hw *phw) > + struct _ccu_nkm *nkm, struct clk_hw *phw, > + unsigned long features) > { > - unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent; > + unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; > + unsigned long best_diff = ULONG_MAX; > unsigned long best_n = 0, best_k = 0, best_m = 0; > unsigned long _n, _k, _m; > > @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un > for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { > for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { > unsigned long tmp_rate; > + unsigned long tmp_diff; > > tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); > > tmp_rate = tmp_parent * _n * _k / _m; > - if (tmp_rate > rate) > - continue; > > - if ((rate - tmp_rate) < (rate - best_rate)) { > + if (features & CCU_FEATURE_CLOSEST_RATE) { > + tmp_diff = rate > tmp_rate ? > + rate - tmp_rate : > + tmp_rate - rate; > + } else { > + if (tmp_rate > rate) > + continue; > + tmp_diff = rate - tmp_diff; Sorry, this should of course be tmp_diff = rate - tmp_rate. I'll fix that in v4. Also I'll do tests on my phone where CCU_FEATURE_CLOSEST_RATE is not set (i.e., without PATCH 8), so see if it replicates the old behaviour. I'll also look into adding kunit tests, so that this doesn't happen again. I'm not sure if this is feasible, but I'll ask here for advise, if/when I encounter obstacles. Best regards, Frank > + } > + > + if (tmp_diff < best_diff) { > best_rate = tmp_rate; > best_parent_rate = tmp_parent; > + best_diff = tmp_diff; > best_n = _n; > best_k = _k; > best_m = _m; > @@ -56,9 +68,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un > } > > static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, > - struct _ccu_nkm *nkm) > + struct _ccu_nkm *nkm, unsigned long features) > { > unsigned long best_rate = 0; > + unsigned long best_diff = ULONG_MAX; > unsigned long best_n = 0, best_k = 0, best_m = 0; > unsigned long _n, _k, _m; > > @@ -66,13 +79,23 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, > for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { > for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { > unsigned long tmp_rate; > + unsigned long tmp_diff; > > tmp_rate = parent * _n * _k / _m; > > - if (tmp_rate > rate) > - continue; > - if ((rate - tmp_rate) < (rate - best_rate)) { > + if (features & CCU_FEATURE_CLOSEST_RATE) { > + tmp_diff = rate > tmp_rate ? > + rate - tmp_rate : > + tmp_rate - rate; > + } else { > + if (tmp_rate > rate) > + continue; > + tmp_diff = rate - tmp_diff; > + } > + > + if (tmp_diff < best_diff) { > best_rate = tmp_rate; > + best_diff = tmp_diff; > best_n = _n; > best_k = _k; > best_m = _m; > @@ -164,9 +187,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, > rate *= nkm->fixed_post_div; > > if (!clk_hw_can_set_rate_parent(&nkm->common.hw)) > - rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm); > + rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, nkm->common.features); > else > - rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw); > + rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw, > + nkm->common.features); > > if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) > rate /= nkm->fixed_post_div; > @@ -201,7 +225,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, > _nkm.min_m = 1; > _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; > > - ccu_nkm_find_best(&parent_rate, rate, &_nkm); > + ccu_nkm_find_best(parent_rate, rate, &_nkm, nkm->common.features); > > spin_lock_irqsave(nkm->common.lock, flags);
On Mon, Jul 03, 2023 at 09:17:43AM +0200, Frank Oltmanns wrote: > > On 2023-07-02 at 19:55:24 +0200, Frank Oltmanns <frank@oltmanns.dev> wrote: > > When finding the best rate for a NKM clock, consider rates that are > > higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is > > set. > > > > Accommodate ccu_mux_helper_determine_rate to this change. > > > > Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> > > --- > > drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++----- > > drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++----------- > > 2 files changed, 54 insertions(+), 17 deletions(-) > > > > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c > > index 1d557e323169..8594d6a4addd 100644 > > --- a/drivers/clk/sunxi-ng/ccu_mux.c > > +++ b/drivers/clk/sunxi-ng/ccu_mux.c > > @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > > } > > > > for (i = 0; i < clk_hw_get_num_parents(hw); i++) { > > - unsigned long tmp_rate, parent_rate; > > + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; > > struct clk_hw *parent; > > > > parent = clk_hw_get_parent_by_index(hw, i); > > @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > > goto out; > > } > > > > - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > > - best_rate = tmp_rate; > > - best_parent_rate = parent_rate; > > - best_parent = parent; > > + if (common->features & CCU_FEATURE_CLOSEST_RATE) { > > + unsigned long tmp_diff = req->rate > tmp_rate ? > > + req->rate - tmp_rate : > > + tmp_rate - req->rate; > > + > > + if (tmp_diff < best_diff) { > > + best_rate = tmp_rate; > > + best_parent_rate = parent_rate; > > + best_parent = parent; > > + best_diff = tmp_diff; > > + } > > + } else { > > + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > > + best_rate = tmp_rate; > > + best_parent_rate = parent_rate; > > + best_parent = parent; > > + } > > } > > } > > > > diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c > > index d83843e69c25..36d9e987e4d8 100644 > > --- a/drivers/clk/sunxi-ng/ccu_nkm.c > > +++ b/drivers/clk/sunxi-ng/ccu_nkm.c > > @@ -18,9 +18,11 @@ struct _ccu_nkm { > > }; > > > > static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, > > - struct _ccu_nkm *nkm, struct clk_hw *phw) > > + struct _ccu_nkm *nkm, struct clk_hw *phw, > > + unsigned long features) > > { > > - unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent; > > + unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; > > + unsigned long best_diff = ULONG_MAX; > > unsigned long best_n = 0, best_k = 0, best_m = 0; > > unsigned long _n, _k, _m; > > > > @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un > > for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { > > for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { > > unsigned long tmp_rate; > > + unsigned long tmp_diff; > > > > tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); > > > > tmp_rate = tmp_parent * _n * _k / _m; > > - if (tmp_rate > rate) > > - continue; > > > > - if ((rate - tmp_rate) < (rate - best_rate)) { > > + if (features & CCU_FEATURE_CLOSEST_RATE) { > > + tmp_diff = rate > tmp_rate ? > > + rate - tmp_rate : > > + tmp_rate - rate; > > + } else { > > + if (tmp_rate > rate) > > + continue; > > + tmp_diff = rate - tmp_diff; > > Sorry, this should of course be tmp_diff = rate - tmp_rate. I'll fix > that in v4. Also I'll do tests on my phone where > CCU_FEATURE_CLOSEST_RATE is not set (i.e., without PATCH 8), so see if > it replicates the old behaviour. I'll also look into adding kunit tests, > so that this doesn't happen again. I'm not sure if this is feasible, but > I'll ask here for advise, if/when I encounter obstacles. While this would obviously be great, I don't think we have the infrastructure just yet to allow to easily add kunit tests for entire clocks. Maxime
On Sun, Jul 02, 2023 at 07:55:24PM +0200, Frank Oltmanns wrote: > When finding the best rate for a NKM clock, consider rates that are > higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is > set. > > Accommodate ccu_mux_helper_determine_rate to this change. > > Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> > --- > drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++----- > drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++----------- > 2 files changed, 54 insertions(+), 17 deletions(-) > > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c > index 1d557e323169..8594d6a4addd 100644 > --- a/drivers/clk/sunxi-ng/ccu_mux.c > +++ b/drivers/clk/sunxi-ng/ccu_mux.c > @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > } > > for (i = 0; i < clk_hw_get_num_parents(hw); i++) { > - unsigned long tmp_rate, parent_rate; > + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; > struct clk_hw *parent; > > parent = clk_hw_get_parent_by_index(hw, i); > @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > goto out; > } > > - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > - best_rate = tmp_rate; > - best_parent_rate = parent_rate; > - best_parent = parent; > + if (common->features & CCU_FEATURE_CLOSEST_RATE) { > + unsigned long tmp_diff = req->rate > tmp_rate ? > + req->rate - tmp_rate : > + tmp_rate - req->rate; > + > + if (tmp_diff < best_diff) { > + best_rate = tmp_rate; > + best_parent_rate = parent_rate; > + best_parent = parent; > + best_diff = tmp_diff; > + } > + } else { > + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > + best_rate = tmp_rate; > + best_parent_rate = parent_rate; > + best_parent = parent; > + } > } > } Like I said in the previous patch, I think we could do something like: bool ccu_is_better_rate(struct ccu_common *common, unsigned long target_rate, unsigned long current_rate, unsigned long best_rate) { if (common->features & CCU_FEATURE_CLOSEST_RATE) return abs(current_rate - target_rate) < abs(best_rate - target_rate); return current_rate <= target_rate && current_rate > best_rate; } Then, the code above would look like: if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) { best_rate = tmp_rate; best_parent_rate = parent_rate; best_parent = parent; } It's simpler, and we can share it easily between drivers. Maxime
On 2023-07-03 at 09:25:59 +0200, Maxime Ripard <maxime@cerno.tech> wrote: > [[PGP Signed Part:Undecided]] > On Mon, Jul 03, 2023 at 09:17:43AM +0200, Frank Oltmanns wrote: >> >> On 2023-07-02 at 19:55:24 +0200, Frank Oltmanns <frank@oltmanns.dev> wrote: >> > When finding the best rate for a NKM clock, consider rates that are >> > higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is >> > set. >> > >> > Accommodate ccu_mux_helper_determine_rate to this change. >> > >> > Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> >> > --- >> > drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++----- >> > drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++----------- >> > 2 files changed, 54 insertions(+), 17 deletions(-) >> > >> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c >> > index 1d557e323169..8594d6a4addd 100644 >> > --- a/drivers/clk/sunxi-ng/ccu_mux.c >> > +++ b/drivers/clk/sunxi-ng/ccu_mux.c >> > @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, >> > } >> > >> > for (i = 0; i < clk_hw_get_num_parents(hw); i++) { >> > - unsigned long tmp_rate, parent_rate; >> > + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; >> > struct clk_hw *parent; >> > >> > parent = clk_hw_get_parent_by_index(hw, i); >> > @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, >> > goto out; >> > } >> > >> > - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { >> > - best_rate = tmp_rate; >> > - best_parent_rate = parent_rate; >> > - best_parent = parent; >> > + if (common->features & CCU_FEATURE_CLOSEST_RATE) { >> > + unsigned long tmp_diff = req->rate > tmp_rate ? >> > + req->rate - tmp_rate : >> > + tmp_rate - req->rate; >> > + >> > + if (tmp_diff < best_diff) { >> > + best_rate = tmp_rate; >> > + best_parent_rate = parent_rate; >> > + best_parent = parent; >> > + best_diff = tmp_diff; >> > + } >> > + } else { >> > + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { >> > + best_rate = tmp_rate; >> > + best_parent_rate = parent_rate; >> > + best_parent = parent; >> > + } >> > } >> > } >> > >> > diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c >> > index d83843e69c25..36d9e987e4d8 100644 >> > --- a/drivers/clk/sunxi-ng/ccu_nkm.c >> > +++ b/drivers/clk/sunxi-ng/ccu_nkm.c >> > @@ -18,9 +18,11 @@ struct _ccu_nkm { >> > }; >> > >> > static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, >> > - struct _ccu_nkm *nkm, struct clk_hw *phw) >> > + struct _ccu_nkm *nkm, struct clk_hw *phw, >> > + unsigned long features) >> > { >> > - unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent; >> > + unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; >> > + unsigned long best_diff = ULONG_MAX; >> > unsigned long best_n = 0, best_k = 0, best_m = 0; >> > unsigned long _n, _k, _m; >> > >> > @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un >> > for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { >> > for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { >> > unsigned long tmp_rate; >> > + unsigned long tmp_diff; >> > >> > tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); >> > >> > tmp_rate = tmp_parent * _n * _k / _m; >> > - if (tmp_rate > rate) >> > - continue; >> > >> > - if ((rate - tmp_rate) < (rate - best_rate)) { >> > + if (features & CCU_FEATURE_CLOSEST_RATE) { >> > + tmp_diff = rate > tmp_rate ? >> > + rate - tmp_rate : >> > + tmp_rate - rate; >> > + } else { >> > + if (tmp_rate > rate) >> > + continue; >> > + tmp_diff = rate - tmp_diff; >> >> Sorry, this should of course be tmp_diff = rate - tmp_rate. I'll fix >> that in v4. Also I'll do tests on my phone where >> CCU_FEATURE_CLOSEST_RATE is not set (i.e., without PATCH 8), so see if >> it replicates the old behaviour. I'll also look into adding kunit tests, >> so that this doesn't happen again. I'm not sure if this is feasible, but >> I'll ask here for advise, if/when I encounter obstacles. > > While this would obviously be great, I don't think we have the > infrastructure just yet to allow to easily add kunit tests for entire > clocks. I think, clk_test.c provides a good blueprint. I tried to do that for clk-fractional-divider [1], but Stephen wanted to go a different route, so I dropped it. You could look at clk_fd_test_init() in [1]. A similar approach might work for the sunxi-ng clocks. I don't see any real blockers, but maybe that's me being naive. [1]: https://lore.kernel.org/all/20230614185521.477924-3-frank@oltmanns.dev/ Best regards, Frank > > Maxime > > [[End of PGP Signed Part]]
On Mon, Jul 03, 2023 at 10:59:43AM +0200, Frank Oltmanns wrote: > > On 2023-07-03 at 09:25:59 +0200, Maxime Ripard <maxime@cerno.tech> wrote: > > [[PGP Signed Part:Undecided]] > > On Mon, Jul 03, 2023 at 09:17:43AM +0200, Frank Oltmanns wrote: > >> > >> On 2023-07-02 at 19:55:24 +0200, Frank Oltmanns <frank@oltmanns.dev> wrote: > >> > When finding the best rate for a NKM clock, consider rates that are > >> > higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is > >> > set. > >> > > >> > Accommodate ccu_mux_helper_determine_rate to this change. > >> > > >> > Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> > >> > --- > >> > drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++----- > >> > drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++----------- > >> > 2 files changed, 54 insertions(+), 17 deletions(-) > >> > > >> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c > >> > index 1d557e323169..8594d6a4addd 100644 > >> > --- a/drivers/clk/sunxi-ng/ccu_mux.c > >> > +++ b/drivers/clk/sunxi-ng/ccu_mux.c > >> > @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > >> > } > >> > > >> > for (i = 0; i < clk_hw_get_num_parents(hw); i++) { > >> > - unsigned long tmp_rate, parent_rate; > >> > + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; > >> > struct clk_hw *parent; > >> > > >> > parent = clk_hw_get_parent_by_index(hw, i); > >> > @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, > >> > goto out; > >> > } > >> > > >> > - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > >> > - best_rate = tmp_rate; > >> > - best_parent_rate = parent_rate; > >> > - best_parent = parent; > >> > + if (common->features & CCU_FEATURE_CLOSEST_RATE) { > >> > + unsigned long tmp_diff = req->rate > tmp_rate ? > >> > + req->rate - tmp_rate : > >> > + tmp_rate - req->rate; > >> > + > >> > + if (tmp_diff < best_diff) { > >> > + best_rate = tmp_rate; > >> > + best_parent_rate = parent_rate; > >> > + best_parent = parent; > >> > + best_diff = tmp_diff; > >> > + } > >> > + } else { > >> > + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { > >> > + best_rate = tmp_rate; > >> > + best_parent_rate = parent_rate; > >> > + best_parent = parent; > >> > + } > >> > } > >> > } > >> > > >> > diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c > >> > index d83843e69c25..36d9e987e4d8 100644 > >> > --- a/drivers/clk/sunxi-ng/ccu_nkm.c > >> > +++ b/drivers/clk/sunxi-ng/ccu_nkm.c > >> > @@ -18,9 +18,11 @@ struct _ccu_nkm { > >> > }; > >> > > >> > static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, > >> > - struct _ccu_nkm *nkm, struct clk_hw *phw) > >> > + struct _ccu_nkm *nkm, struct clk_hw *phw, > >> > + unsigned long features) > >> > { > >> > - unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent; > >> > + unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; > >> > + unsigned long best_diff = ULONG_MAX; > >> > unsigned long best_n = 0, best_k = 0, best_m = 0; > >> > unsigned long _n, _k, _m; > >> > > >> > @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un > >> > for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { > >> > for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { > >> > unsigned long tmp_rate; > >> > + unsigned long tmp_diff; > >> > > >> > tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); > >> > > >> > tmp_rate = tmp_parent * _n * _k / _m; > >> > - if (tmp_rate > rate) > >> > - continue; > >> > > >> > - if ((rate - tmp_rate) < (rate - best_rate)) { > >> > + if (features & CCU_FEATURE_CLOSEST_RATE) { > >> > + tmp_diff = rate > tmp_rate ? > >> > + rate - tmp_rate : > >> > + tmp_rate - rate; > >> > + } else { > >> > + if (tmp_rate > rate) > >> > + continue; > >> > + tmp_diff = rate - tmp_diff; > >> > >> Sorry, this should of course be tmp_diff = rate - tmp_rate. I'll fix > >> that in v4. Also I'll do tests on my phone where > >> CCU_FEATURE_CLOSEST_RATE is not set (i.e., without PATCH 8), so see if > >> it replicates the old behaviour. I'll also look into adding kunit tests, > >> so that this doesn't happen again. I'm not sure if this is feasible, but > >> I'll ask here for advise, if/when I encounter obstacles. > > > > While this would obviously be great, I don't think we have the > > infrastructure just yet to allow to easily add kunit tests for entire > > clocks. > > I think, clk_test.c provides a good blueprint. I tried to do that for > clk-fractional-divider [1], but Stephen wanted to go a different route, > so I dropped it. You could look at clk_fd_test_init() in [1]. A similar > approach might work for the sunxi-ng clocks. I don't see any real > blockers, but maybe that's me being naive. The main issue will be probing and mocking. Those clocks are meant to be probed through the device tree and expect to have underlying registers accessible. We would need some way to mock / prevent any register access, while still registering a clock with its device tree node, parent, etc. for the tests to be meaningful. And that's not going to be an easy thing to do :) Maxime
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c index 1d557e323169..8594d6a4addd 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.c +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, } for (i = 0; i < clk_hw_get_num_parents(hw); i++) { - unsigned long tmp_rate, parent_rate; + unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX; struct clk_hw *parent; parent = clk_hw_get_parent_by_index(hw, i); @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, goto out; } - if ((req->rate - tmp_rate) < (req->rate - best_rate)) { - best_rate = tmp_rate; - best_parent_rate = parent_rate; - best_parent = parent; + if (common->features & CCU_FEATURE_CLOSEST_RATE) { + unsigned long tmp_diff = req->rate > tmp_rate ? + req->rate - tmp_rate : + tmp_rate - req->rate; + + if (tmp_diff < best_diff) { + best_rate = tmp_rate; + best_parent_rate = parent_rate; + best_parent = parent; + best_diff = tmp_diff; + } + } else { + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { + best_rate = tmp_rate; + best_parent_rate = parent_rate; + best_parent = parent; + } } } diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index d83843e69c25..36d9e987e4d8 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -18,9 +18,11 @@ struct _ccu_nkm { }; static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate, - struct _ccu_nkm *nkm, struct clk_hw *phw) + struct _ccu_nkm *nkm, struct clk_hw *phw, + unsigned long features) { - unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent; + unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent; + unsigned long best_diff = ULONG_MAX; unsigned long best_n = 0, best_k = 0, best_m = 0; unsigned long _n, _k, _m; @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { unsigned long tmp_rate; + unsigned long tmp_diff; tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k)); tmp_rate = tmp_parent * _n * _k / _m; - if (tmp_rate > rate) - continue; - if ((rate - tmp_rate) < (rate - best_rate)) { + if (features & CCU_FEATURE_CLOSEST_RATE) { + tmp_diff = rate > tmp_rate ? + rate - tmp_rate : + tmp_rate - rate; + } else { + if (tmp_rate > rate) + continue; + tmp_diff = rate - tmp_diff; + } + + if (tmp_diff < best_diff) { best_rate = tmp_rate; best_parent_rate = tmp_parent; + best_diff = tmp_diff; best_n = _n; best_k = _k; best_m = _m; @@ -56,9 +68,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un } static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, - struct _ccu_nkm *nkm) + struct _ccu_nkm *nkm, unsigned long features) { unsigned long best_rate = 0; + unsigned long best_diff = ULONG_MAX; unsigned long best_n = 0, best_k = 0, best_m = 0; unsigned long _n, _k, _m; @@ -66,13 +79,23 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { unsigned long tmp_rate; + unsigned long tmp_diff; tmp_rate = parent * _n * _k / _m; - if (tmp_rate > rate) - continue; - if ((rate - tmp_rate) < (rate - best_rate)) { + if (features & CCU_FEATURE_CLOSEST_RATE) { + tmp_diff = rate > tmp_rate ? + rate - tmp_rate : + tmp_rate - rate; + } else { + if (tmp_rate > rate) + continue; + tmp_diff = rate - tmp_diff; + } + + if (tmp_diff < best_diff) { best_rate = tmp_rate; + best_diff = tmp_diff; best_n = _n; best_k = _k; best_m = _m; @@ -164,9 +187,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, rate *= nkm->fixed_post_div; if (!clk_hw_can_set_rate_parent(&nkm->common.hw)) - rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm); + rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, nkm->common.features); else - rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw); + rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw, + nkm->common.features); if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) rate /= nkm->fixed_post_div; @@ -201,7 +225,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, _nkm.min_m = 1; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; - ccu_nkm_find_best(&parent_rate, rate, &_nkm); + ccu_nkm_find_best(parent_rate, rate, &_nkm, nkm->common.features); spin_lock_irqsave(nkm->common.lock, flags);