Root/drivers/clk/clk-wm831x.c

1/*
2 * WM831x clock control
3 *
4 * Copyright 2011-2 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/clk.h>
16#include <linux/clk-provider.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/platform_device.h>
21#include <linux/mfd/wm831x/core.h>
22
23struct wm831x_clk {
24    struct wm831x *wm831x;
25    struct clk_hw xtal_hw;
26    struct clk_hw fll_hw;
27    struct clk_hw clkout_hw;
28    struct clk *xtal;
29    struct clk *fll;
30    struct clk *clkout;
31    bool xtal_ena;
32};
33
34static int wm831x_xtal_is_enabled(struct clk_hw *hw)
35{
36    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
37                          xtal_hw);
38
39    return clkdata->xtal_ena;
40}
41
42static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
43                         unsigned long parent_rate)
44{
45    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
46                          xtal_hw);
47
48    if (clkdata->xtal_ena)
49        return 32768;
50    else
51        return 0;
52}
53
54static const struct clk_ops wm831x_xtal_ops = {
55    .is_enabled = wm831x_xtal_is_enabled,
56    .recalc_rate = wm831x_xtal_recalc_rate,
57};
58
59static struct clk_init_data wm831x_xtal_init = {
60    .name = "xtal",
61    .ops = &wm831x_xtal_ops,
62    .flags = CLK_IS_ROOT,
63};
64
65static const unsigned long wm831x_fll_auto_rates[] = {
66     2048000,
67    11289600,
68    12000000,
69    12288000,
70    19200000,
71    22579600,
72    24000000,
73    24576000,
74};
75
76static int wm831x_fll_is_enabled(struct clk_hw *hw)
77{
78    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
79                          fll_hw);
80    struct wm831x *wm831x = clkdata->wm831x;
81    int ret;
82
83    ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
84    if (ret < 0) {
85        dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
86            ret);
87        return true;
88    }
89
90    return (ret & WM831X_FLL_ENA) != 0;
91}
92
93static int wm831x_fll_prepare(struct clk_hw *hw)
94{
95    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
96                          fll_hw);
97    struct wm831x *wm831x = clkdata->wm831x;
98    int ret;
99
100    ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
101                  WM831X_FLL_ENA, WM831X_FLL_ENA);
102    if (ret != 0)
103        dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
104
105    usleep_range(2000, 2000);
106
107    return ret;
108}
109
110static void wm831x_fll_unprepare(struct clk_hw *hw)
111{
112    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
113                          fll_hw);
114    struct wm831x *wm831x = clkdata->wm831x;
115    int ret;
116
117    ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
118    if (ret != 0)
119        dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
120}
121
122static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
123                        unsigned long parent_rate)
124{
125    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
126                          fll_hw);
127    struct wm831x *wm831x = clkdata->wm831x;
128    int ret;
129
130    ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
131    if (ret < 0) {
132        dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
133            ret);
134        return 0;
135    }
136
137    if (ret & WM831X_FLL_AUTO)
138        return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
139
140    dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
141
142    return 0;
143}
144
145static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
146                  unsigned long *unused)
147{
148    int best = 0;
149    int i;
150
151    for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
152        if (abs(wm831x_fll_auto_rates[i] - rate) <
153            abs(wm831x_fll_auto_rates[best] - rate))
154            best = i;
155
156    return wm831x_fll_auto_rates[best];
157}
158
159static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
160                   unsigned long parent_rate)
161{
162    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
163                          fll_hw);
164    struct wm831x *wm831x = clkdata->wm831x;
165    int i;
166
167    for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
168        if (wm831x_fll_auto_rates[i] == rate)
169            break;
170    if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
171        return -EINVAL;
172
173    if (wm831x_fll_is_enabled(hw))
174        return -EPERM;
175
176    return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
177                   WM831X_FLL_AUTO_FREQ_MASK, i);
178}
179
180static const char *wm831x_fll_parents[] = {
181    "xtal",
182    "clkin",
183};
184
185static u8 wm831x_fll_get_parent(struct clk_hw *hw)
186{
187    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
188                          fll_hw);
189    struct wm831x *wm831x = clkdata->wm831x;
190    int ret;
191
192    /* AUTO mode is always clocked from the crystal */
193    ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
194    if (ret < 0) {
195        dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
196            ret);
197        return 0;
198    }
199
200    if (ret & WM831X_FLL_AUTO)
201        return 0;
202
203    ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
204    if (ret < 0) {
205        dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
206            ret);
207        return 0;
208    }
209
210    switch (ret & WM831X_FLL_CLK_SRC_MASK) {
211    case 0:
212        return 0;
213    case 1:
214        return 1;
215    default:
216        dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
217            ret & WM831X_FLL_CLK_SRC_MASK);
218        return 0;
219    }
220}
221
222static const struct clk_ops wm831x_fll_ops = {
223    .is_enabled = wm831x_fll_is_enabled,
224    .prepare = wm831x_fll_prepare,
225    .unprepare = wm831x_fll_unprepare,
226    .round_rate = wm831x_fll_round_rate,
227    .recalc_rate = wm831x_fll_recalc_rate,
228    .set_rate = wm831x_fll_set_rate,
229    .get_parent = wm831x_fll_get_parent,
230};
231
232static struct clk_init_data wm831x_fll_init = {
233    .name = "fll",
234    .ops = &wm831x_fll_ops,
235    .parent_names = wm831x_fll_parents,
236    .num_parents = ARRAY_SIZE(wm831x_fll_parents),
237    .flags = CLK_SET_RATE_GATE,
238};
239
240static int wm831x_clkout_is_enabled(struct clk_hw *hw)
241{
242    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
243                          clkout_hw);
244    struct wm831x *wm831x = clkdata->wm831x;
245    int ret;
246
247    ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
248    if (ret < 0) {
249        dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
250            ret);
251        return true;
252    }
253
254    return (ret & WM831X_CLKOUT_ENA) != 0;
255}
256
257static int wm831x_clkout_prepare(struct clk_hw *hw)
258{
259    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
260                          clkout_hw);
261    struct wm831x *wm831x = clkdata->wm831x;
262    int ret;
263
264    ret = wm831x_reg_unlock(wm831x);
265    if (ret != 0) {
266        dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
267        return ret;
268    }
269
270    ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
271                  WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
272    if (ret != 0)
273        dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
274
275    wm831x_reg_lock(wm831x);
276
277    return ret;
278}
279
280static void wm831x_clkout_unprepare(struct clk_hw *hw)
281{
282    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
283                          clkout_hw);
284    struct wm831x *wm831x = clkdata->wm831x;
285    int ret;
286
287    ret = wm831x_reg_unlock(wm831x);
288    if (ret != 0) {
289        dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
290        return;
291    }
292
293    ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
294                  WM831X_CLKOUT_ENA, 0);
295    if (ret != 0)
296        dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
297
298    wm831x_reg_lock(wm831x);
299}
300
301static const char *wm831x_clkout_parents[] = {
302    "xtal",
303    "fll",
304};
305
306static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
307{
308    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
309                          clkout_hw);
310    struct wm831x *wm831x = clkdata->wm831x;
311    int ret;
312
313    ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
314    if (ret < 0) {
315        dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
316            ret);
317        return 0;
318    }
319
320    if (ret & WM831X_CLKOUT_SRC)
321        return 0;
322    else
323        return 1;
324}
325
326static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
327{
328    struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
329                          clkout_hw);
330    struct wm831x *wm831x = clkdata->wm831x;
331
332    return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
333                   WM831X_CLKOUT_SRC,
334                   parent << WM831X_CLKOUT_SRC_SHIFT);
335}
336
337static const struct clk_ops wm831x_clkout_ops = {
338    .is_enabled = wm831x_clkout_is_enabled,
339    .prepare = wm831x_clkout_prepare,
340    .unprepare = wm831x_clkout_unprepare,
341    .get_parent = wm831x_clkout_get_parent,
342    .set_parent = wm831x_clkout_set_parent,
343};
344
345static struct clk_init_data wm831x_clkout_init = {
346    .name = "clkout",
347    .ops = &wm831x_clkout_ops,
348    .parent_names = wm831x_clkout_parents,
349    .num_parents = ARRAY_SIZE(wm831x_clkout_parents),
350    .flags = CLK_SET_RATE_PARENT,
351};
352
353static __devinit int wm831x_clk_probe(struct platform_device *pdev)
354{
355    struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
356    struct wm831x_clk *clkdata;
357    int ret;
358
359    clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
360    if (!clkdata)
361        return -ENOMEM;
362
363    /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
364    ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
365    if (ret < 0) {
366        dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
367            ret);
368        return ret;
369    }
370    clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
371
372    clkdata->xtal_hw.init = &wm831x_xtal_init;
373    clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
374    if (!clkdata->xtal)
375        return -EINVAL;
376
377    clkdata->fll_hw.init = &wm831x_fll_init;
378    clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
379    if (!clkdata->fll) {
380        ret = -EINVAL;
381        goto err_xtal;
382    }
383
384    clkdata->clkout_hw.init = &wm831x_clkout_init;
385    clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
386    if (!clkdata->clkout) {
387        ret = -EINVAL;
388        goto err_fll;
389    }
390
391    dev_set_drvdata(&pdev->dev, clkdata);
392
393    return 0;
394
395err_fll:
396    clk_unregister(clkdata->fll);
397err_xtal:
398    clk_unregister(clkdata->xtal);
399    return ret;
400}
401
402static int __devexit wm831x_clk_remove(struct platform_device *pdev)
403{
404    struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
405
406    clk_unregister(clkdata->clkout);
407    clk_unregister(clkdata->fll);
408    clk_unregister(clkdata->xtal);
409
410    return 0;
411}
412
413static struct platform_driver wm831x_clk_driver = {
414    .probe = wm831x_clk_probe,
415    .remove = __devexit_p(wm831x_clk_remove),
416    .driver = {
417        .name = "wm831x-clk",
418        .owner = THIS_MODULE,
419    },
420};
421
422module_platform_driver(wm831x_clk_driver);
423
424/* Module information */
425MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
426MODULE_DESCRIPTION("WM831x clock driver");
427MODULE_LICENSE("GPL");
428MODULE_ALIAS("platform:wm831x-clk");
429

Archive Download this file



interactive