cpufreq: kirkwood: Add a cpufreq driver for Marvell Kirkwood SoCs
[cascardo/linux.git] / drivers / clk / mvebu / clk-gating-ctrl.c
1 /*
2  * Marvell MVEBU clock gating control.
3  *
4  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5  * Andrew Lunn <andrew@lunn.ch>
6  *
7  * This file is licensed under the terms of the GNU General Public
8  * License version 2. This program is licensed "as is" without any
9  * warranty of any kind, whether express or implied.
10  */
11 #include <linux/kernel.h>
12 #include <linux/bitops.h>
13 #include <linux/io.h>
14 #include <linux/clk.h>
15 #include <linux/clkdev.h>
16 #include <linux/clk-provider.h>
17 #include <linux/clk/mvebu.h>
18 #include <linux/of.h>
19 #include <linux/of_address.h>
20
21 struct mvebu_gating_ctrl {
22         spinlock_t lock;
23         struct clk **gates;
24         int num_gates;
25 };
26
27 struct mvebu_soc_descr {
28         const char *name;
29         const char *parent;
30         int bit_idx;
31 };
32
33 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
34
35 static struct clk *mvebu_clk_gating_get_src(
36         struct of_phandle_args *clkspec, void *data)
37 {
38         struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
39         int n;
40
41         if (clkspec->args_count < 1)
42                 return ERR_PTR(-EINVAL);
43
44         for (n = 0; n < ctrl->num_gates; n++) {
45                 struct clk_gate *gate =
46                         to_clk_gate(__clk_get_hw(ctrl->gates[n]));
47                 if (clkspec->args[0] == gate->bit_idx)
48                         return ctrl->gates[n];
49         }
50         return ERR_PTR(-ENODEV);
51 }
52
53 static void __init mvebu_clk_gating_setup(
54         struct device_node *np, const struct mvebu_soc_descr *descr)
55 {
56         struct mvebu_gating_ctrl *ctrl;
57         struct clk *clk;
58         void __iomem *base;
59         const char *default_parent = NULL;
60         int n;
61
62         base = of_iomap(np, 0);
63
64         clk = of_clk_get(np, 0);
65         if (!IS_ERR(clk)) {
66                 default_parent = __clk_get_name(clk);
67                 clk_put(clk);
68         }
69
70         ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
71         if (WARN_ON(!ctrl))
72                 return;
73
74         spin_lock_init(&ctrl->lock);
75
76         /*
77          * Count, allocate, and register clock gates
78          */
79         for (n = 0; descr[n].name;)
80                 n++;
81
82         ctrl->num_gates = n;
83         ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
84                               GFP_KERNEL);
85         if (WARN_ON(!ctrl->gates)) {
86                 kfree(ctrl);
87                 return;
88         }
89
90         for (n = 0; n < ctrl->num_gates; n++) {
91                 u8 flags = 0;
92                 const char *parent =
93                         (descr[n].parent) ? descr[n].parent : default_parent;
94
95                 /*
96                  * On Armada 370, the DDR clock is a special case: it
97                  * isn't taken by any driver, but should anyway be
98                  * kept enabled, so we mark it as IGNORE_UNUSED for
99                  * now.
100                  */
101                 if (!strcmp(descr[n].name, "ddr"))
102                         flags |= CLK_IGNORE_UNUSED;
103
104                 ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
105                                    flags, base, descr[n].bit_idx, 0, &ctrl->lock);
106                 WARN_ON(IS_ERR(ctrl->gates[n]));
107         }
108         of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
109 }
110
111 /*
112  * SoC specific clock gating control
113  */
114
115 #ifdef CONFIG_MACH_ARMADA_370
116 static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
117         { "audio", NULL, 0 },
118         { "pex0_en", NULL, 1 },
119         { "pex1_en", NULL,  2 },
120         { "ge1", NULL, 3 },
121         { "ge0", NULL, 4 },
122         { "pex0", NULL, 5 },
123         { "pex1", NULL, 9 },
124         { "sata0", NULL, 15 },
125         { "sdio", NULL, 17 },
126         { "tdm", NULL, 25 },
127         { "ddr", NULL, 28 },
128         { "sata1", NULL, 30 },
129         { }
130 };
131 #endif
132
133 #ifdef CONFIG_MACH_ARMADA_XP
134 static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
135         { "audio", NULL, 0 },
136         { "ge3", NULL, 1 },
137         { "ge2", NULL,  2 },
138         { "ge1", NULL, 3 },
139         { "ge0", NULL, 4 },
140         { "pex0", NULL, 5 },
141         { "pex1", NULL, 6 },
142         { "pex2", NULL, 7 },
143         { "pex3", NULL, 8 },
144         { "bp", NULL, 13 },
145         { "sata0lnk", NULL, 14 },
146         { "sata0", "sata0lnk", 15 },
147         { "lcd", NULL, 16 },
148         { "sdio", NULL, 17 },
149         { "usb0", NULL, 18 },
150         { "usb1", NULL, 19 },
151         { "usb2", NULL, 20 },
152         { "xor0", NULL, 22 },
153         { "crypto", NULL, 23 },
154         { "tdm", NULL, 25 },
155         { "xor1", NULL, 28 },
156         { "sata1lnk", NULL, 29 },
157         { "sata1", "sata1lnk", 30 },
158         { }
159 };
160 #endif
161
162 #ifdef CONFIG_ARCH_DOVE
163 static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
164         { "usb0", NULL, 0 },
165         { "usb1", NULL, 1 },
166         { "ge", "gephy", 2 },
167         { "sata", NULL, 3 },
168         { "pex0", NULL, 4 },
169         { "pex1", NULL, 5 },
170         { "sdio0", NULL, 8 },
171         { "sdio1", NULL, 9 },
172         { "nand", NULL, 10 },
173         { "camera", NULL, 11 },
174         { "i2s0", NULL, 12 },
175         { "i2s1", NULL, 13 },
176         { "crypto", NULL, 15 },
177         { "ac97", NULL, 21 },
178         { "pdma", NULL, 22 },
179         { "xor0", NULL, 23 },
180         { "xor1", NULL, 24 },
181         { "gephy", NULL, 30 },
182         { }
183 };
184 #endif
185
186 #ifdef CONFIG_ARCH_KIRKWOOD
187 static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
188         { "ge0", NULL, 0 },
189         { "pex0", NULL, 2 },
190         { "usb0", NULL, 3 },
191         { "sdio", NULL, 4 },
192         { "tsu", NULL, 5 },
193         { "runit", NULL, 7 },
194         { "xor0", NULL, 8 },
195         { "audio", NULL, 9 },
196         { "powersave", "cpuclk", 11 },
197         { "sata0", NULL, 14 },
198         { "sata1", NULL, 15 },
199         { "xor1", NULL, 16 },
200         { "crypto", NULL, 17 },
201         { "pex1", NULL, 18 },
202         { "ge1", NULL, 19 },
203         { "tdm", NULL, 20 },
204         { }
205 };
206 #endif
207
208 static const __initdata struct of_device_id clk_gating_match[] = {
209 #ifdef CONFIG_MACH_ARMADA_370
210         {
211                 .compatible = "marvell,armada-370-gating-clock",
212                 .data = armada_370_gating_descr,
213         },
214 #endif
215
216 #ifdef CONFIG_MACH_ARMADA_XP
217         {
218                 .compatible = "marvell,armada-xp-gating-clock",
219                 .data = armada_xp_gating_descr,
220         },
221 #endif
222
223 #ifdef CONFIG_ARCH_DOVE
224         {
225                 .compatible = "marvell,dove-gating-clock",
226                 .data = dove_gating_descr,
227         },
228 #endif
229
230 #ifdef CONFIG_ARCH_KIRKWOOD
231         {
232                 .compatible = "marvell,kirkwood-gating-clock",
233                 .data = kirkwood_gating_descr,
234         },
235 #endif
236
237         { }
238 };
239
240 void __init mvebu_gating_clk_init(void)
241 {
242         struct device_node *np;
243
244         for_each_matching_node(np, clk_gating_match) {
245                 const struct of_device_id *match =
246                         of_match_node(clk_gating_match, np);
247                 mvebu_clk_gating_setup(np,
248                        (const struct mvebu_soc_descr *)match->data);
249         }
250 }