summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lechner <[email protected]>2026-03-03 13:54:50 -0600
committerDavid Lechner <[email protected]>2026-03-17 16:34:35 -0500
commit00d0ff7f81bfdf341a06fa4b476b669236986d45 (patch)
tree45954dfb9c4440cc56a2d29c6ff8f1fc497bd2e8
parent5d247265812cd60d5d92c9c7fcc5fd5834c21259 (diff)
clk: mediatek: refactor parent rate lookup functions
Refactor duplicate parent rate lookup code into a common function. Instead of relying on rules like X is always the parent of Y, we use the driver ops pointer to make sure we are actually getting the correct parent clock device. This allows the same function to be called from different clock types and will allow future chip-specific clock drivers to not have to follow the rules as strictly. Reviewed-by: Julien Stephan <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: David Lechner <[email protected]>
-rw-r--r--drivers/clk/mediatek/clk-mtk.c126
1 files changed, 54 insertions, 72 deletions
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index b3f05bf5a21..921c3c0ff6a 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -168,6 +168,53 @@ static ulong mtk_clk_find_parent_rate(struct clk *clk, int id,
return clk_get_rate(&parent);
}
+const struct clk_ops mtk_clk_apmixedsys_ops;
+const struct clk_ops mtk_clk_topckgen_ops;
+const struct clk_ops mtk_clk_infrasys_ops;
+
+static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
+ const int parent, u16 flags)
+{
+ struct udevice *parent_dev;
+
+ switch (flags & CLK_PARENT_MASK) {
+ case CLK_PARENT_APMIXED:
+ /* APMIXEDSYS can be parent or grandparent. */
+ if (dev_get_driver_ops(clk->dev) == &mtk_clk_apmixedsys_ops)
+ parent_dev = clk->dev;
+ else if (dev_get_driver_ops(priv->parent) == &mtk_clk_apmixedsys_ops)
+ parent_dev = priv->parent;
+ else if (dev_get_driver_ops(dev_get_parent(priv->parent)) == &mtk_clk_apmixedsys_ops)
+ parent_dev = dev_get_parent(priv->parent);
+ else
+ return -EINVAL;
+
+ break;
+ case CLK_PARENT_TOPCKGEN:
+ if (dev_get_driver_ops(clk->dev) == &mtk_clk_topckgen_ops)
+ parent_dev = clk->dev;
+ else if (dev_get_driver_ops(priv->parent) == &mtk_clk_topckgen_ops)
+ parent_dev = priv->parent;
+ else
+ return -EINVAL;
+
+ break;
+ case CLK_PARENT_INFRASYS:
+ if (dev_get_driver_ops(clk->dev) != &mtk_clk_infrasys_ops)
+ return -EINVAL;
+
+ parent_dev = clk->dev;
+ break;
+ case CLK_PARENT_XTAL:
+ return priv->tree->xtal_rate;
+ default:
+ parent_dev = NULL;
+ break;
+ }
+
+ return mtk_clk_find_parent_rate(clk, parent, parent_dev);
+}
+
static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
u32 parent_type,
const struct mtk_composite *mux)
@@ -470,7 +517,7 @@ static ulong mtk_apmixedsys_get_rate(struct clk *clk)
/* GATE handling */
if (priv->tree->gates && clk->id >= priv->tree->gates_offs) {
gate = &priv->tree->gates[clk->id - priv->tree->gates_offs];
- return mtk_clk_find_parent_rate(clk, gate->parent, NULL);
+ return mtk_find_parent_rate(priv, clk, gate->parent, gate->flags);
}
pll = &priv->tree->plls[clk->id];
@@ -637,39 +684,13 @@ static ulong mtk_topckgen_get_factor_rate(struct clk *clk, u32 off)
const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
ulong rate;
- switch (fdiv->flags & CLK_PARENT_MASK) {
- case CLK_PARENT_APMIXED:
- rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
- priv->parent);
- break;
- case CLK_PARENT_TOPCKGEN:
- rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
- break;
-
- case CLK_PARENT_XTAL:
- default:
- rate = priv->tree->xtal_rate;
- }
-
+ rate = mtk_find_parent_rate(priv, clk, fdiv->parent, fdiv->flags);
if (IS_ERR_VALUE(rate))
return rate;
return mtk_factor_recalc_rate(fdiv, rate);
}
-static ulong mtk_topckgen_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
- const int parent, u16 flags)
-{
- switch (flags & CLK_PARENT_MASK) {
- case CLK_PARENT_XTAL:
- return priv->tree->xtal_rate;
- case CLK_PARENT_APMIXED:
- return mtk_clk_find_parent_rate(clk, parent, priv->parent);
- default:
- return mtk_clk_find_parent_rate(clk, parent, NULL);
- }
-}
-
static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
@@ -687,33 +708,14 @@ static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
if (mux->flags & CLK_PARENT_MIXED) {
const struct mtk_parent *parent = &mux->parent_flags[index];
- return mtk_topckgen_find_parent_rate(priv, clk, parent->id,
- parent->flags);
+ return mtk_find_parent_rate(priv, clk, parent->id, parent->flags);
}
if (mux->parent[index] == CLK_XTAL &&
!(priv->tree->flags & CLK_BYPASS_XTAL))
return priv->tree->xtal_rate;
- return mtk_topckgen_find_parent_rate(priv, clk, mux->parent[index],
- mux->flags);
-}
-
-static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
- const int parent, u16 flags)
-{
- switch (flags & CLK_PARENT_MASK) {
- case CLK_PARENT_XTAL:
- return priv->tree->xtal_rate;
- /* Assume the second level parent is always APMIXED */
- case CLK_PARENT_APMIXED:
- priv = dev_get_priv(priv->parent);
- fallthrough;
- case CLK_PARENT_TOPCKGEN:
- return mtk_clk_find_parent_rate(clk, parent, priv->parent);
- default:
- return mtk_clk_find_parent_rate(clk, parent, NULL);
- }
+ return mtk_find_parent_rate(priv, clk, mux->parent[index], mux->flags);
}
static ulong mtk_topckgen_get_rate(struct clk *clk)
@@ -725,7 +727,7 @@ static ulong mtk_topckgen_get_rate(struct clk *clk)
clk->id < tree->gates_offs + tree->num_gates) {
const struct mtk_gate *gate = &tree->gates[clk->id - tree->gates_offs];
- return mtk_clk_find_parent_rate(clk, gate->parent, NULL);
+ return mtk_find_parent_rate(priv, clk, gate->parent, gate->flags);
}
if (clk->id < priv->tree->fdivs_offs)
@@ -963,18 +965,7 @@ static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off)
const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off];
ulong rate;
- switch (fdiv->flags & CLK_PARENT_MASK) {
- case CLK_PARENT_TOPCKGEN:
- rate = mtk_clk_find_parent_rate(clk, fdiv->parent,
- priv->parent);
- break;
- case CLK_PARENT_XTAL:
- rate = priv->tree->xtal_rate;
- break;
- default:
- rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL);
- }
-
+ rate = mtk_find_parent_rate(priv, clk, fdiv->parent, fdiv->flags);
if (IS_ERR_VALUE(rate))
return rate;
@@ -1024,20 +1015,11 @@ static ulong mtk_infrasys_get_rate(struct clk *clk)
priv->tree->muxes_offs);
/* Only valid with muxes + gates implementation */
} else {
- struct udevice *parent = NULL;
const struct mtk_gate *gate;
gate = &priv->tree->gates[clk->id - priv->tree->gates_offs];
- if (gate->flags & CLK_PARENT_TOPCKGEN)
- parent = priv->parent;
- /*
- * Assume xtal_rate to be declared if some gates have
- * XTAL as parent
- */
- else if (gate->flags & CLK_PARENT_XTAL)
- return priv->tree->xtal_rate;
- rate = mtk_clk_find_parent_rate(clk, gate->parent, parent);
+ rate = mtk_find_parent_rate(priv, clk, gate->parent, gate->flags);
}
return rate;