diff options
Diffstat (limited to 'drivers/mfd/wm8350-core.c')
-rw-r--r-- | drivers/mfd/wm8350-core.c | 354 |
1 files changed, 29 insertions, 325 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 8a9b11ca076a..7c1ae24605d9 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -32,9 +32,6 @@ | |||
32 | #include <linux/mfd/wm8350/supply.h> | 32 | #include <linux/mfd/wm8350/supply.h> |
33 | #include <linux/mfd/wm8350/wdt.h> | 33 | #include <linux/mfd/wm8350/wdt.h> |
34 | 34 | ||
35 | #define WM8350_UNLOCK_KEY 0x0013 | ||
36 | #define WM8350_LOCK_KEY 0x0000 | ||
37 | |||
38 | #define WM8350_CLOCK_CONTROL_1 0x28 | 35 | #define WM8350_CLOCK_CONTROL_1 0x28 |
39 | #define WM8350_AIF_TEST 0x74 | 36 | #define WM8350_AIF_TEST 0x74 |
40 | 37 | ||
@@ -63,181 +60,32 @@ | |||
63 | /* | 60 | /* |
64 | * WM8350 Device IO | 61 | * WM8350 Device IO |
65 | */ | 62 | */ |
66 | static DEFINE_MUTEX(io_mutex); | ||
67 | static DEFINE_MUTEX(reg_lock_mutex); | 63 | static DEFINE_MUTEX(reg_lock_mutex); |
68 | 64 | ||
69 | /* Perform a physical read from the device. | ||
70 | */ | ||
71 | static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, | ||
72 | u16 *dest) | ||
73 | { | ||
74 | int i, ret; | ||
75 | int bytes = num_regs * 2; | ||
76 | |||
77 | dev_dbg(wm8350->dev, "volatile read\n"); | ||
78 | ret = regmap_raw_read(wm8350->regmap, reg, dest, bytes); | ||
79 | |||
80 | for (i = reg; i < reg + num_regs; i++) { | ||
81 | /* Cache is CPU endian */ | ||
82 | dest[i - reg] = be16_to_cpu(dest[i - reg]); | ||
83 | |||
84 | /* Mask out non-readable bits */ | ||
85 | dest[i - reg] &= wm8350_reg_io_map[i].readable; | ||
86 | } | ||
87 | |||
88 | dump(num_regs, dest); | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) | ||
94 | { | ||
95 | int i; | ||
96 | int end = reg + num_regs; | ||
97 | int ret = 0; | ||
98 | int bytes = num_regs * 2; | ||
99 | |||
100 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | ||
101 | dev_err(wm8350->dev, "invalid reg %x\n", | ||
102 | reg + num_regs - 1); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | dev_dbg(wm8350->dev, | ||
107 | "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); | ||
108 | |||
109 | #if WM8350_BUS_DEBUG | ||
110 | /* we can _safely_ read any register, but warn if read not supported */ | ||
111 | for (i = reg; i < end; i++) { | ||
112 | if (!wm8350_reg_io_map[i].readable) | ||
113 | dev_warn(wm8350->dev, | ||
114 | "reg R%d is not readable\n", i); | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | /* if any volatile registers are required, then read back all */ | ||
119 | for (i = reg; i < end; i++) | ||
120 | if (wm8350_reg_io_map[i].vol) | ||
121 | return wm8350_phys_read(wm8350, reg, num_regs, dest); | ||
122 | |||
123 | /* no volatiles, then cache is good */ | ||
124 | dev_dbg(wm8350->dev, "cache read\n"); | ||
125 | memcpy(dest, &wm8350->reg_cache[reg], bytes); | ||
126 | dump(num_regs, dest); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) | ||
131 | { | ||
132 | if (reg == WM8350_SECURITY || | ||
133 | wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) | ||
134 | return 0; | ||
135 | |||
136 | if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && | ||
137 | reg <= WM8350_GPIO_FUNCTION_SELECT_4) || | ||
138 | (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && | ||
139 | reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) | ||
140 | return 1; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) | ||
145 | { | ||
146 | int i; | ||
147 | int end = reg + num_regs; | ||
148 | int bytes = num_regs * 2; | ||
149 | |||
150 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | ||
151 | dev_err(wm8350->dev, "invalid reg %x\n", | ||
152 | reg + num_regs - 1); | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | /* it's generally not a good idea to write to RO or locked registers */ | ||
157 | for (i = reg; i < end; i++) { | ||
158 | if (!wm8350_reg_io_map[i].writable) { | ||
159 | dev_err(wm8350->dev, | ||
160 | "attempted write to read only reg R%d\n", i); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | if (is_reg_locked(wm8350, i)) { | ||
165 | dev_err(wm8350->dev, | ||
166 | "attempted write to locked reg R%d\n", i); | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | src[i - reg] &= wm8350_reg_io_map[i].writable; | ||
171 | |||
172 | wm8350->reg_cache[i] = | ||
173 | (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) | ||
174 | | src[i - reg]; | ||
175 | |||
176 | src[i - reg] = cpu_to_be16(src[i - reg]); | ||
177 | } | ||
178 | |||
179 | /* Actually write it out */ | ||
180 | return regmap_raw_write(wm8350->regmap, reg, src, bytes); | ||
181 | } | ||
182 | |||
183 | /* | 65 | /* |
184 | * Safe read, modify, write methods | 66 | * Safe read, modify, write methods |
185 | */ | 67 | */ |
186 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 68 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
187 | { | 69 | { |
188 | u16 data; | 70 | return regmap_update_bits(wm8350->regmap, reg, mask, 0); |
189 | int err; | ||
190 | |||
191 | mutex_lock(&io_mutex); | ||
192 | err = wm8350_read(wm8350, reg, 1, &data); | ||
193 | if (err) { | ||
194 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | ||
195 | goto out; | ||
196 | } | ||
197 | |||
198 | data &= ~mask; | ||
199 | err = wm8350_write(wm8350, reg, 1, &data); | ||
200 | if (err) | ||
201 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | ||
202 | out: | ||
203 | mutex_unlock(&io_mutex); | ||
204 | return err; | ||
205 | } | 71 | } |
206 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); | 72 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); |
207 | 73 | ||
208 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 74 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
209 | { | 75 | { |
210 | u16 data; | 76 | return regmap_update_bits(wm8350->regmap, reg, mask, mask); |
211 | int err; | ||
212 | |||
213 | mutex_lock(&io_mutex); | ||
214 | err = wm8350_read(wm8350, reg, 1, &data); | ||
215 | if (err) { | ||
216 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | ||
217 | goto out; | ||
218 | } | ||
219 | |||
220 | data |= mask; | ||
221 | err = wm8350_write(wm8350, reg, 1, &data); | ||
222 | if (err) | ||
223 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | ||
224 | out: | ||
225 | mutex_unlock(&io_mutex); | ||
226 | return err; | ||
227 | } | 77 | } |
228 | EXPORT_SYMBOL_GPL(wm8350_set_bits); | 78 | EXPORT_SYMBOL_GPL(wm8350_set_bits); |
229 | 79 | ||
230 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) | 80 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) |
231 | { | 81 | { |
232 | u16 data; | 82 | unsigned int data; |
233 | int err; | 83 | int err; |
234 | 84 | ||
235 | mutex_lock(&io_mutex); | 85 | err = regmap_read(wm8350->regmap, reg, &data); |
236 | err = wm8350_read(wm8350, reg, 1, &data); | ||
237 | if (err) | 86 | if (err) |
238 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | 87 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); |
239 | 88 | ||
240 | mutex_unlock(&io_mutex); | ||
241 | return data; | 89 | return data; |
242 | } | 90 | } |
243 | EXPORT_SYMBOL_GPL(wm8350_reg_read); | 91 | EXPORT_SYMBOL_GPL(wm8350_reg_read); |
@@ -245,13 +93,11 @@ EXPORT_SYMBOL_GPL(wm8350_reg_read); | |||
245 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) | 93 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) |
246 | { | 94 | { |
247 | int ret; | 95 | int ret; |
248 | u16 data = val; | ||
249 | 96 | ||
250 | mutex_lock(&io_mutex); | 97 | ret = regmap_write(wm8350->regmap, reg, val); |
251 | ret = wm8350_write(wm8350, reg, 1, &data); | 98 | |
252 | if (ret) | 99 | if (ret) |
253 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | 100 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); |
254 | mutex_unlock(&io_mutex); | ||
255 | return ret; | 101 | return ret; |
256 | } | 102 | } |
257 | EXPORT_SYMBOL_GPL(wm8350_reg_write); | 103 | EXPORT_SYMBOL_GPL(wm8350_reg_write); |
@@ -261,12 +107,11 @@ int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, | |||
261 | { | 107 | { |
262 | int err = 0; | 108 | int err = 0; |
263 | 109 | ||
264 | mutex_lock(&io_mutex); | 110 | err = regmap_bulk_read(wm8350->regmap, start_reg, dest, regs); |
265 | err = wm8350_read(wm8350, start_reg, regs, dest); | ||
266 | if (err) | 111 | if (err) |
267 | dev_err(wm8350->dev, "block read starting from R%d failed\n", | 112 | dev_err(wm8350->dev, "block read starting from R%d failed\n", |
268 | start_reg); | 113 | start_reg); |
269 | mutex_unlock(&io_mutex); | 114 | |
270 | return err; | 115 | return err; |
271 | } | 116 | } |
272 | EXPORT_SYMBOL_GPL(wm8350_block_read); | 117 | EXPORT_SYMBOL_GPL(wm8350_block_read); |
@@ -276,12 +121,11 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, | |||
276 | { | 121 | { |
277 | int ret = 0; | 122 | int ret = 0; |
278 | 123 | ||
279 | mutex_lock(&io_mutex); | 124 | ret = regmap_bulk_write(wm8350->regmap, start_reg, src, regs); |
280 | ret = wm8350_write(wm8350, start_reg, regs, src); | ||
281 | if (ret) | 125 | if (ret) |
282 | dev_err(wm8350->dev, "block write starting at R%d failed\n", | 126 | dev_err(wm8350->dev, "block write starting at R%d failed\n", |
283 | start_reg); | 127 | start_reg); |
284 | mutex_unlock(&io_mutex); | 128 | |
285 | return ret; | 129 | return ret; |
286 | } | 130 | } |
287 | EXPORT_SYMBOL_GPL(wm8350_block_write); | 131 | EXPORT_SYMBOL_GPL(wm8350_block_write); |
@@ -295,15 +139,20 @@ EXPORT_SYMBOL_GPL(wm8350_block_write); | |||
295 | */ | 139 | */ |
296 | int wm8350_reg_lock(struct wm8350 *wm8350) | 140 | int wm8350_reg_lock(struct wm8350 *wm8350) |
297 | { | 141 | { |
298 | u16 key = WM8350_LOCK_KEY; | ||
299 | int ret; | 142 | int ret; |
300 | 143 | ||
144 | mutex_lock(®_lock_mutex); | ||
145 | |||
301 | ldbg(__func__); | 146 | ldbg(__func__); |
302 | mutex_lock(&io_mutex); | 147 | |
303 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); | 148 | ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_LOCK_KEY); |
304 | if (ret) | 149 | if (ret) |
305 | dev_err(wm8350->dev, "lock failed\n"); | 150 | dev_err(wm8350->dev, "lock failed\n"); |
306 | mutex_unlock(&io_mutex); | 151 | |
152 | wm8350->unlocked = false; | ||
153 | |||
154 | mutex_unlock(®_lock_mutex); | ||
155 | |||
307 | return ret; | 156 | return ret; |
308 | } | 157 | } |
309 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); | 158 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); |
@@ -319,15 +168,20 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock); | |||
319 | */ | 168 | */ |
320 | int wm8350_reg_unlock(struct wm8350 *wm8350) | 169 | int wm8350_reg_unlock(struct wm8350 *wm8350) |
321 | { | 170 | { |
322 | u16 key = WM8350_UNLOCK_KEY; | ||
323 | int ret; | 171 | int ret; |
324 | 172 | ||
173 | mutex_lock(®_lock_mutex); | ||
174 | |||
325 | ldbg(__func__); | 175 | ldbg(__func__); |
326 | mutex_lock(&io_mutex); | 176 | |
327 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); | 177 | ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_UNLOCK_KEY); |
328 | if (ret) | 178 | if (ret) |
329 | dev_err(wm8350->dev, "unlock failed\n"); | 179 | dev_err(wm8350->dev, "unlock failed\n"); |
330 | mutex_unlock(&io_mutex); | 180 | |
181 | wm8350->unlocked = true; | ||
182 | |||
183 | mutex_unlock(®_lock_mutex); | ||
184 | |||
331 | return ret; | 185 | return ret; |
332 | } | 186 | } |
333 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); | 187 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); |
@@ -395,146 +249,6 @@ static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) | |||
395 | } | 249 | } |
396 | 250 | ||
397 | /* | 251 | /* |
398 | * Cache is always host endian. | ||
399 | */ | ||
400 | static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | ||
401 | { | ||
402 | int i, ret = 0; | ||
403 | u16 value; | ||
404 | const u16 *reg_map; | ||
405 | |||
406 | switch (type) { | ||
407 | case 0: | ||
408 | switch (mode) { | ||
409 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 | ||
410 | case 0: | ||
411 | reg_map = wm8350_mode0_defaults; | ||
412 | break; | ||
413 | #endif | ||
414 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 | ||
415 | case 1: | ||
416 | reg_map = wm8350_mode1_defaults; | ||
417 | break; | ||
418 | #endif | ||
419 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 | ||
420 | case 2: | ||
421 | reg_map = wm8350_mode2_defaults; | ||
422 | break; | ||
423 | #endif | ||
424 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 | ||
425 | case 3: | ||
426 | reg_map = wm8350_mode3_defaults; | ||
427 | break; | ||
428 | #endif | ||
429 | default: | ||
430 | dev_err(wm8350->dev, | ||
431 | "WM8350 configuration mode %d not supported\n", | ||
432 | mode); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | break; | ||
436 | |||
437 | case 1: | ||
438 | switch (mode) { | ||
439 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 | ||
440 | case 0: | ||
441 | reg_map = wm8351_mode0_defaults; | ||
442 | break; | ||
443 | #endif | ||
444 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 | ||
445 | case 1: | ||
446 | reg_map = wm8351_mode1_defaults; | ||
447 | break; | ||
448 | #endif | ||
449 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 | ||
450 | case 2: | ||
451 | reg_map = wm8351_mode2_defaults; | ||
452 | break; | ||
453 | #endif | ||
454 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 | ||
455 | case 3: | ||
456 | reg_map = wm8351_mode3_defaults; | ||
457 | break; | ||
458 | #endif | ||
459 | default: | ||
460 | dev_err(wm8350->dev, | ||
461 | "WM8351 configuration mode %d not supported\n", | ||
462 | mode); | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | break; | ||
466 | |||
467 | case 2: | ||
468 | switch (mode) { | ||
469 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 | ||
470 | case 0: | ||
471 | reg_map = wm8352_mode0_defaults; | ||
472 | break; | ||
473 | #endif | ||
474 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 | ||
475 | case 1: | ||
476 | reg_map = wm8352_mode1_defaults; | ||
477 | break; | ||
478 | #endif | ||
479 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 | ||
480 | case 2: | ||
481 | reg_map = wm8352_mode2_defaults; | ||
482 | break; | ||
483 | #endif | ||
484 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 | ||
485 | case 3: | ||
486 | reg_map = wm8352_mode3_defaults; | ||
487 | break; | ||
488 | #endif | ||
489 | default: | ||
490 | dev_err(wm8350->dev, | ||
491 | "WM8352 configuration mode %d not supported\n", | ||
492 | mode); | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | break; | ||
496 | |||
497 | default: | ||
498 | dev_err(wm8350->dev, | ||
499 | "WM835x configuration mode %d not supported\n", | ||
500 | mode); | ||
501 | return -EINVAL; | ||
502 | } | ||
503 | |||
504 | wm8350->reg_cache = | ||
505 | kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); | ||
506 | if (wm8350->reg_cache == NULL) | ||
507 | return -ENOMEM; | ||
508 | |||
509 | /* Read the initial cache state back from the device - this is | ||
510 | * a PMIC so the device many not be in a virgin state and we | ||
511 | * can't rely on the silicon values. | ||
512 | */ | ||
513 | ret = regmap_raw_read(wm8350->regmap, 0, wm8350->reg_cache, | ||
514 | sizeof(u16) * (WM8350_MAX_REGISTER + 1)); | ||
515 | if (ret < 0) { | ||
516 | dev_err(wm8350->dev, | ||
517 | "failed to read initial cache values\n"); | ||
518 | goto out; | ||
519 | } | ||
520 | |||
521 | /* Mask out uncacheable/unreadable bits and the audio. */ | ||
522 | for (i = 0; i < WM8350_MAX_REGISTER; i++) { | ||
523 | if (wm8350_reg_io_map[i].readable && | ||
524 | (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { | ||
525 | value = be16_to_cpu(wm8350->reg_cache[i]); | ||
526 | value &= wm8350_reg_io_map[i].readable; | ||
527 | wm8350->reg_cache[i] = value; | ||
528 | } else | ||
529 | wm8350->reg_cache[i] = reg_map[i]; | ||
530 | } | ||
531 | |||
532 | out: | ||
533 | kfree(wm8350->reg_cache); | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | /* | ||
538 | * Register a client device. This is non-fatal since there is no need to | 252 | * Register a client device. This is non-fatal since there is no need to |
539 | * fail the entire device init due to a single platform device failing. | 253 | * fail the entire device init due to a single platform device failing. |
540 | */ | 254 | */ |
@@ -681,18 +395,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
681 | goto err; | 395 | goto err; |
682 | } | 396 | } |
683 | 397 | ||
684 | ret = wm8350_create_cache(wm8350, mask_rev, mode); | ||
685 | if (ret < 0) { | ||
686 | dev_err(wm8350->dev, "Failed to create register cache\n"); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | mutex_init(&wm8350->auxadc_mutex); | 398 | mutex_init(&wm8350->auxadc_mutex); |
691 | init_completion(&wm8350->auxadc_done); | 399 | init_completion(&wm8350->auxadc_done); |
692 | 400 | ||
693 | ret = wm8350_irq_init(wm8350, irq, pdata); | 401 | ret = wm8350_irq_init(wm8350, irq, pdata); |
694 | if (ret < 0) | 402 | if (ret < 0) |
695 | goto err_free; | 403 | goto err; |
696 | 404 | ||
697 | if (wm8350->irq_base) { | 405 | if (wm8350->irq_base) { |
698 | ret = request_threaded_irq(wm8350->irq_base + | 406 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -730,8 +438,6 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
730 | 438 | ||
731 | err_irq: | 439 | err_irq: |
732 | wm8350_irq_exit(wm8350); | 440 | wm8350_irq_exit(wm8350); |
733 | err_free: | ||
734 | kfree(wm8350->reg_cache); | ||
735 | err: | 441 | err: |
736 | return ret; | 442 | return ret; |
737 | } | 443 | } |
@@ -758,8 +464,6 @@ void wm8350_device_exit(struct wm8350 *wm8350) | |||
758 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); | 464 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); |
759 | 465 | ||
760 | wm8350_irq_exit(wm8350); | 466 | wm8350_irq_exit(wm8350); |
761 | |||
762 | kfree(wm8350->reg_cache); | ||
763 | } | 467 | } |
764 | EXPORT_SYMBOL_GPL(wm8350_device_exit); | 468 | EXPORT_SYMBOL_GPL(wm8350_device_exit); |
765 | 469 | ||