From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
To: "Michael Turquette" <mturquette@baylibre.com>,
"Stephen Boyd" <sboyd@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
"Guangjie Song" <guangjie.song@mediatek.com>,
"Laura Nao" <laura.nao@collabora.com>,
"Nícolas F. R. A. Prado" <nfraprado@collabora.com>,
"Yassine Oudjana" <y.oudjana@protonmail.com>,
"AngeloGioacchino Del Regno"
<angelogioacchino.delregno@collabora.com>
Cc: kernel@collabora.com,
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>,
linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org
Subject: Re: [PATCH 4/4] clk: mediatek: Add rpm clocks to clk-mt8196-mfg
Date: Wed, 01 Oct 2025 15:17:13 +0200 [thread overview]
Message-ID: <6441788.lOV4Wx5bFT@workhorse> (raw)
In-Reply-To: <748f1176-c73c-48af-a1af-0b63d088e834@collabora.com>
On Wednesday, 1 October 2025 13:49:54 Central European Summer Time AngeloGioacchino Del Regno wrote:
> Il 29/09/25 14:13, Nicolas Frattaroli ha scritto:
> > The mfgpll clocks on mt8196 require that the MFG's EB clock is on if
> > their control registers are touched in any way at all.
>
> ....so, the MFGPLL clocks are children of EB?
>
> Why are you using such a convoluted way of adding a parent clock to the MFGPLL
> instead of just
> ----> `.parent_name = "mfg_eb"` <-----
>
> ???????
They're not children. A child would mean that they derive their
clock rate from the parent clock. This isn't the relationship here
though, their clock signal is completely independent of mfg_eb,
but the registers they access for clock control depend on mfg_eb to
be on. This means that even if mfgpll is off, and something wants to
check if they're on or not, the mfg_eb needs to be on for that
register access to happen. Similarly, when reconfiguring the mfgpll
rate, the clock rate of mfg_eb plays no role. It just needs to be on
for the register access.
mfg_eb here is a clock that drives a register, the register just
happens to be part of a clock controller.
Kind regards,
Nicolas Frattaroli
>
> Cheers,
> Angelo
>
> > Failing to ensure
> > this results in a pleasant SError interrupt if the EB clock happens to
> > be off.
> >
> > To achieve this, leverage the CCF core's runtime power management
> > support. Define the necessary suspend/resume callbacks, add the
> > necessary code to get RPM clocks from the DT, and make sure RPM is
> > enabled before clock registration happens.
> >
> > For the RPM callbacks to really make much sense at all, we change the
> > drvdata from clk_data to a new private struct, as is common in drivers
> > across the Linux kernel.
> >
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> > ---
> > drivers/clk/mediatek/clk-mt8196-mfg.c | 104 +++++++++++++++++++++++++++-------
> > drivers/clk/mediatek/clk-pll.h | 2 +
> > 2 files changed, 87 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/clk/mediatek/clk-mt8196-mfg.c b/drivers/clk/mediatek/clk-mt8196-mfg.c
> > index 8e09c0f7b7548f8e286671cea2dac64530b8ce47..64cc0c037f62d7eab8d0e7fc00c05d122bf4130c 100644
> > --- a/drivers/clk/mediatek/clk-mt8196-mfg.c
> > +++ b/drivers/clk/mediatek/clk-mt8196-mfg.c
> > @@ -13,6 +13,7 @@
> > #include <linux/of_address.h>
> > #include <linux/of_device.h>
> > #include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> >
> > #include "clk-mtk.h"
> > #include "clk-pll.h"
> > @@ -38,7 +39,7 @@
> > _flags, _rst_bar_mask, \
> > _pd_reg, _pd_shift, _tuner_reg, \
> > _tuner_en_reg, _tuner_en_bit, \
> > - _pcw_reg, _pcw_shift, _pcwbits) { \
> > + _pcw_reg, _pcw_shift, _pcwbits, _rpm_clks) { \
> > .id = _id, \
> > .name = _name, \
> > .reg = _reg, \
> > @@ -58,26 +59,60 @@
> > .pcw_shift = _pcw_shift, \
> > .pcwbits = _pcwbits, \
> > .pcwibits = MT8196_INTEGER_BITS, \
> > + .rpm_clk_names = _rpm_clks, \
> > + .num_rpm_clks = ARRAY_SIZE(_rpm_clks), \
> > }
> >
> > +static const char * const mfgpll_rpm_clk_names[] = {
> > + NULL
> > +};
> > +
> > static const struct mtk_pll_data mfg_ao_plls[] = {
> > PLL(CLK_MFG_AO_MFGPLL, "mfgpll", MFGPLL_CON0, MFGPLL_CON0, 0, 0, 0,
> > - BIT(0), MFGPLL_CON1, 24, 0, 0, 0,
> > - MFGPLL_CON1, 0, 22),
> > + BIT(0), MFGPLL_CON1, 24, 0, 0, 0, MFGPLL_CON1, 0, 22,
> > + mfgpll_rpm_clk_names),
> > };
> >
> > static const struct mtk_pll_data mfgsc0_ao_plls[] = {
> > PLL(CLK_MFGSC0_AO_MFGPLL_SC0, "mfgpll-sc0", MFGPLL_SC0_CON0,
> > MFGPLL_SC0_CON0, 0, 0, 0, BIT(0), MFGPLL_SC0_CON1, 24, 0, 0, 0,
> > - MFGPLL_SC0_CON1, 0, 22),
> > + MFGPLL_SC0_CON1, 0, 22, mfgpll_rpm_clk_names),
> > };
> >
> > static const struct mtk_pll_data mfgsc1_ao_plls[] = {
> > PLL(CLK_MFGSC1_AO_MFGPLL_SC1, "mfgpll-sc1", MFGPLL_SC1_CON0,
> > MFGPLL_SC1_CON0, 0, 0, 0, BIT(0), MFGPLL_SC1_CON1, 24, 0, 0, 0,
> > - MFGPLL_SC1_CON1, 0, 22),
> > + MFGPLL_SC1_CON1, 0, 22, mfgpll_rpm_clk_names),
> > };
> >
> > +struct clk_mt8196_mfg {
> > + struct clk_hw_onecell_data *clk_data;
> > + struct clk_bulk_data *rpm_clks;
> > + unsigned int num_rpm_clks;
> > +};
> > +
> > +static int __maybe_unused clk_mt8196_mfg_resume(struct device *dev)
> > +{
> > + struct clk_mt8196_mfg *clk_mfg = dev_get_drvdata(dev);
> > +
> > + if (!clk_mfg || !clk_mfg->rpm_clks)
> > + return 0;
> > +
> > + return clk_bulk_prepare_enable(clk_mfg->num_rpm_clks, clk_mfg->rpm_clks);
> > +}
> > +
> > +static int __maybe_unused clk_mt8196_mfg_suspend(struct device *dev)
> > +{
> > + struct clk_mt8196_mfg *clk_mfg = dev_get_drvdata(dev);
> > +
> > + if (!clk_mfg || !clk_mfg->rpm_clks)
> > + return 0;
> > +
> > + clk_bulk_disable_unprepare(clk_mfg->num_rpm_clks, clk_mfg->rpm_clks);
> > +
> > + return 0;
> > +}
> > +
> > static const struct of_device_id of_match_clk_mt8196_mfg[] = {
> > { .compatible = "mediatek,mt8196-mfgpll-pll-ctrl",
> > .data = &mfg_ao_plls },
> > @@ -92,35 +127,60 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8196_mfg);
> > static int clk_mt8196_mfg_probe(struct platform_device *pdev)
> > {
> > const struct mtk_pll_data *plls;
> > - struct clk_hw_onecell_data *clk_data;
> > + struct clk_mt8196_mfg *clk_mfg;
> > struct device_node *node = pdev->dev.of_node;
> > + struct device *dev = &pdev->dev;
> > const int num_plls = 1;
> > - int r;
> > + int r, i;
> >
> > - plls = of_device_get_match_data(&pdev->dev);
> > + plls = of_device_get_match_data(dev);
> > if (!plls)
> > return -EINVAL;
> >
> > - clk_data = mtk_alloc_clk_data(num_plls);
> > - if (!clk_data)
> > + clk_mfg = devm_kzalloc(dev, sizeof(*clk_mfg), GFP_KERNEL);
> > + if (!clk_mfg)
> > return -ENOMEM;
> >
> > - r = mtk_clk_register_plls(&pdev->dev, plls, num_plls, clk_data);
> > + clk_mfg->num_rpm_clks = plls[0].num_rpm_clks;
> > +
> > + if (clk_mfg->num_rpm_clks) {
> > + clk_mfg->rpm_clks = devm_kcalloc(dev, clk_mfg->num_rpm_clks,
> > + sizeof(*clk_mfg->rpm_clks),
> > + GFP_KERNEL);
> > + if (!clk_mfg->rpm_clks)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < clk_mfg->num_rpm_clks; i++)
> > + clk_mfg->rpm_clks->id = plls[0].rpm_clk_names[i];
> > +
> > + r = devm_clk_bulk_get(dev, clk_mfg->num_rpm_clks,
> > + clk_mfg->rpm_clks);
> > + if (r)
> > + return r;
> > + }
> > +
> > + clk_mfg->clk_data = mtk_alloc_clk_data(num_plls);
> > + if (!clk_mfg->clk_data)
> > + return -ENOMEM;
> > +
> > + dev_set_drvdata(dev, clk_mfg);
> > + pm_runtime_enable(dev);
> > +
> > + r = mtk_clk_register_plls(dev, plls, num_plls, clk_mfg->clk_data);
> > if (r)
> > goto free_clk_data;
> >
> > - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
> > + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
> > + clk_mfg->clk_data);
> > if (r)
> > goto unregister_plls;
> >
> > - platform_set_drvdata(pdev, clk_data);
> > -
> > return r;
> >
> > unregister_plls:
> > - mtk_clk_unregister_plls(plls, num_plls, clk_data);
> > + mtk_clk_unregister_plls(plls, num_plls, clk_mfg->clk_data);
> > free_clk_data:
> > - mtk_free_clk_data(clk_data);
> > + mtk_free_clk_data(clk_mfg->clk_data);
> >
> > return r;
> > }
> > @@ -128,20 +188,26 @@ static int clk_mt8196_mfg_probe(struct platform_device *pdev)
> > static void clk_mt8196_mfg_remove(struct platform_device *pdev)
> > {
> > const struct mtk_pll_data *plls = of_device_get_match_data(&pdev->dev);
> > - struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
> > + struct clk_mt8196_mfg *clk_mfg = dev_get_drvdata(&pdev->dev);
> > struct device_node *node = pdev->dev.of_node;
> >
> > of_clk_del_provider(node);
> > - mtk_clk_unregister_plls(plls, 1, clk_data);
> > - mtk_free_clk_data(clk_data);
> > + mtk_clk_unregister_plls(plls, 1, clk_mfg->clk_data);
> > + mtk_free_clk_data(clk_mfg->clk_data);
> > }
> >
> > +static DEFINE_RUNTIME_DEV_PM_OPS(clk_mt8196_mfg_pm_ops,
> > + clk_mt8196_mfg_suspend,
> > + clk_mt8196_mfg_resume,
> > + NULL);
> > +
> > static struct platform_driver clk_mt8196_mfg_drv = {
> > .probe = clk_mt8196_mfg_probe,
> > .remove = clk_mt8196_mfg_remove,
> > .driver = {
> > .name = "clk-mt8196-mfg",
> > .of_match_table = of_match_clk_mt8196_mfg,
> > + .pm = pm_ptr(&clk_mt8196_mfg_pm_ops),
> > },
> > };
> > module_platform_driver(clk_mt8196_mfg_drv);
> > diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
> > index 0f2a1d19eea78b7390b221af47016eb9897f3596..82b86b849a67359d8f23d828f50422081c2747e3 100644
> > --- a/drivers/clk/mediatek/clk-pll.h
> > +++ b/drivers/clk/mediatek/clk-pll.h
> > @@ -53,6 +53,8 @@ struct mtk_pll_data {
> > u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */
> > u8 pcw_chg_bit;
> > u8 fenc_sta_bit;
> > + const char * const *rpm_clk_names;
> > + unsigned int num_rpm_clks;
> > };
> >
> > /*
> >
>
>
>
next prev parent reply other threads:[~2025-10-01 13:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-29 12:13 [PATCH 0/4] MediaTek Runtime Power Management Clocks for PLL Nicolas Frattaroli
2025-09-29 12:13 ` [PATCH 1/4] dt-bindings: clock: mediatek: Add clocks for MT8196 mfgpll Nicolas Frattaroli
2025-09-29 17:31 ` Conor Dooley
2025-09-30 15:57 ` Nicolas Frattaroli
2025-09-30 18:36 ` Conor Dooley
2025-09-29 12:13 ` [PATCH 2/4] clk: mediatek: Refactor pll registration to pass device Nicolas Frattaroli
2025-10-01 11:43 ` AngeloGioacchino Del Regno
2025-09-29 12:13 ` [PATCH 3/4] clk: mediatek: Pass device to clk_hw_register for PLLs Nicolas Frattaroli
2025-10-01 11:40 ` AngeloGioacchino Del Regno
2025-09-29 12:13 ` [PATCH 4/4] clk: mediatek: Add rpm clocks to clk-mt8196-mfg Nicolas Frattaroli
2025-10-01 11:49 ` AngeloGioacchino Del Regno
2025-10-01 13:17 ` Nicolas Frattaroli [this message]
2025-10-06 19:01 ` Nicolas Frattaroli
2025-10-07 7:36 ` AngeloGioacchino Del Regno
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=6441788.lOV4Wx5bFT@workhorse \
--to=nicolas.frattaroli@collabora.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=guangjie.song@mediatek.com \
--cc=kernel@collabora.com \
--cc=krzk+dt@kernel.org \
--cc=krzysztof.kozlowski@linaro.org \
--cc=laura.nao@collabora.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=mturquette@baylibre.com \
--cc=nfraprado@collabora.com \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=y.oudjana@protonmail.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.