Skip to content

Commit

Permalink
ARM: imx: add shared gate clock support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Shawn Guo committed May 12, 2014
1 parent 94b5c02 commit f9f28cd
Showing 2 changed files with 23 additions and 3 deletions.
13 changes: 12 additions & 1 deletion arch/arm/mach-imx/clk-gate2.c
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ struct clk_gate2 {
u8 bit_idx;
u8 flags;
spinlock_t *lock;
unsigned int *share_count;
};

#define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw)
@@ -45,10 +46,14 @@ static int clk_gate2_enable(struct clk_hw *hw)

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;
writel(reg, gate->reg);

out:
spin_unlock_irqrestore(gate->lock, flags);

return 0;
@@ -62,10 +67,14 @@ static void clk_gate2_disable(struct clk_hw *hw)

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);
writel(reg, gate->reg);

out:
spin_unlock_irqrestore(gate->lock, flags);
}

@@ -91,7 +100,8 @@ 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,
u8 clk_gate2_flags, spinlock_t *lock)
u8 clk_gate2_flags, spinlock_t *lock,
unsigned int *share_count)
{
struct clk_gate2 *gate;
struct clk *clk;
@@ -106,6 +116,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
gate->bit_idx = bit_idx;
gate->flags = clk_gate2_flags;
gate->lock = lock;
gate->share_count = share_count;

init.name = name;
init.ops = &clk_gate2_ops;
13 changes: 11 additions & 2 deletions arch/arm/mach-imx/clk.h
Original file line number Diff line number Diff line change
@@ -28,7 +28,8 @@ 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,
u8 clk_gate_flags, spinlock_t *lock);
u8 clk_gate_flags, spinlock_t *lock,
unsigned int *share_count);

struct clk * imx_obtain_fixed_clock(
const char *name, unsigned long rate);
@@ -37,7 +38,15 @@ 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);
shift, 0, &imx_ccm_lock, NULL);
}

static inline struct clk *imx_clk_gate2_shared(const char *name,
const char *parent, void __iomem *reg, u8 shift,
unsigned int *share_count)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
shift, 0, &imx_ccm_lock, share_count);
}

struct clk *imx_clk_pfd(const char *name, const char *parent_name,

0 comments on commit f9f28cd

Please sign in to comment.