cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wm8350-irq.c (14160B)


      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}