clk: imx: clk-gate2: allow custom gate configuration
authorStefan Agner <stefan@agner.ch>
Thu, 10 Mar 2016 02:16:47 +0000 (18:16 -0800)
committerShawn Guo <shawnguo@kernel.org>
Thu, 31 Mar 2016 09:01:55 +0000 (17:01 +0800)
The 2-bit gates found i.MX and Vybrid SoC support different clock
configuration:

0b00: clk disabled
0b01: clk enabled in RUN mode but disabled in WAIT and STOP mode
0b10: clk enabled in RUN, WAIT and STOP mode (only Vybrid)
0b11: clk enabled in RUN and WAIT mode

For some clocks, we might want to configure different behaviour,
e.g. a memory clock should be on even in STOP mode. Add a new
function imx_clk_gate2_cgr which allow to configure specific
gate values through the cgr_val parameter.

Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/clk/imx/clk-gate2.c
drivers/clk/imx/clk.h

index 8935bff99fe7acc083fb631c5ff8b7e97e7544c6..db44a198a0d9999f3e998033a3f8a517035c5e74 100644 (file)
@@ -31,6 +31,7 @@ struct clk_gate2 {
        struct clk_hw hw;
        void __iomem    *reg;
        u8              bit_idx;
+       u8              cgr_val;
        u8              flags;
        spinlock_t      *lock;
        unsigned int    *share_count;
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw)
                goto out;
 
        reg = readl(gate->reg);
-       reg |= 3 << gate->bit_idx;
+       reg &= ~(3 << gate->bit_idx);
+       reg |= gate->cgr_val << gate->bit_idx;
        writel(reg, gate->reg);
 
 out:
@@ -125,7 +127,7 @@ static struct clk_ops clk_gate2_ops = {
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 bit_idx,
+               void __iomem *reg, u8 bit_idx, u8 cgr_val,
                u8 clk_gate2_flags, spinlock_t *lock,
                unsigned int *share_count)
 {
@@ -140,6 +142,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
        /* struct clk_gate2 assignments */
        gate->reg = reg;
        gate->bit_idx = bit_idx;
+       gate->cgr_val = cgr_val;
        gate->flags = clk_gate2_flags;
        gate->lock = lock;
        gate->share_count = share_count;
index d942f5748d08ecad14f06cb6461765212a52f6a1..508d0fad84cf0744d7a7d4c73d8ba748be03a09f 100644 (file)
@@ -41,7 +41,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 bit_idx,
+               void __iomem *reg, u8 bit_idx, u8 cgr_val,
                u8 clk_gate_flags, spinlock_t *lock,
                unsigned int *share_count);
 
@@ -55,7 +55,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
                void __iomem *reg, u8 shift)
 {
        return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0, &imx_ccm_lock, NULL);
+                       shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk *imx_clk_gate2_shared(const char *name,
@@ -63,7 +63,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
                unsigned int *share_count)
 {
        return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0, &imx_ccm_lock, share_count);
+                       shift, 0x3, 0, &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)
+{
+       return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+                       shift, cgr_val, 0, &imx_ccm_lock, NULL);
 }
 
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,