aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/wm8350-core.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-10-10 10:58:10 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2008-10-13 16:51:55 -0400
commit89b4012befb1abca5e86d232bc0e2a797b0d9825 (patch)
tree948e0ed0c35df087f0069356650da431a9fe50ff /drivers/mfd/wm8350-core.c
parent213f326810b6852bc54f38fd8bb71793f70f2c7a (diff)
mfd: Core support for the WM8350 AudioPlus PMIC
The WM8350 is an integrated audio and power management subsystem intended for use as the primary PMIC in mobile multimedia applications. The WM8350 can be controlled via either I2C or SPI - the control interface is provided by a separate module in order to allow greatest flexibility in configuring the kernel. This driver was originally written by Liam Girdwood and has since been updated to current kernel APIs and split up for submission by me. All the heavy lifting here was done by Liam. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Samuel Ortiz <sameo@openedhand.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers/mfd/wm8350-core.c')
-rw-r--r--drivers/mfd/wm8350-core.c456
1 files changed, 456 insertions, 0 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
new file mode 100644
index 000000000000..c7552c0b7797
--- /dev/null
+++ b/drivers/mfd/wm8350-core.c
@@ -0,0 +1,456 @@
1/*
2 * wm8350-core.c -- Device access for Wolfson WM8350
3 *
4 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Liam Girdwood, Mark Brown
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/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/device.h>
19#include <linux/delay.h>
20#include <linux/interrupt.h>
21
22#include <linux/mfd/wm8350/core.h>
23#include <linux/mfd/wm8350/audio.h>
24#include <linux/mfd/wm8350/gpio.h>
25#include <linux/mfd/wm8350/pmic.h>
26#include <linux/mfd/wm8350/supply.h>
27
28#define WM8350_UNLOCK_KEY 0x0013
29#define WM8350_LOCK_KEY 0x0000
30
31#define WM8350_CLOCK_CONTROL_1 0x28
32#define WM8350_AIF_TEST 0x74
33
34/* debug */
35#define WM8350_BUS_DEBUG 0
36#if WM8350_BUS_DEBUG
37#define dump(regs, src) do { \
38 int i_; \
39 u16 *src_ = src; \
40 printk(KERN_DEBUG); \
41 for (i_ = 0; i_ < regs; i_++) \
42 printk(" 0x%4.4x", *src_++); \
43 printk("\n"); \
44} while (0);
45#else
46#define dump(bytes, src)
47#endif
48
49#define WM8350_LOCK_DEBUG 0
50#if WM8350_LOCK_DEBUG
51#define ldbg(format, arg...) printk(format, ## arg)
52#else
53#define ldbg(format, arg...)
54#endif
55
56/*
57 * WM8350 Device IO
58 */
59static DEFINE_MUTEX(io_mutex);
60static DEFINE_MUTEX(reg_lock_mutex);
61static DEFINE_MUTEX(auxadc_mutex);
62
63/* Perform a physical read from the device.
64 */
65static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
66 u16 *dest)
67{
68 int i, ret;
69 int bytes = num_regs * 2;
70
71 dev_dbg(wm8350->dev, "volatile read\n");
72 ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
73
74 for (i = reg; i < reg + num_regs; i++) {
75 /* Cache is CPU endian */
76 dest[i - reg] = be16_to_cpu(dest[i - reg]);
77
78 /* Satisfy non-volatile bits from cache */
79 dest[i - reg] &= wm8350_reg_io_map[i].vol;
80 dest[i - reg] |= wm8350->reg_cache[i];
81
82 /* Mask out non-readable bits */
83 dest[i - reg] &= wm8350_reg_io_map[i].readable;
84 }
85
86 dump(num_regs, dest);
87
88 return ret;
89}
90
91static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
92{
93 int i;
94 int end = reg + num_regs;
95 int ret = 0;
96 int bytes = num_regs * 2;
97
98 if (wm8350->read_dev == NULL)
99 return -ENODEV;
100
101 if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
102 dev_err(wm8350->dev, "invalid reg %x\n",
103 reg + num_regs - 1);
104 return -EINVAL;
105 }
106
107 dev_dbg(wm8350->dev,
108 "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs);
109
110#if WM8350_BUS_DEBUG
111 /* we can _safely_ read any register, but warn if read not supported */
112 for (i = reg; i < end; i++) {
113 if (!wm8350_reg_io_map[i].readable)
114 dev_warn(wm8350->dev,
115 "reg R%d is not readable\n", i);
116 }
117#endif
118
119 /* if any volatile registers are required, then read back all */
120 for (i = reg; i < end; i++)
121 if (wm8350_reg_io_map[i].vol)
122 return wm8350_phys_read(wm8350, reg, num_regs, dest);
123
124 /* no volatiles, then cache is good */
125 dev_dbg(wm8350->dev, "cache read\n");
126 memcpy(dest, &wm8350->reg_cache[reg], bytes);
127 dump(num_regs, dest);
128 return ret;
129}
130
131static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
132{
133 if (reg == WM8350_SECURITY ||
134 wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
135 return 0;
136
137 if ((reg == WM8350_GPIO_CONFIGURATION_I_O) ||
138 (reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
139 reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
140 (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
141 reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
142 return 1;
143 return 0;
144}
145
146static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
147{
148 int i;
149 int end = reg + num_regs;
150 int bytes = num_regs * 2;
151
152 if (wm8350->write_dev == NULL)
153 return -ENODEV;
154
155 if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
156 dev_err(wm8350->dev, "invalid reg %x\n",
157 reg + num_regs - 1);
158 return -EINVAL;
159 }
160
161 /* it's generally not a good idea to write to RO or locked registers */
162 for (i = reg; i < end; i++) {
163 if (!wm8350_reg_io_map[i].writable) {
164 dev_err(wm8350->dev,
165 "attempted write to read only reg R%d\n", i);
166 return -EINVAL;
167 }
168
169 if (is_reg_locked(wm8350, i)) {
170 dev_err(wm8350->dev,
171 "attempted write to locked reg R%d\n", i);
172 return -EINVAL;
173 }
174
175 src[i - reg] &= wm8350_reg_io_map[i].writable;
176
177 wm8350->reg_cache[i] =
178 (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
179 | src[i - reg];
180
181 src[i - reg] = cpu_to_be16(src[i - reg]);
182 }
183
184 /* Actually write it out */
185 return wm8350->write_dev(wm8350, reg, bytes, (char *)src);
186}
187
188/*
189 * Safe read, modify, write methods
190 */
191int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
192{
193 u16 data;
194 int err;
195
196 mutex_lock(&io_mutex);
197 err = wm8350_read(wm8350, reg, 1, &data);
198 if (err) {
199 dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
200 goto out;
201 }
202
203 data &= ~mask;
204 err = wm8350_write(wm8350, reg, 1, &data);
205 if (err)
206 dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
207out:
208 mutex_unlock(&io_mutex);
209 return err;
210}
211EXPORT_SYMBOL_GPL(wm8350_clear_bits);
212
213int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
214{
215 u16 data;
216 int err;
217
218 mutex_lock(&io_mutex);
219 err = wm8350_read(wm8350, reg, 1, &data);
220 if (err) {
221 dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
222 goto out;
223 }
224
225 data |= mask;
226 err = wm8350_write(wm8350, reg, 1, &data);
227 if (err)
228 dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
229out:
230 mutex_unlock(&io_mutex);
231 return err;
232}
233EXPORT_SYMBOL_GPL(wm8350_set_bits);
234
235u16 wm8350_reg_read(struct wm8350 *wm8350, int reg)
236{
237 u16 data;
238 int err;
239
240 mutex_lock(&io_mutex);
241 err = wm8350_read(wm8350, reg, 1, &data);
242 if (err)
243 dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
244
245 mutex_unlock(&io_mutex);
246 return data;
247}
248EXPORT_SYMBOL_GPL(wm8350_reg_read);
249
250int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val)
251{
252 int ret;
253 u16 data = val;
254
255 mutex_lock(&io_mutex);
256 ret = wm8350_write(wm8350, reg, 1, &data);
257 if (ret)
258 dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
259 mutex_unlock(&io_mutex);
260 return ret;
261}
262EXPORT_SYMBOL_GPL(wm8350_reg_write);
263
264int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs,
265 u16 *dest)
266{
267 int err = 0;
268
269 mutex_lock(&io_mutex);
270 err = wm8350_read(wm8350, start_reg, regs, dest);
271 if (err)
272 dev_err(wm8350->dev, "block read starting from R%d failed\n",
273 start_reg);
274 mutex_unlock(&io_mutex);
275 return err;
276}
277EXPORT_SYMBOL_GPL(wm8350_block_read);
278
279int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
280 u16 *src)
281{
282 int ret = 0;
283
284 mutex_lock(&io_mutex);
285 ret = wm8350_write(wm8350, start_reg, regs, src);
286 if (ret)
287 dev_err(wm8350->dev, "block write starting at R%d failed\n",
288 start_reg);
289 mutex_unlock(&io_mutex);
290 return ret;
291}
292EXPORT_SYMBOL_GPL(wm8350_block_write);
293
294int wm8350_reg_lock(struct wm8350 *wm8350)
295{
296 u16 key = WM8350_LOCK_KEY;
297 int ret;
298
299 ldbg(__func__);
300 mutex_lock(&io_mutex);
301 ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
302 if (ret)
303 dev_err(wm8350->dev, "lock failed\n");
304 mutex_unlock(&io_mutex);
305 return ret;
306}
307EXPORT_SYMBOL_GPL(wm8350_reg_lock);
308
309int wm8350_reg_unlock(struct wm8350 *wm8350)
310{
311 u16 key = WM8350_UNLOCK_KEY;
312 int ret;
313
314 ldbg(__func__);
315 mutex_lock(&io_mutex);
316 ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
317 if (ret)
318 dev_err(wm8350->dev, "unlock failed\n");
319 mutex_unlock(&io_mutex);
320 return ret;
321}
322EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
323
324/*
325 * Cache is always host endian.
326 */
327static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
328{
329 int i, ret = 0;
330 u16 value;
331 const u16 *reg_map;
332
333 switch (mode) {
334#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
335 case 0:
336 reg_map = wm8350_mode0_defaults;
337 break;
338#endif
339#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
340 case 1:
341 reg_map = wm8350_mode1_defaults;
342 break;
343#endif
344#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
345 case 2:
346 reg_map = wm8350_mode2_defaults;
347 break;
348#endif
349#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
350 case 3:
351 reg_map = wm8350_mode3_defaults;
352 break;
353#endif
354 default:
355 dev_err(wm8350->dev, "Configuration mode %d not supported\n",
356 mode);
357 return -EINVAL;
358 }
359
360 wm8350->reg_cache =
361 kzalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
362 if (wm8350->reg_cache == NULL)
363 return -ENOMEM;
364
365 /* Read the initial cache state back from the device - this is
366 * a PMIC so the device many not be in a virgin state and we
367 * can't rely on the silicon values.
368 */
369 for (i = 0; i < WM8350_MAX_REGISTER; i++) {
370 /* audio register range */
371 if (wm8350_reg_io_map[i].readable &&
372 (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
373 ret = wm8350->read_dev(wm8350, i, 2, (char *)&value);
374 if (ret < 0) {
375 dev_err(wm8350->dev,
376 "failed to read initial cache value\n");
377 goto out;
378 }
379 value = be16_to_cpu(value);
380 value &= wm8350_reg_io_map[i].readable;
381 wm8350->reg_cache[i] = value;
382 } else
383 wm8350->reg_cache[i] = reg_map[i];
384 }
385
386out:
387 return ret;
388}
389EXPORT_SYMBOL_GPL(wm8350_create_cache);
390
391int wm8350_device_init(struct wm8350 *wm8350)
392{
393 int ret = -EINVAL;
394 u16 id1, id2, mask, mode;
395
396 /* get WM8350 revision and config mode */
397 wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
398 wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
399
400 id1 = be16_to_cpu(id1);
401 id2 = be16_to_cpu(id2);
402
403 if (id1 == 0x0)
404 dev_info(wm8350->dev, "Found Rev C device\n");
405 else if (id1 == 0x6143) {
406 switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
407 case WM8350_REV_E:
408 dev_info(wm8350->dev, "Found Rev E device\n");
409 wm8350->rev = WM8350_REV_E;
410 break;
411 case WM8350_REV_F:
412 dev_info(wm8350->dev, "Found Rev F device\n");
413 wm8350->rev = WM8350_REV_F;
414 break;
415 case WM8350_REV_G:
416 dev_info(wm8350->dev, "Found Rev G device\n");
417 wm8350->rev = WM8350_REV_G;
418 break;
419 default:
420 /* For safety we refuse to run on unknown hardware */
421 dev_info(wm8350->dev, "Found unknown rev\n");
422 ret = -ENODEV;
423 goto err;
424 }
425 } else {
426 dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
427 id1);
428 ret = -ENODEV;
429 goto err;
430 }
431
432 mode = id2 & WM8350_CONF_STS_MASK >> 10;
433 mask = id2 & WM8350_CUST_ID_MASK;
434 dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
435
436 ret = wm8350_create_cache(wm8350, mode);
437 if (ret < 0) {
438 printk(KERN_ERR "wm8350: failed to create register cache\n");
439 return ret;
440 }
441
442 return 0;
443
444err:
445 kfree(wm8350->reg_cache);
446 return ret;
447}
448EXPORT_SYMBOL_GPL(wm8350_device_init);
449
450void wm8350_device_exit(struct wm8350 *wm8350)
451{
452 kfree(wm8350->reg_cache);
453}
454EXPORT_SYMBOL_GPL(wm8350_device_exit);
455
456MODULE_LICENSE("GPL");