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