]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/clk/sunxi/clk-mod0.c
Merge remote-tracking branch 'tty/tty-next'
[karo-tx-linux.git] / drivers / clk / sunxi / clk-mod0.c
1 /*
2  * Copyright 2013 Emilio López
3  *
4  * Emilio López <emilio@elopez.com.ar>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/clk.h>
18 #include <linux/clkdev.h>
19 #include <linux/clk-provider.h>
20 #include <linux/of_address.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23
24 #include "clk-factors.h"
25
26 /**
27  * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
28  * MOD0 rate is calculated as follows
29  * rate = (parent_rate >> p) / (m + 1);
30  */
31
32 static void sun4i_a10_get_mod0_factors(struct factors_request *req)
33 {
34         u8 div, calcm, calcp;
35
36         /* These clocks can only divide, so we will never be able to achieve
37          * frequencies higher than the parent frequency */
38         if (req->rate > req->parent_rate)
39                 req->rate = req->parent_rate;
40
41         div = DIV_ROUND_UP(req->parent_rate, req->rate);
42
43         if (div < 16)
44                 calcp = 0;
45         else if (div / 2 < 16)
46                 calcp = 1;
47         else if (div / 4 < 16)
48                 calcp = 2;
49         else
50                 calcp = 3;
51
52         calcm = DIV_ROUND_UP(div, 1 << calcp);
53
54         req->rate = (req->parent_rate >> calcp) / calcm;
55         req->m = calcm - 1;
56         req->p = calcp;
57 }
58
59 /* user manual says "n" but it's really "p" */
60 static const struct clk_factors_config sun4i_a10_mod0_config = {
61         .mshift = 0,
62         .mwidth = 4,
63         .pshift = 16,
64         .pwidth = 2,
65 };
66
67 static const struct factors_data sun4i_a10_mod0_data = {
68         .enable = 31,
69         .mux = 24,
70         .muxmask = BIT(1) | BIT(0),
71         .table = &sun4i_a10_mod0_config,
72         .getter = sun4i_a10_get_mod0_factors,
73 };
74
75 static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
76
77 static void __init sun4i_a10_mod0_setup(struct device_node *node)
78 {
79         void __iomem *reg;
80
81         reg = of_iomap(node, 0);
82         if (!reg) {
83                 /*
84                  * This happens with mod0 clk nodes instantiated through
85                  * mfd, as those do not have their resources assigned at
86                  * CLK_OF_DECLARE time yet, so do not print an error.
87                  */
88                 return;
89         }
90
91         sunxi_factors_register(node, &sun4i_a10_mod0_data,
92                                &sun4i_a10_mod0_lock, reg);
93 }
94 CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
95
96 static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev)
97 {
98         struct device_node *np = pdev->dev.of_node;
99         struct resource *r;
100         void __iomem *reg;
101
102         if (!np)
103                 return -ENODEV;
104
105         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
106         reg = devm_ioremap_resource(&pdev->dev, r);
107         if (IS_ERR(reg))
108                 return PTR_ERR(reg);
109
110         sunxi_factors_register(np, &sun4i_a10_mod0_data,
111                                &sun4i_a10_mod0_lock, reg);
112         return 0;
113 }
114
115 static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = {
116         { .compatible = "allwinner,sun4i-a10-mod0-clk" },
117         { /* sentinel */ }
118 };
119
120 static struct platform_driver sun4i_a10_mod0_clk_driver = {
121         .driver = {
122                 .name = "sun4i-a10-mod0-clk",
123                 .of_match_table = sun4i_a10_mod0_clk_dt_ids,
124         },
125         .probe = sun4i_a10_mod0_clk_probe,
126 };
127 builtin_platform_driver(sun4i_a10_mod0_clk_driver);
128
129 static const struct factors_data sun9i_a80_mod0_data __initconst = {
130         .enable = 31,
131         .mux = 24,
132         .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
133         .table = &sun4i_a10_mod0_config,
134         .getter = sun4i_a10_get_mod0_factors,
135 };
136
137 static void __init sun9i_a80_mod0_setup(struct device_node *node)
138 {
139         void __iomem *reg;
140
141         reg = of_io_request_and_map(node, 0, of_node_full_name(node));
142         if (IS_ERR(reg)) {
143                 pr_err("Could not get registers for mod0-clk: %s\n",
144                        node->name);
145                 return;
146         }
147
148         sunxi_factors_register(node, &sun9i_a80_mod0_data,
149                                &sun4i_a10_mod0_lock, reg);
150 }
151 CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup);
152
153 static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
154
155 static void __init sun5i_a13_mbus_setup(struct device_node *node)
156 {
157         struct clk *mbus;
158         void __iomem *reg;
159
160         reg = of_iomap(node, 0);
161         if (!reg) {
162                 pr_err("Could not get registers for a13-mbus-clk\n");
163                 return;
164         }
165
166         mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data,
167                                       &sun5i_a13_mbus_lock, reg);
168
169         /* The MBUS clocks needs to be always enabled */
170         __clk_get(mbus);
171         clk_prepare_enable(mbus);
172 }
173 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
174
175 struct mmc_phase {
176         struct clk_hw           hw;
177         u8                      offset;
178         void __iomem            *reg;
179         spinlock_t              *lock;
180 };
181
182 #define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
183
184 static int mmc_get_phase(struct clk_hw *hw)
185 {
186         struct clk *mmc, *mmc_parent, *clk = hw->clk;
187         struct mmc_phase *phase = to_mmc_phase(hw);
188         unsigned int mmc_rate, mmc_parent_rate;
189         u16 step, mmc_div;
190         u32 value;
191         u8 delay;
192
193         value = readl(phase->reg);
194         delay = (value >> phase->offset) & 0x3;
195
196         if (!delay)
197                 return 180;
198
199         /* Get the main MMC clock */
200         mmc = clk_get_parent(clk);
201         if (!mmc)
202                 return -EINVAL;
203
204         /* And its rate */
205         mmc_rate = clk_get_rate(mmc);
206         if (!mmc_rate)
207                 return -EINVAL;
208
209         /* Now, get the MMC parent (most likely some PLL) */
210         mmc_parent = clk_get_parent(mmc);
211         if (!mmc_parent)
212                 return -EINVAL;
213
214         /* And its rate */
215         mmc_parent_rate = clk_get_rate(mmc_parent);
216         if (!mmc_parent_rate)
217                 return -EINVAL;
218
219         /* Get MMC clock divider */
220         mmc_div = mmc_parent_rate / mmc_rate;
221
222         step = DIV_ROUND_CLOSEST(360, mmc_div);
223         return delay * step;
224 }
225
226 static int mmc_set_phase(struct clk_hw *hw, int degrees)
227 {
228         struct clk *mmc, *mmc_parent, *clk = hw->clk;
229         struct mmc_phase *phase = to_mmc_phase(hw);
230         unsigned int mmc_rate, mmc_parent_rate;
231         unsigned long flags;
232         u32 value;
233         u8 delay;
234
235         /* Get the main MMC clock */
236         mmc = clk_get_parent(clk);
237         if (!mmc)
238                 return -EINVAL;
239
240         /* And its rate */
241         mmc_rate = clk_get_rate(mmc);
242         if (!mmc_rate)
243                 return -EINVAL;
244
245         /* Now, get the MMC parent (most likely some PLL) */
246         mmc_parent = clk_get_parent(mmc);
247         if (!mmc_parent)
248                 return -EINVAL;
249
250         /* And its rate */
251         mmc_parent_rate = clk_get_rate(mmc_parent);
252         if (!mmc_parent_rate)
253                 return -EINVAL;
254
255         if (degrees != 180) {
256                 u16 step, mmc_div;
257
258                 /* Get MMC clock divider */
259                 mmc_div = mmc_parent_rate / mmc_rate;
260
261                 /*
262                  * We can only outphase the clocks by multiple of the
263                  * PLL's period.
264                  *
265                  * Since the MMC clock in only a divider, and the
266                  * formula to get the outphasing in degrees is deg =
267                  * 360 * delta / period
268                  *
269                  * If we simplify this formula, we can see that the
270                  * only thing that we're concerned about is the number
271                  * of period we want to outphase our clock from, and
272                  * the divider set by the MMC clock.
273                  */
274                 step = DIV_ROUND_CLOSEST(360, mmc_div);
275                 delay = DIV_ROUND_CLOSEST(degrees, step);
276         } else {
277                 delay = 0;
278         }
279
280         spin_lock_irqsave(phase->lock, flags);
281         value = readl(phase->reg);
282         value &= ~GENMASK(phase->offset + 3, phase->offset);
283         value |= delay << phase->offset;
284         writel(value, phase->reg);
285         spin_unlock_irqrestore(phase->lock, flags);
286
287         return 0;
288 }
289
290 static const struct clk_ops mmc_clk_ops = {
291         .get_phase      = mmc_get_phase,
292         .set_phase      = mmc_set_phase,
293 };
294
295 /*
296  * sunxi_mmc_setup - Common setup function for mmc module clocks
297  *
298  * The only difference between module clocks on different platforms is the
299  * width of the mux register bits and the valid values, which are passed in
300  * through struct factors_data. The phase clocks parts are identical.
301  */
302 static void __init sunxi_mmc_setup(struct device_node *node,
303                                    const struct factors_data *data,
304                                    spinlock_t *lock)
305 {
306         struct clk_onecell_data *clk_data;
307         const char *parent;
308         void __iomem *reg;
309         int i;
310
311         reg = of_io_request_and_map(node, 0, of_node_full_name(node));
312         if (IS_ERR(reg)) {
313                 pr_err("Couldn't map the %s clock registers\n", node->name);
314                 return;
315         }
316
317         clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
318         if (!clk_data)
319                 return;
320
321         clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
322         if (!clk_data->clks)
323                 goto err_free_data;
324
325         clk_data->clk_num = 3;
326         clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg);
327         if (!clk_data->clks[0])
328                 goto err_free_clks;
329
330         parent = __clk_get_name(clk_data->clks[0]);
331
332         for (i = 1; i < 3; i++) {
333                 struct clk_init_data init = {
334                         .num_parents    = 1,
335                         .parent_names   = &parent,
336                         .ops            = &mmc_clk_ops,
337                 };
338                 struct mmc_phase *phase;
339
340                 phase = kmalloc(sizeof(*phase), GFP_KERNEL);
341                 if (!phase)
342                         continue;
343
344                 phase->hw.init = &init;
345                 phase->reg = reg;
346                 phase->lock = lock;
347
348                 if (i == 1)
349                         phase->offset = 8;
350                 else
351                         phase->offset = 20;
352
353                 if (of_property_read_string_index(node, "clock-output-names",
354                                                   i, &init.name))
355                         init.name = node->name;
356
357                 clk_data->clks[i] = clk_register(NULL, &phase->hw);
358                 if (IS_ERR(clk_data->clks[i])) {
359                         kfree(phase);
360                         continue;
361                 }
362         }
363
364         of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
365
366         return;
367
368 err_free_clks:
369         kfree(clk_data->clks);
370 err_free_data:
371         kfree(clk_data);
372 }
373
374 static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
375
376 static void __init sun4i_a10_mmc_setup(struct device_node *node)
377 {
378         sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock);
379 }
380 CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
381
382 static DEFINE_SPINLOCK(sun9i_a80_mmc_lock);
383
384 static void __init sun9i_a80_mmc_setup(struct device_node *node)
385 {
386         sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock);
387 }
388 CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup);