Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: mediatek: clk-mux: Support custom parent indices for muxes

Add support for customized parent indices for MediaTek muxes: this is
necessary for the case in which we want to exclude some clocks from
a mux's parent clocks list, where the exclusions are not from the
very bottom of the list but either in the middle or the beginning.

Example:
- MUX1 (all parents)
- parent1; idx=0
- parent2; idx=1
- parent3; idx=2

- MUX1 (wanted parents)
- parent1; idx=0
- parent3; idx=2

To achieve that add a `parent_index` array pointer to struct mtk_mux,
then in .set_parent(), .get_parent() callbacks check if this array
was populated and eventually get the index from that.

Also, to avoid updating all clock drivers for all SoCs, rename the
"main" macro to __GATE_CLR_SET_UPD_FLAGS (so, `__` was added) and
add the new member to it; furthermore, GATE_CLK_SET_UPD_FLAGS has
been reintroduced as being fully compatible with the older version.

The new parent_index can be specified with the new `_INDEXED`
variants of the MUX_GATE_CLR_SET_UPD_xxxx macros.

Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20231103102533.69280-2-angelogioacchino.delregno@collabora.com
Tested-by: Fei Shao <fshao@chromium.org>
Reviewed-by: Fei Shao <fshao@chromium.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

AngeloGioacchino Del Regno and committed by
Stephen Boyd
a6a70a67 616eceb1

+53 -4
+14
drivers/clk/mediatek/clk-mux.c
··· 89 89 regmap_read(mux->regmap, mux->data->mux_ofs, &val); 90 90 val = (val >> mux->data->mux_shift) & mask; 91 91 92 + if (mux->data->parent_index) { 93 + int i; 94 + 95 + for (i = 0; i < mux->data->num_parents; i++) 96 + if (mux->data->parent_index[i] == val) 97 + return i; 98 + 99 + /* Not found: return an impossible index to generate error */ 100 + return mux->data->num_parents + 1; 101 + } 102 + 92 103 return val; 93 104 } 94 105 ··· 114 103 spin_lock_irqsave(mux->lock, flags); 115 104 else 116 105 __acquire(mux->lock); 106 + 107 + if (mux->data->parent_index) 108 + index = mux->data->parent_index[index]; 117 109 118 110 regmap_read(mux->regmap, mux->data->mux_ofs, &orig); 119 111 val = (orig & ~(mask << mux->data->mux_shift))
+39 -4
drivers/clk/mediatek/clk-mux.h
··· 21 21 int id; 22 22 const char *name; 23 23 const char * const *parent_names; 24 + const u8 *parent_index; 24 25 unsigned int flags; 25 26 26 27 u32 mux_ofs; ··· 38 37 signed char num_parents; 39 38 }; 40 39 41 - #define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ 42 - _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ 43 - _gate, _upd_ofs, _upd, _flags, _ops) { \ 40 + #define __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _paridx, \ 41 + _num_parents, _mux_ofs, _mux_set_ofs, \ 42 + _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \ 43 + _upd, _flags, _ops) { \ 44 44 .id = _id, \ 45 45 .name = _name, \ 46 46 .mux_ofs = _mux_ofs, \ ··· 53 51 .gate_shift = _gate, \ 54 52 .upd_shift = _upd, \ 55 53 .parent_names = _parents, \ 56 - .num_parents = ARRAY_SIZE(_parents), \ 54 + .parent_index = _paridx, \ 55 + .num_parents = _num_parents, \ 57 56 .flags = _flags, \ 58 57 .ops = &_ops, \ 59 58 } 59 + 60 + #define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ 61 + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ 62 + _gate, _upd_ofs, _upd, _flags, _ops) \ 63 + __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \ 64 + NULL, ARRAY_SIZE(_parents), _mux_ofs, \ 65 + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ 66 + _gate, _upd_ofs, _upd, _flags, _ops) \ 67 + 68 + #define GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, _paridx, \ 69 + _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \ 70 + _width, _gate, _upd_ofs, _upd, _flags, _ops) \ 71 + __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \ 72 + _paridx, ARRAY_SIZE(_paridx), _mux_ofs, \ 73 + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ 74 + _gate, _upd_ofs, _upd, _flags, _ops) \ 60 75 61 76 extern const struct clk_ops mtk_mux_clr_set_upd_ops; 62 77 extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; ··· 86 67 _gate, _upd_ofs, _upd, _flags, \ 87 68 mtk_mux_gate_clr_set_upd_ops) 88 69 70 + #define MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, \ 71 + _paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \ 72 + _shift, _width, _gate, _upd_ofs, _upd, _flags) \ 73 + GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, \ 74 + _paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \ 75 + _shift, _width, _gate, _upd_ofs, _upd, _flags, \ 76 + mtk_mux_gate_clr_set_upd_ops) 77 + 89 78 #define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ 90 79 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ 91 80 _gate, _upd_ofs, _upd) \ ··· 101 74 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \ 102 75 _width, _gate, _upd_ofs, _upd, \ 103 76 CLK_SET_RATE_PARENT) 77 + 78 + #define MUX_GATE_CLR_SET_UPD_INDEXED(_id, _name, _parents, _paridx, \ 79 + _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \ 80 + _width, _gate, _upd_ofs, _upd) \ 81 + MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, \ 82 + _parents, _paridx, _mux_ofs, _mux_set_ofs, \ 83 + _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \ 84 + _upd, CLK_SET_RATE_PARENT) 104 85 105 86 #define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ 106 87 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \