clk: mediatek: allow gates in topckgen drivers

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 <dlechner@baylibre.com>
This commit is contained in:
David Lechner
2026-01-07 10:21:13 -06:00
committed by Tom Rini
parent 4cc0f1b318
commit 8aeeeff50d

View File

@@ -582,7 +582,7 @@ static const int mtk_topckgen_of_xlate(struct clk *clk,
if (ret) if (ret)
return 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) if (tree->fclks && clk->id < tree->num_fclks)
return 0; return 0;
@@ -595,6 +595,10 @@ static const int mtk_topckgen_of_xlate(struct clk *clk,
clk->id < tree->muxes_offs + tree->num_muxes) clk->id < tree->muxes_offs + tree->num_muxes)
return 0; return 0;
if (tree->gates && clk->id >= tree->gates_offs &&
clk->id < tree->gates_offs + tree->num_gates)
return 0;
return -ENOENT; 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) static ulong mtk_topckgen_get_rate(struct clk *clk)
{ {
struct mtk_clk_priv *priv = dev_get_priv(clk->dev); 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) if (clk->id < priv->tree->fdivs_offs)
return priv->tree->fclks[clk->id].rate; return priv->tree->fclks[clk->id].rate;
@@ -740,6 +752,21 @@ static int mtk_clk_mux_enable(struct clk *clk)
return 0; 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) static int mtk_clk_mux_disable(struct clk *clk)
{ {
struct mtk_clk_priv *priv = dev_get_priv(clk->dev); 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; 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) 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 *parent_priv = dev_get_priv(parent->dev);
struct mtk_clk_priv *priv = dev_get_priv(clk->dev); struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
u32 parent_type; 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; return 0;
if (!parent_priv) if (!parent_priv)
@@ -821,6 +864,16 @@ static void mtk_topckgen_dump(struct udevice *dev)
mtk_clk_print_mux_parents(priv, mux); mtk_clk_print_mux_parents(priv, mux);
printf("\n"); 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 #endif
@@ -1124,8 +1177,8 @@ const struct clk_ops mtk_clk_fixed_pll_ops = {
const struct clk_ops mtk_clk_topckgen_ops = { const struct clk_ops mtk_clk_topckgen_ops = {
.of_xlate = mtk_topckgen_of_xlate, .of_xlate = mtk_topckgen_of_xlate,
.enable = mtk_clk_mux_enable, .enable = mtk_topckgen_enable,
.disable = mtk_clk_mux_disable, .disable = mtk_topckgen_disable,
.get_rate = mtk_topckgen_get_rate, .get_rate = mtk_topckgen_get_rate,
.set_parent = mtk_common_clk_set_parent, .set_parent = mtk_common_clk_set_parent,
#if CONFIG_IS_ENABLED(CMD_CLK) #if CONFIG_IS_ENABLED(CMD_CLK)