diff options
| -rw-r--r-- | drivers/clk/mediatek/clk-mtk.c | 126 |
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; |
