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