mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 10:46:33 +00:00
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
This commit is contained in:
parent
728e309674
commit
9611b3aacc
@ -145,17 +145,19 @@ const struct clk_ops clk_mux_ro_ops = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
|
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
|
||||||
|
|
||||||
struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
|
||||||
const char * const *parent_names, u8 num_parents,
|
const char *name, u8 num_parents,
|
||||||
unsigned long flags,
|
const char * const *parent_names,
|
||||||
void __iomem *reg, u8 shift, u32 mask,
|
const struct clk_hw **parent_hws,
|
||||||
|
const struct clk_parent_data *parent_data,
|
||||||
|
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct clk_mux *mux;
|
struct clk_mux *mux;
|
||||||
struct clk_hw *hw;
|
struct clk_hw *hw;
|
||||||
struct clk_init_data init = {};
|
struct clk_init_data init = {};
|
||||||
u8 width = 0;
|
u8 width = 0;
|
||||||
int ret;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
|
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
|
||||||
width = fls(mask) - ffs(mask) + 1;
|
width = fls(mask) - ffs(mask) + 1;
|
||||||
@ -177,6 +179,8 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|||||||
init.ops = &clk_mux_ops;
|
init.ops = &clk_mux_ops;
|
||||||
init.flags = flags;
|
init.flags = flags;
|
||||||
init.parent_names = parent_names;
|
init.parent_names = parent_names;
|
||||||
|
init.parent_data = parent_data;
|
||||||
|
init.parent_hws = parent_hws;
|
||||||
init.num_parents = num_parents;
|
init.num_parents = num_parents;
|
||||||
|
|
||||||
/* struct clk_mux assignments */
|
/* struct clk_mux assignments */
|
||||||
@ -189,7 +193,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|||||||
mux->hw.init = &init;
|
mux->hw.init = &init;
|
||||||
|
|
||||||
hw = &mux->hw;
|
hw = &mux->hw;
|
||||||
|
if (dev || !np)
|
||||||
ret = clk_hw_register(dev, hw);
|
ret = clk_hw_register(dev, hw);
|
||||||
|
else if (np)
|
||||||
|
ret = of_clk_hw_register(np, hw);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(mux);
|
kfree(mux);
|
||||||
hw = ERR_PTR(ret);
|
hw = ERR_PTR(ret);
|
||||||
@ -197,53 +204,24 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|||||||
|
|
||||||
return hw;
|
return hw;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(clk_hw_register_mux_table);
|
EXPORT_SYMBOL_GPL(__clk_hw_register_mux);
|
||||||
|
|
||||||
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||||
const char * const *parent_names, u8 num_parents,
|
const char * const *parent_names, u8 num_parents,
|
||||||
unsigned long flags,
|
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||||
void __iomem *reg, u8 shift, u32 mask,
|
|
||||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct clk_hw *hw;
|
struct clk_hw *hw;
|
||||||
|
|
||||||
hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents,
|
hw = clk_hw_register_mux_table(dev, name, parent_names,
|
||||||
flags, reg, shift, mask, clk_mux_flags,
|
num_parents, flags, reg, shift, mask,
|
||||||
table, lock);
|
clk_mux_flags, table, lock);
|
||||||
if (IS_ERR(hw))
|
if (IS_ERR(hw))
|
||||||
return ERR_CAST(hw);
|
return ERR_CAST(hw);
|
||||||
return hw->clk;
|
return hw->clk;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(clk_register_mux_table);
|
EXPORT_SYMBOL_GPL(clk_register_mux_table);
|
||||||
|
|
||||||
struct clk *clk_register_mux(struct device *dev, const char *name,
|
|
||||||
const char * const *parent_names, u8 num_parents,
|
|
||||||
unsigned long flags,
|
|
||||||
void __iomem *reg, u8 shift, u8 width,
|
|
||||||
u8 clk_mux_flags, spinlock_t *lock)
|
|
||||||
{
|
|
||||||
u32 mask = BIT(width) - 1;
|
|
||||||
|
|
||||||
return clk_register_mux_table(dev, name, parent_names, num_parents,
|
|
||||||
flags, reg, shift, mask, clk_mux_flags,
|
|
||||||
NULL, lock);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(clk_register_mux);
|
|
||||||
|
|
||||||
struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
|
|
||||||
const char * const *parent_names, u8 num_parents,
|
|
||||||
unsigned long flags,
|
|
||||||
void __iomem *reg, u8 shift, u8 width,
|
|
||||||
u8 clk_mux_flags, spinlock_t *lock)
|
|
||||||
{
|
|
||||||
u32 mask = BIT(width) - 1;
|
|
||||||
|
|
||||||
return clk_hw_register_mux_table(dev, name, parent_names, num_parents,
|
|
||||||
flags, reg, shift, mask, clk_mux_flags,
|
|
||||||
NULL, lock);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(clk_hw_register_mux);
|
|
||||||
|
|
||||||
void clk_unregister_mux(struct clk *clk)
|
void clk_unregister_mux(struct clk *clk)
|
||||||
{
|
{
|
||||||
struct clk_mux *mux;
|
struct clk_mux *mux;
|
||||||
|
@ -751,9 +751,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
|
|||||||
snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
|
snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
|
||||||
|
|
||||||
hw = clk_hw_register_mux(dev, clk_name,
|
hw = clk_hw_register_mux(dev, clk_name,
|
||||||
(const char *[]){
|
((const char *[]){
|
||||||
parent, parent2, parent3, parent4
|
parent, parent2, parent3, parent4
|
||||||
}, 4, 0, pll_10nm->phy_cmn_mmio +
|
}), 4, 0, pll_10nm->phy_cmn_mmio +
|
||||||
REG_DSI_10nm_PHY_CMN_CLK_CFG1,
|
REG_DSI_10nm_PHY_CMN_CLK_CFG1,
|
||||||
0, 2, 0, NULL);
|
0, 2, 0, NULL);
|
||||||
if (IS_ERR(hw)) {
|
if (IS_ERR(hw)) {
|
||||||
|
@ -554,9 +554,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
|
|||||||
snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
|
snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
|
||||||
snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
|
snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
|
||||||
clks[num++] = clk_register_mux(dev, clk_name,
|
clks[num++] = clk_register_mux(dev, clk_name,
|
||||||
(const char *[]){
|
((const char *[]){
|
||||||
parent1, parent2
|
parent1, parent2
|
||||||
}, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
|
}), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
|
||||||
REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
|
REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
|
||||||
|
|
||||||
snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
|
snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
|
||||||
|
@ -645,28 +645,48 @@ struct clk_mux {
|
|||||||
extern const struct clk_ops clk_mux_ops;
|
extern const struct clk_ops clk_mux_ops;
|
||||||
extern const struct clk_ops clk_mux_ro_ops;
|
extern const struct clk_ops clk_mux_ro_ops;
|
||||||
|
|
||||||
struct clk *clk_register_mux(struct device *dev, const char *name,
|
struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
|
||||||
const char * const *parent_names, u8 num_parents,
|
const char *name, u8 num_parents,
|
||||||
unsigned long flags,
|
const char * const *parent_names,
|
||||||
void __iomem *reg, u8 shift, u8 width,
|
const struct clk_hw **parent_hws,
|
||||||
u8 clk_mux_flags, spinlock_t *lock);
|
const struct clk_parent_data *parent_data,
|
||||||
struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
|
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||||
const char * const *parent_names, u8 num_parents,
|
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||||
unsigned long flags,
|
|
||||||
void __iomem *reg, u8 shift, u8 width,
|
|
||||||
u8 clk_mux_flags, spinlock_t *lock);
|
|
||||||
|
|
||||||
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||||
const char * const *parent_names, u8 num_parents,
|
const char * const *parent_names, u8 num_parents,
|
||||||
unsigned long flags,
|
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||||
void __iomem *reg, u8 shift, u32 mask,
|
|
||||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
|
||||||
struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
|
|
||||||
const char * const *parent_names, u8 num_parents,
|
|
||||||
unsigned long flags,
|
|
||||||
void __iomem *reg, u8 shift, u32 mask,
|
|
||||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||||
|
|
||||||
|
#define clk_register_mux(dev, name, parent_names, num_parents, flags, reg, \
|
||||||
|
shift, width, clk_mux_flags, lock) \
|
||||||
|
clk_register_mux_table((dev), (name), (parent_names), (num_parents), \
|
||||||
|
(flags), (reg), (shift), BIT((width)) - 1, \
|
||||||
|
(clk_mux_flags), NULL, (lock))
|
||||||
|
#define clk_hw_register_mux_table(dev, name, parent_names, num_parents, \
|
||||||
|
flags, reg, shift, mask, clk_mux_flags, \
|
||||||
|
table, lock) \
|
||||||
|
__clk_hw_register_mux((dev), NULL, (name), (num_parents), \
|
||||||
|
(parent_names), NULL, NULL, (flags), (reg), \
|
||||||
|
(shift), (mask), (clk_mux_flags), (table), \
|
||||||
|
(lock))
|
||||||
|
#define clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
|
||||||
|
shift, width, clk_mux_flags, lock) \
|
||||||
|
__clk_hw_register_mux((dev), NULL, (name), (num_parents), \
|
||||||
|
(parent_names), NULL, NULL, (flags), (reg), \
|
||||||
|
(shift), BIT((width)) - 1, (clk_mux_flags), \
|
||||||
|
NULL, (lock))
|
||||||
|
#define clk_hw_register_mux_hws(dev, name, parent_hws, num_parents, flags, \
|
||||||
|
reg, shift, width, clk_mux_flags, lock) \
|
||||||
|
__clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, \
|
||||||
|
(parent_hws), NULL, (flags), (reg), (shift), \
|
||||||
|
BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
|
||||||
|
#define clk_hw_register_mux_parent_data(dev, name, parent_data, num_parents, \
|
||||||
|
flags, reg, shift, width, \
|
||||||
|
clk_mux_flags, lock) \
|
||||||
|
__clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
|
||||||
|
(parent_data), (flags), (reg), (shift), \
|
||||||
|
BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
|
||||||
|
|
||||||
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
|
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
|
||||||
unsigned int val);
|
unsigned int val);
|
||||||
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
|
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user