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