From: Brian Masney <bmasney@redhat.com>
To: Yu-Chun Lin <eleanor.lin@realtek.com>
Cc: mturquette@baylibre.com, sboyd@kernel.org, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, p.zabel@pengutronix.de,
cylee12@realtek.com, afaerber@suse.com, jyanchou@realtek.com,
devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org, james.tai@realtek.com,
cy.huang@realtek.com, stanley_chang@realtek.com
Subject: Re: [PATCH v6 04/10] clk: realtek: Add support for phase locked loops (PLLs)
Date: Fri, 3 Apr 2026 10:34:44 -0400 [thread overview]
Message-ID: <ac_QBGY8VxcvuVlY@redhat.com> (raw)
In-Reply-To: <20260402073957.2742459-5-eleanor.lin@realtek.com>
Hi Cheng-Yu,
On Thu, Apr 02, 2026 at 03:39:51PM +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
>
> Provide a full set of PLL operations for programmable PLLs and a read-only
> variant for fixed or hardware-managed PLLs.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v6:
> - Add the headers used in c file to follow the "Include What You Use" principle.
> - Move to_clk_pll() from clk-pll.h to clk-pll.c to limit its scope.
> ---
> drivers/clk/realtek/Makefile | 2 +
> drivers/clk/realtek/clk-pll.c | 164 +++++++++++++++++++++++++++++++
> drivers/clk/realtek/clk-pll.h | 42 ++++++++
> drivers/clk/realtek/freq_table.c | 36 +++++++
> drivers/clk/realtek/freq_table.h | 21 ++++
> 5 files changed, 265 insertions(+)
> create mode 100644 drivers/clk/realtek/clk-pll.c
> create mode 100644 drivers/clk/realtek/clk-pll.h
> create mode 100644 drivers/clk/realtek/freq_table.c
> create mode 100644 drivers/clk/realtek/freq_table.h
>
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index 377ec776ee47..a89ad77993e9 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -2,3 +2,5 @@
> obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
>
> clk-rtk-y += common.o
> +clk-rtk-y += clk-pll.o
> +clk-rtk-y += freq_table.o
> diff --git a/drivers/clk/realtek/clk-pll.c b/drivers/clk/realtek/clk-pll.c
> new file mode 100644
> index 000000000000..44730b22a94c
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-pll.c
> @@ -0,0 +1,164 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2024 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <linux/regmap.h>
> +#include "clk-pll.h"
> +
> +#define TIMEOUT 2000
> +
> +static inline struct clk_pll *to_clk_pll(struct clk_hw *hw)
> +{
> + struct clk_regmap *clkr = to_clk_regmap(hw);
> +
> + return container_of(clkr, struct clk_pll, clkr);
> +}
> +
> +static int wait_freq_ready(struct clk_pll *clkp)
> +{
> + u32 pollval;
> +
> + if (!clkp->freq_ready_valid)
> + return 0;
> +
> + return regmap_read_poll_timeout_atomic(clkp->clkr.regmap, clkp->freq_ready_reg, pollval,
> + (pollval & clkp->freq_ready_mask)
> + == clkp->freq_ready_val, 0, TIMEOUT);
I would put the "(pollval & clkp->freq_ready_mask) == clkp->freq_ready_val" on
the same line to improve readability. You can go out to 100 characters.
Also should the delay be greater than 0 to avoid tons of constant
retries?
> +}
> +
> +static bool is_power_on(struct clk_pll *clkp)
> +{
> + u32 val;
> +
> + if (!clkp->power_reg)
> + return true;
> +
> + if (regmap_read(clkp->clkr.regmap, clkp->power_reg, &val))
> + return true;
Is the intention if there is an error, then it marks it as success?
> +
> + return (val & clkp->power_mask) == clkp->power_val_on;
> +}
> +
> +static void clk_pll_disable(struct clk_hw *hw)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> +
> + if (!clkp->seq_power_off)
> + return;
> +
> + regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_off,
> + clkp->num_seq_power_off);
> +}
> +
> +static int clk_pll_is_enabled(struct clk_hw *hw)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> +
> + return is_power_on(clkp);
> +}
> +
> +static int clk_pll_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> + const struct freq_table *ftblv = NULL;
> +
> + ftblv = ftbl_find_by_rate(clkp->freq_tbl, req->rate);
> + if (!ftblv)
> + return -EINVAL;
> +
> + req->rate = ftblv->rate;
> + return 0;
Add newline before return.
> +}
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> + const struct freq_table *fv;
> + u32 freq_val;
> +
> + if (regmap_read(clkp->clkr.regmap, clkp->freq_reg, &freq_val))
> + return 0;
> +
> + freq_val &= clkp->freq_mask;
> +
> + fv = ftbl_find_by_val_with_mask(clkp->freq_tbl, clkp->freq_mask,
> + freq_val);
> + return fv ? fv->rate : 0;
Add newline before return.
> +}
> +
> +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> + const struct freq_table *fv;
> + int ret;
> +
> + fv = ftbl_find_by_rate(clkp->freq_tbl, rate);
> + if (!fv || fv->rate != rate)
> + return -EINVAL;
> +
> + if (clkp->seq_pre_set_freq) {
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_pre_set_freq,
> + clkp->num_seq_pre_set_freq);
> + if (ret)
> + return ret;
> + }
> +
> + ret = regmap_update_bits(clkp->clkr.regmap, clkp->freq_reg,
> + clkp->freq_mask, fv->val);
> + if (ret)
> + return ret;
> +
> + if (clkp->seq_post_set_freq) {
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_post_set_freq,
> + clkp->num_seq_post_set_freq);
> + if (ret)
> + return ret;
> + }
> +
> + if (is_power_on(clkp)) {
> + ret = wait_freq_ready(clkp);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int clk_pll_enable(struct clk_hw *hw)
> +{
> + struct clk_pll *clkp = to_clk_pll(hw);
> + int ret;
> +
> + if (!clkp->seq_power_on)
> + return 0;
> +
> + if (is_power_on(clkp))
> + return 0;
> +
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_on,
> + clkp->num_seq_power_on);
> + if (ret)
> + return ret;
> +
> + return wait_freq_ready(clkp);
> +}
> +
> +const struct clk_ops rtk_clk_pll_ops = {
> + .enable = clk_pll_enable,
> + .disable = clk_pll_disable,
> + .is_enabled = clk_pll_is_enabled,
> + .recalc_rate = clk_pll_recalc_rate,
> + .determine_rate = clk_pll_determine_rate,
> + .set_rate = clk_pll_set_rate,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ops, "REALTEK_CLK");
> +
> +const struct clk_ops rtk_clk_pll_ro_ops = {
> + .recalc_rate = clk_pll_recalc_rate,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ro_ops, "REALTEK_CLK");
> diff --git a/drivers/clk/realtek/clk-pll.h b/drivers/clk/realtek/clk-pll.h
> new file mode 100644
> index 000000000000..00884585a242
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-pll.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2017-2019 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#ifndef __CLK_REALTEK_CLK_PLL_H
> +#define __CLK_REALTEK_CLK_PLL_H
> +
> +#include "common.h"
> +#include "freq_table.h"
> +
> +struct reg_sequence;
> +
> +struct clk_pll {
> + struct clk_regmap clkr;
> + const struct reg_sequence *seq_power_on;
> + u32 num_seq_power_on;
> + const struct reg_sequence *seq_power_off;
> + u32 num_seq_power_off;
> + const struct reg_sequence *seq_pre_set_freq;
> + u32 num_seq_pre_set_freq;
> + const struct reg_sequence *seq_post_set_freq;
> + u32 num_seq_post_set_freq;
> + const struct freq_table *freq_tbl;
> + u32 freq_reg;
> + u32 freq_mask;
> + u32 freq_ready_valid;
> + u32 freq_ready_mask;
> + u32 freq_ready_reg;
> + u32 freq_ready_val;
> + u32 power_reg;
> + u32 power_mask;
> + u32 power_val_on;
> +};
> +
> +#define __clk_pll_hw(_ptr) __clk_regmap_hw(&(_ptr)->clkr)
> +
> +extern const struct clk_ops rtk_clk_pll_ops;
> +extern const struct clk_ops rtk_clk_pll_ro_ops;
> +
> +#endif /* __CLK_REALTEK_CLK_PLL_H */
> diff --git a/drivers/clk/realtek/freq_table.c b/drivers/clk/realtek/freq_table.c
> new file mode 100644
> index 000000000000..272a10e75a54
> --- /dev/null
> +++ b/drivers/clk/realtek/freq_table.c
> @@ -0,0 +1,36 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <linux/bitops.h>
> +#include "freq_table.h"
> +
> +const struct freq_table *ftbl_find_by_rate(const struct freq_table *ftbl,
> + unsigned long rate)
> +{
> + unsigned long best_rate = 0;
> + const struct freq_table *best = NULL;
Put variables in reverse Christmas tree order.
> +
> + for (; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
> + if (ftbl->rate == rate)
> + return ftbl;
> +
> + if (ftbl->rate > rate)
> + continue;
> +
> + if (ftbl->rate > best_rate) {
> + best_rate = ftbl->rate;
> + best = ftbl;
> + }
> + }
> +
> + return best;
> +}
> +
> +const struct freq_table *
> +ftbl_find_by_val_with_mask(const struct freq_table *ftbl, u32 mask, u32 value)
> +{
> + for (; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
> + if ((ftbl->val & mask) == (value & mask))
> + return ftbl;
> + }
> + return NULL;
> +};
> diff --git a/drivers/clk/realtek/freq_table.h b/drivers/clk/realtek/freq_table.h
> new file mode 100644
> index 000000000000..6d9116651105
> --- /dev/null
> +++ b/drivers/clk/realtek/freq_table.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +struct freq_table {
> + u32 val;
> + unsigned long rate;
> +};
> +
> +/* ofs check */
> +#define CLK_OFS_INVALID -1
> +#define CLK_OFS_IS_VALID(_ofs) ((_ofs) != CLK_OFS_INVALID)
Is this used anywhere?
Brian
> +
> +#define FREQ_TABLE_END \
> + { \
> + .rate = 0 \
> + }
> +#define IS_FREQ_TABLE_END(_f) ((_f)->rate == 0)
> +
> +const struct freq_table *ftbl_find_by_rate(const struct freq_table *ftbl,
> + unsigned long rate);
> +const struct freq_table *
> +ftbl_find_by_val_with_mask(const struct freq_table *ftbl, u32 mask, u32 value);
> --
> 2.34.1
>
next prev parent reply other threads:[~2026-04-03 14:35 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 7:39 [PATCH v6 00/10] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 01/10] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 02/10] reset: Add Realtek basic reset support Yu-Chun Lin
2026-04-02 9:15 ` Philipp Zabel
2026-04-10 6:49 ` Yu-Chun Lin [林祐君]
2026-04-02 7:39 ` [PATCH v6 03/10] clk: realtek: Introduce a common probe() Yu-Chun Lin
2026-04-03 14:21 ` Brian Masney
2026-04-10 7:22 ` Yu-Chun Lin [林祐君]
2026-04-02 7:39 ` [PATCH v6 04/10] clk: realtek: Add support for phase locked loops (PLLs) Yu-Chun Lin
2026-04-03 14:34 ` Brian Masney [this message]
2026-04-10 7:43 ` Yu-Chun Lin [林祐君]
2026-04-03 14:44 ` Brian Masney
2026-04-10 7:53 ` Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 05/10] clk: realtek: Add support for gate clock Yu-Chun Lin
2026-04-03 14:40 ` Brian Masney
2026-04-10 8:19 ` Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 06/10] clk: realtek: Add support for mux clock Yu-Chun Lin
2026-04-03 14:54 ` Brian Masney
2026-04-10 8:24 ` Yu-Chun Lin [林祐君]
2026-04-02 7:39 ` [PATCH v6 07/10] clk: realtek: Add support for MMC-tuned PLL clocks Yu-Chun Lin
2026-04-03 15:07 ` Brian Masney
2026-04-17 7:40 ` Yu-Chun Lin
2026-04-03 15:10 ` Brian Masney
2026-04-17 7:43 ` Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 08/10] clk: realtek: Add RTD1625-CRT clock controller driver Yu-Chun Lin
2026-04-03 15:24 ` Brian Masney
2026-04-17 7:45 ` Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 09/10] clk: realtek: Add RTD1625-ISO " Yu-Chun Lin
2026-04-03 15:29 ` Brian Masney
2026-04-17 8:09 ` Yu-Chun Lin
2026-04-02 7:39 ` [PATCH v6 10/10] arm64: dts: realtek: Add clock support for RTD1625 Yu-Chun Lin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ac_QBGY8VxcvuVlY@redhat.com \
--to=bmasney@redhat.com \
--cc=afaerber@suse.com \
--cc=conor+dt@kernel.org \
--cc=cy.huang@realtek.com \
--cc=cylee12@realtek.com \
--cc=devicetree@vger.kernel.org \
--cc=eleanor.lin@realtek.com \
--cc=james.tai@realtek.com \
--cc=jyanchou@realtek.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-realtek-soc@lists.infradead.org \
--cc=mturquette@baylibre.com \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=stanley_chang@realtek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.