clk: mediatek: add CLK_PARENT_EXT

Add support for external clock parent type in MediaTek clock driver to
allow multiple external clock sources.

This is intended to eventually replace CLK_PARENT_XTAL which only allows
a single external clock source. Replacing CLK_PARENT_XTAL is not trivial
since it would required touching all chip-specific drivers. So that is
saved for another day.

Before this change, the only way to add additional external clocks was
to use a clock ID mapping and add the external clock in the fixed clocks
portion of the CLK_PARENT_TOPCKGEN clocks. After this change, such hacks
are no longer necessary and external clocks can be added in a cleaner
way.

Reviewed-by: Julien Stephan <jstephan@baylibre.com>
Link: https://patch.msgid.link/20260303-mtk-mt8189-clocks-v4-4-ee85f8dd2f0d@baylibre.com
Signed-off-by: David Lechner <dlechner@baylibre.com>
This commit is contained in:
David Lechner
2026-03-03 13:54:52 -06:00
parent d09876c4f6
commit b6d11f69ac
2 changed files with 21 additions and 2 deletions

View File

@@ -168,6 +168,14 @@ static int mtk_gate_disable(void __iomem *base, const struct mtk_gate *gate)
return 0;
}
static ulong mtk_ext_clock_get_rate(const struct mtk_clk_tree *tree, int id)
{
if (!tree->ext_clk_rates || id >= tree->num_ext_clks)
return -ENOENT;
return tree->ext_clk_rates[id];
}
/*
* In case the rate change propagation to parent clocks is undesirable,
* this function is recursively called to find the parent to calculate
@@ -235,6 +243,8 @@ static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
break;
case CLK_PARENT_XTAL:
return priv->tree->xtal_rate;
case CLK_PARENT_EXT:
return mtk_ext_clock_get_rate(priv->tree, parent);
default:
parent_dev = NULL;
break;
@@ -337,6 +347,9 @@ static void mtk_clk_print_parent(const char *prefix, int parent, u32 flags)
case CLK_PARENT_XTAL:
parent_type_str = "xtal";
break;
case CLK_PARENT_EXT:
parent_type_str = "ext";
break;
case CLK_PARENT_MIXED:
parent_type_str = "mixed";
break;
@@ -1134,6 +1147,8 @@ static ulong mtk_clk_gate_get_rate(struct clk *clk)
*/
} else if (gate->flags & CLK_PARENT_XTAL) {
return priv->tree->xtal_rate;
} else if (gate->flags & CLK_PARENT_EXT) {
return mtk_ext_clock_get_rate(priv->tree, gate->parent);
}
return mtk_clk_find_parent_rate(clk, gate->parent, parent);

View File

@@ -34,12 +34,13 @@
#define CLK_PARENT_TOPCKGEN BIT(5)
#define CLK_PARENT_INFRASYS BIT(6)
#define CLK_PARENT_XTAL BIT(7)
#define CLK_PARENT_EXT BIT(8)
/*
* For CLK_PARENT_MIXED to correctly work, is required to
* define in clk_tree flags the clk type using the alias.
*/
#define CLK_PARENT_MIXED BIT(8)
#define CLK_PARENT_MASK GENMASK(8, 4)
#define CLK_PARENT_MIXED BIT(9)
#define CLK_PARENT_MASK GENMASK(9, 4)
#define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34
@@ -255,6 +256,9 @@ struct mtk_gate {
struct mtk_clk_tree {
unsigned long xtal_rate;
unsigned long xtal2_rate;
/* External fixed clocks - excluded from mapping. */
const ulong *ext_clk_rates;
const int num_ext_clks;
/*
* Clock IDs may be remapped with an auxiliary table. Enable this by
* defining .id_offs_map and .id_offs_map_size. This is needed e.g. when