]> Pileus Git - ~andy/linux/blob - drivers/clk/clk-ppc-corenet.c
Linux 3.14
[~andy/linux] / drivers / clk / clk-ppc-corenet.c
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * clock driver for Freescale PowerPC corenet SoCs.
9  */
10 #include <linux/clk-provider.h>
11 #include <linux/io.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/of_address.h>
15 #include <linux/of_platform.h>
16 #include <linux/of.h>
17 #include <linux/slab.h>
18
19 struct cmux_clk {
20         struct clk_hw hw;
21         void __iomem *reg;
22         u32 flags;
23 };
24
25 #define PLL_KILL                        BIT(31)
26 #define CLKSEL_SHIFT            27
27 #define CLKSEL_ADJUST           BIT(0)
28 #define to_cmux_clk(p)          container_of(p, struct cmux_clk, hw)
29
30 static void __iomem *base;
31 static unsigned int clocks_per_pll;
32
33 static int cmux_set_parent(struct clk_hw *hw, u8 idx)
34 {
35         struct cmux_clk *clk = to_cmux_clk(hw);
36         u32 clksel;
37
38         clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
39         if (clk->flags & CLKSEL_ADJUST)
40                 clksel += 8;
41         clksel = (clksel & 0xf) << CLKSEL_SHIFT;
42         iowrite32be(clksel, clk->reg);
43
44         return 0;
45 }
46
47 static u8 cmux_get_parent(struct clk_hw *hw)
48 {
49         struct cmux_clk *clk = to_cmux_clk(hw);
50         u32 clksel;
51
52         clksel = ioread32be(clk->reg);
53         clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
54         if (clk->flags & CLKSEL_ADJUST)
55                 clksel -= 8;
56         clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
57
58         return clksel;
59 }
60
61 const struct clk_ops cmux_ops = {
62         .get_parent = cmux_get_parent,
63         .set_parent = cmux_set_parent,
64 };
65
66 static void __init core_mux_init(struct device_node *np)
67 {
68         struct clk *clk;
69         struct clk_init_data init;
70         struct cmux_clk *cmux_clk;
71         struct device_node *node;
72         int rc, count, i;
73         u32     offset;
74         const char *clk_name;
75         const char **parent_names;
76
77         rc = of_property_read_u32(np, "reg", &offset);
78         if (rc) {
79                 pr_err("%s: could not get reg property\n", np->name);
80                 return;
81         }
82
83         /* get the input clock source count */
84         count = of_property_count_strings(np, "clock-names");
85         if (count < 0) {
86                 pr_err("%s: get clock count error\n", np->name);
87                 return;
88         }
89         parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
90         if (!parent_names) {
91                 pr_err("%s: could not allocate parent_names\n", __func__);
92                 return;
93         }
94
95         for (i = 0; i < count; i++)
96                 parent_names[i] = of_clk_get_parent_name(np, i);
97
98         cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
99         if (!cmux_clk) {
100                 pr_err("%s: could not allocate cmux_clk\n", __func__);
101                 goto err_name;
102         }
103         cmux_clk->reg = base + offset;
104
105         node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
106         if (node && (offset >= 0x80))
107                 cmux_clk->flags = CLKSEL_ADJUST;
108
109         rc = of_property_read_string_index(np, "clock-output-names",
110                         0, &clk_name);
111         if (rc) {
112                 pr_err("%s: read clock names error\n", np->name);
113                 goto err_clk;
114         }
115
116         init.name = clk_name;
117         init.ops = &cmux_ops;
118         init.parent_names = parent_names;
119         init.num_parents = count;
120         init.flags = 0;
121         cmux_clk->hw.init = &init;
122
123         clk = clk_register(NULL, &cmux_clk->hw);
124         if (IS_ERR(clk)) {
125                 pr_err("%s: could not register clock\n", clk_name);
126                 goto err_clk;
127         }
128
129         rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
130         if (rc) {
131                 pr_err("Could not register clock provider for node:%s\n",
132                          np->name);
133                 goto err_clk;
134         }
135         goto err_name;
136
137 err_clk:
138         kfree(cmux_clk);
139 err_name:
140         /* free *_names because they are reallocated when registered */
141         kfree(parent_names);
142 }
143
144 static void __init core_pll_init(struct device_node *np)
145 {
146         u32 offset, mult;
147         int i, rc, count;
148         const char *clk_name, *parent_name;
149         struct clk_onecell_data *onecell_data;
150         struct clk      **subclks;
151
152         rc = of_property_read_u32(np, "reg", &offset);
153         if (rc) {
154                 pr_err("%s: could not get reg property\n", np->name);
155                 return;
156         }
157
158         /* get the multiple of PLL */
159         mult = ioread32be(base + offset);
160
161         /* check if this PLL is disabled */
162         if (mult & PLL_KILL) {
163                 pr_debug("PLL:%s is disabled\n", np->name);
164                 return;
165         }
166         mult = (mult >> 1) & 0x3f;
167
168         parent_name = of_clk_get_parent_name(np, 0);
169         if (!parent_name) {
170                 pr_err("PLL: %s must have a parent\n", np->name);
171                 return;
172         }
173
174         count = of_property_count_strings(np, "clock-output-names");
175         if (count < 0 || count > 4) {
176                 pr_err("%s: clock is not supported\n", np->name);
177                 return;
178         }
179
180         /* output clock number per PLL */
181         clocks_per_pll = count;
182
183         subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
184         if (!subclks) {
185                 pr_err("%s: could not allocate subclks\n", __func__);
186                 return;
187         }
188
189         onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
190         if (!onecell_data) {
191                 pr_err("%s: could not allocate onecell_data\n", __func__);
192                 goto err_clks;
193         }
194
195         for (i = 0; i < count; i++) {
196                 rc = of_property_read_string_index(np, "clock-output-names",
197                                 i, &clk_name);
198                 if (rc) {
199                         pr_err("%s: could not get clock names\n", np->name);
200                         goto err_cell;
201                 }
202
203                 /*
204                  * when count == 4, there are 4 output clocks:
205                  * /1, /2, /3, /4 respectively
206                  * when count < 4, there are at least 2 output clocks:
207                  * /1, /2, (/4, if count == 3) respectively.
208                  */
209                 if (count == 4)
210                         subclks[i] = clk_register_fixed_factor(NULL, clk_name,
211                                         parent_name, 0, mult, 1 + i);
212                 else
213
214                         subclks[i] = clk_register_fixed_factor(NULL, clk_name,
215                                         parent_name, 0, mult, 1 << i);
216
217                 if (IS_ERR(subclks[i])) {
218                         pr_err("%s: could not register clock\n", clk_name);
219                         goto err_cell;
220                 }
221         }
222
223         onecell_data->clks = subclks;
224         onecell_data->clk_num = count;
225
226         rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
227         if (rc) {
228                 pr_err("Could not register clk provider for node:%s\n",
229                          np->name);
230                 goto err_cell;
231         }
232
233         return;
234 err_cell:
235         kfree(onecell_data);
236 err_clks:
237         kfree(subclks);
238 }
239
240 static const struct of_device_id clk_match[] __initconst = {
241         { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
242         { .compatible = "fsl,core-pll-clock", .data = core_pll_init, },
243         { .compatible = "fsl,core-mux-clock", .data = core_mux_init, },
244         {}
245 };
246
247 static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
248 {
249         struct device_node *np;
250
251         np = pdev->dev.of_node;
252         base = of_iomap(np, 0);
253         if (!base) {
254                 dev_err(&pdev->dev, "iomap error\n");
255                 return -ENOMEM;
256         }
257         of_clk_init(clk_match);
258
259         return 0;
260 }
261
262 static const struct of_device_id ppc_clk_ids[] __initconst = {
263         { .compatible = "fsl,qoriq-clockgen-1.0", },
264         { .compatible = "fsl,qoriq-clockgen-2.0", },
265         {}
266 };
267
268 static struct platform_driver ppc_corenet_clk_driver = {
269         .driver = {
270                 .name = "ppc_corenet_clock",
271                 .owner = THIS_MODULE,
272                 .of_match_table = ppc_clk_ids,
273         },
274         .probe = ppc_corenet_clk_probe,
275 };
276
277 static int __init ppc_corenet_clk_init(void)
278 {
279         return platform_driver_register(&ppc_corenet_clk_driver);
280 }
281 subsys_initcall(ppc_corenet_clk_init);