diff options
Diffstat (limited to 'drivers/clk/imx/clk-pfdv2.c')
-rw-r--r-- | drivers/clk/imx/clk-pfdv2.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c index 6b744c84278e..6ca53a960eb7 100644 --- a/drivers/clk/imx/clk-pfdv2.c +++ b/drivers/clk/imx/clk-pfdv2.c @@ -161,8 +161,17 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate, if (!rate) return -EINVAL; - /* PFD can NOT change rate without gating */ - WARN_ON(clk_pfdv2_is_enabled(hw)); + /* + * PFD can NOT change rate without gating. + * as the PFDs may enabled in HW by default but no + * consumer used it, the enable count is '0', so the + * 'SET_RATE_GATE' can NOT help on blocking the set_rate + * ops especially for 'assigned-clock-xxx'. In order + * to simplify the case, just disable the PFD if it is + * enabled in HW but not in SW. + */ + if (clk_pfdv2_is_enabled(hw)) + clk_pfdv2_disable(hw); tmp = tmp * 18 + rate / 2; do_div(tmp, rate); @@ -191,8 +200,8 @@ static const struct clk_ops clk_pfdv2_ops = { .is_enabled = clk_pfdv2_is_enabled, }; -struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, - void __iomem *reg, u8 idx) +struct clk_hw *imx_clk_hw_pfdv2(enum imx_pfdv2_type type, const char *name, + const char *parent_name, void __iomem *reg, u8 idx) { struct clk_init_data init; struct clk_pfdv2 *pfd; @@ -214,7 +223,10 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, init.ops = &clk_pfdv2_ops; init.parent_names = &parent_name; init.num_parents = 1; - init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; + if (type == IMX_PFDV2_IMX7ULP) + init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; + else + init.flags = CLK_SET_RATE_GATE; pfd->hw.init = &init; @@ -227,3 +239,4 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name, return hw; } +EXPORT_SYMBOL_GPL(imx_clk_hw_pfdv2); |