[PATCH 23/31] clk: mediatek: add support to configure clock driver parent
Weijie Gao
weijie.gao at mediatek.com
Tue Aug 23 12:43:06 CEST 2022
On Sat, 2022-08-13 at 00:18 -0400, Sean Anderson wrote:
> On 8/3/22 11:36 PM, Weijie Gao wrote:
> > This patch adds support for a clock node to configure its parent
> > clock
> > where possible.
> >
> > Signed-off-by: Weijie Gao <weijie.gao at mediatek.com>
> > ---
> > drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++---------
> > -----
> > drivers/clk/mediatek/clk-mtk.h | 2 +
> > 2 files changed, 48 insertions(+), 33 deletions(-)
> >
> > diff --git a/drivers/clk/mediatek/clk-mtk.c
> > b/drivers/clk/mediatek/clk-mtk.c
> > index d99ea55df0..908ed2b4ba 100644
> > --- a/drivers/clk/mediatek/clk-mtk.c
> > +++ b/drivers/clk/mediatek/clk-mtk.c
> > @@ -42,20 +42,14 @@
> > * the accurate frequency.
> > */
> > static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
> > - const struct driver *drv)
> > + struct udevice *pdev)
> > {
> > struct clk parent = { .id = id, };
> >
> > - if (drv) {
> > - struct udevice *dev;
> > -
> > - if (uclass_get_device_by_driver(UCLASS_CLK, drv,
> > &dev))
> > - return -ENODEV;
> > -
> > - parent.dev = dev;
> > - } else {
> > + if (pdev)
> > + parent.dev = pdev;
> > + else
> > parent.dev = clk->dev;
> > - }
> >
> > return clk_get_rate(&parent);
>
> You must call clk_request(parent) before calling clk_get_rate.
Currently the mtk clock driver doest not really register all the clock
devices. The ops->request is NULL.
The clk->id is only used by the specific soc clock driver (clk-
mtxxxx.c) as a reference to the soc's clock list.
Once clk_get_rate is called, the driver will use clk->id to search the
actual clock internally in the driver.
If a clock has its parent clock, the driver will fill up the parent
clock's id and then call clk_get_rate again. Again clk_get_rate will go
into the driver and do the same thing until a clock has no parent.
As you can see we only use the clk->id, not the clk udevice, there's no
need to call clk_request. Only a few top-level clk udevices are
registered as the entrace to this driver (topckgen/infrasys/...).
>
> > }
> > @@ -296,7 +290,7 @@ static ulong
> > mtk_topckgen_get_factor_rate(struct clk
> > *clk, u32 off)
> > switch (fdiv->flags & CLK_PARENT_MASK) {
> > case CLK_PARENT_APMIXED:
> > rate = mtk_clk_find_parent_rate(clk, fdiv-
> > >parent,
> > - DM_DRIVER_GET(mtk_clk_apmixedsys))
> > ;
> > + priv->parent);
> > break;
> > case CLK_PARENT_TOPCKGEN:
> > rate = mtk_clk_find_parent_rate(clk, fdiv-
> > >parent, NULL);
> > @@ -322,9 +316,18 @@ static ulong mtk_topckgen_get_mux_rate(struct
> > clk *clk,
> > u32 off)
> >
> > if (mux->parent[index] == CLK_XTAL && priv->tree->flags &
> > CLK_BYPASS_XTAL)
> > flag = 1;
> > - if (mux->parent[index] > 0 || flag == 1)
> > - return mtk_clk_find_parent_rate(clk, mux-
> > >parent[index],
> > - NULL);
> > + if (mux->parent[index] > 0 || flag == 1) {
> > + switch (mux->flags & CLK_PARENT_MASK) {
> > + case CLK_PARENT_APMIXED:
> > + return mtk_clk_find_parent_rate(clk, mux-
> > >parent[index],
> > + priv-
> > >parent);
> > + break;
> > + default:
> > + return mtk_clk_find_parent_rate(clk, mux-
> > >parent[index],
> > + NULL);
> > + break;
> > + }
> > + }
> >
> > return priv->tree->xtal_rate;
> > }
> > @@ -343,7 +346,7 @@ static ulong mtk_topckgen_get_rate(struct clk
> > *clk)
> > priv->tree-
> > >muxes_offs);
> > }
> >
> > -static int mtk_topckgen_enable(struct clk *clk)
> > +static int mtk_clk_mux_enable(struct clk *clk)
> > {
> > struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> > const struct mtk_composite *mux;
> > @@ -376,7 +379,7 @@ static int mtk_topckgen_enable(struct clk *clk)
> > return 0;
> > }
> >
> > -static int mtk_topckgen_disable(struct clk *clk)
> > +static int mtk_clk_mux_disable(struct clk *clk)
> > {
> > struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> > const struct mtk_composite *mux;
> > @@ -402,7 +405,7 @@ static int mtk_topckgen_disable(struct clk
> > *clk)
> > return 0;
> > }
> >
> > -static int mtk_topckgen_set_parent(struct clk *clk, struct clk
> > *parent)
> > +static int mtk_common_clk_set_parent(struct clk *clk, struct clk
> > *parent)
> > {
> > struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
> >
> > @@ -474,19 +477,7 @@ static ulong mtk_clk_gate_get_rate(struct clk
> > *clk)
> > struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
> > const struct mtk_gate *gate = &priv->gates[clk->id];
> >
> > - switch (gate->flags & CLK_PARENT_MASK) {
> > - case CLK_PARENT_APMIXED:
> > - return mtk_clk_find_parent_rate(clk, gate->parent,
> > - DM_DRIVER_GET(mtk_clk_apmixedsys))
> > ;
> > - break;
> > - case CLK_PARENT_TOPCKGEN:
> > - return mtk_clk_find_parent_rate(clk, gate->parent,
> > - DM_DRIVER_GET(mtk_clk_topckgen));
> > - break;
> > -
> > - default:
> > - return priv->tree->xtal_rate;
> > - }
> > + return mtk_clk_find_parent_rate(clk, gate->parent, priv-
> > >parent);
> > }
> >
> > const struct clk_ops mtk_clk_apmixedsys_ops = {
> > @@ -497,10 +488,10 @@ const struct clk_ops mtk_clk_apmixedsys_ops =
> > {
> > };
> >
> > const struct clk_ops mtk_clk_topckgen_ops = {
> > - .enable = mtk_topckgen_enable,
> > - .disable = mtk_topckgen_disable,
> > + .enable = mtk_clk_mux_enable,
> > + .disable = mtk_clk_mux_disable,
> > .get_rate = mtk_topckgen_get_rate,
> > - .set_parent = mtk_topckgen_set_parent,
> > + .set_parent = mtk_common_clk_set_parent,
> > };
> >
> > const struct clk_ops mtk_clk_gate_ops = {
> > @@ -513,11 +504,22 @@ int mtk_common_clk_init(struct udevice *dev,
> > const struct mtk_clk_tree *tree)
> > {
> > struct mtk_clk_priv *priv = dev_get_priv(dev);
> > + struct udevice *parent;
> > + int ret;
> >
> > priv->base = dev_read_addr_ptr(dev);
> > if (!priv->base)
> > return -ENOENT;
> >
> > + ret = uclass_get_device_by_phandle(UCLASS_CLK, dev,
> > "clock-parent",
> > &parent);
> > + if (ret || !parent) {
> > + ret = uclass_get_device_by_driver(UCLASS_CLK,
> > + DM_DRIVER_GET(mtk_clk_apmixedsys),
> > &parent);
> > + if (ret || !parent)
> > + return -ENOENT;
> > + }
> > +
> > + priv->parent = parent;
> > priv->tree = tree;
> >
> > return 0;
> > @@ -528,11 +530,22 @@ int mtk_common_clk_gate_init(struct udevice
> > *dev,
> > const struct mtk_gate *gates)
> > {
> > struct mtk_cg_priv *priv = dev_get_priv(dev);
> > + struct udevice *parent;
> > + int ret;
> >
> > priv->base = dev_read_addr_ptr(dev);
> > if (!priv->base)
> > return -ENOENT;
> >
> > + ret = uclass_get_device_by_phandle(UCLASS_CLK, dev,
> > "clock-parent",
> > &parent);
>
> Why not just use clk_get?
As I mentioned before, this driver does not register clk udevices, the
clk_get_* won't work, and there's no real parent clocks. We have to
parse the fdt to get the actual top-level clk udevice specified as the
parent clock.
>
> > + if (ret || !parent) {
> > + ret = uclass_get_device_by_driver(UCLASS_CLK,
> > + DM_DRIVER_GET(mtk_clk_topckgen),
> > &parent);
> > + if (ret || !parent)
> > + return -ENOENT;
> > + }
> > +
> > + priv->parent = parent;
> > priv->tree = tree;
> > priv->gates = gates;
> >
> > diff --git a/drivers/clk/mediatek/clk-mtk.h
> > b/drivers/clk/mediatek/clk-mtk.h
> > index 0ab6912bf0..7955d469db 100644
> > --- a/drivers/clk/mediatek/clk-mtk.h
> > +++ b/drivers/clk/mediatek/clk-mtk.h
> > @@ -203,11 +203,13 @@ struct mtk_clk_tree {
> > };
> >
> > struct mtk_clk_priv {
> > + struct udevice *parent;
> > void __iomem *base;
> > const struct mtk_clk_tree *tree;
> > };
> >
> > struct mtk_cg_priv {
> > + struct udevice *parent;
> > void __iomem *base;
> > const struct mtk_clk_tree *tree;
> > const struct mtk_gate *gates;
> >
>
> --Sean
More information about the U-Boot
mailing list