Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[pandora-kernel.git] / drivers / mfd / wm8350-irq.c
1 /*
2  * wm8350-irq.c  --  IRQ support for Wolfson WM8350
3  *
4  * Copyright 2007, 2008, 2009 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/bug.h>
19 #include <linux/device.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22
23 #include <linux/mfd/wm8350/core.h>
24 #include <linux/mfd/wm8350/audio.h>
25 #include <linux/mfd/wm8350/comparator.h>
26 #include <linux/mfd/wm8350/gpio.h>
27 #include <linux/mfd/wm8350/pmic.h>
28 #include <linux/mfd/wm8350/rtc.h>
29 #include <linux/mfd/wm8350/supply.h>
30 #include <linux/mfd/wm8350/wdt.h>
31
32 #define WM8350_INT_OFFSET_1                     0
33 #define WM8350_INT_OFFSET_2                     1
34 #define WM8350_POWER_UP_INT_OFFSET              2
35 #define WM8350_UNDER_VOLTAGE_INT_OFFSET         3
36 #define WM8350_OVER_CURRENT_INT_OFFSET          4
37 #define WM8350_GPIO_INT_OFFSET                  5
38 #define WM8350_COMPARATOR_INT_OFFSET            6
39
40 struct wm8350_irq_data {
41         int primary;
42         int reg;
43         int mask;
44         int primary_only;
45 };
46
47 static struct wm8350_irq_data wm8350_irqs[] = {
48         [WM8350_IRQ_OC_LS] = {
49                 .primary = WM8350_OC_INT,
50                 .reg = WM8350_OVER_CURRENT_INT_OFFSET,
51                 .mask = WM8350_OC_LS_EINT,
52                 .primary_only = 1,
53         },
54         [WM8350_IRQ_UV_DC1] = {
55                 .primary = WM8350_UV_INT,
56                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
57                 .mask = WM8350_UV_DC1_EINT,
58         },
59         [WM8350_IRQ_UV_DC2] = {
60                 .primary = WM8350_UV_INT,
61                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
62                 .mask = WM8350_UV_DC2_EINT,
63         },
64         [WM8350_IRQ_UV_DC3] = {
65                 .primary = WM8350_UV_INT,
66                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
67                 .mask = WM8350_UV_DC3_EINT,
68         },
69         [WM8350_IRQ_UV_DC4] = {
70                 .primary = WM8350_UV_INT,
71                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
72                 .mask = WM8350_UV_DC4_EINT,
73         },
74         [WM8350_IRQ_UV_DC5] = {
75                 .primary = WM8350_UV_INT,
76                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
77                 .mask = WM8350_UV_DC5_EINT,
78         },
79         [WM8350_IRQ_UV_DC6] = {
80                 .primary = WM8350_UV_INT,
81                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
82                 .mask = WM8350_UV_DC6_EINT,
83         },
84         [WM8350_IRQ_UV_LDO1] = {
85                 .primary = WM8350_UV_INT,
86                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
87                 .mask = WM8350_UV_LDO1_EINT,
88         },
89         [WM8350_IRQ_UV_LDO2] = {
90                 .primary = WM8350_UV_INT,
91                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
92                 .mask = WM8350_UV_LDO2_EINT,
93         },
94         [WM8350_IRQ_UV_LDO3] = {
95                 .primary = WM8350_UV_INT,
96                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
97                 .mask = WM8350_UV_LDO3_EINT,
98         },
99         [WM8350_IRQ_UV_LDO4] = {
100                 .primary = WM8350_UV_INT,
101                 .reg = WM8350_UNDER_VOLTAGE_INT_OFFSET,
102                 .mask = WM8350_UV_LDO4_EINT,
103         },
104         [WM8350_IRQ_CHG_BAT_HOT] = {
105                 .primary = WM8350_CHG_INT,
106                 .reg = WM8350_INT_OFFSET_1,
107                 .mask = WM8350_CHG_BAT_HOT_EINT,
108         },
109         [WM8350_IRQ_CHG_BAT_COLD] = {
110                 .primary = WM8350_CHG_INT,
111                 .reg = WM8350_INT_OFFSET_1,
112                 .mask = WM8350_CHG_BAT_COLD_EINT,
113         },
114         [WM8350_IRQ_CHG_BAT_FAIL] = {
115                 .primary = WM8350_CHG_INT,
116                 .reg = WM8350_INT_OFFSET_1,
117                 .mask = WM8350_CHG_BAT_FAIL_EINT,
118         },
119         [WM8350_IRQ_CHG_TO] = {
120                 .primary = WM8350_CHG_INT,
121                 .reg = WM8350_INT_OFFSET_1,
122                 .mask = WM8350_CHG_TO_EINT,
123         },
124         [WM8350_IRQ_CHG_END] = {
125                 .primary = WM8350_CHG_INT,
126                 .reg = WM8350_INT_OFFSET_1,
127                 .mask = WM8350_CHG_END_EINT,
128         },
129         [WM8350_IRQ_CHG_START] = {
130                 .primary = WM8350_CHG_INT,
131                 .reg = WM8350_INT_OFFSET_1,
132                 .mask = WM8350_CHG_START_EINT,
133         },
134         [WM8350_IRQ_CHG_FAST_RDY] = {
135                 .primary = WM8350_CHG_INT,
136                 .reg = WM8350_INT_OFFSET_1,
137                 .mask = WM8350_CHG_FAST_RDY_EINT,
138         },
139         [WM8350_IRQ_CHG_VBATT_LT_3P9] = {
140                 .primary = WM8350_CHG_INT,
141                 .reg = WM8350_INT_OFFSET_1,
142                 .mask = WM8350_CHG_VBATT_LT_3P9_EINT,
143         },
144         [WM8350_IRQ_CHG_VBATT_LT_3P1] = {
145                 .primary = WM8350_CHG_INT,
146                 .reg = WM8350_INT_OFFSET_1,
147                 .mask = WM8350_CHG_VBATT_LT_3P1_EINT,
148         },
149         [WM8350_IRQ_CHG_VBATT_LT_2P85] = {
150                 .primary = WM8350_CHG_INT,
151                 .reg = WM8350_INT_OFFSET_1,
152                 .mask = WM8350_CHG_VBATT_LT_2P85_EINT,
153         },
154         [WM8350_IRQ_RTC_ALM] = {
155                 .primary = WM8350_RTC_INT,
156                 .reg = WM8350_INT_OFFSET_1,
157                 .mask = WM8350_RTC_ALM_EINT,
158         },
159         [WM8350_IRQ_RTC_SEC] = {
160                 .primary = WM8350_RTC_INT,
161                 .reg = WM8350_INT_OFFSET_1,
162                 .mask = WM8350_RTC_SEC_EINT,
163         },
164         [WM8350_IRQ_RTC_PER] = {
165                 .primary = WM8350_RTC_INT,
166                 .reg = WM8350_INT_OFFSET_1,
167                 .mask = WM8350_RTC_PER_EINT,
168         },
169         [WM8350_IRQ_CS1] = {
170                 .primary = WM8350_CS_INT,
171                 .reg = WM8350_INT_OFFSET_2,
172                 .mask = WM8350_CS1_EINT,
173         },
174         [WM8350_IRQ_CS2] = {
175                 .primary = WM8350_CS_INT,
176                 .reg = WM8350_INT_OFFSET_2,
177                 .mask = WM8350_CS2_EINT,
178         },
179         [WM8350_IRQ_SYS_HYST_COMP_FAIL] = {
180                 .primary = WM8350_SYS_INT,
181                 .reg = WM8350_INT_OFFSET_2,
182                 .mask = WM8350_SYS_HYST_COMP_FAIL_EINT,
183         },
184         [WM8350_IRQ_SYS_CHIP_GT115] = {
185                 .primary = WM8350_SYS_INT,
186                 .reg = WM8350_INT_OFFSET_2,
187                 .mask = WM8350_SYS_CHIP_GT115_EINT,
188         },
189         [WM8350_IRQ_SYS_CHIP_GT140] = {
190                 .primary = WM8350_SYS_INT,
191                 .reg = WM8350_INT_OFFSET_2,
192                 .mask = WM8350_SYS_CHIP_GT140_EINT,
193         },
194         [WM8350_IRQ_SYS_WDOG_TO] = {
195                 .primary = WM8350_SYS_INT,
196                 .reg = WM8350_INT_OFFSET_2,
197                 .mask = WM8350_SYS_WDOG_TO_EINT,
198         },
199         [WM8350_IRQ_AUXADC_DATARDY] = {
200                 .primary = WM8350_AUXADC_INT,
201                 .reg = WM8350_INT_OFFSET_2,
202                 .mask = WM8350_AUXADC_DATARDY_EINT,
203         },
204         [WM8350_IRQ_AUXADC_DCOMP4] = {
205                 .primary = WM8350_AUXADC_INT,
206                 .reg = WM8350_INT_OFFSET_2,
207                 .mask = WM8350_AUXADC_DCOMP4_EINT,
208         },
209         [WM8350_IRQ_AUXADC_DCOMP3] = {
210                 .primary = WM8350_AUXADC_INT,
211                 .reg = WM8350_INT_OFFSET_2,
212                 .mask = WM8350_AUXADC_DCOMP3_EINT,
213         },
214         [WM8350_IRQ_AUXADC_DCOMP2] = {
215                 .primary = WM8350_AUXADC_INT,
216                 .reg = WM8350_INT_OFFSET_2,
217                 .mask = WM8350_AUXADC_DCOMP2_EINT,
218         },
219         [WM8350_IRQ_AUXADC_DCOMP1] = {
220                 .primary = WM8350_AUXADC_INT,
221                 .reg = WM8350_INT_OFFSET_2,
222                 .mask = WM8350_AUXADC_DCOMP1_EINT,
223         },
224         [WM8350_IRQ_USB_LIMIT] = {
225                 .primary = WM8350_USB_INT,
226                 .reg = WM8350_INT_OFFSET_2,
227                 .mask = WM8350_USB_LIMIT_EINT,
228                 .primary_only = 1,
229         },
230         [WM8350_IRQ_WKUP_OFF_STATE] = {
231                 .primary = WM8350_WKUP_INT,
232                 .reg = WM8350_COMPARATOR_INT_OFFSET,
233                 .mask = WM8350_WKUP_OFF_STATE_EINT,
234         },
235         [WM8350_IRQ_WKUP_HIB_STATE] = {
236                 .primary = WM8350_WKUP_INT,
237                 .reg = WM8350_COMPARATOR_INT_OFFSET,
238                 .mask = WM8350_WKUP_HIB_STATE_EINT,
239         },
240         [WM8350_IRQ_WKUP_CONV_FAULT] = {
241                 .primary = WM8350_WKUP_INT,
242                 .reg = WM8350_COMPARATOR_INT_OFFSET,
243                 .mask = WM8350_WKUP_CONV_FAULT_EINT,
244         },
245         [WM8350_IRQ_WKUP_WDOG_RST] = {
246                 .primary = WM8350_WKUP_INT,
247                 .reg = WM8350_COMPARATOR_INT_OFFSET,
248                 .mask = WM8350_WKUP_WDOG_RST_EINT,
249         },
250         [WM8350_IRQ_WKUP_GP_PWR_ON] = {
251                 .primary = WM8350_WKUP_INT,
252                 .reg = WM8350_COMPARATOR_INT_OFFSET,
253                 .mask = WM8350_WKUP_GP_PWR_ON_EINT,
254         },
255         [WM8350_IRQ_WKUP_ONKEY] = {
256                 .primary = WM8350_WKUP_INT,
257                 .reg = WM8350_COMPARATOR_INT_OFFSET,
258                 .mask = WM8350_WKUP_ONKEY_EINT,
259         },
260         [WM8350_IRQ_WKUP_GP_WAKEUP] = {
261                 .primary = WM8350_WKUP_INT,
262                 .reg = WM8350_COMPARATOR_INT_OFFSET,
263                 .mask = WM8350_WKUP_GP_WAKEUP_EINT,
264         },
265         [WM8350_IRQ_CODEC_JCK_DET_L] = {
266                 .primary = WM8350_CODEC_INT,
267                 .reg = WM8350_COMPARATOR_INT_OFFSET,
268                 .mask = WM8350_CODEC_JCK_DET_L_EINT,
269         },
270         [WM8350_IRQ_CODEC_JCK_DET_R] = {
271                 .primary = WM8350_CODEC_INT,
272                 .reg = WM8350_COMPARATOR_INT_OFFSET,
273                 .mask = WM8350_CODEC_JCK_DET_R_EINT,
274         },
275         [WM8350_IRQ_CODEC_MICSCD] = {
276                 .primary = WM8350_CODEC_INT,
277                 .reg = WM8350_COMPARATOR_INT_OFFSET,
278                 .mask = WM8350_CODEC_MICSCD_EINT,
279         },
280         [WM8350_IRQ_CODEC_MICD] = {
281                 .primary = WM8350_CODEC_INT,
282                 .reg = WM8350_COMPARATOR_INT_OFFSET,
283                 .mask = WM8350_CODEC_MICD_EINT,
284         },
285         [WM8350_IRQ_EXT_USB_FB] = {
286                 .primary = WM8350_EXT_INT,
287                 .reg = WM8350_COMPARATOR_INT_OFFSET,
288                 .mask = WM8350_EXT_USB_FB_EINT,
289         },
290         [WM8350_IRQ_EXT_WALL_FB] = {
291                 .primary = WM8350_EXT_INT,
292                 .reg = WM8350_COMPARATOR_INT_OFFSET,
293                 .mask = WM8350_EXT_WALL_FB_EINT,
294         },
295         [WM8350_IRQ_EXT_BAT_FB] = {
296                 .primary = WM8350_EXT_INT,
297                 .reg = WM8350_COMPARATOR_INT_OFFSET,
298                 .mask = WM8350_EXT_BAT_FB_EINT,
299         },
300         [WM8350_IRQ_GPIO(0)] = {
301                 .primary = WM8350_GP_INT,
302                 .reg = WM8350_GPIO_INT_OFFSET,
303                 .mask = WM8350_GP0_EINT,
304         },
305         [WM8350_IRQ_GPIO(1)] = {
306                 .primary = WM8350_GP_INT,
307                 .reg = WM8350_GPIO_INT_OFFSET,
308                 .mask = WM8350_GP1_EINT,
309         },
310         [WM8350_IRQ_GPIO(2)] = {
311                 .primary = WM8350_GP_INT,
312                 .reg = WM8350_GPIO_INT_OFFSET,
313                 .mask = WM8350_GP2_EINT,
314         },
315         [WM8350_IRQ_GPIO(3)] = {
316                 .primary = WM8350_GP_INT,
317                 .reg = WM8350_GPIO_INT_OFFSET,
318                 .mask = WM8350_GP3_EINT,
319         },
320         [WM8350_IRQ_GPIO(4)] = {
321                 .primary = WM8350_GP_INT,
322                 .reg = WM8350_GPIO_INT_OFFSET,
323                 .mask = WM8350_GP4_EINT,
324         },
325         [WM8350_IRQ_GPIO(5)] = {
326                 .primary = WM8350_GP_INT,
327                 .reg = WM8350_GPIO_INT_OFFSET,
328                 .mask = WM8350_GP5_EINT,
329         },
330         [WM8350_IRQ_GPIO(6)] = {
331                 .primary = WM8350_GP_INT,
332                 .reg = WM8350_GPIO_INT_OFFSET,
333                 .mask = WM8350_GP6_EINT,
334         },
335         [WM8350_IRQ_GPIO(7)] = {
336                 .primary = WM8350_GP_INT,
337                 .reg = WM8350_GPIO_INT_OFFSET,
338                 .mask = WM8350_GP7_EINT,
339         },
340         [WM8350_IRQ_GPIO(8)] = {
341                 .primary = WM8350_GP_INT,
342                 .reg = WM8350_GPIO_INT_OFFSET,
343                 .mask = WM8350_GP8_EINT,
344         },
345         [WM8350_IRQ_GPIO(9)] = {
346                 .primary = WM8350_GP_INT,
347                 .reg = WM8350_GPIO_INT_OFFSET,
348                 .mask = WM8350_GP9_EINT,
349         },
350         [WM8350_IRQ_GPIO(10)] = {
351                 .primary = WM8350_GP_INT,
352                 .reg = WM8350_GPIO_INT_OFFSET,
353                 .mask = WM8350_GP10_EINT,
354         },
355         [WM8350_IRQ_GPIO(11)] = {
356                 .primary = WM8350_GP_INT,
357                 .reg = WM8350_GPIO_INT_OFFSET,
358                 .mask = WM8350_GP11_EINT,
359         },
360         [WM8350_IRQ_GPIO(12)] = {
361                 .primary = WM8350_GP_INT,
362                 .reg = WM8350_GPIO_INT_OFFSET,
363                 .mask = WM8350_GP12_EINT,
364         },
365 };
366
367 static inline struct wm8350_irq_data *irq_to_wm8350_irq(struct wm8350 *wm8350,
368                                                         int irq)
369 {
370         return &wm8350_irqs[irq - wm8350->irq_base];
371 }
372
373 /*
374  * This is a threaded IRQ handler so can access I2C/SPI.  Since all
375  * interrupts are clear on read the IRQ line will be reasserted and
376  * the physical IRQ will be handled again if another interrupt is
377  * asserted while we run - in the normal course of events this is a
378  * rare occurrence so we save I2C/SPI reads.  We're also assuming that
379  * it's rare to get lots of interrupts firing simultaneously so try to
380  * minimise I/O.
381  */
382 static irqreturn_t wm8350_irq(int irq, void *irq_data)
383 {
384         struct wm8350 *wm8350 = irq_data;
385         u16 level_one;
386         u16 sub_reg[WM8350_NUM_IRQ_REGS];
387         int read_done[WM8350_NUM_IRQ_REGS];
388         struct wm8350_irq_data *data;
389         int i;
390
391         level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
392                 & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
393
394         if (!level_one)
395                 return IRQ_NONE;
396
397         memset(&read_done, 0, sizeof(read_done));
398
399         for (i = 0; i < ARRAY_SIZE(wm8350_irqs); i++) {
400                 data = &wm8350_irqs[i];
401
402                 if (!(level_one & data->primary))
403                         continue;
404
405                 if (!read_done[data->reg]) {
406                         sub_reg[data->reg] =
407                                 wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 +
408                                                 data->reg);
409                         sub_reg[data->reg] &= ~wm8350->irq_masks[data->reg];
410                         read_done[data->reg] = 1;
411                 }
412
413                 if (sub_reg[data->reg] & data->mask)
414                         handle_nested_irq(wm8350->irq_base + i);
415         }
416
417         return IRQ_HANDLED;
418 }
419
420 static void wm8350_irq_lock(unsigned int irq)
421 {
422         struct wm8350 *wm8350 = get_irq_chip_data(irq);
423
424         mutex_lock(&wm8350->irq_lock);
425 }
426
427 static void wm8350_irq_sync_unlock(unsigned int irq)
428 {
429         struct wm8350 *wm8350 = get_irq_chip_data(irq);
430         int i;
431
432         for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
433                 /* If there's been a change in the mask write it back
434                  * to the hardware. */
435                 if (wm8350->irq_masks[i] !=
436                     wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i])
437                         WARN_ON(wm8350_reg_write(wm8350,
438                                          WM8350_INT_STATUS_1_MASK + i,
439                                                  wm8350->irq_masks[i]));
440         }
441
442         mutex_unlock(&wm8350->irq_lock);
443 }
444
445 static void wm8350_irq_enable(unsigned int irq)
446 {
447         struct wm8350 *wm8350 = get_irq_chip_data(irq);
448         struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
449
450         wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
451 }
452
453 static void wm8350_irq_disable(unsigned int irq)
454 {
455         struct wm8350 *wm8350 = get_irq_chip_data(irq);
456         struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
457
458         wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
459 }
460
461 static struct irq_chip wm8350_irq_chip = {
462         .name = "wm8350",
463         .bus_lock = wm8350_irq_lock,
464         .bus_sync_unlock = wm8350_irq_sync_unlock,
465         .disable = wm8350_irq_disable,
466         .enable = wm8350_irq_enable,
467 };
468
469 int wm8350_irq_init(struct wm8350 *wm8350, int irq,
470                     struct wm8350_platform_data *pdata)
471 {
472         int ret, cur_irq, i;
473         int flags = IRQF_ONESHOT;
474
475         if (!irq) {
476                 dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
477                 return 0;
478         }
479
480         if (!pdata || !pdata->irq_base) {
481                 dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
482                 return 0;
483         }
484
485         /* Mask top level interrupts */
486         wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
487
488         /* Mask all individual interrupts by default and cache the
489          * masks.  We read the masks back since there are unwritable
490          * bits in the mask registers. */
491         for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
492                 wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK + i,
493                                  0xFFFF);
494                 wm8350->irq_masks[i] =
495                         wm8350_reg_read(wm8350,
496                                         WM8350_INT_STATUS_1_MASK + i);
497         }
498
499         mutex_init(&wm8350->irq_lock);
500         wm8350->chip_irq = irq;
501         wm8350->irq_base = pdata->irq_base;
502
503         if (pdata->irq_high) {
504                 flags |= IRQF_TRIGGER_HIGH;
505
506                 wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
507                                 WM8350_IRQ_POL);
508         } else {
509                 flags |= IRQF_TRIGGER_LOW;
510
511                 wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
512                                   WM8350_IRQ_POL);
513         }
514
515         /* Register with genirq */
516         for (cur_irq = wm8350->irq_base;
517              cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
518              cur_irq++) {
519                 set_irq_chip_data(cur_irq, wm8350);
520                 set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
521                                          handle_edge_irq);
522                 set_irq_nested_thread(cur_irq, 1);
523
524                 /* ARM needs us to explicitly flag the IRQ as valid
525                  * and will set them noprobe when we do so. */
526 #ifdef CONFIG_ARM
527                 set_irq_flags(cur_irq, IRQF_VALID);
528 #else
529                 set_irq_noprobe(cur_irq);
530 #endif
531         }
532
533         ret = request_threaded_irq(irq, NULL, wm8350_irq, flags,
534                                    "wm8350", wm8350);
535         if (ret != 0)
536                 dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret);
537
538         /* Allow interrupts to fire */
539         wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0);
540
541         return ret;
542 }
543
544 int wm8350_irq_exit(struct wm8350 *wm8350)
545 {
546         free_irq(wm8350->chip_irq, wm8350);
547         return 0;
548 }