diff options
Diffstat (limited to 'arch/arm')
| -rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-gate2.c | 118 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk.h | 12 |
3 files changed, 131 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 66bc6bed0bcd..1b3f2aea8f48 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
| @@ -11,7 +11,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i | |||
| 11 | 11 | ||
| 12 | obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o | 12 | obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o |
| 13 | 13 | ||
| 14 | obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o | 14 | obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o |
| 15 | 15 | ||
| 16 | # Support for CMOS sensor interface | 16 | # Support for CMOS sensor interface |
| 17 | obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o | 17 | obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o |
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 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> | ||
| 3 | * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * Gated clock implementation | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/clk-provider.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/string.h> | ||
| 18 | |||
| 19 | /** | ||
| 20 | * DOC: basic gatable clock which can gate and ungate it's ouput | ||
| 21 | * | ||
| 22 | * Traits of this clock: | ||
| 23 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
| 24 | * enable - clk_enable and clk_disable are functional & control gating | ||
| 25 | * rate - inherits rate from parent. No clk_set_rate support | ||
| 26 | * parent - fixed parent. No clk_set_parent support | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) | ||
| 30 | |||
| 31 | static int clk_gate2_enable(struct clk_hw *hw) | ||
| 32 | { | ||
| 33 | struct clk_gate *gate = to_clk_gate(hw); | ||
| 34 | u32 reg; | ||
| 35 | unsigned long flags = 0; | ||
| 36 | |||
| 37 | if (gate->lock) | ||
| 38 | spin_lock_irqsave(gate->lock, flags); | ||
| 39 | |||
| 40 | reg = readl(gate->reg); | ||
| 41 | reg |= 3 << gate->bit_idx; | ||
| 42 | writel(reg, gate->reg); | ||
| 43 | |||
| 44 | if (gate->lock) | ||
| 45 | spin_unlock_irqrestore(gate->lock, flags); | ||
| 46 | |||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static void clk_gate2_disable(struct clk_hw *hw) | ||
| 51 | { | ||
| 52 | struct clk_gate *gate = to_clk_gate(hw); | ||
| 53 | u32 reg; | ||
| 54 | unsigned long flags = 0; | ||
| 55 | |||
| 56 | if (gate->lock) | ||
| 57 | spin_lock_irqsave(gate->lock, flags); | ||
| 58 | |||
| 59 | reg = readl(gate->reg); | ||
| 60 | reg &= ~(3 << gate->bit_idx); | ||
| 61 | writel(reg, gate->reg); | ||
| 62 | |||
| 63 | if (gate->lock) | ||
| 64 | spin_unlock_irqrestore(gate->lock, flags); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int clk_gate2_is_enabled(struct clk_hw *hw) | ||
| 68 | { | ||
| 69 | u32 reg; | ||
| 70 | struct clk_gate *gate = to_clk_gate(hw); | ||
| 71 | |||
| 72 | reg = readl(gate->reg); | ||
| 73 | |||
| 74 | if (((reg >> gate->bit_idx) & 3) == 3) | ||
| 75 | return 1; | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static struct clk_ops clk_gate2_ops = { | ||
| 81 | .enable = clk_gate2_enable, | ||
| 82 | .disable = clk_gate2_disable, | ||
| 83 | .is_enabled = clk_gate2_is_enabled, | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct clk *clk_register_gate2(struct device *dev, const char *name, | ||
| 87 | const char *parent_name, unsigned long flags, | ||
| 88 | void __iomem *reg, u8 bit_idx, | ||
| 89 | u8 clk_gate2_flags, spinlock_t *lock) | ||
| 90 | { | ||
| 91 | struct clk_gate *gate; | ||
| 92 | struct clk *clk; | ||
| 93 | struct clk_init_data init; | ||
| 94 | |||
| 95 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 96 | if (!gate) | ||
| 97 | return ERR_PTR(-ENOMEM); | ||
| 98 | |||
| 99 | /* struct clk_gate assignments */ | ||
| 100 | gate->reg = reg; | ||
| 101 | gate->bit_idx = bit_idx; | ||
| 102 | gate->flags = clk_gate2_flags; | ||
| 103 | gate->lock = lock; | ||
| 104 | |||
| 105 | init.name = name; | ||
| 106 | init.ops = &clk_gate2_ops; | ||
| 107 | init.flags = flags; | ||
| 108 | init.parent_names = parent_name ? &parent_name : NULL; | ||
| 109 | init.num_parents = parent_name ? 1 : 0; | ||
| 110 | |||
| 111 | gate->hw.init = &init; | ||
| 112 | |||
| 113 | clk = clk_register(dev, &gate->hw); | ||
| 114 | if (IS_ERR(clk)) | ||
| 115 | kfree(clk); | ||
| 116 | |||
| 117 | return clk; | ||
| 118 | } | ||
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 331316d6a4de..5f6e435da4ae 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h | |||
| @@ -24,6 +24,18 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | |||
| 24 | const char *parent_name, void __iomem *base, u32 gate_mask, | 24 | const char *parent_name, void __iomem *base, u32 gate_mask, |
| 25 | u32 div_mask); | 25 | u32 div_mask); |
| 26 | 26 | ||
| 27 | struct clk *clk_register_gate2(struct device *dev, const char *name, | ||
| 28 | const char *parent_name, unsigned long flags, | ||
| 29 | void __iomem *reg, u8 bit_idx, | ||
| 30 | u8 clk_gate_flags, spinlock_t *lock); | ||
| 31 | |||
| 32 | static inline struct clk *imx_clk_gate2(const char *name, const char *parent, | ||
| 33 | void __iomem *reg, u8 shift) | ||
| 34 | { | ||
| 35 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
| 36 | shift, 0, &imx_ccm_lock); | ||
| 37 | } | ||
| 38 | |||
| 27 | static inline struct clk *imx_clk_fixed(const char *name, int rate) | 39 | static inline struct clk *imx_clk_fixed(const char *name, int rate) |
| 28 | { | 40 | { |
| 29 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); | 41 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); |
