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.
Signed-off-by: David Lechner <[email protected]> --- drivers/clk/mediatek/clk-mtk.c | 111 +++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index b3f05bf5a21..0123b0ce7b1 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) @@ -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) @@ -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; -- 2.43.0

