diff mbox series

[23/31] clk: mediatek: add support to configure clock driver parent

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

Commit Message

Weijie Gao (高惟杰) Aug. 4, 2022, 3:36 a.m. UTC
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(-)

Comments

Simon Glass Aug. 4, 2022, 1:57 p.m. UTC | #1
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>
Sean Anderson Aug. 13, 2022, 4:18 a.m. UTC | #2
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
Weijie Gao (高惟杰) Aug. 23, 2022, 10:43 a.m. UTC | #3
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 mbox series

Patch

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;