]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-imx/clk-gate2.c
Merge remote-tracking branch 'kbuild/for-next'
[karo-tx-linux.git] / arch / arm / mach-imx / clk-gate2.c
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 #include "clk.h"
19
20 /**
21  * DOC: basic gatable clock which can gate and ungate it's ouput
22  *
23  * Traits of this clock:
24  * prepare - clk_(un)prepare only ensures parent is (un)prepared
25  * enable - clk_enable and clk_disable are functional & control gating
26  * rate - inherits rate from parent.  No clk_set_rate support
27  * parent - fixed parent.  No clk_set_parent support
28  */
29
30 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
31
32 static int clk_gate2_enable(struct clk_hw *hw)
33 {
34         struct clk_gate *gate = to_clk_gate(hw);
35         u32 reg;
36         unsigned long flags = 0;
37
38         if (gate->lock)
39                 spin_lock_irqsave(gate->lock, flags);
40
41         reg = readl(gate->reg);
42         reg |= 3 << gate->bit_idx;
43         writel(reg, gate->reg);
44
45         if (gate->lock)
46                 spin_unlock_irqrestore(gate->lock, flags);
47
48         return 0;
49 }
50
51 static void clk_gate2_disable(struct clk_hw *hw)
52 {
53         struct clk_gate *gate = to_clk_gate(hw);
54         u32 reg;
55         unsigned long flags = 0;
56
57         if (gate->lock)
58                 spin_lock_irqsave(gate->lock, flags);
59
60         reg = readl(gate->reg);
61         reg &= ~(3 << gate->bit_idx);
62         writel(reg, gate->reg);
63
64         if (gate->lock)
65                 spin_unlock_irqrestore(gate->lock, flags);
66 }
67
68 static int clk_gate2_is_enabled(struct clk_hw *hw)
69 {
70         u32 reg;
71         struct clk_gate *gate = to_clk_gate(hw);
72
73         reg = readl(gate->reg);
74
75         if (((reg >> gate->bit_idx) & 3) == 3)
76                 return 1;
77
78         return 0;
79 }
80
81 static struct clk_ops clk_gate2_ops = {
82         .enable = clk_gate2_enable,
83         .disable = clk_gate2_disable,
84         .is_enabled = clk_gate2_is_enabled,
85 };
86
87 struct clk *clk_register_gate2(struct device *dev, const char *name,
88                 const char *parent_name, unsigned long flags,
89                 void __iomem *reg, u8 bit_idx,
90                 u8 clk_gate2_flags, spinlock_t *lock)
91 {
92         struct clk_gate *gate;
93         struct clk *clk;
94         struct clk_init_data init;
95
96         gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
97         if (!gate)
98                 return ERR_PTR(-ENOMEM);
99
100         /* struct clk_gate assignments */
101         gate->reg = reg;
102         gate->bit_idx = bit_idx;
103         gate->flags = clk_gate2_flags;
104         gate->lock = lock;
105
106         init.name = name;
107         init.ops = &clk_gate2_ops;
108         init.flags = flags;
109         init.parent_names = parent_name ? &parent_name : NULL;
110         init.num_parents = parent_name ? 1 : 0;
111
112         gate->hw.init = &init;
113
114         clk = clk_register(dev, &gate->hw);
115         if (IS_ERR(clk))
116                 kfree(gate);
117
118         return clk;
119 }