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....@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

Reply via email to