]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: imx: gate2: Allow single bit gating clock
authorAbel Vesa <abel.vesa@nxp.com>
Wed, 15 Apr 2020 08:02:45 +0000 (11:02 +0300)
committerShawn Guo <shawnguo@kernel.org>
Wed, 29 Apr 2020 02:00:05 +0000 (10:00 +0800)
Audiomix on i.MX8MP registers two gates that share the same enable count
but use the same bit to control the gate instead of two bits. By adding
the flag IMX_CLK_GATE2_SINGLE_BIT we allow the gate2 to use the generic
gate ops for enable, disable and is_enabled.
For the disable_unused, nothing happens if this flag is specified.

Signed-off-by: Abel Vesa <abel.vesa@nxp.com>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/clk/imx/clk-gate2.c
drivers/clk/imx/clk.h

index ce0060e8873eb44ce2ba4c5b62590ebff6fd1cf2..b87ab3c3ba1ea7df2f3f053500a50f21a80240d5 100644 (file)
@@ -41,21 +41,26 @@ static int clk_gate2_enable(struct clk_hw *hw)
        struct clk_gate2 *gate = to_clk_gate2(hw);
        u32 reg;
        unsigned long flags;
+       int ret = 0;
 
        spin_lock_irqsave(gate->lock, flags);
 
        if (gate->share_count && (*gate->share_count)++ > 0)
                goto out;
 
-       reg = readl(gate->reg);
-       reg &= ~(3 << gate->bit_idx);
-       reg |= gate->cgr_val << gate->bit_idx;
-       writel(reg, gate->reg);
+       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
+               ret = clk_gate_ops.enable(hw);
+       } else {
+               reg = readl(gate->reg);
+               reg &= ~(3 << gate->bit_idx);
+               reg |= gate->cgr_val << gate->bit_idx;
+               writel(reg, gate->reg);
+       }
 
 out:
        spin_unlock_irqrestore(gate->lock, flags);
 
-       return 0;
+       return ret;
 }
 
 static void clk_gate2_disable(struct clk_hw *hw)
@@ -73,9 +78,13 @@ static void clk_gate2_disable(struct clk_hw *hw)
                        goto out;
        }
 
-       reg = readl(gate->reg);
-       reg &= ~(3 << gate->bit_idx);
-       writel(reg, gate->reg);
+       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
+               clk_gate_ops.disable(hw);
+       } else {
+               reg = readl(gate->reg);
+               reg &= ~(3 << gate->bit_idx);
+               writel(reg, gate->reg);
+       }
 
 out:
        spin_unlock_irqrestore(gate->lock, flags);
@@ -95,6 +104,9 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
 
+       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
+               return clk_gate_ops.is_enabled(hw);
+
        return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
 }
 
@@ -104,6 +116,9 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
        unsigned long flags;
        u32 reg;
 
+       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
+               return;
+
        spin_lock_irqsave(gate->lock, flags);
 
        if (!gate->share_count || *gate->share_count == 0) {
index f074dd8ec42e77341f68d0088ab61cc90b0e7f0e..01ff1dbfbdef59b8bd93f5598a4162f42bb4a6a9 100644 (file)
@@ -5,6 +5,8 @@
 #include <linux/spinlock.h>
 #include <linux/clk-provider.h>
 
+#define IMX_CLK_GATE2_SINGLE_BIT       1
+
 extern spinlock_t imx_ccm_lock;
 
 void imx_check_clocks(struct clk *clks[], unsigned int count);
@@ -355,6 +357,17 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
                                  &imx_ccm_lock, share_count);
 }
 
+static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev,
+                               const char *name, const char *parent,
+                               void __iomem *reg, u8 shift,
+                               unsigned int *share_count)
+{
+       return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
+                                       CLK_OPS_PARENT_ENABLE, reg, shift, 0x3,
+                                       IMX_CLK_GATE2_SINGLE_BIT,
+                                       &imx_ccm_lock, share_count);
+}
+
 static inline struct clk *imx_clk_gate2_cgr(const char *name,
                const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
 {