Add handling for gates in the topckgen clk drivers. This avoids the need to have separate topckgen-cg drivers and devicetree nodes for the same address space and clock ID range.
Signed-off-by: David Lechner <[email protected]> --- drivers/clk/mediatek/clk-mtk.c | 61 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index e370d304c03..82306ae285c 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -582,7 +582,7 @@ static const int mtk_topckgen_of_xlate(struct clk *clk, if (ret) return ret; - /* topckgen only uses fclks, fdivs and muxes. */ + /* topckgen only uses fclks, fdivs, muxes and gates. */ if (tree->fclks && clk->id < tree->num_fclks) return 0; @@ -595,6 +595,10 @@ static const int mtk_topckgen_of_xlate(struct clk *clk, clk->id < tree->muxes_offs + tree->num_muxes) return 0; + if (tree->gates && clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + tree->num_gates) + return 0; + return -ENOENT; } @@ -696,6 +700,14 @@ static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, static ulong mtk_topckgen_get_rate(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + + if (tree->gates && clk->id >= tree->gates_offs && + 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); + } if (clk->id < priv->tree->fdivs_offs) return priv->tree->fclks[clk->id].rate; @@ -740,6 +752,21 @@ static int mtk_clk_mux_enable(struct clk *clk) return 0; } +static int mtk_topckgen_enable(struct clk *clk) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + + if (tree->gates && clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + tree->num_gates) { + const struct mtk_gate *gate = &tree->gates[clk->id - tree->gates_offs]; + + return mtk_gate_enable(priv->base, gate); + } + + return mtk_clk_mux_enable(clk); +} + static int mtk_clk_mux_disable(struct clk *clk) { struct mtk_clk_priv *priv = dev_get_priv(clk->dev); @@ -766,13 +793,29 @@ static int mtk_clk_mux_disable(struct clk *clk) return 0; } +static int mtk_topckgen_disable(struct clk *clk) +{ + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_clk_tree *tree = priv->tree; + + if (tree->gates && clk->id >= tree->gates_offs && + clk->id < tree->gates_offs + tree->num_gates) { + const struct mtk_gate *gate = &tree->gates[clk->id - tree->gates_offs]; + + return mtk_gate_disable(priv->base, gate); + } + + return mtk_clk_mux_disable(clk); +} + static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) { struct mtk_clk_priv *parent_priv = dev_get_priv(parent->dev); struct mtk_clk_priv *priv = dev_get_priv(clk->dev); u32 parent_type; - if (clk->id < priv->tree->muxes_offs) + if (!priv->tree->muxes || clk->id < priv->tree->muxes_offs || + clk->id >= priv->tree->muxes_offs + priv->tree->num_muxes) return 0; if (!parent_priv) @@ -821,6 +864,16 @@ static void mtk_topckgen_dump(struct udevice *dev) mtk_clk_print_mux_parents(priv, mux); printf("\n"); } + + for (i = 0; i < tree->num_gates; i++) { + const struct mtk_gate *gate = &tree->gates[i]; + + printf("[GATE%u] DT: %u", i, gate->id); + mtk_clk_print_mapped_id(gate->id, i + tree->gates_offs, tree->id_offs_map); + mtk_clk_print_rate(dev, i + tree->gates_offs); + mtk_clk_print_single_parent(gate->parent, gate->flags); + printf("\n"); + } } #endif @@ -1124,8 +1177,8 @@ const struct clk_ops mtk_clk_fixed_pll_ops = { const struct clk_ops mtk_clk_topckgen_ops = { .of_xlate = mtk_topckgen_of_xlate, - .enable = mtk_clk_mux_enable, - .disable = mtk_clk_mux_disable, + .enable = mtk_topckgen_enable, + .disable = mtk_topckgen_disable, .get_rate = mtk_topckgen_get_rate, .set_parent = mtk_common_clk_set_parent, #if CONFIG_IS_ENABLED(CMD_CLK) -- 2.43.0

