Message ID | 239a96b2760e0a014b9046cd94b7760317c24511.1659581119.git.weijie.gao@mediatek.com |
---|---|
State | Superseded |
Delegated to: | Tom Rini |
Headers | show |
Series | Add support for MediaTek MT7981/MT7986 SoCs | expand |
On Wed, 3 Aug 2022 at 21:39, Weijie Gao <weijie.gao@mediatek.com> wrote: > > This patch adds support for a clock node to configure its parent clock > where possible. > > Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> > --- > drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++-------------- > drivers/clk/mediatek/clk-mtk.h | 2 + > 2 files changed, 48 insertions(+), 33 deletions(-) > Reviewed-by: Simon Glass <sjg@chromium.org>
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@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. > } > @@ -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? > + 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
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@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
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); } @@ -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); + 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;
This patch adds support for a clock node to configure its parent clock where possible. Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> --- drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++-------------- drivers/clk/mediatek/clk-mtk.h | 2 + 2 files changed, 48 insertions(+), 33 deletions(-)