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

clk: mux: Add support for specifying parents via DT/pointers

After commit fc0c209c147f ("clk: Allow parents to be specified without
string names") we can use DT or direct clk_hw pointers to specify
parents. Create a generic function that shouldn't be used very often to
encode the multitude of ways of registering a mux clk with different
parent information. Then add a bunch of wrapper macros that only pass
down what needs to be passed down to the generic function to support
this with less arguments.

Note: the msm drm driver passes an anonymous array through the macro
which seems to confuse my compiler. Adding a parenthesis around the
whole thing at the call site seems to fix it but it must be wrong. Maybe
it's better to split this patch and pick out the array bits there?

Cc: Rob Clark <robdclark@gmail.com>
Cc: Sean Paul <sean@poorly.run>
Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lkml.kernel.org/r/20190830150923.259497-11-sboyd@kernel.org

+60 -62
+18 -40
drivers/clk/clk-mux.c
··· 145 145 }; 146 146 EXPORT_SYMBOL_GPL(clk_mux_ro_ops); 147 147 148 - struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, 149 - const char * const *parent_names, u8 num_parents, 150 - unsigned long flags, 151 - void __iomem *reg, u8 shift, u32 mask, 148 + struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np, 149 + const char *name, u8 num_parents, 150 + const char * const *parent_names, 151 + const struct clk_hw **parent_hws, 152 + const struct clk_parent_data *parent_data, 153 + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, 152 154 u8 clk_mux_flags, u32 *table, spinlock_t *lock) 153 155 { 154 156 struct clk_mux *mux; 155 157 struct clk_hw *hw; 156 158 struct clk_init_data init = {}; 157 159 u8 width = 0; 158 - int ret; 160 + int ret = -EINVAL; 159 161 160 162 if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { 161 163 width = fls(mask) - ffs(mask) + 1; ··· 179 177 init.ops = &clk_mux_ops; 180 178 init.flags = flags; 181 179 init.parent_names = parent_names; 180 + init.parent_data = parent_data; 181 + init.parent_hws = parent_hws; 182 182 init.num_parents = num_parents; 183 183 184 184 /* struct clk_mux assignments */ ··· 193 189 mux->hw.init = &init; 194 190 195 191 hw = &mux->hw; 196 - ret = clk_hw_register(dev, hw); 192 + if (dev || !np) 193 + ret = clk_hw_register(dev, hw); 194 + else if (np) 195 + ret = of_clk_hw_register(np, hw); 197 196 if (ret) { 198 197 kfree(mux); 199 198 hw = ERR_PTR(ret); ··· 204 197 205 198 return hw; 206 199 } 207 - EXPORT_SYMBOL_GPL(clk_hw_register_mux_table); 200 + EXPORT_SYMBOL_GPL(__clk_hw_register_mux); 208 201 209 202 struct clk *clk_register_mux_table(struct device *dev, const char *name, 210 203 const char * const *parent_names, u8 num_parents, 211 - unsigned long flags, 212 - void __iomem *reg, u8 shift, u32 mask, 204 + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, 213 205 u8 clk_mux_flags, u32 *table, spinlock_t *lock) 214 206 { 215 207 struct clk_hw *hw; 216 208 217 - hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents, 218 - flags, reg, shift, mask, clk_mux_flags, 219 - table, lock); 209 + hw = clk_hw_register_mux_table(dev, name, parent_names, 210 + num_parents, flags, reg, shift, mask, 211 + clk_mux_flags, table, lock); 220 212 if (IS_ERR(hw)) 221 213 return ERR_CAST(hw); 222 214 return hw->clk; 223 215 } 224 216 EXPORT_SYMBOL_GPL(clk_register_mux_table); 225 - 226 - struct clk *clk_register_mux(struct device *dev, const char *name, 227 - const char * const *parent_names, u8 num_parents, 228 - unsigned long flags, 229 - void __iomem *reg, u8 shift, u8 width, 230 - u8 clk_mux_flags, spinlock_t *lock) 231 - { 232 - u32 mask = BIT(width) - 1; 233 - 234 - return clk_register_mux_table(dev, name, parent_names, num_parents, 235 - flags, reg, shift, mask, clk_mux_flags, 236 - NULL, lock); 237 - } 238 - EXPORT_SYMBOL_GPL(clk_register_mux); 239 - 240 - struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, 241 - const char * const *parent_names, u8 num_parents, 242 - unsigned long flags, 243 - void __iomem *reg, u8 shift, u8 width, 244 - u8 clk_mux_flags, spinlock_t *lock) 245 - { 246 - u32 mask = BIT(width) - 1; 247 - 248 - return clk_hw_register_mux_table(dev, name, parent_names, num_parents, 249 - flags, reg, shift, mask, clk_mux_flags, 250 - NULL, lock); 251 - } 252 - EXPORT_SYMBOL_GPL(clk_hw_register_mux); 253 217 254 218 void clk_unregister_mux(struct clk *clk) 255 219 {
+2 -2
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
··· 751 751 snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id); 752 752 753 753 hw = clk_hw_register_mux(dev, clk_name, 754 - (const char *[]){ 754 + ((const char *[]){ 755 755 parent, parent2, parent3, parent4 756 - }, 4, 0, pll_10nm->phy_cmn_mmio + 756 + }), 4, 0, pll_10nm->phy_cmn_mmio + 757 757 REG_DSI_10nm_PHY_CMN_CLK_CFG1, 758 758 0, 2, 0, NULL); 759 759 if (IS_ERR(hw)) {
+2 -2
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
··· 554 554 snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id); 555 555 snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id); 556 556 clks[num++] = clk_register_mux(dev, clk_name, 557 - (const char *[]){ 557 + ((const char *[]){ 558 558 parent1, parent2 559 - }, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio + 559 + }), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio + 560 560 REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL); 561 561 562 562 snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+38 -18
include/linux/clk-provider.h
··· 645 645 extern const struct clk_ops clk_mux_ops; 646 646 extern const struct clk_ops clk_mux_ro_ops; 647 647 648 - struct clk *clk_register_mux(struct device *dev, const char *name, 649 - const char * const *parent_names, u8 num_parents, 650 - unsigned long flags, 651 - void __iomem *reg, u8 shift, u8 width, 652 - u8 clk_mux_flags, spinlock_t *lock); 653 - struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, 654 - const char * const *parent_names, u8 num_parents, 655 - unsigned long flags, 656 - void __iomem *reg, u8 shift, u8 width, 657 - u8 clk_mux_flags, spinlock_t *lock); 658 - 648 + struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np, 649 + const char *name, u8 num_parents, 650 + const char * const *parent_names, 651 + const struct clk_hw **parent_hws, 652 + const struct clk_parent_data *parent_data, 653 + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, 654 + u8 clk_mux_flags, u32 *table, spinlock_t *lock); 659 655 struct clk *clk_register_mux_table(struct device *dev, const char *name, 660 656 const char * const *parent_names, u8 num_parents, 661 - unsigned long flags, 662 - void __iomem *reg, u8 shift, u32 mask, 657 + unsigned long flags, void __iomem *reg, u8 shift, u32 mask, 663 658 u8 clk_mux_flags, u32 *table, spinlock_t *lock); 664 - struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, 665 - const char * const *parent_names, u8 num_parents, 666 - unsigned long flags, 667 - void __iomem *reg, u8 shift, u32 mask, 668 - u8 clk_mux_flags, u32 *table, spinlock_t *lock); 659 + 660 + #define clk_register_mux(dev, name, parent_names, num_parents, flags, reg, \ 661 + shift, width, clk_mux_flags, lock) \ 662 + clk_register_mux_table((dev), (name), (parent_names), (num_parents), \ 663 + (flags), (reg), (shift), BIT((width)) - 1, \ 664 + (clk_mux_flags), NULL, (lock)) 665 + #define clk_hw_register_mux_table(dev, name, parent_names, num_parents, \ 666 + flags, reg, shift, mask, clk_mux_flags, \ 667 + table, lock) \ 668 + __clk_hw_register_mux((dev), NULL, (name), (num_parents), \ 669 + (parent_names), NULL, NULL, (flags), (reg), \ 670 + (shift), (mask), (clk_mux_flags), (table), \ 671 + (lock)) 672 + #define clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \ 673 + shift, width, clk_mux_flags, lock) \ 674 + __clk_hw_register_mux((dev), NULL, (name), (num_parents), \ 675 + (parent_names), NULL, NULL, (flags), (reg), \ 676 + (shift), BIT((width)) - 1, (clk_mux_flags), \ 677 + NULL, (lock)) 678 + #define clk_hw_register_mux_hws(dev, name, parent_hws, num_parents, flags, \ 679 + reg, shift, width, clk_mux_flags, lock) \ 680 + __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, \ 681 + (parent_hws), NULL, (flags), (reg), (shift), \ 682 + BIT((width)) - 1, (clk_mux_flags), NULL, (lock)) 683 + #define clk_hw_register_mux_parent_data(dev, name, parent_data, num_parents, \ 684 + flags, reg, shift, width, \ 685 + clk_mux_flags, lock) \ 686 + __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \ 687 + (parent_data), (flags), (reg), (shift), \ 688 + BIT((width)) - 1, (clk_mux_flags), NULL, (lock)) 669 689 670 690 int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, 671 691 unsigned int val);