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. Signed-off-by: David Lechner <[email protected]> --- drivers/clk/mediatek/clk-mtk.c | 17 +++++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 8 ++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 3bd9021b9cf..6f7e2144332 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -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; @@ -1027,6 +1040,8 @@ static ulong mtk_infrasys_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); rate = mtk_clk_find_parent_rate(clk, gate->parent, parent); } @@ -1143,6 +1158,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); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index f3d2377aee4..c6874445dbe 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -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 -- 2.43.0

