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)
/* 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];
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);
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)
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)
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;
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;