diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-05-14 15:24:45 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-05-14 15:28:19 +0200 |
commit | 304ea74770c892cf115e128b0e0dc6636148b010 (patch) | |
tree | ccf06fa8a8fa9321beaab730ac19160966033d52 /arch/arm/mach-imx/clk-gate2.c | |
parent | Merge branch 'mxs/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2... (diff) | |
parent | Merge branch 'imx/pinctrl' into imx/dt (diff) | |
download | linux-304ea74770c892cf115e128b0e0dc6636148b010.tar.xz linux-304ea74770c892cf115e128b0e0dc6636148b010.zip |
Merge branch 'imx/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2.6.git into next/dt2
Shawn Guo <shawn.guo@linaro.org> writes:
I chose to base it on Sascha's imx-common-clk series than -rc, because
otherwise it will keep patching clock file that has been removed by
imx-common-clk series. It also depends on imx-pinctrl pull-request
I just sent to be functional.
Note: when imx-common-clk and imx-pinctrl get merged together, the
following files will have conflicts. But the conflicts should not be
so hard to resolve.
[arnd: resolved those merge conflicts by pulling pinctrl branch]
* imx/dt: (24 commits)
ARM: dts: imx53-qsb: enable audio support
ARM: dts: imx51-babbage: enable audio support
ARM: imx: add audio codec clk lookup for imx53-qsb
ARM: imx: add audmux pad setting for imx51-babbage
ARM: imx: add more imx5 ssi clocks
ARM: dts: imx53-qsb: Add Dialog DA9053 PMIC support
ARM: dts: imx6q-sabrelite: add serial2 pinctrl support
ARM: dts: imx6q-sabrelite: add sound device imx6q-sabrelite-sgtl5000
ARM: imx6q_sabrelite: clk_register_clkdev cko1 for sgtl5000
ARM: imx6q: add ssi1_ipg clk_lookup
ARM: dts: imx6q-sabrelite: add audmux pinctrl support
ARM: dts: imx6q-sabrelite: add i2c1 pinctrl support
ARM: dts: imx6q-sabrelite: add audmux device
ARM: dts: imx6q-sabrelite: add ssi device
ARM: dts: imx6q-arm2: add pinctrl state for usdhc
ARM: imx6: Add UART2 for low-level debug
ARM: imx6q: register phy fixup only when CONFIG_PHYLIB is enabled
ARM: imx6q: move imx6q_sabrelite specific code to a dedicated function
ARM: dts: imx6q-sabrelite: Add SPI NOR support
ARM: dts: Add basic support for imx6q-sabresd
...
Pulls in imx/pinctrl and imx/clock as dependencies.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-imx/clk-gate2.c')
-rw-r--r-- | arch/arm/mach-imx/clk-gate2.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c new file mode 100644 index 000000000000..3c1b8ff9a0a6 --- /dev/null +++ b/arch/arm/mach-imx/clk-gate2.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Gated clock implementation + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/string.h> + +/** + * DOC: basic gatable clock which can gate and ungate it's ouput + * + * Traits of this clock: + * prepare - clk_(un)prepare only ensures parent is (un)prepared + * enable - clk_enable and clk_disable are functional & control gating + * rate - inherits rate from parent. No clk_set_rate support + * parent - fixed parent. No clk_set_parent support + */ + +#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) + +static int clk_gate2_enable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + u32 reg; + unsigned long flags = 0; + + if (gate->lock) + spin_lock_irqsave(gate->lock, flags); + + reg = readl(gate->reg); + reg |= 3 << gate->bit_idx; + writel(reg, gate->reg); + + if (gate->lock) + spin_unlock_irqrestore(gate->lock, flags); + + return 0; +} + +static void clk_gate2_disable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + u32 reg; + unsigned long flags = 0; + + if (gate->lock) + spin_lock_irqsave(gate->lock, flags); + + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + writel(reg, gate->reg); + + if (gate->lock) + spin_unlock_irqrestore(gate->lock, flags); +} + +static int clk_gate2_is_enabled(struct clk_hw *hw) +{ + u32 reg; + struct clk_gate *gate = to_clk_gate(hw); + + reg = readl(gate->reg); + + if (((reg >> gate->bit_idx) & 3) == 3) + return 1; + + return 0; +} + +static struct clk_ops clk_gate2_ops = { + .enable = clk_gate2_enable, + .disable = clk_gate2_disable, + .is_enabled = clk_gate2_is_enabled, +}; + +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) +{ + struct clk_gate *gate; + struct clk *clk; + struct clk_init_data init; + + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + /* struct clk_gate assignments */ + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = clk_gate2_flags; + gate->lock = lock; + + init.name = name; + init.ops = &clk_gate2_ops; + init.flags = flags; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + + gate->hw.init = &init; + + clk = clk_register(dev, &gate->hw); + if (IS_ERR(clk)) + kfree(clk); + + return clk; +} |