Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: imx: add shared gate clock support

It's quite common on i.MX that one gate bit controls the gating of
multiple clocks, i.e. this is a shared gate. The patch adds the
function imx_clk_gate2_shared() for such case. The clocks controlled
by the same gate bits should call this function with a pointer to a
single share count variable, so that the gate bits will only be
operated on the first enabling and the last disabling of these shared
gate clocks.

Thanks to Gerhard Sittig <gsi@denx.de> for this idea.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>

Shawn Guo f9f28cdf 94b5c028

+23 -3
+12 -1
arch/arm/mach-imx/clk-gate2.c
··· 33 33 u8 bit_idx; 34 34 u8 flags; 35 35 spinlock_t *lock; 36 + unsigned int *share_count; 36 37 }; 37 38 38 39 #define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw) ··· 46 45 47 46 spin_lock_irqsave(gate->lock, flags); 48 47 48 + if (gate->share_count && (*gate->share_count)++ > 0) 49 + goto out; 50 + 49 51 reg = readl(gate->reg); 50 52 reg |= 3 << gate->bit_idx; 51 53 writel(reg, gate->reg); 52 54 55 + out: 53 56 spin_unlock_irqrestore(gate->lock, flags); 54 57 55 58 return 0; ··· 67 62 68 63 spin_lock_irqsave(gate->lock, flags); 69 64 65 + if (gate->share_count && --(*gate->share_count) > 0) 66 + goto out; 67 + 70 68 reg = readl(gate->reg); 71 69 reg &= ~(3 << gate->bit_idx); 72 70 writel(reg, gate->reg); 73 71 72 + out: 74 73 spin_unlock_irqrestore(gate->lock, flags); 75 74 } 76 75 ··· 100 91 struct clk *clk_register_gate2(struct device *dev, const char *name, 101 92 const char *parent_name, unsigned long flags, 102 93 void __iomem *reg, u8 bit_idx, 103 - u8 clk_gate2_flags, spinlock_t *lock) 94 + u8 clk_gate2_flags, spinlock_t *lock, 95 + unsigned int *share_count) 104 96 { 105 97 struct clk_gate2 *gate; 106 98 struct clk *clk; ··· 116 106 gate->bit_idx = bit_idx; 117 107 gate->flags = clk_gate2_flags; 118 108 gate->lock = lock; 109 + gate->share_count = share_count; 119 110 120 111 init.name = name; 121 112 init.ops = &clk_gate2_ops;
+11 -2
arch/arm/mach-imx/clk.h
··· 28 28 struct clk *clk_register_gate2(struct device *dev, const char *name, 29 29 const char *parent_name, unsigned long flags, 30 30 void __iomem *reg, u8 bit_idx, 31 - u8 clk_gate_flags, spinlock_t *lock); 31 + u8 clk_gate_flags, spinlock_t *lock, 32 + unsigned int *share_count); 32 33 33 34 struct clk * imx_obtain_fixed_clock( 34 35 const char *name, unsigned long rate); ··· 38 37 void __iomem *reg, u8 shift) 39 38 { 40 39 return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, 41 - shift, 0, &imx_ccm_lock); 40 + shift, 0, &imx_ccm_lock, NULL); 41 + } 42 + 43 + static inline struct clk *imx_clk_gate2_shared(const char *name, 44 + const char *parent, void __iomem *reg, u8 shift, 45 + unsigned int *share_count) 46 + { 47 + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, 48 + shift, 0, &imx_ccm_lock, share_count); 42 49 } 43 50 44 51 struct clk *imx_clk_pfd(const char *name, const char *parent_name,