1e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*
2e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * twl6030-irq.c - TWL6030 irq support
3e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
4e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Copyright (C) 2005-2009 Texas Instruments, Inc.
5e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
6e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Modifications to defer interrupt handling to a kernel thread:
7e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Copyright (C) 2006 MontaVista Software, Inc.
8e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
9e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Based on tlv320aic23.c:
10e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Copyright (c) by Kai Svahn <kai.svahn@nokia.com>
11e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
12e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Code cleanup and modifications to IRQ handler.
13e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * by syed khasim <x0khasim@ti.com>
14e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
15e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * TWL6030 specific code and IRQ handling changes by
16e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
17e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Balaji T K <balajitk@ti.com>
18e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
19e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * This program is free software; you can redistribute it and/or modify
20e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * it under the terms of the GNU General Public License as published by
21e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * the Free Software Foundation; either version 2 of the License, or
22e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * (at your option) any later version.
23e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
24e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * This program is distributed in the hope that it will be useful,
25e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * but WITHOUT ANY WARRANTY; without even the implied warranty of
26e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * GNU General Public License for more details.
28e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
29e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * You should have received a copy of the GNU General Public License
30e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * along with this program; if not, write to the Free Software
31e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K */
33e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
34e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#include <linux/init.h>
355d4a357d8f5e07868a90071f328fec73036e9628Paul Gortmaker#include <linux/export.h>
36e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#include <linux/interrupt.h>
37e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#include <linux/irq.h>
38e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#include <linux/kthread.h>
39e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#include <linux/i2c/twl.h>
4072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala#include <linux/platform_device.h>
41ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor#include <linux/suspend.h>
42e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
43b0b4a7c28ebee0763cae90d470cfff501a83be37G, Manjunath Kondaiah#include "twl-core.h"
44b0b4a7c28ebee0763cae90d470cfff501a83be37G, Manjunath Kondaiah
45e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*
46e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * TWL6030 (unlike its predecessors, which had two level interrupt handling)
47e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
48e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * It exposes status bits saying who has raised an interrupt. There are
49e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * three mask registers that corresponds to these status registers, that
50e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * enables/disables these interrupts.
51e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
52e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * We set up IRQs starting at a platform-specified base. An interrupt map table,
53e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * specifies mapping between interrupt number and the associated module.
54e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K *
55e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K */
56e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
57e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic int twl6030_interrupt_mapping[24] = {
58e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	PWR_INTR_OFFSET,	/* Bit 0	PWRON			*/
59e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	PWR_INTR_OFFSET,	/* Bit 1	RPWRON			*/
60e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	PWR_INTR_OFFSET,	/* Bit 2	BAT_VLOW		*/
61e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	RTC_INTR_OFFSET,	/* Bit 3	RTC_ALARM		*/
62e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	RTC_INTR_OFFSET,	/* Bit 4	RTC_PERIOD		*/
63e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	HOTDIE_INTR_OFFSET,	/* Bit 5	HOT_DIE			*/
64e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	SMPSLDO_INTR_OFFSET,	/* Bit 6	VXXX_SHORT		*/
65e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	SMPSLDO_INTR_OFFSET,	/* Bit 7	VMMC_SHORT		*/
66e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
67e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	SMPSLDO_INTR_OFFSET,	/* Bit 8	VUSIM_SHORT		*/
68e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	BATDETECT_INTR_OFFSET,	/* Bit 9	BAT			*/
69e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	SIMDETECT_INTR_OFFSET,	/* Bit 10	SIM			*/
70e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	MMCDETECT_INTR_OFFSET,	/* Bit 11	MMC			*/
71e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	RSV_INTR_OFFSET,  	/* Bit 12	Reserved		*/
72e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	MADC_INTR_OFFSET,	/* Bit 13	GPADC_RT_EOC		*/
73e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	MADC_INTR_OFFSET,	/* Bit 14	GPADC_SW_EOC		*/
74e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	GASGAUGE_INTR_OFFSET,	/* Bit 15	CC_AUTOCAL		*/
75e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
76e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	USBOTG_INTR_OFFSET,	/* Bit 16	ID_WKUP			*/
77e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	USBOTG_INTR_OFFSET,	/* Bit 17	VBUS_WKUP		*/
78e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	USBOTG_INTR_OFFSET,	/* Bit 18	ID			*/
7977b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK	USB_PRES_INTR_OFFSET,	/* Bit 19	VBUS			*/
80e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	CHARGER_INTR_OFFSET,	/* Bit 20	CHRG_CTRL		*/
816523b148b44be38d89c2ee9865d34da30d9f5f1cGraeme Gregory	CHARGERFAULT_INTR_OFFSET,	/* Bit 21	EXT_CHRG	*/
826523b148b44be38d89c2ee9865d34da30d9f5f1cGraeme Gregory	CHARGERFAULT_INTR_OFFSET,	/* Bit 22	INT_CHRG	*/
83e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	RSV_INTR_OFFSET,	/* Bit 23	Reserved		*/
84e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K};
85e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*----------------------------------------------------------------------*/
86e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
87e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic unsigned twl6030_irq_base;
88ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynorstatic int twl_irq;
89ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynorstatic bool twl_irq_wake_enabled;
90e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
91e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic struct completion irq_event;
92ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynorstatic atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
93ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
94ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynorstatic int twl6030_irq_pm_notifier(struct notifier_block *notifier,
95ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor				   unsigned long pm_event, void *unused)
96ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor{
97ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	int chained_wakeups;
98ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
99ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	switch (pm_event) {
100ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	case PM_SUSPEND_PREPARE:
101ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		chained_wakeups = atomic_read(&twl6030_wakeirqs);
102ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
103ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		if (chained_wakeups && !twl_irq_wake_enabled) {
104ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor			if (enable_irq_wake(twl_irq))
105ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor				pr_err("twl6030 IRQ wake enable failed\n");
106ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor			else
107ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor				twl_irq_wake_enabled = true;
108ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		} else if (!chained_wakeups && twl_irq_wake_enabled) {
109ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor			disable_irq_wake(twl_irq);
110ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor			twl_irq_wake_enabled = false;
111ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		}
112ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
113782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor		disable_irq(twl_irq);
114ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		break;
115782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor
116782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor	case PM_POST_SUSPEND:
117782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor		enable_irq(twl_irq);
118782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor		break;
119782baa20b201100e14ce065bb7b890169e7a5d3cTodd Poynor
120ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	default:
121ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		break;
122ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	}
123ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
124ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	return NOTIFY_DONE;
125ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor}
126ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
127ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynorstatic struct notifier_block twl6030_irq_pm_notifier_block = {
128ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	.notifier_call = twl6030_irq_pm_notifier,
129ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor};
130e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
131e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*
132e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * This thread processes interrupts reported by the Primary Interrupt Handler.
133e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K */
134e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic int twl6030_irq_thread(void *data)
135e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
136e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	long irq = (long)data;
137e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	static unsigned i2c_errors;
138e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	static const unsigned max_i2c_errors = 100;
139e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int ret;
140e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
141e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	while (!kthread_should_stop()) {
142e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		int i;
143e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		union {
144e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		u8 bytes[4];
145e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		u32 int_sts;
146e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		} sts;
147e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
148e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		/* Wait for IRQ, then read PIH irq status (also blocking) */
149e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		wait_for_completion_interruptible(&irq_event);
150e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
151e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		/* read INT_STS_A, B and C in one shot using a burst read */
152e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
153e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				REG_INT_STS_A, 3);
154e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		if (ret) {
155e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			pr_warning("twl6030: I2C error %d reading PIH ISR\n",
156e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K					ret);
157e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			if (++i2c_errors >= max_i2c_errors) {
158e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				printk(KERN_ERR "Maximum I2C error count"
159e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K						" exceeded.  Terminating %s.\n",
160e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K						__func__);
161e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				break;
162e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			}
163e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			complete(&irq_event);
164e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			continue;
165e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		}
166e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
167e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
168e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
169e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		sts.bytes[3] = 0; /* Only 24 bits are valid*/
170e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
17177b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK		/*
17277b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK		 * Since VBUS status bit is not reliable for VBUS disconnect
17377b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK		 * use CHARGER VBUS detection status bit instead.
17477b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK		 */
17577b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK		if (sts.bytes[2] & 0x10)
17677b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK			sts.bytes[2] |= 0x08;
17777b1d3fa88dcb9d6e885926f972c421e4069b849Hema HK
178e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
179e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			local_irq_disable();
180e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			if (sts.int_sts & 0x1) {
181e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				int module_irq = twl6030_irq_base +
182e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K					twl6030_interrupt_mapping[i];
183c22435a307e00b8ae947b79a8c0d94ab0bef404cThomas Gleixner				generic_handle_irq(module_irq);
184e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
185e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			}
186e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		local_irq_enable();
187e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		}
188e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
189e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				REG_INT_STS_A, 3); /* clear INT_STS_A */
190e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		if (ret)
191e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			pr_warning("twl6030: I2C error in clearing PIH ISR\n");
192e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
193e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		enable_irq(irq);
194e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	}
195e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
196e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return 0;
197e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
198e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
199e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*
200e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * handle_twl6030_int() is the desc->handle method for the twl6030 interrupt.
201e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * This is a chained interrupt, so there is no desc->action method for it.
202e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * Now we need to query the interrupt controller in the twl6030 to determine
203e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * which module is generating the interrupt request.  However, we can't do i2c
204e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * transactions in interrupt context, so we must defer that work to a kernel
205e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * thread.  All we do here is acknowledge and mask the interrupt and wakeup
206e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K * the kernel thread.
207e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K */
208e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic irqreturn_t handle_twl6030_pih(int irq, void *devid)
209e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
210e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	disable_irq_nosync(irq);
211e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	complete(devid);
212e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return IRQ_HANDLED;
213e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
214e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
215e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*----------------------------------------------------------------------*/
216e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
217e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic inline void activate_irq(int irq)
218e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
219e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#ifdef CONFIG_ARM
220e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	/* ARM requires an extra step to clear IRQ_NOREQUEST, which it
221e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	 * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
222e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	 */
223e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	set_irq_flags(irq, IRQF_VALID);
224e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#else
225e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	/* same effect on other architectures */
226d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner	irq_set_noprobe(irq);
227e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K#endif
228e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
229e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
23049dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkarint twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
23149dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar{
232ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	if (on)
233ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		atomic_inc(&twl6030_wakeirqs);
234ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	else
235ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor		atomic_dec(&twl6030_wakeirqs);
23649dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar
237ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	return 0;
23849dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar}
23949dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar
240e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*----------------------------------------------------------------------*/
241e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
242e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kstatic unsigned twl6030_irq_next;
243e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
244e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K/*----------------------------------------------------------------------*/
245e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kint twl6030_interrupt_unmask(u8 bit_mask, u8 offset)
246e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
247e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int ret;
248e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	u8 unmask_value;
249e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value,
250e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_STS_A + offset);
251e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	unmask_value &= (~(bit_mask));
252e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret |= twl_i2c_write_u8(TWL_MODULE_PIH, unmask_value,
253e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_STS_A + offset); /* unmask INT_MSK_A/B/C */
254e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return ret;
255e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
256e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T KEXPORT_SYMBOL(twl6030_interrupt_unmask);
257e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
258e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kint twl6030_interrupt_mask(u8 bit_mask, u8 offset)
259e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
260e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int ret;
261e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	u8 mask_value;
262e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value,
263e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_STS_A + offset);
264e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	mask_value |= (bit_mask);
265e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret |= twl_i2c_write_u8(TWL_MODULE_PIH, mask_value,
266e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_STS_A + offset); /* mask INT_MSK_A/B/C */
267e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return ret;
268e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
269e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T KEXPORT_SYMBOL(twl6030_interrupt_mask);
270e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
27172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyalaint twl6030_mmc_card_detect_config(void)
27272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala{
27372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	int ret;
27472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	u8 reg_val = 0;
27572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala
27672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	/* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */
27772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
27872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala						REG_INT_MSK_LINE_B);
27972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
28072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala						REG_INT_MSK_STS_B);
28172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	/*
28225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * Initially Configuring MMC_CTRL for receiving interrupts &
28372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	 * Card status on TWL6030 for MMC1
28472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	 */
28572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val, TWL6030_MMCCTRL);
28672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (ret < 0) {
28772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		pr_err("twl6030: Failed to read MMCCTRL, error %d\n", ret);
28872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		return ret;
28972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	}
29072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	reg_val &= ~VMMC_AUTO_OFF;
29172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	reg_val |= SW_FC;
29272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL);
29372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (ret < 0) {
29472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		pr_err("twl6030: Failed to write MMCCTRL, error %d\n", ret);
29572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		return ret;
29672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	}
29772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala
29872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	/* Configuring PullUp-PullDown register */
29972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val,
30072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala						TWL6030_CFG_INPUT_PUPD3);
30172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (ret < 0) {
30272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		pr_err("twl6030: Failed to read CFG_INPUT_PUPD3, error %d\n",
30372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala									ret);
30472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		return ret;
30572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	}
30672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	reg_val &= ~(MMC_PU | MMC_PD);
30772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val,
30872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala						TWL6030_CFG_INPUT_PUPD3);
30972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (ret < 0) {
31072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		pr_err("twl6030: Failed to write CFG_INPUT_PUPD3, error %d\n",
31172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala									ret);
31272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		return ret;
31372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	}
31472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	return 0;
31572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala}
31672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyalaEXPORT_SYMBOL(twl6030_mmc_card_detect_config);
31772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala
31872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyalaint twl6030_mmc_card_detect(struct device *dev, int slot)
31972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala{
32072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	int ret = -EIO;
32172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	u8 read_reg = 0;
32272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	struct platform_device *pdev = to_platform_device(dev);
32372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala
32472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (pdev->id) {
32572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		/* TWL6030 provide's Card detect support for
32672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		 * only MMC1 controller.
32772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		 */
32825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		pr_err("Unknown MMC controller %d in %s\n", pdev->id, __func__);
32972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		return ret;
33072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	}
33172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	/*
33272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	 * BIT0 of MMC_CTRL on TWL6030 provides card status for MMC1
33372f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	 * 0 - Card not present ,1 - Card present
33472f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	 */
33572f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &read_reg,
33672f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala						TWL6030_MMCCTRL);
33772f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	if (ret >= 0)
33872f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala		ret = read_reg & STS_MMC;
33972f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala	return ret;
34072f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala}
34172f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyalaEXPORT_SYMBOL(twl6030_mmc_card_detect);
34272f2e2c763edc41f8eead042b6ff933acb0378e2kishore kadiyala
343e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kint twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
344e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
345e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
346e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int	status = 0;
347e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int	i;
348e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	struct task_struct	*task;
349e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	int ret;
350e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	u8 mask[4];
351e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
352e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	static struct irq_chip	twl6030_irq_chip;
353e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	mask[1] = 0xFF;
354e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	mask[2] = 0xFF;
355e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	mask[3] = 0xFF;
356e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
357e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */
358e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
359e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */
360e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
361e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */
362e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
363e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	twl6030_irq_base = irq_base;
364e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
365e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	/* install an irq handler for each of the modules;
366e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	 * clone dummy irq_chip since PIH can't *do* anything
367e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	 */
368e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	twl6030_irq_chip = dummy_irq_chip;
369e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	twl6030_irq_chip.name = "twl6030";
370c45c685c1a582e27787b5aa85844f2ee6986018cLennert Buytenhek	twl6030_irq_chip.irq_set_type = NULL;
37149dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar	twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake;
372e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
373e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	for (i = irq_base; i < irq_end; i++) {
374d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_chip_and_handler(i, &twl6030_irq_chip,
375d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner					 handle_simple_irq);
37649dcd070d0718a8b8db344d7b3d5e278362ecd86Santosh Shilimkar		irq_set_chip_data(i, (void *)irq_num);
377e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		activate_irq(i);
378e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	}
379e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
380e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	twl6030_irq_next = i;
381e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
382e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K			irq_num, irq_base, twl6030_irq_next - 1);
383e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
384e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	/* install an irq handler to demultiplex the TWL6030 interrupt */
385e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	init_completion(&irq_event);
386e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
387f742b96e42f886a415633a1fed0db2bb09d2baa3Yong Zhang	status = request_irq(irq_num, handle_twl6030_pih, 0,
388e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K				"TWL6030-PIH", &irq_event);
389e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	if (status < 0) {
390e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
391e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		goto fail_irq;
392e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	}
393862de70c12bb6227943e155251c75e7fa4558068Axel Lin
394862de70c12bb6227943e155251c75e7fa4558068Axel Lin	task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
395862de70c12bb6227943e155251c75e7fa4558068Axel Lin	if (IS_ERR(task)) {
396862de70c12bb6227943e155251c75e7fa4558068Axel Lin		pr_err("twl6030: could not create irq %d thread!\n", irq_num);
397862de70c12bb6227943e155251c75e7fa4558068Axel Lin		status = PTR_ERR(task);
398862de70c12bb6227943e155251c75e7fa4558068Axel Lin		goto fail_kthread;
399862de70c12bb6227943e155251c75e7fa4558068Axel Lin	}
400ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor
401ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	twl_irq = irq_num;
402ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	register_pm_notifier(&twl6030_irq_pm_notifier_block);
403e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return status;
404e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
405e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kfail_kthread:
406862de70c12bb6227943e155251c75e7fa4558068Axel Lin	free_irq(irq_num, &irq_event);
407862de70c12bb6227943e155251c75e7fa4558068Axel Lin
408862de70c12bb6227943e155251c75e7fa4558068Axel Linfail_irq:
409e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	for (i = irq_base; i < irq_end; i++)
410d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_chip_and_handler(i, NULL, NULL);
411e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return status;
412e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
413e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
414e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T Kint twl6030_exit_irq(void)
415e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K{
416ab2b9260df67e29d5bd69d989f2f84f8c2ed4238Todd Poynor	unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
417e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
418e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	if (twl6030_irq_base) {
419e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		pr_err("twl6030: can't yet clean up IRQs?\n");
420e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K		return -ENOSYS;
421e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	}
422e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K	return 0;
423e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K}
424e8deb28ca8e221de0239eafb3c3d431d8854278eBalaji T K
425