aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/imx/clk-pfdv2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/imx/clk-pfdv2.c')
-rw-r--r--drivers/clk/imx/clk-pfdv2.c23
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);