mfd: wcd9xxx: Refactor codec core driver and irq driver

IRQ driver can be used by codecs that do not use the core driver.
Refactor the drivers so that codec drivers that are not children
of the core driver can also request/access the interrupt routines
provided by the IRQ driver.

Change-Id: I3086be02839fd735db2d32665abf7b984958dc2b
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
(cherry picked from commit c68ed369921e8d08f4254b9243872785a3a5cf2f)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c99bed1..75a76c0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -75,11 +75,14 @@
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 
-obj-$(CONFIG_WCD9310_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
-obj-$(CONFIG_WCD9304_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
-obj-$(CONFIG_WCD9320_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
-obj-$(CONFIG_WCD9306_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
-
+obj-$(CONFIG_WCD9310_CODEC)	+= wcd9xxx-core.o wcd9xxx-irq.o \
+						wcd9xxx-slimslave.o wcd9xxx-core-resource.o
+obj-$(CONFIG_WCD9304_CODEC)	+= wcd9xxx-core.o wcd9xxx-irq.o \
+						wcd9xxx-slimslave.o wcd9xxx-core-resource.o
+obj-$(CONFIG_WCD9320_CODEC)	+= wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o\
+						wcd9xxx-core-resource.o
+obj-$(CONFIG_WCD9306_CODEC)	+= wcd9xxx-core.o wcd9xxx-irq.o\
+						wcd9xxx-slimslave.o wcd9xxx-core-resource.o
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-assabet.o
diff --git a/drivers/mfd/wcd9xxx-core-resource.c b/drivers/mfd/wcd9xxx-core-resource.c
new file mode 100644
index 0000000..1791d72
--- /dev/null
+++ b/drivers/mfd/wcd9xxx-core-resource.c
@@ -0,0 +1,194 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
+
+
+static enum wcd9xxx_intf_status wcd9xxx_intf = -1;
+
+int wcd9xxx_core_irq_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	int ret = 0;
+
+	if (wcd9xxx_core_res->irq != 1) {
+		ret = wcd9xxx_irq_init(wcd9xxx_core_res);
+		if (ret)
+			pr_err("IRQ initialization failed\n");
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_irq_init);
+
+int wcd9xxx_initialize_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	unsigned int irq,
+	unsigned int irq_base)
+{
+	wcd9xxx_core_res->irq = irq;
+	wcd9xxx_core_res->irq_base = irq_base;
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd9xxx_initialize_irq);
+
+int wcd9xxx_core_res_init(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	int num_irqs, int num_irq_regs,
+	int (*codec_read)(struct wcd9xxx_core_resource*, unsigned short),
+	int (*codec_write)(struct wcd9xxx_core_resource*, unsigned short, u8),
+	int (*codec_bulk_read) (struct wcd9xxx_core_resource*, unsigned short,
+							int, u8*))
+{
+	mutex_init(&wcd9xxx_core_res->pm_lock);
+	wcd9xxx_core_res->wlock_holders = 0;
+	wcd9xxx_core_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+	init_waitqueue_head(&wcd9xxx_core_res->pm_wq);
+	pm_qos_add_request(&wcd9xxx_core_res->pm_qos_req,
+				PM_QOS_CPU_DMA_LATENCY,
+				PM_QOS_DEFAULT_VALUE);
+
+	wcd9xxx_core_res->codec_reg_read = codec_read;
+	wcd9xxx_core_res->codec_reg_write = codec_write;
+	wcd9xxx_core_res->codec_bulk_read = codec_bulk_read;
+	wcd9xxx_core_res->num_irqs = num_irqs;
+	wcd9xxx_core_res->num_irq_regs = num_irq_regs;
+
+	pr_info("%s: num_irqs = %d, num_irq_regs = %d\n",
+			__func__, wcd9xxx_core_res->num_irqs,
+			wcd9xxx_core_res->num_irq_regs);
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_init);
+
+void wcd9xxx_core_res_deinit(struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	pm_qos_remove_request(&wcd9xxx_core_res->pm_qos_req);
+	mutex_destroy(&wcd9xxx_core_res->pm_lock);
+	wcd9xxx_core_res->codec_reg_read = NULL;
+	wcd9xxx_core_res->codec_reg_write = NULL;
+	wcd9xxx_core_res->codec_bulk_read = NULL;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_deinit);
+
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(
+		struct wcd9xxx_core_resource *wcd9xxx_core_res,
+		enum wcd9xxx_pm_state o,
+		enum wcd9xxx_pm_state n)
+{
+	enum wcd9xxx_pm_state old;
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	old = wcd9xxx_core_res->pm_state;
+	if (old == o)
+		wcd9xxx_core_res->pm_state = n;
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+	return old;
+}
+EXPORT_SYMBOL(wcd9xxx_pm_cmpxchg);
+
+int wcd9xxx_core_res_suspend(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res,
+	pm_message_t pmesg)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	/*
+	 * pm_qos_update_request() can be called after this suspend chain call
+	 * started. thus suspend can be called while lock is being held
+	 */
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_SLEEPABLE) {
+		pr_debug("%s: suspending system, state %d, wlock %d\n",
+			 __func__, wcd9xxx_core_res->pm_state,
+			 wcd9xxx_core_res->wlock_holders);
+		wcd9xxx_core_res->pm_state = WCD9XXX_PM_ASLEEP;
+	} else if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_AWAKE) {
+		/*
+		 * unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
+		 * then set to WCD9XXX_PM_ASLEEP
+		 */
+		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+			 __func__, wcd9xxx_core_res->pm_state,
+			 wcd9xxx_core_res->wlock_holders);
+		mutex_unlock(&wcd9xxx_core_res->pm_lock);
+		if (!(wait_event_timeout(wcd9xxx_core_res->pm_wq,
+					 wcd9xxx_pm_cmpxchg(wcd9xxx_core_res,
+						  WCD9XXX_PM_SLEEPABLE,
+						  WCD9XXX_PM_ASLEEP) ==
+							WCD9XXX_PM_SLEEPABLE,
+					 HZ))) {
+			pr_debug("%s: suspend failed state %d, wlock %d\n",
+				 __func__, wcd9xxx_core_res->pm_state,
+				 wcd9xxx_core_res->wlock_holders);
+			ret = -EBUSY;
+		} else {
+			pr_debug("%s: done, state %d, wlock %d\n", __func__,
+				 wcd9xxx_core_res->pm_state,
+				 wcd9xxx_core_res->wlock_holders);
+		}
+		mutex_lock(&wcd9xxx_core_res->pm_lock);
+	} else if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_warn("%s: system is already suspended, state %d, wlock %dn",
+			__func__, wcd9xxx_core_res->pm_state,
+			wcd9xxx_core_res->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_suspend);
+
+int wcd9xxx_core_res_resume(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res)
+{
+	int ret = 0;
+
+	pr_debug("%s: enter\n", __func__);
+	mutex_lock(&wcd9xxx_core_res->pm_lock);
+	if (wcd9xxx_core_res->pm_state == WCD9XXX_PM_ASLEEP) {
+		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+				wcd9xxx_core_res->pm_state,
+				wcd9xxx_core_res->wlock_holders);
+		wcd9xxx_core_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+	} else {
+		pr_warn("%s: system is already awake, state %d wlock %d\n",
+				__func__, wcd9xxx_core_res->pm_state,
+				wcd9xxx_core_res->wlock_holders);
+	}
+	mutex_unlock(&wcd9xxx_core_res->pm_lock);
+	wake_up_all(&wcd9xxx_core_res->pm_wq);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcd9xxx_core_res_resume);
+
+enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
+{
+	return wcd9xxx_intf;
+}
+EXPORT_SYMBOL(wcd9xxx_get_intf_type);
+
+void wcd9xxx_set_intf_type(enum wcd9xxx_intf_status intf_status)
+{
+	wcd9xxx_intf = intf_status;
+}
+EXPORT_SYMBOL(wcd9xxx_set_intf_type);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 0fd4b79..d718c40 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 #include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
 #include <linux/mfd/wcd9xxx/pdata.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 
@@ -68,7 +69,6 @@
 static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
 
 struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
-static int wcd9xxx_intf = -1;
 
 static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
 		       int bytes, void *dest, bool interface_reg)
@@ -92,7 +92,9 @@
 
 	return 0;
 }
-int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+static int __wcd9xxx_reg_read(
+	struct wcd9xxx *wcd9xxx,
+	unsigned short reg)
 {
 	u8 val;
 	int ret;
@@ -106,7 +108,16 @@
 	else
 		return val;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
+
+int wcd9xxx_reg_read(
+	struct wcd9xxx_core_resource *core_res,
+	unsigned short reg)
+{
+	struct wcd9xxx *wcd9xxx = (struct wcd9xxx *) core_res->parent;
+	return __wcd9xxx_reg_read(wcd9xxx, reg);
+
+}
+EXPORT_SYMBOL(wcd9xxx_reg_read);
 
 static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
 			int bytes, void *src, bool interface_reg)
@@ -125,8 +136,9 @@
 	return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
 }
 
-int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
-		     u8 val)
+static int __wcd9xxx_reg_write(
+	struct wcd9xxx *wcd9xxx,
+	unsigned short reg, u8 val)
 {
 	int ret;
 
@@ -136,7 +148,15 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
+
+int wcd9xxx_reg_write(
+	struct wcd9xxx_core_resource *core_res,
+	unsigned short reg, u8 val)
+{
+	struct wcd9xxx *wcd9xxx = (struct wcd9xxx *) core_res->parent;
+	return __wcd9xxx_reg_write(wcd9xxx, reg, val);
+}
+EXPORT_SYMBOL(wcd9xxx_reg_write);
 
 static u8 wcd9xxx_pgd_la;
 static u8 wcd9xxx_inf_la;
@@ -155,7 +175,7 @@
 	else
 		return val;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
+EXPORT_SYMBOL(wcd9xxx_interface_reg_read);
 
 int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
 		     u8 val)
@@ -168,37 +188,54 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
+EXPORT_SYMBOL(wcd9xxx_interface_reg_write);
 
-int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
-		     int count, u8 *buf)
+static int __wcd9xxx_bulk_read(
+	struct wcd9xxx *wcd9xxx,
+	unsigned short reg,
+	int count, u8 *buf)
 {
 	int ret;
 
 	mutex_lock(&wcd9xxx->io_lock);
-
 	ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
-
 	mutex_unlock(&wcd9xxx->io_lock);
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
 
-int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+int wcd9xxx_bulk_read(
+	struct wcd9xxx_core_resource *core_res,
+	unsigned short reg,
+	int count, u8 *buf)
+{
+	struct wcd9xxx *wcd9xxx =
+			(struct wcd9xxx *) core_res->parent;
+	return __wcd9xxx_bulk_read(wcd9xxx, reg, count, buf);
+}
+EXPORT_SYMBOL(wcd9xxx_bulk_read);
+
+static int __wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
 		     int count, u8 *buf)
 {
 	int ret;
 
 	mutex_lock(&wcd9xxx->io_lock);
-
 	ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
-
 	mutex_unlock(&wcd9xxx->io_lock);
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
+
+int wcd9xxx_bulk_write(
+	struct wcd9xxx_core_resource *core_res,
+	unsigned short reg, int count, u8 *buf)
+{
+	struct wcd9xxx *wcd9xxx =
+			(struct wcd9xxx *) core_res->parent;
+	return __wcd9xxx_bulk_write(wcd9xxx, reg, count, buf);
+}
+EXPORT_SYMBOL(wcd9xxx_bulk_write);
 
 static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
 				int bytes, void *dest, bool interface)
@@ -337,19 +374,19 @@
 
 static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
 {
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
 	usleep_range(5000, 5000);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
 }
 
 static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
 {
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
-	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
+	__wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
 }
 
 static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
@@ -388,13 +425,13 @@
 	int i, rc;
 	const struct wcd9xxx_codec_type *c, *d = NULL;
 
-	rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
+	rc = __wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
 			       sizeof(wcd9xxx->id_minor),
 			       (u8 *)&wcd9xxx->id_minor);
 	if (rc < 0)
 		goto exit;
 
-	rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
+	rc = __wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
 			       sizeof(wcd9xxx->id_major),
 			       (u8 *)&wcd9xxx->id_major);
 	if (rc < 0)
@@ -434,7 +471,8 @@
 		if (d->version > -1) {
 			*version = d->version;
 		} else {
-			rc = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
+			rc = __wcd9xxx_reg_read(wcd9xxx,
+							WCD9XXX_A_CHIP_VERSION);
 			if (rc < 0) {
 				d = NULL;
 				goto exit;
@@ -450,24 +488,94 @@
 	return d;
 }
 
+static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
+{
+	return (wcd9xxx->codec_type->num_irqs / 8) +
+		((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
+}
+
+/*
+ * Interrupt table for v1 corresponds to newer version
+ * codecs (wcd9304 and wcd9310)
+ */
+static const struct intr_data intr_tbl_v1[] = {
+	{WCD9XXX_IRQ_SLIMBUS, false},
+	{WCD9XXX_IRQ_MBHC_INSERTION, true},
+	{WCD9XXX_IRQ_MBHC_POTENTIAL, true},
+	{WCD9XXX_IRQ_MBHC_RELEASE, true},
+	{WCD9XXX_IRQ_MBHC_PRESS, true},
+	{WCD9XXX_IRQ_MBHC_SHORT_TERM, true},
+	{WCD9XXX_IRQ_MBHC_REMOVAL, true},
+	{WCD9XXX_IRQ_BG_PRECHARGE, false},
+	{WCD9XXX_IRQ_PA1_STARTUP, false},
+	{WCD9XXX_IRQ_PA2_STARTUP, false},
+	{WCD9XXX_IRQ_PA3_STARTUP, false},
+	{WCD9XXX_IRQ_PA4_STARTUP, false},
+	{WCD9XXX_IRQ_PA5_STARTUP, false},
+	{WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
+	{WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
+	{WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
+	{WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
+	{WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
+	{WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
+	{WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
+	{WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
+	{WCD9320_IRQ_EAR_PA_STARTUP, false},
+	{WCD9XXX_IRQ_RESERVED_0, false},
+	{WCD9XXX_IRQ_RESERVED_1, false},
+};
+
+/*
+ * Interrupt table for v2 corresponds to newer version
+ * codecs (wcd9320 and wcd9306)
+ */
+static const struct intr_data intr_tbl_v2[] = {
+	{WCD9XXX_IRQ_SLIMBUS, false},
+	{WCD9XXX_IRQ_MBHC_INSERTION, true},
+	{WCD9XXX_IRQ_MBHC_POTENTIAL, true},
+	{WCD9XXX_IRQ_MBHC_RELEASE, true},
+	{WCD9XXX_IRQ_MBHC_PRESS, true},
+	{WCD9XXX_IRQ_MBHC_SHORT_TERM, true},
+	{WCD9XXX_IRQ_MBHC_REMOVAL, true},
+	{WCD9320_IRQ_MBHC_JACK_SWITCH, true},
+	{WCD9306_IRQ_MBHC_JACK_SWITCH, true},
+	{WCD9XXX_IRQ_BG_PRECHARGE, false},
+	{WCD9XXX_IRQ_PA1_STARTUP, false},
+	{WCD9XXX_IRQ_PA2_STARTUP, false},
+	{WCD9XXX_IRQ_PA3_STARTUP, false},
+	{WCD9XXX_IRQ_PA4_STARTUP, false},
+	{WCD9XXX_IRQ_PA5_STARTUP, false},
+	{WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
+	{WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
+	{WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
+	{WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
+	{WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
+	{WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
+	{WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
+	{WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
+	{WCD9320_IRQ_EAR_PA_STARTUP, false},
+	{WCD9XXX_IRQ_RESERVED_0, false},
+	{WCD9XXX_IRQ_RESERVED_1, false},
+	{WCD9XXX_IRQ_MAD_AUDIO, false},
+	{WCD9XXX_IRQ_MAD_BEACON, false},
+	{WCD9XXX_IRQ_MAD_ULTRASOUND, false},
+	{WCD9XXX_IRQ_SPEAKER_CLIPPING, false},
+	{WCD9XXX_IRQ_VBAT_MONITOR_ATTACK, false},
+	{WCD9XXX_IRQ_VBAT_MONITOR_RELEASE, false},
+	{WCD9XXX_IRQ_RESERVED_2, false},
+};
+
 static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
 {
-	int ret;
+	int ret = 0;
 	u8 version;
 	const struct wcd9xxx_codec_type *found;
+	struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
 
 	mutex_init(&wcd9xxx->io_lock);
 	mutex_init(&wcd9xxx->xfer_lock);
 
-	mutex_init(&wcd9xxx->pm_lock);
-	wcd9xxx->wlock_holders = 0;
-	wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
-	init_waitqueue_head(&wcd9xxx->pm_wq);
-	pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
-				PM_QOS_DEFAULT_VALUE);
-
 	dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
-
 	wcd9xxx_bring_up(wcd9xxx);
 
 	found = wcd9xxx_check_codec_type(wcd9xxx, &version);
@@ -479,14 +587,27 @@
 		wcd9xxx->version = version;
 	}
 
-	if (wcd9xxx->irq != -1) {
-		ret = wcd9xxx_irq_init(wcd9xxx);
-		if (ret) {
-			pr_err("IRQ initialization failed\n");
-			goto err;
-		}
+	core_res->parent = wcd9xxx;
+	core_res->dev = wcd9xxx->dev;
+
+	if (wcd9xxx->codec_type->id_major == TABLA_MAJOR
+		|| wcd9xxx->codec_type->id_major == SITAR_MAJOR) {
+		core_res->intr_table = intr_tbl_v1;
+		core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v1);
+	} else {
+		core_res->intr_table = intr_tbl_v2;
+		core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v2);
 	}
 
+	wcd9xxx_core_res_init(&wcd9xxx->core_res,
+				wcd9xxx->codec_type->num_irqs,
+				wcd9xxx_num_irq_regs(wcd9xxx),
+				wcd9xxx_reg_read, wcd9xxx_reg_write,
+				wcd9xxx_bulk_read);
+
+	if (wcd9xxx_core_irq_init(&wcd9xxx->core_res))
+		goto err;
+
 	ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
 			      NULL, 0);
 	if (ret != 0) {
@@ -502,11 +623,10 @@
 
 	return ret;
 err_irq:
-	wcd9xxx_irq_exit(wcd9xxx);
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
 err:
 	wcd9xxx_bring_down(wcd9xxx);
-	pm_qos_remove_request(&wcd9xxx->pm_qos_req);
-	mutex_destroy(&wcd9xxx->pm_lock);
+	wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
 	mutex_destroy(&wcd9xxx->io_lock);
 	mutex_destroy(&wcd9xxx->xfer_lock);
 	return ret;
@@ -515,14 +635,13 @@
 static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
 {
 	device_init_wakeup(wcd9xxx->dev, false);
-	wcd9xxx_irq_exit(wcd9xxx);
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
 	wcd9xxx_bring_down(wcd9xxx);
 	wcd9xxx_free_reset(wcd9xxx);
-	mutex_destroy(&wcd9xxx->pm_lock);
-	pm_qos_remove_request(&wcd9xxx->pm_qos_req);
+	wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
 	mutex_destroy(&wcd9xxx->io_lock);
 	mutex_destroy(&wcd9xxx->xfer_lock);
-	if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		slim_remove_device(wcd9xxx->slim_slave);
 	kfree(wcd9xxx);
 }
@@ -747,13 +866,6 @@
 	kfree(wcd9xxx->supplies);
 }
 
-enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
-{
-	return wcd9xxx_intf;
-}
-
-EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
-
 struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
 {
 	u16 mask = 0x0f00;
@@ -905,13 +1017,16 @@
 	int ret = 0;
 	int wcd9xx_index = 0;
 	struct device *dev;
+	int intf_type;
 
-	pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
-	if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+	intf_type = wcd9xxx_get_intf_type();
+
+	pr_debug("%s: interface status %d\n", __func__, intf_type);
+	if (intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
 		dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
 			__func__);
 		return -ENODEV;
-	} else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
+	} else if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 		ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
 		if (ret != 0)
 			dev_err(&client->dev, "%s: I2C set codec I2C\n"
@@ -923,7 +1038,7 @@
 			wcd9xxx_modules[wcd9xx_index].client = client;
 		}
 		return ret;
-	} else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
+	} else if (intf_type == WCD9XXX_INTERFACE_TYPE_PROBING) {
 		dev = &client->dev;
 		if (client->dev.of_node) {
 			dev_dbg(&client->dev, "%s:Platform data\n"
@@ -990,10 +1105,9 @@
 		wcd9xxx_modules[wcd9xx_index].client = client;
 		wcd9xxx->read_dev = wcd9xxx_i2c_read;
 		wcd9xxx->write_dev = wcd9xxx_i2c_write;
-		if (!wcd9xxx->dev->of_node) {
-			wcd9xxx->irq = pdata->irq;
-			wcd9xxx->irq_base = pdata->irq_base;
-		}
+		if (!wcd9xxx->dev->of_node)
+			wcd9xxx_initialize_irq(&wcd9xxx->core_res,
+					pdata->irq, pdata->irq_base);
 
 		ret = wcd9xxx_device_init(wcd9xxx);
 		if (ret) {
@@ -1009,7 +1123,7 @@
 		if (val != wcd9xxx->codec_type->i2c_chip_status)
 			pr_err("%s: unknown chip status 0x%x\n", __func__, val);
 
-		wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
+		wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_I2C);
 
 		return ret;
 	} else
@@ -1392,8 +1506,11 @@
 	struct wcd9xxx *wcd9xxx;
 	struct wcd9xxx_pdata *pdata;
 	int ret = 0;
+	int intf_type;
 
-	if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
+	intf_type = wcd9xxx_get_intf_type();
+
+	if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
 		dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
 			__func__);
 		return -ENODEV;
@@ -1471,10 +1588,9 @@
 	wcd9xxx->write_dev = wcd9xxx_slim_write_device;
 	wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
 	wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
-	if (!wcd9xxx->dev->of_node) {
-		wcd9xxx->irq = pdata->irq;
-		wcd9xxx->irq_base = pdata->irq_base;
-	}
+	if (!wcd9xxx->dev->of_node)
+		wcd9xxx_initialize_irq(&wcd9xxx->core_res,
+					pdata->irq, pdata->irq_base);
 
 	ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
 	if (ret) {
@@ -1492,7 +1608,7 @@
 		goto err_slim_add;
 	}
 	wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
-	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_SLIMBUS);
 
 	ret = wcd9xxx_device_init(wcd9xxx);
 	if (ret) {
@@ -1546,29 +1662,10 @@
 	return 0;
 }
 
-static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
-{
-	int ret = 0;
-
-	pr_debug("%s: enter\n", __func__);
-	mutex_lock(&wcd9xxx->pm_lock);
-	if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
-		pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
-			 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-		wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
-	} else {
-		pr_warn("%s: system is already awake, state %d wlock %d\n",
-			__func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-	}
-	mutex_unlock(&wcd9xxx->pm_lock);
-	wake_up_all(&wcd9xxx->pm_wq);
-
-	return ret;
-}
-
 static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
 {
 	int ret = 0;
+	struct wcd9xxx_core_resource *wcd9xxx_res = &wcd9xxx->core_res;
 
 	if (wcd9xxx->slim_device_bootup) {
 		wcd9xxx->slim_device_bootup = false;
@@ -1579,7 +1676,7 @@
 		pr_err("%s: Resetting Codec failed\n", __func__);
 
 	wcd9xxx_bring_up(wcd9xxx);
-	ret = wcd9xxx_irq_init(wcd9xxx);
+	ret = wcd9xxx_irq_init(wcd9xxx_res);
 	if (ret) {
 		pr_err("%s: wcd9xx_irq_init failed : %d\n", __func__, ret);
 	} else {
@@ -1600,7 +1697,7 @@
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
 
-	wcd9xxx_irq_exit(wcd9xxx);
+	wcd9xxx_irq_exit(&wcd9xxx->core_res);
 	if (wcd9xxx->dev_down)
 		wcd9xxx->dev_down(wcd9xxx);
 	dev_dbg(wcd9xxx->dev, "%s: device down\n", __func__);
@@ -1610,73 +1707,29 @@
 static int wcd9xxx_slim_resume(struct slim_device *sldev)
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
-	return wcd9xxx_resume(wcd9xxx);
+	return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
 }
 
 static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
 {
 	struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
 	if (wcd9xxx)
-		return wcd9xxx_resume(wcd9xxx);
+		return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
 	else
 		return 0;
 }
 
-static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
-{
-	int ret = 0;
-
-	pr_debug("%s: enter\n", __func__);
-	/*
-	 * pm_qos_update_request() can be called after this suspend chain call
-	 * started. thus suspend can be called while lock is being held
-	 */
-	mutex_lock(&wcd9xxx->pm_lock);
-	if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
-		pr_debug("%s: suspending system, state %d, wlock %d\n",
-			 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-		wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
-	} else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
-		/* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
-		 * then set to WCD9XXX_PM_ASLEEP */
-		pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
-			 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-		mutex_unlock(&wcd9xxx->pm_lock);
-		if (!(wait_event_timeout(wcd9xxx->pm_wq,
-					 wcd9xxx_pm_cmpxchg(wcd9xxx,
-						  WCD9XXX_PM_SLEEPABLE,
-						  WCD9XXX_PM_ASLEEP) ==
-							WCD9XXX_PM_SLEEPABLE,
-					 HZ))) {
-			pr_debug("%s: suspend failed state %d, wlock %d\n",
-				 __func__, wcd9xxx->pm_state,
-				 wcd9xxx->wlock_holders);
-			ret = -EBUSY;
-		} else {
-			pr_debug("%s: done, state %d, wlock %d\n", __func__,
-				 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-		}
-		mutex_lock(&wcd9xxx->pm_lock);
-	} else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
-		pr_warn("%s: system is already suspended, state %d, wlock %dn",
-			__func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
-	}
-	mutex_unlock(&wcd9xxx->pm_lock);
-
-	return ret;
-}
-
 static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
-	return wcd9xxx_suspend(wcd9xxx, pmesg);
+	return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
 }
 
 static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
 {
 	struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
 	if (wcd9xxx)
-		return wcd9xxx_suspend(wcd9xxx, pmesg);
+		return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
 	else
 		return 0;
 }
@@ -1832,7 +1885,7 @@
 	int ret[NUM_WCD9XXX_REG_RET];
 	int i = 0;
 
-	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
 
 	ret[0] = slim_driver_register(&tabla_slim_driver);
 	if (ret[0])
@@ -1876,6 +1929,7 @@
 
 static void __exit wcd9xxx_exit(void)
 {
+	wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
 }
 module_exit(wcd9xxx_exit);
 
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 18d815b..dc32efd 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -15,10 +15,9 @@
 #include <linux/sched.h>
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
-#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 #include <linux/mfd/wcd9xxx/wcd9310_registers.h>
-#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 #include <linux/delay.h>
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
@@ -40,57 +39,76 @@
 };
 #endif
 
-static int virq_to_phyirq(struct wcd9xxx *wcd9xxx, int virq);
-static int phyirq_to_virq(struct wcd9xxx *wcd9xxx, int irq);
-static unsigned int wcd9xxx_irq_get_upstream_irq(struct wcd9xxx *wcd9xxx);
-static void wcd9xxx_irq_put_upstream_irq(struct wcd9xxx *wcd9xxx);
-static int wcd9xxx_map_irq(struct wcd9xxx *wcd9xxx, int irq);
+static int virq_to_phyirq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int virq);
+static int phyirq_to_virq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int irq);
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res);
+static void wcd9xxx_irq_put_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res);
+static int wcd9xxx_map_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res, int irq);
 
 static void wcd9xxx_irq_lock(struct irq_data *data)
 {
-	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
-	mutex_lock(&wcd9xxx->irq_lock);
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	mutex_lock(&wcd9xxx_res->irq_lock);
 }
 
 static void wcd9xxx_irq_sync_unlock(struct irq_data *data)
 {
-	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
 	int i;
 
-	if (ARRAY_SIZE(wcd9xxx->irq_masks_cur) > WCD9XXX_NUM_IRQ_REGS ||
-		ARRAY_SIZE(wcd9xxx->irq_masks_cache) > WCD9XXX_NUM_IRQ_REGS) {
+	if ((ARRAY_SIZE(wcd9xxx_res->irq_masks_cur) >
+			WCD9XXX_MAX_IRQ_REGS) ||
+		(ARRAY_SIZE(wcd9xxx_res->irq_masks_cache) >
+			WCD9XXX_MAX_IRQ_REGS)) {
 			pr_err("%s: Array Size out of bound\n", __func__);
 			 return;
 	}
+	if (!wcd9xxx_res->codec_reg_write) {
+		pr_err("%s: Codec reg write callback function not defined\n",
+				__func__);
+		return;
+	}
 
-	for (i = 0; i < ARRAY_SIZE(wcd9xxx->irq_masks_cur); i++) {
+	for (i = 0; i < ARRAY_SIZE(wcd9xxx_res->irq_masks_cur); i++) {
 		/* If there's been a change in the mask write it back
 		 * to the hardware.
 		 */
-		if (wcd9xxx->irq_masks_cur[i] != wcd9xxx->irq_masks_cache[i]) {
-			wcd9xxx->irq_masks_cache[i] = wcd9xxx->irq_masks_cur[i];
-			wcd9xxx_reg_write(wcd9xxx,
+		if (wcd9xxx_res->irq_masks_cur[i] !=
+					wcd9xxx_res->irq_masks_cache[i]) {
+
+			wcd9xxx_res->irq_masks_cache[i] =
+					wcd9xxx_res->irq_masks_cur[i];
+			wcd9xxx_res->codec_reg_write(wcd9xxx_res,
 					  WCD9XXX_A_INTR_MASK0 + i,
-					  wcd9xxx->irq_masks_cur[i]);
+					  wcd9xxx_res->irq_masks_cur[i]);
 		}
 	}
 
-	mutex_unlock(&wcd9xxx->irq_lock);
+	mutex_unlock(&wcd9xxx_res->irq_lock);
 }
 
 static void wcd9xxx_irq_enable(struct irq_data *data)
 {
-	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
-	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx, data->irq);
-	wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)] &=
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx_res, data->irq);
+	wcd9xxx_res->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)] &=
 		~(BYTE_BIT_MASK(wcd9xxx_irq));
 }
 
 static void wcd9xxx_irq_disable(struct irq_data *data)
 {
-	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
-	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx, data->irq);
-	wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)]
+	struct wcd9xxx_core_resource *wcd9xxx_res =
+			irq_data_get_irq_chip_data(data);
+	int wcd9xxx_irq = virq_to_phyirq(wcd9xxx_res, data->irq);
+	wcd9xxx_res->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)]
 		|= BYTE_BIT_MASK(wcd9xxx_irq);
 }
 
@@ -108,21 +126,8 @@
 	.irq_mask = wcd9xxx_irq_mask,
 };
 
-enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
-		enum wcd9xxx_pm_state o,
-		enum wcd9xxx_pm_state n)
-{
-	enum wcd9xxx_pm_state old;
-	mutex_lock(&wcd9xxx->pm_lock);
-	old = wcd9xxx->pm_state;
-	if (old == o)
-		wcd9xxx->pm_state = n;
-	mutex_unlock(&wcd9xxx->pm_lock);
-	return old;
-}
-EXPORT_SYMBOL_GPL(wcd9xxx_pm_cmpxchg);
-
-bool wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx)
+bool wcd9xxx_lock_sleep(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	enum wcd9xxx_pm_state os;
 
@@ -138,164 +143,154 @@
 	 * As interrupt line is still active, codec will have another IRQ to
 	 * retry shortly.
 	 */
-	mutex_lock(&wcd9xxx->pm_lock);
-	if (wcd9xxx->wlock_holders++ == 0) {
+	mutex_lock(&wcd9xxx_res->pm_lock);
+	if (wcd9xxx_res->wlock_holders++ == 0) {
 		pr_debug("%s: holding wake lock\n", __func__);
-		pm_qos_update_request(&wcd9xxx->pm_qos_req,
+		pm_qos_update_request(&wcd9xxx_res->pm_qos_req,
 				      msm_cpuidle_get_deep_idle_latency());
 	}
-	mutex_unlock(&wcd9xxx->pm_lock);
-	if (!wait_event_timeout(wcd9xxx->pm_wq,
-			((os = wcd9xxx_pm_cmpxchg(wcd9xxx, WCD9XXX_PM_SLEEPABLE,
-						WCD9XXX_PM_AWAKE)) ==
-						    WCD9XXX_PM_SLEEPABLE ||
-			 (os == WCD9XXX_PM_AWAKE)),
+	mutex_unlock(&wcd9xxx_res->pm_lock);
+	os = wcd9xxx_pm_cmpxchg(wcd9xxx_res,
+					WCD9XXX_PM_SLEEPABLE,
+					WCD9XXX_PM_AWAKE);
+	if (!wait_event_timeout(wcd9xxx_res->pm_wq,
+			(os  == WCD9XXX_PM_SLEEPABLE ||
+			 os == WCD9XXX_PM_AWAKE),
 			msecs_to_jiffies(WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
 		pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
 			__func__,
-			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx->pm_state,
-			wcd9xxx->wlock_holders);
-		wcd9xxx_unlock_sleep(wcd9xxx);
+			WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state,
+			wcd9xxx_res->wlock_holders);
+		wcd9xxx_unlock_sleep(wcd9xxx_res);
 		return false;
 	}
-	wake_up_all(&wcd9xxx->pm_wq);
+	wake_up_all(&wcd9xxx_res->pm_wq);
 	return true;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_lock_sleep);
+EXPORT_SYMBOL(wcd9xxx_lock_sleep);
 
-void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx)
+void wcd9xxx_unlock_sleep(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
 {
-	mutex_lock(&wcd9xxx->pm_lock);
-	if (--wcd9xxx->wlock_holders == 0) {
+	mutex_lock(&wcd9xxx_res->pm_lock);
+	if (--wcd9xxx_res->wlock_holders == 0) {
 		pr_debug("%s: releasing wake lock pm_state %d -> %d\n",
-			 __func__, wcd9xxx->pm_state, WCD9XXX_PM_SLEEPABLE);
+			 __func__, wcd9xxx_res->pm_state, WCD9XXX_PM_SLEEPABLE);
 		/*
 		 * if wcd9xxx_lock_sleep failed, pm_state would be still
 		 * WCD9XXX_PM_ASLEEP, don't overwrite
 		 */
-		if (likely(wcd9xxx->pm_state == WCD9XXX_PM_AWAKE))
-			wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
-		pm_qos_update_request(&wcd9xxx->pm_qos_req,
+		if (likely(wcd9xxx_res->pm_state == WCD9XXX_PM_AWAKE))
+			wcd9xxx_res->pm_state = WCD9XXX_PM_SLEEPABLE;
+		pm_qos_update_request(&wcd9xxx_res->pm_qos_req,
 				PM_QOS_DEFAULT_VALUE);
 	}
-	mutex_unlock(&wcd9xxx->pm_lock);
-	wake_up_all(&wcd9xxx->pm_wq);
+	mutex_unlock(&wcd9xxx_res->pm_lock);
+	wake_up_all(&wcd9xxx_res->pm_wq);
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_unlock_sleep);
+EXPORT_SYMBOL(wcd9xxx_unlock_sleep);
 
-void wcd9xxx_nested_irq_lock(struct wcd9xxx *wcd9xxx)
+void wcd9xxx_nested_irq_lock(struct wcd9xxx_core_resource *wcd9xxx_res)
 {
-	mutex_lock(&wcd9xxx->nested_irq_lock);
+	mutex_lock(&wcd9xxx_res->nested_irq_lock);
 }
 
-void wcd9xxx_nested_irq_unlock(struct wcd9xxx *wcd9xxx)
+void wcd9xxx_nested_irq_unlock(struct wcd9xxx_core_resource *wcd9xxx_res)
 {
-	mutex_unlock(&wcd9xxx->nested_irq_lock);
+	mutex_unlock(&wcd9xxx_res->nested_irq_lock);
 }
 
-static bool wcd9xxx_is_mbhc_irq(struct wcd9xxx *wcd9xxx, int irqbit)
-{
-	if ((irqbit <= WCD9XXX_IRQ_MBHC_INSERTION) &&
-	    (irqbit >= WCD9XXX_IRQ_MBHC_REMOVAL))
-		return true;
-	else if (wcd9xxx->codec_type->id_major == TAIKO_MAJOR &&
-		 irqbit == WCD9320_IRQ_MBHC_JACK_SWITCH)
-		return true;
-	else if (wcd9xxx->codec_type->id_major == TAPAN_MAJOR &&
-		 irqbit == WCD9306_IRQ_MBHC_JACK_SWITCH)
-		return true;
-	else
-		return false;
-}
 
-static void wcd9xxx_irq_dispatch(struct wcd9xxx *wcd9xxx, int irqbit)
+static void wcd9xxx_irq_dispatch(struct wcd9xxx_core_resource *wcd9xxx_res,
+			struct intr_data *irqdata)
 {
-	if (wcd9xxx_is_mbhc_irq(wcd9xxx, irqbit)) {
-		wcd9xxx_nested_irq_lock(wcd9xxx);
-		wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_CLEAR0 +
-					   BIT_BYTE(irqbit),
-				  BYTE_BIT_MASK(irqbit));
-		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
-			wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MODE, 0x02);
-		handle_nested_irq(phyirq_to_virq(wcd9xxx, irqbit));
-		wcd9xxx_nested_irq_unlock(wcd9xxx);
-	} else {
-		wcd9xxx_nested_irq_lock(wcd9xxx);
-		handle_nested_irq(phyirq_to_virq(wcd9xxx, irqbit));
-		wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_CLEAR0 +
-					   BIT_BYTE(irqbit),
-				  BYTE_BIT_MASK(irqbit));
-		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
-			wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MODE, 0x02);
-		wcd9xxx_nested_irq_unlock(wcd9xxx);
+	int irqbit = irqdata->intr_num;
+	if (!wcd9xxx_res->codec_reg_write) {
+		pr_err("%s: codec read/write callback not defined\n",
+			   __func__);
+		return;
 	}
-}
 
-static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
-{
-	return (wcd9xxx->codec_type->num_irqs / 8) +
-		((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
+	if (irqdata->clear_first) {
+		wcd9xxx_nested_irq_lock(wcd9xxx_res);
+		wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+				WCD9XXX_A_INTR_CLEAR0 + BIT_BYTE(irqbit),
+				BYTE_BIT_MASK(irqbit));
+
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+						WCD9XXX_A_INTR_MODE, 0x02);
+		handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit));
+		wcd9xxx_nested_irq_unlock(wcd9xxx_res);
+	} else {
+		wcd9xxx_nested_irq_lock(wcd9xxx_res);
+		handle_nested_irq(phyirq_to_virq(wcd9xxx_res, irqbit));
+		wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+				WCD9XXX_A_INTR_CLEAR0 + BIT_BYTE(irqbit),
+				BYTE_BIT_MASK(irqbit));
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+						WCD9XXX_A_INTR_MODE, 0x02);
+
+		wcd9xxx_nested_irq_unlock(wcd9xxx_res);
+	}
 }
 
 static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
 {
 	int ret;
 	int i;
+	struct intr_data irqdata;
 	char linebuf[128];
-	struct wcd9xxx *wcd9xxx = data;
-	int num_irq_regs = wcd9xxx_num_irq_regs(wcd9xxx);
-	u8 status[num_irq_regs], status1[num_irq_regs];
 	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
+	struct wcd9xxx_core_resource *wcd9xxx_res = data;
+	int num_irq_regs = wcd9xxx_res->num_irq_regs;
+	u8 status[num_irq_regs], status1[num_irq_regs];
 
-	if (unlikely(wcd9xxx_lock_sleep(wcd9xxx) == false)) {
-		dev_err(wcd9xxx->dev, "Failed to hold suspend\n");
+	if (unlikely(wcd9xxx_lock_sleep(wcd9xxx_res) == false)) {
+		dev_err(wcd9xxx_res->dev, "Failed to hold suspend\n");
 		return IRQ_NONE;
 	}
-	ret = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_INTR_STATUS0,
+
+	if (!wcd9xxx_res->codec_bulk_read) {
+		dev_err(wcd9xxx_res->dev,
+				"%s: Codec Bulk Register read callback not supplied\n",
+			   __func__);
+		goto err_disable_irq;
+	}
+
+	ret = wcd9xxx_res->codec_bulk_read(wcd9xxx_res,
+				WCD9XXX_A_INTR_STATUS0,
 				num_irq_regs, status);
+
 	if (ret < 0) {
-		dev_err(wcd9xxx->dev, "Failed to read interrupt status: %d\n",
-			ret);
-		dev_err(wcd9xxx->dev, "Disable irq %d\n", wcd9xxx->irq);
-		disable_irq_wake(wcd9xxx->irq);
-		disable_irq_nosync(wcd9xxx->irq);
-		wcd9xxx_unlock_sleep(wcd9xxx);
-		return IRQ_NONE;
+		dev_err(wcd9xxx_res->dev,
+				"Failed to read interrupt status: %d\n", ret);
+		goto err_disable_irq;
 	}
 
 	/* Apply masking */
 	for (i = 0; i < num_irq_regs; i++)
-		status[i] &= ~wcd9xxx->irq_masks_cur[i];
+		status[i] &= ~wcd9xxx_res->irq_masks_cur[i];
 
 	memcpy(status1, status, sizeof(status1));
 
 	/* Find out which interrupt was triggered and call that interrupt's
 	 * handler function
-	 */
-	if (status[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &
-	    BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS)) {
-		wcd9xxx_irq_dispatch(wcd9xxx, WCD9XXX_IRQ_SLIMBUS);
-		status1[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &=
-		    ~BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS);
-	}
-
-	/* Since codec has only one hardware irq line which is shared by
+	 *
+	 * Since codec has only one hardware irq line which is shared by
 	 * codec's different internal interrupts, so it's possible master irq
 	 * handler dispatches multiple nested irq handlers after breaking
-	 * order.  Dispatch MBHC interrupts order to follow MBHC state
-	 * machine's order */
-	for (i = WCD9XXX_IRQ_MBHC_INSERTION;
-	     i >= WCD9XXX_IRQ_MBHC_REMOVAL; i--) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
-			wcd9xxx_irq_dispatch(wcd9xxx, i);
-			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
-		}
-	}
-	for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->codec_type->num_irqs;
-	     i++) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
-			wcd9xxx_irq_dispatch(wcd9xxx, i);
-			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
+	 * order.  Dispatch interrupts in the order that is maintained by
+	 * the interrupt table.
+	 */
+	for (i = 0; i < wcd9xxx_res->intr_table_size; i++) {
+		irqdata = wcd9xxx_res->intr_table[i];
+		if (status[BIT_BYTE(irqdata.intr_num)] &
+			BYTE_BIT_MASK(irqdata.intr_num)) {
+			wcd9xxx_irq_dispatch(wcd9xxx_res, &irqdata);
+			status1[BIT_BYTE(irqdata.intr_num)] &=
+					~BYTE_BIT_MASK(irqdata.intr_num);
 		}
 	}
 
@@ -319,45 +314,58 @@
 		}
 
 		memset(status, 0xff, num_irq_regs);
-		wcd9xxx_bulk_write(wcd9xxx, WCD9XXX_A_INTR_CLEAR0,
+		wcd9xxx_bulk_write(wcd9xxx_res, WCD9XXX_A_INTR_CLEAR0,
 				   num_irq_regs, status);
 		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
-			wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MODE, 0x02);
+			wcd9xxx_reg_write(wcd9xxx_res,
+					WCD9XXX_A_INTR_MODE, 0x02);
 	}
-	wcd9xxx_unlock_sleep(wcd9xxx);
+	wcd9xxx_unlock_sleep(wcd9xxx_res);
 
 	return IRQ_HANDLED;
+
+err_disable_irq:
+		dev_err(wcd9xxx_res->dev,
+				"Disable irq %d\n", wcd9xxx_res->irq);
+
+		disable_irq_wake(wcd9xxx_res->irq);
+		disable_irq_nosync(wcd9xxx_res->irq);
+		wcd9xxx_unlock_sleep(wcd9xxx_res);
+		return IRQ_NONE;
 }
 
-void wcd9xxx_free_irq(struct wcd9xxx *wcd9xxx, int irq, void *data)
+void wcd9xxx_free_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq, void *data)
 {
-	free_irq(phyirq_to_virq(wcd9xxx, irq), data);
+	free_irq(phyirq_to_virq(wcd9xxx_res, irq), data);
 }
 
-void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq)
+void wcd9xxx_enable_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
 {
-	enable_irq(phyirq_to_virq(wcd9xxx, irq));
+	enable_irq(phyirq_to_virq(wcd9xxx_res, irq));
 }
 
-void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq)
+void wcd9xxx_disable_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
 {
-	disable_irq_nosync(phyirq_to_virq(wcd9xxx, irq));
+	disable_irq_nosync(phyirq_to_virq(wcd9xxx_res, irq));
 }
 
-void wcd9xxx_disable_irq_sync(struct wcd9xxx *wcd9xxx, int irq)
+void wcd9xxx_disable_irq_sync(
+			struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
 {
-	disable_irq(phyirq_to_virq(wcd9xxx, irq));
+	disable_irq(phyirq_to_virq(wcd9xxx_res, irq));
 }
 
-static int wcd9xxx_irq_setup_downstream_irq(struct wcd9xxx *wcd9xxx)
+static int wcd9xxx_irq_setup_downstream_irq(
+			struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	int irq, virq, ret;
 
 	pr_debug("%s: enter\n", __func__);
 
-	for (irq = 0; irq < wcd9xxx->codec_type->num_irqs; irq++) {
+	for (irq = 0; irq < wcd9xxx_res->num_irqs; irq++) {
 		/* Map OF irq */
-		virq = wcd9xxx_map_irq(wcd9xxx, irq);
+		virq = wcd9xxx_map_irq(wcd9xxx_res, irq);
 		pr_debug("%s: irq %d -> %d\n", __func__, irq, virq);
 		if (virq == NO_IRQ) {
 			pr_err("%s, No interrupt specifier for irq %d\n",
@@ -365,14 +373,14 @@
 			return NO_IRQ;
 		}
 
-		ret = irq_set_chip_data(virq, wcd9xxx);
+		ret = irq_set_chip_data(virq, wcd9xxx_res);
 		if (ret) {
 			pr_err("%s: Failed to configure irq %d (%d)\n",
 			       __func__, irq, ret);
 			return ret;
 		}
 
-		if (wcd9xxx->irq_level_high[irq])
+		if (wcd9xxx_res->irq_level_high[irq])
 			irq_set_chip_and_handler(virq, &wcd9xxx_irq_chip,
 						 handle_level_irq);
 		else
@@ -387,84 +395,100 @@
 	return 0;
 }
 
-int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx)
+int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	int i, ret;
-	u8 irq_level[wcd9xxx_num_irq_regs(wcd9xxx)];
+	u8 irq_level[wcd9xxx_res->num_irq_regs];
 
-	mutex_init(&wcd9xxx->irq_lock);
-	mutex_init(&wcd9xxx->nested_irq_lock);
+	mutex_init(&wcd9xxx_res->irq_lock);
+	mutex_init(&wcd9xxx_res->nested_irq_lock);
 
-	wcd9xxx->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx);
-	if (!wcd9xxx->irq) {
+	wcd9xxx_res->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx_res);
+	if (!wcd9xxx_res->irq) {
 		pr_warn("%s: irq driver is not yet initialized\n", __func__);
-		mutex_destroy(&wcd9xxx->irq_lock);
-		mutex_destroy(&wcd9xxx->nested_irq_lock);
+		mutex_destroy(&wcd9xxx_res->irq_lock);
+		mutex_destroy(&wcd9xxx_res->nested_irq_lock);
 		return -EPROBE_DEFER;
 	}
-	pr_debug("%s: probed irq %d\n", __func__, wcd9xxx->irq);
+	pr_debug("%s: probed irq %d\n", __func__, wcd9xxx_res->irq);
 
 	/* Setup downstream IRQs */
-	ret = wcd9xxx_irq_setup_downstream_irq(wcd9xxx);
+	ret = wcd9xxx_irq_setup_downstream_irq(wcd9xxx_res);
 	if (ret) {
 		pr_err("%s: Failed to setup downstream IRQ\n", __func__);
-		wcd9xxx_irq_put_upstream_irq(wcd9xxx);
-		mutex_destroy(&wcd9xxx->irq_lock);
-		mutex_destroy(&wcd9xxx->nested_irq_lock);
+		wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
+		mutex_destroy(&wcd9xxx_res->irq_lock);
+		mutex_destroy(&wcd9xxx_res->nested_irq_lock);
 		return ret;
 	}
 
 	/* All other wcd9xxx interrupts are edge triggered */
-	wcd9xxx->irq_level_high[0] = true;
+	wcd9xxx_res->irq_level_high[0] = true;
 
 	/* mask all the interrupts */
-	memset(irq_level, 0, wcd9xxx_num_irq_regs(wcd9xxx));
-	for (i = 0; i < wcd9xxx->codec_type->num_irqs; i++) {
-		wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
-		wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+	memset(irq_level, 0, wcd9xxx_res->num_irq_regs);
+	for (i = 0; i < wcd9xxx_res->num_irqs; i++) {
+		wcd9xxx_res->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+		wcd9xxx_res->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
 		irq_level[BIT_BYTE(i)] |=
-		    wcd9xxx->irq_level_high[i] << (i % BITS_PER_BYTE);
+		    wcd9xxx_res->irq_level_high[i] << (i % BITS_PER_BYTE);
 	}
 
-	for (i = 0; i < wcd9xxx_num_irq_regs(wcd9xxx); i++) {
+	if (!wcd9xxx_res->codec_reg_write) {
+		dev_err(wcd9xxx_res->dev,
+				"%s: Codec Register write callback not defined\n",
+			   __func__);
+		ret = -EINVAL;
+		goto fail_irq_init;
+	}
+
+	for (i = 0; i < wcd9xxx_res->num_irq_regs; i++) {
 		/* Initialize interrupt mask and level registers */
-		wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_LEVEL0 + i,
-				  irq_level[i]);
-		wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MASK0 + i,
-				  wcd9xxx->irq_masks_cur[i]);
+		wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+					WCD9XXX_A_INTR_LEVEL0 + i,
+					irq_level[i]);
+		wcd9xxx_res->codec_reg_write(wcd9xxx_res,
+					WCD9XXX_A_INTR_MASK0 + i,
+					wcd9xxx_res->irq_masks_cur[i]);
 	}
 
-	ret = request_threaded_irq(wcd9xxx->irq, NULL, wcd9xxx_irq_thread,
+	ret = request_threaded_irq(wcd9xxx_res->irq, NULL, wcd9xxx_irq_thread,
 				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-				   "wcd9xxx", wcd9xxx);
+				   "wcd9xxx", wcd9xxx_res);
 	if (ret != 0)
-		dev_err(wcd9xxx->dev, "Failed to request IRQ %d: %d\n",
-			wcd9xxx->irq, ret);
+		dev_err(wcd9xxx_res->dev, "Failed to request IRQ %d: %d\n",
+			wcd9xxx_res->irq, ret);
 	else {
-		ret = enable_irq_wake(wcd9xxx->irq);
+		ret = enable_irq_wake(wcd9xxx_res->irq);
 		if (ret)
-			dev_err(wcd9xxx->dev, "Failed to set wake interrupt on"
-				" IRQ %d: %d\n", wcd9xxx->irq, ret);
+			dev_err(wcd9xxx_res->dev,
+				"Failed to set wake interrupt on IRQ %d: %d\n",
+				wcd9xxx_res->irq, ret);
 		if (ret)
-			free_irq(wcd9xxx->irq, wcd9xxx);
+			free_irq(wcd9xxx_res->irq, wcd9xxx_res);
 	}
 
-	if (ret) {
-		pr_err("%s: Failed to init wcd9xxx irq\n", __func__);
-		wcd9xxx_irq_put_upstream_irq(wcd9xxx);
-		mutex_destroy(&wcd9xxx->irq_lock);
-		mutex_destroy(&wcd9xxx->nested_irq_lock);
-	}
+	if (ret)
+		goto fail_irq_init;
 
 	return ret;
+
+fail_irq_init:
+	dev_err(wcd9xxx_res->dev,
+			"%s: Failed to init wcd9xxx irq\n", __func__);
+	wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
+	mutex_destroy(&wcd9xxx_res->irq_lock);
+	mutex_destroy(&wcd9xxx_res->nested_irq_lock);
+	return ret;
 }
 
-int wcd9xxx_request_irq(struct wcd9xxx *wcd9xxx, int irq, irq_handler_t handler,
+int wcd9xxx_request_irq(struct wcd9xxx_core_resource *wcd9xxx_res,
+			int irq, irq_handler_t handler,
 			const char *name, void *data)
 {
 	int virq;
 
-	virq = phyirq_to_virq(wcd9xxx, irq);
+	virq = phyirq_to_virq(wcd9xxx_res, irq);
 
 	/*
 	 * ARM needs us to explicitly flag the IRQ as valid
@@ -480,44 +504,52 @@
 				    name, data);
 }
 
-void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx)
+void wcd9xxx_irq_exit(struct wcd9xxx_core_resource *wcd9xxx_res)
 {
-	dev_dbg(wcd9xxx->dev, "%s: Cleaning up irq %d\n", __func__,
-		wcd9xxx->irq);
-	if (wcd9xxx->irq) {
-		disable_irq_wake(wcd9xxx->irq);
-		free_irq(wcd9xxx->irq, wcd9xxx);
+	dev_dbg(wcd9xxx_res->dev, "%s: Cleaning up irq %d\n", __func__,
+		wcd9xxx_res->irq);
+
+	if (wcd9xxx_res->irq) {
+		disable_irq_wake(wcd9xxx_res->irq);
+		free_irq(wcd9xxx_res->irq, wcd9xxx_res);
 		/* Release parent's of node */
-		wcd9xxx_irq_put_upstream_irq(wcd9xxx);
+		wcd9xxx_irq_put_upstream_irq(wcd9xxx_res);
 	}
-	mutex_destroy(&wcd9xxx->irq_lock);
-	mutex_destroy(&wcd9xxx->nested_irq_lock);
+	mutex_destroy(&wcd9xxx_res->irq_lock);
+	mutex_destroy(&wcd9xxx_res->nested_irq_lock);
 }
 
 #ifndef CONFIG_OF
-static int phyirq_to_virq(struct wcd9xxx *wcd9xxx, int offset)
+static int phyirq_to_virq(
+	struct wcd9xxx_core_resource *wcd9xxx_res,
+	int offset)
 {
-	return wcd9xxx->irq_base + offset;
+	return wcd9xxx_res->irq_base + offset;
 }
 
-static int virq_to_phyirq(struct wcd9xxx *wcd9xxx, int virq)
+static int virq_to_phyirq(
+	struct wcd9xxx_core_resource *wcd9xxx_res,
+	int virq)
 {
-	return virq - wcd9xxx->irq_base;
+	return virq - wcd9xxx_res->irq_base;
 }
 
-static unsigned int wcd9xxx_irq_get_upstream_irq(struct wcd9xxx *wcd9xxx)
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
 {
-	return wcd9xxx->irq;
+	return wcd9xxx_res->irq;
 }
 
-static void wcd9xxx_irq_put_upstream_irq(struct wcd9xxx *wcd9xxx)
+static void wcd9xxx_irq_put_upstream_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	/* Do nothing */
 }
 
-static int wcd9xxx_map_irq(struct wcd9xxx *wcd9xxx, int irq)
+static int wcd9xxx_map_irq(
+	struct wcd9xxx_core_resource *wcd9xxx_core_res, int irq)
 {
-	return phyirq_to_virq(wcd9xxx, irq);
+	return phyirq_to_virq(wcd9xxx_core_res, irq);
 }
 #else
 int __init wcd9xxx_irq_of_init(struct device_node *node,
@@ -549,12 +581,12 @@
 }
 
 static struct wcd9xxx_irq_drv_data *
-wcd9xxx_get_irq_drv_d(const struct wcd9xxx *wcd9xxx)
+wcd9xxx_get_irq_drv_d(const struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	struct device_node *pnode;
 	struct irq_domain *domain;
 
-	pnode = of_irq_find_parent(wcd9xxx->dev->of_node);
+	pnode = of_irq_find_parent(wcd9xxx_res->dev->of_node);
 	/* Shouldn't happen */
 	if (unlikely(!pnode))
 		return NULL;
@@ -563,11 +595,11 @@
 	return (struct wcd9xxx_irq_drv_data *)domain->host_data;
 }
 
-static int phyirq_to_virq(struct wcd9xxx *wcd9xxx, int offset)
+static int phyirq_to_virq(struct wcd9xxx_core_resource *wcd9xxx_res, int offset)
 {
 	struct wcd9xxx_irq_drv_data *data;
 
-	data = wcd9xxx_get_irq_drv_d(wcd9xxx);
+	data = wcd9xxx_get_irq_drv_d(wcd9xxx_res);
 	if (!data) {
 		pr_warn("%s: not registered to interrupt controller\n",
 			__func__);
@@ -576,21 +608,22 @@
 	return irq_linear_revmap(data->domain, offset);
 }
 
-static int virq_to_phyirq(struct wcd9xxx *wcd9xxx, int virq)
+static int virq_to_phyirq(struct wcd9xxx_core_resource *wcd9xxx_res, int virq)
 {
 	struct irq_data *irq_data = irq_get_irq_data(virq);
 	return irq_data->hwirq;
 }
 
-static unsigned int wcd9xxx_irq_get_upstream_irq(struct wcd9xxx *wcd9xxx)
+static unsigned int wcd9xxx_irq_get_upstream_irq(
+				struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	struct wcd9xxx_irq_drv_data *data;
 
 	/* Hold parent's of node */
-	if (!of_node_get(of_irq_find_parent(wcd9xxx->dev->of_node)))
+	if (!of_node_get(of_irq_find_parent(wcd9xxx_res->dev->of_node)))
 		return -EINVAL;
 
-	data = wcd9xxx_get_irq_drv_d(wcd9xxx);
+	data = wcd9xxx_get_irq_drv_d(wcd9xxx_res);
 	if (!data) {
 		pr_err("%s: interrupt controller is not registerd\n", __func__);
 		return 0;
@@ -600,15 +633,16 @@
 	return data->irq;
 }
 
-static void wcd9xxx_irq_put_upstream_irq(struct wcd9xxx *wcd9xxx)
+static void wcd9xxx_irq_put_upstream_irq(
+			struct wcd9xxx_core_resource *wcd9xxx_res)
 {
 	/* Hold parent's of node */
-	of_node_put(of_irq_find_parent(wcd9xxx->dev->of_node));
+	of_node_put(of_irq_find_parent(wcd9xxx_res->dev->of_node));
 }
 
-static int wcd9xxx_map_irq(struct wcd9xxx *wcd9xxx, int irq)
+static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq)
 {
-	return of_irq_to_resource(wcd9xxx->dev->of_node, irq, NULL);
+	return of_irq_to_resource(wcd9xxx_res->dev->of_node, irq, NULL);
 }
 
 static int __devinit wcd9xxx_irq_probe(struct platform_device *pdev)
diff --git a/include/linux/mfd/wcd9xxx/core-resource.h b/include/linux/mfd/wcd9xxx/core-resource.h
new file mode 100644
index 0000000..442496e
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/core-resource.h
@@ -0,0 +1,137 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_CORE_RESOURCE_H__
+#define __MFD_CORE_RESOURCE_H__
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pm_qos.h>
+
+#define WCD9XXX_MAX_IRQ_REGS 4
+#define WCD9XXX_MAX_NUM_IRQS (WCD9XXX_MAX_IRQ_REGS * 8)
+
+struct intr_data {
+	int intr_num;
+	bool clear_first;
+};
+
+enum wcd9xxx_pm_state {
+	WCD9XXX_PM_SLEEPABLE,
+	WCD9XXX_PM_AWAKE,
+	WCD9XXX_PM_ASLEEP,
+};
+
+enum wcd9xxx_intf_status {
+	WCD9XXX_INTERFACE_TYPE_PROBING,
+	WCD9XXX_INTERFACE_TYPE_SLIMBUS,
+	WCD9XXX_INTERFACE_TYPE_I2C,
+};
+
+struct wcd9xxx_core_resource {
+	struct mutex irq_lock;
+	struct mutex nested_irq_lock;
+
+	enum wcd9xxx_pm_state pm_state;
+	struct mutex pm_lock;
+	/* pm_wq notifies change of pm_state */
+	wait_queue_head_t pm_wq;
+	struct pm_qos_request pm_qos_req;
+	int wlock_holders;
+
+
+	/* holds the table of interrupts per codec */
+	const struct intr_data *intr_table;
+	int intr_table_size;
+	unsigned int irq_base;
+	unsigned int irq;
+	u8 irq_masks_cur[WCD9XXX_MAX_IRQ_REGS];
+	u8 irq_masks_cache[WCD9XXX_MAX_IRQ_REGS];
+	bool irq_level_high[WCD9XXX_MAX_NUM_IRQS];
+	int num_irqs;
+	int num_irq_regs;
+
+	/* Callback functions to read/write codec registers */
+	int (*codec_reg_read) (struct wcd9xxx_core_resource *,
+				unsigned short);
+	int (*codec_reg_write) (struct wcd9xxx_core_resource *,
+				unsigned short, u8);
+	int (*codec_bulk_read) (struct wcd9xxx_core_resource *,
+				unsigned short, int, u8 *);
+
+	/* Pointer to parent container data structure */
+	void *parent;
+
+	struct device *dev;
+};
+
+extern int wcd9xxx_core_res_init(
+	struct wcd9xxx_core_resource*,
+	int, int,
+	int (*codec_read)(struct wcd9xxx_core_resource *, unsigned short),
+	int (*codec_write)(struct wcd9xxx_core_resource *, unsigned short, u8),
+	int (*codec_bulk_read) (struct wcd9xxx_core_resource *, unsigned short,
+							int, u8 *));
+
+extern void wcd9xxx_core_res_deinit(
+	struct wcd9xxx_core_resource *);
+
+extern int wcd9xxx_core_res_suspend(
+	struct wcd9xxx_core_resource *,
+	pm_message_t);
+
+extern int wcd9xxx_core_res_resume(
+	struct wcd9xxx_core_resource *);
+
+extern int wcd9xxx_core_irq_init(
+	struct wcd9xxx_core_resource*);
+
+extern int wcd9xxx_initialize_irq(
+	struct wcd9xxx_core_resource*,
+	unsigned int,
+	unsigned int);
+
+enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void);
+void wcd9xxx_set_intf_type(enum wcd9xxx_intf_status);
+
+bool wcd9xxx_lock_sleep(struct wcd9xxx_core_resource *);
+void wcd9xxx_unlock_sleep(struct wcd9xxx_core_resource *);
+void wcd9xxx_nested_irq_lock(struct wcd9xxx_core_resource *);
+void wcd9xxx_nested_irq_unlock(struct wcd9xxx_core_resource *);
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(
+			struct wcd9xxx_core_resource *,
+			enum wcd9xxx_pm_state,
+			enum wcd9xxx_pm_state);
+
+int wcd9xxx_request_irq(struct wcd9xxx_core_resource *, int,
+			irq_handler_t, const char *, void *);
+
+void wcd9xxx_free_irq(struct wcd9xxx_core_resource *, int, void*);
+void wcd9xxx_enable_irq(struct wcd9xxx_core_resource *, int);
+void wcd9xxx_disable_irq(struct wcd9xxx_core_resource *, int);
+void wcd9xxx_disable_irq_sync(struct wcd9xxx_core_resource *, int);
+int wcd9xxx_reg_read(struct wcd9xxx_core_resource *,
+					 unsigned short);
+int wcd9xxx_reg_write(struct wcd9xxx_core_resource *,
+					  unsigned short, u8);
+int wcd9xxx_bulk_read(struct wcd9xxx_core_resource *,
+					unsigned short, int, u8 *);
+int wcd9xxx_bulk_write(struct wcd9xxx_core_resource*,
+					 unsigned short, int, u8*);
+int wcd9xxx_irq_init(struct wcd9xxx_core_resource *);
+void wcd9xxx_irq_exit(struct wcd9xxx_core_resource *);
+int wcd9xxx_core_res_resume(
+	struct wcd9xxx_core_resource *);
+int wcd9xxx_core_res_suspend(
+	struct wcd9xxx_core_resource *,
+	pm_message_t);
+#endif
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index eefb3dc..c2ad2b4 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -14,12 +14,10 @@
 #define __MFD_TABLA_CORE_H__
 
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/pm_qos.h>
 #include <linux/platform_device.h>
 #include <linux/of_irq.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
 
-#define WCD9XXX_NUM_IRQ_REGS 4
 
 #define WCD9XXX_SLIM_NUM_PORT_REG 3
 #define TABLA_VERSION_1_0	0
@@ -90,6 +88,7 @@
 	WCD9XXX_IRQ_VBAT_MONITOR_ATTACK,
 	WCD9XXX_IRQ_VBAT_MONITOR_RELEASE,
 	WCD9XXX_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_2 = WCD9XXX_NUM_IRQS,
 };
 
 enum {
@@ -99,17 +98,6 @@
 	TAPAN_NUM_IRQS = WCD9XXX_NUM_IRQS,
 };
 
-
-#define MAX(X, Y) (((int)X) >= ((int)Y) ? (X) : (Y))
-#define WCD9XXX_MAX_NUM_IRQS (MAX(MAX(TABLA_NUM_IRQS, SITAR_NUM_IRQS), \
-				  TAIKO_NUM_IRQS))
-
-enum wcd9xxx_pm_state {
-	WCD9XXX_PM_SLEEPABLE,
-	WCD9XXX_PM_AWAKE,
-	WCD9XXX_PM_ASLEEP,
-};
-
 /*
  * data structure for Slimbus and I2S channel.
  * Some of fields are only used in smilbus mode
@@ -145,12 +133,6 @@
 	wait_queue_head_t dai_wait;
 };
 
-enum wcd9xxx_intf_status {
-	WCD9XXX_INTERFACE_TYPE_PROBING,
-	WCD9XXX_INTERFACE_TYPE_SLIMBUS,
-	WCD9XXX_INTERFACE_TYPE_I2C,
-};
-
 #define WCD9XXX_CH(xport, xshift) \
 	{.port = xport, .shift = xshift}
 
@@ -178,8 +160,6 @@
 	struct slim_device *slim_slave;
 	struct mutex io_lock;
 	struct mutex xfer_lock;
-	struct mutex irq_lock;
-	struct mutex nested_irq_lock;
 	u8 version;
 
 	int reset_gpio;
@@ -197,21 +177,11 @@
 	u32 num_of_supplies;
 	struct regulator_bulk_data *supplies;
 
-	enum wcd9xxx_pm_state pm_state;
-	struct mutex pm_lock;
-	/* pm_wq notifies change of pm_state */
-	wait_queue_head_t pm_wq;
-	struct pm_qos_request pm_qos_req;
-	int wlock_holders;
+	struct wcd9xxx_core_resource core_res;
 
 	u16 id_minor;
 	u16 id_major;
 
-	unsigned int irq_base;
-	unsigned int irq;
-	u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS];
-	u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS];
-	bool irq_level_high[WCD9XXX_MAX_NUM_IRQS];
 	/* Slimbus or I2S port */
 	u32 num_rx_port;
 	u32 num_tx_port;
@@ -222,36 +192,11 @@
 	const struct wcd9xxx_codec_type *codec_type;
 };
 
-int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
-int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
-		u8 val);
 int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
 int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
 		u8 val);
-int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
-			int count, u8 *buf);
-int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
-			int count, u8 *buf);
-int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx);
-void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx);
 int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
-enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void);
 
-bool wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx);
-void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx);
-void wcd9xxx_nested_irq_lock(struct wcd9xxx *wcd9xxx);
-void wcd9xxx_nested_irq_unlock(struct wcd9xxx *wcd9xxx);
-enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
-				enum wcd9xxx_pm_state o,
-				enum wcd9xxx_pm_state n);
-
-int wcd9xxx_request_irq(struct wcd9xxx *wcd9xxx, int irq,
-			irq_handler_t handler, const char *name, void *data);
-
-void wcd9xxx_free_irq(struct wcd9xxx *wcd9xxx, int irq, void *data);
-void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq);
-void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq);
-void wcd9xxx_disable_irq_sync(struct wcd9xxx *wcd9xxx, int irq);
 #if defined(CONFIG_WCD9310_CODEC) || \
 	defined(CONFIG_WCD9304_CODEC) || \
 	defined(CONFIG_WCD9320_CODEC) || \
@@ -272,9 +217,9 @@
 	u8 reg_val;
 
 	if (core) {
-		reg_val = wcd9xxx_reg_read(core, reg);
+		reg_val = wcd9xxx_reg_read(&core->core_res, reg);
 		reg_val = (reg_val & ~mask) | (val & mask);
-		wcd9xxx_reg_write(core, reg, reg_val);
+		wcd9xxx_reg_write(&core->core_res, reg, reg_val);
 	}
 }
 #endif
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 58ea22d..a68722c 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -3961,8 +3961,10 @@
 {
 	short bias_value;
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	if (noreldetection)
 		sitar_turn_onoff_rel_detection(codec, false);
 
@@ -4103,11 +4105,12 @@
 {
 	int r = 0;
 	struct wcd9xxx *core = dev_get_drvdata(sitar->codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
 	if (cancel_delayed_work_sync(&sitar->mbhc_btn_dwork)) {
 		/* if scheduled mbhc_btn_dwork is canceled from here,
 		 * we have to unlock from here instead btn_work */
-		wcd9xxx_unlock_sleep(core);
+		wcd9xxx_unlock_sleep(core_res);
 		r = 1;
 	}
 	return r;
@@ -4171,12 +4174,14 @@
 	short bias_value;
 	int dce_mv, sta_mv;
 	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	pr_debug("%s:\n", __func__);
 
 	delayed_work = to_delayed_work(work);
 	sitar = container_of(delayed_work, struct sitar_priv, mbhc_btn_dwork);
 	core = dev_get_drvdata(sitar->codec->dev->parent);
+	core_res = &core->core_res;
 
 	if (sitar) {
 		if (sitar->mbhc_cfg.button_jack) {
@@ -4198,7 +4203,7 @@
 	}
 
 	pr_debug("%s: leave\n", __func__);
-	wcd9xxx_unlock_sleep(core);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 
@@ -4212,11 +4217,13 @@
 	u32 dce_wait, sta_wait;
 	u8 *n_cic;
 	void *calibration;
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
 	sitar = snd_soc_codec_get_drvdata(codec);
 	calibration = sitar->mbhc_cfg.calibration;
 
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	sitar_turn_onoff_rel_detection(codec, false);
 
 	/* First compute the DCE / STA wait times
@@ -4707,22 +4714,28 @@
 /* should be called under interrupt context that hold suspend */
 static void sitar_schedule_hs_detect_plug(struct sitar_priv *sitar)
 {
+	struct wcd9xxx *core = sitar->codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
+
 	pr_debug("%s: scheduling sitar_hs_correct_gpio_plug\n", __func__);
 	sitar->hs_detect_work_stop = false;
-	wcd9xxx_lock_sleep(sitar->codec->control_data);
+	wcd9xxx_lock_sleep(core_res);
 	schedule_work(&sitar->hs_correct_plug_work);
 }
 
 /* called under codec_resource_lock acquisition */
 static void sitar_cancel_hs_detect_plug(struct sitar_priv *sitar)
 {
+	struct wcd9xxx *core = sitar->codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
+
 	pr_debug("%s: canceling hs_correct_plug_work\n", __func__);
 	sitar->hs_detect_work_stop = true;
 	wmb();
 	SITAR_RELEASE_LOCK(sitar->codec_resource_lock);
 	if (cancel_work_sync(&sitar->hs_correct_plug_work)) {
 		pr_debug("%s: hs_correct_plug_work is canceled\n", __func__);
-		wcd9xxx_unlock_sleep(sitar->codec->control_data);
+		wcd9xxx_unlock_sleep(core_res);
 	}
 	SITAR_ACQUIRE_LOCK(sitar->codec_resource_lock);
 }
@@ -4737,9 +4750,13 @@
 	short mb_v[MBHC_NUM_DCE_PLUG_DETECT];
 	enum sitar_mbhc_plug_type plug_type[MBHC_NUM_DCE_PLUG_DETECT];
 	unsigned long timeout;
+	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	sitar = container_of(work, struct sitar_priv, hs_correct_plug_work);
 	codec = sitar->codec;
+	core = sitar->codec->control_data;
+	core_res = &core->core_res;
 
 	pr_debug("%s: enter\n", __func__);
 	sitar->mbhc_cfg.mclk_cb_fn(codec, 1, false);
@@ -4815,7 +4832,7 @@
 	sitar->mbhc_cfg.mclk_cb_fn(codec, 0, false);
 	pr_debug("%s: leave\n", __func__);
 	/* unlock sleep */
-	wcd9xxx_unlock_sleep(sitar->codec->control_data);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 /* called under codec_resource_lock acquisition */
@@ -4966,8 +4983,10 @@
 {
 	int r = IRQ_HANDLED;
 	struct snd_soc_codec *codec = data;
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
-	if (unlikely(wcd9xxx_lock_sleep(codec->control_data) == false)) {
+	if (unlikely(wcd9xxx_lock_sleep(core_res) == false)) {
 		pr_warn("%s(): Failed to hold suspend\n", __func__);
 		r = IRQ_NONE;
 	} else {
@@ -5181,6 +5200,7 @@
 	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
 	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 	int n_btn_meas = d->n_btn_meas;
 	u8 mbhc_status = snd_soc_read(codec, SITAR_A_CDC_MBHC_B1_STATUS) & 0x3E;
 
@@ -5271,12 +5291,12 @@
 		}
 		mask = sitar_get_button_mask(btn);
 		priv->buttons_pressed |= mask;
-		wcd9xxx_lock_sleep(core);
+		wcd9xxx_lock_sleep(core_res);
 		if (schedule_delayed_work(&priv->mbhc_btn_dwork,
 					  msecs_to_jiffies(400)) == 0) {
 			WARN(1, "Button pressed twice without release"
 			     "event\n");
-			wcd9xxx_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core_res);
 		}
 	} else {
 		pr_debug("%s: bogus button press, too short press?\n",
@@ -5386,11 +5406,16 @@
 {
 	struct sitar_priv *sitar = data;
 	struct snd_soc_codec *codec;
+	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	pr_info("%s: received HPHL OCP irq\n", __func__);
 
 	if (sitar) {
 		codec = sitar->codec;
+		core = codec->control_data;
+		core_res = &core->core_res;
+
 		if ((sitar->hphlocp_cnt < SITAR_OCP_ATTEMPT) &&
 		    (!sitar->hphrocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
@@ -5400,7 +5425,7 @@
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
 					    0x10);
 		} else {
-			wcd9xxx_disable_irq(codec->control_data,
+			wcd9xxx_disable_irq(core_res,
 					    WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 			sitar->hph_status |= SND_JACK_OC_HPHL;
 			if (sitar->mbhc_cfg.headset_jack)
@@ -5420,11 +5445,16 @@
 {
 	struct sitar_priv *sitar = data;
 	struct snd_soc_codec *codec;
+	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	pr_info("%s: received HPHR OCP irq\n", __func__);
 
 	if (sitar) {
 		codec = sitar->codec;
+		core = codec->control_data;
+		core_res = &core->core_res;
+
 		if ((sitar->hphrocp_cnt < SITAR_OCP_ATTEMPT) &&
 		    (!sitar->hphlocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
@@ -5434,7 +5464,7 @@
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
 					   0x10);
 		} else {
-			wcd9xxx_disable_irq(codec->control_data,
+			wcd9xxx_disable_irq(core_res,
 					    WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 			sitar->hph_status |= SND_JACK_OC_HPHR;
 			if (sitar->mbhc_cfg.headset_jack)
@@ -5454,10 +5484,12 @@
 {
 	struct sitar_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
 	pr_debug("%s: enter\n", __func__);
 	SITAR_ACQUIRE_LOCK(priv->codec_resource_lock);
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
 
@@ -5847,9 +5879,11 @@
 	int i;
 	u8 sitar_version;
 	void *ptr = NULL;
+	struct wcd9xxx_core_resource *core_res;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	core = codec->control_data;
+	core_res = &core->core_res;
 
 	sitar = kzalloc(sizeof(struct sitar_priv), GFP_KERNEL);
 	if (!sitar) {
@@ -5951,7 +5985,7 @@
 	snd_soc_dapm_sync(dapm);
 
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_INSERTION,
 		sitar_hs_insert_irq, "Headset insert detect", sitar);
 	if (ret) {
@@ -5959,9 +5993,9 @@
 		       WCD9XXX_IRQ_MBHC_INSERTION);
 		goto err_insert_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_REMOVAL,
 		sitar_hs_remove_irq, "Headset remove detect", sitar);
 	if (ret) {
@@ -5970,7 +6004,7 @@
 		goto err_remove_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_POTENTIAL,
 		sitar_dce_handler, "DC Estimation detect", sitar);
 	if (ret) {
@@ -5979,7 +6013,7 @@
 		goto err_potential_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_RELEASE,
 				  sitar_release_handler,
 				  "Button Release detect", sitar);
@@ -5989,7 +6023,7 @@
 		goto err_release_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
 				  sitar_slimbus_irq, "SLIMBUS Slave", sitar);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
@@ -6002,7 +6036,7 @@
 			SITAR_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
 
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
 				  sitar_hphl_ocp_irq,
 				  "HPH_L OCP detect", sitar);
@@ -6011,10 +6045,10 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 		goto err_hphl_ocp_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data,
+	wcd9xxx_disable_irq(core_res,
 			    WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
 				  sitar_hphr_ocp_irq, "HPH_R OCP detect",
 				  sitar);
@@ -6023,7 +6057,7 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 		goto err_hphr_ocp_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 
 	codec->ignore_pmdown_time = 1;
 
@@ -6034,19 +6068,19 @@
 	return ret;
 
 err_hphr_ocp_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
 			 sitar);
 err_hphl_ocp_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, sitar);
 err_slimbus_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_RELEASE, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, sitar);
 err_release_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL,
 			 sitar);
 err_potential_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_REMOVAL, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, sitar);
 err_remove_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION,
 			 sitar);
 err_insert_irq:
 	kfree(ptr);
@@ -6059,12 +6093,15 @@
 static int sitar_codec_remove(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, sitar);
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_RELEASE, sitar);
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL,
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
+
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL,
 			 sitar);
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_REMOVAL, sitar);
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, sitar);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION,
 			 sitar);
 	SITAR_ACQUIRE_LOCK(sitar->codec_resource_lock);
 	sitar_codec_disable_clock_block(codec);
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 9c852f9..2661c18 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -2977,6 +2977,7 @@
 	unsigned int value)
 {
 	int ret;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
 
 	if (reg == SND_SOC_NOPM)
 		return 0;
@@ -2990,13 +2991,14 @@
 				reg, ret);
 	}
 
-	return wcd9xxx_reg_write(codec->control_data, reg, value);
+	return wcd9xxx_reg_write(&wcd9xxx->core_res, reg, value);
 }
 static unsigned int tapan_read(struct snd_soc_codec *codec,
 				unsigned int reg)
 {
 	unsigned int val;
 	int ret;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
 
 	if (reg == SND_SOC_NOPM)
 		return 0;
@@ -3013,7 +3015,7 @@
 				reg, ret);
 	}
 
-	val = wcd9xxx_reg_read(codec->control_data, reg);
+	val = wcd9xxx_reg_read(&wcd9xxx->core_res, reg);
 	return val;
 }
 
@@ -4815,8 +4817,10 @@
 {
 	int ret = 0;
 	struct snd_soc_codec *codec = tapan->codec;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
 
-	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
 				  tapan_slimbus_irq, "SLIMBUS Slave", tapan);
 	if (ret)
 		pr_err("%s: Failed to request irq %d\n", __func__,
@@ -4830,7 +4834,9 @@
 static void tapan_cleanup_irqs(struct tapan_priv *tapan)
 {
 	struct snd_soc_codec *codec = tapan->codec;
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, tapan);
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tapan);
 }
 
 
@@ -4905,7 +4911,7 @@
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	return wcd9xxx_mbhc_start(&tapan->mbhc, mbhc_cfg);
 }
-EXPORT_SYMBOL_GPL(tapan_hs_detect);
+EXPORT_SYMBOL(tapan_hs_detect);
 
 static int tapan_device_down(struct wcd9xxx *wcd9xxx)
 {
@@ -5010,10 +5016,12 @@
 
 static void tapan_enable_config_rco(struct wcd9xxx *core, bool enable)
 {
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
+
 	if (enable) {
 		/* Enable RC Oscillator */
 		wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x10, 0x00);
-		wcd9xxx_reg_write(core, WCD9XXX_A_BIAS_OSC_BG_CTL, 0x17);
+		wcd9xxx_reg_write(core_res, WCD9XXX_A_BIAS_OSC_BG_CTL, 0x17);
 		usleep_range(5, 5);
 		wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x80, 0x80);
 		wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_TEST, 0x80, 0x80);
@@ -5022,7 +5030,7 @@
 		usleep_range(20, 20);
 		wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x08, 0x08);
 		/* Enable MCLK and wait 1ms till it gets enabled */
-		wcd9xxx_reg_write(core, WCD9XXX_A_CLK_BUFF_EN2, 0x02);
+		wcd9xxx_reg_write(core_res, WCD9XXX_A_CLK_BUFF_EN2, 0x02);
 		usleep_range(1000, 1000);
 		/* Enable CLK BUFF and wait for 1.2ms */
 		wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x01, 0x01);
@@ -5050,6 +5058,7 @@
 	bool ret = true;
 	unsigned long timeout;
 	bool timedout;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
 	if (!core) {
 		dev_err(cdc_dev, "%s: core not initialized\n", __func__);
@@ -5059,18 +5068,19 @@
 	tapan_enable_config_rco(core, 1);
 
 	if (sensed == false) {
-		reg_val = wcd9xxx_reg_read(core, TAPAN_A_QFUSE_CTL);
-		wcd9xxx_reg_write(core, TAPAN_A_QFUSE_CTL, (reg_val | 0x03));
+		reg_val = wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_CTL);
+		wcd9xxx_reg_write(core_res, TAPAN_A_QFUSE_CTL,
+					(reg_val | 0x03));
 	}
 
 	timeout = jiffies + HZ;
 	do {
-		if ((wcd9xxx_reg_read(core, TAPAN_A_QFUSE_STATUS)))
+		if ((wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_STATUS)))
 			break;
 	} while (!(timedout = time_after(jiffies, timeout)));
 
-	if (wcd9xxx_reg_read(core, TAPAN_A_QFUSE_DATA_OUT1) ||
-	    wcd9xxx_reg_read(core, TAPAN_A_QFUSE_DATA_OUT2)) {
+	if (wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_DATA_OUT1) ||
+	    wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_DATA_OUT2)) {
 		dev_info(cdc_dev, "%s: wcd9302 detected\n", __func__);
 		ret = false;
 	} else
@@ -5090,6 +5100,7 @@
 	int ret = 0;
 	int i, rco_clk_rate;
 	void *ptr = NULL;
+	struct wcd9xxx_core_resource *core_res;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
@@ -5115,8 +5126,9 @@
 
 	/* codec resmgr module init */
 	wcd9xxx = codec->control_data;
+	core_res = &wcd9xxx->core_res;
 	pdata = dev_get_platdata(codec->dev->parent);
-	ret = wcd9xxx_resmgr_init(&tapan->resmgr, codec, wcd9xxx, pdata,
+	ret = wcd9xxx_resmgr_init(&tapan->resmgr, codec, core_res, pdata,
 				  &tapan_reg_address);
 	if (ret) {
 		pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 212924fd..673b634 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -5949,11 +5949,12 @@
 {
 	int r = 0;
 	struct wcd9xxx *core = dev_get_drvdata(tabla->codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
 	if (cancel_delayed_work_sync(&tabla->mbhc_btn_dwork)) {
 		/* if scheduled mbhc_btn_dwork is canceled from here,
 		* we have to unlock from here instead btn_work */
-		wcd9xxx_unlock_sleep(core);
+		wcd9xxx_unlock_sleep(core_res);
 		r = 1;
 	}
 	return r;
@@ -6332,12 +6333,14 @@
 	short bias_value;
 	int dce_mv, sta_mv;
 	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	pr_debug("%s:\n", __func__);
 
 	delayed_work = to_delayed_work(work);
 	tabla = container_of(delayed_work, struct tabla_priv, mbhc_btn_dwork);
 	core = dev_get_drvdata(tabla->codec->dev->parent);
+	core_res = &core->core_res;
 
 	if (tabla) {
 		if (tabla->mbhc_cfg.button_jack) {
@@ -6360,7 +6363,7 @@
 	}
 
 	pr_debug("%s: leave\n", __func__);
-	wcd9xxx_unlock_sleep(core);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 static u16 tabla_get_cfilt_reg(struct snd_soc_codec *codec, u8 cfilt)
@@ -6816,6 +6819,7 @@
 	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
 	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 	int n_btn_meas = d->n_btn_meas;
 	u8 mbhc_status = snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_STATUS) & 0x3E;
 
@@ -6917,12 +6921,12 @@
 		tabla_mbhc_set_rel_thres(codec, btn_high[btn]);
 		mask = tabla_get_button_mask(btn);
 		priv->buttons_pressed |= mask;
-		wcd9xxx_lock_sleep(core);
+		wcd9xxx_lock_sleep(core_res);
 		if (schedule_delayed_work(&priv->mbhc_btn_dwork,
 					  msecs_to_jiffies(400)) == 0) {
 			WARN(1, "Button pressed twice without release"
 			     "event\n");
-			wcd9xxx_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core_res);
 		}
 	} else {
 		pr_debug("%s: bogus button press, too short press?\n",
@@ -7248,9 +7252,11 @@
 static void tabla_schedule_hs_detect_plug(struct tabla_priv *tabla,
 	struct work_struct *correct_plug_work)
 {
+	struct wcd9xxx *core = tabla->codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 	pr_debug("%s: scheduling tabla_hs_correct_gpio_plug\n", __func__);
 	tabla->hs_detect_work_stop = false;
-	wcd9xxx_lock_sleep(tabla->codec->control_data);
+	wcd9xxx_lock_sleep(core_res);
 	schedule_work(correct_plug_work);
 }
 
@@ -7258,13 +7264,15 @@
 static void tabla_cancel_hs_detect_plug(struct tabla_priv *tabla,
 		struct work_struct *correct_plug_work)
 {
+	struct wcd9xxx *core = tabla->codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 	pr_debug("%s: canceling hs_correct_plug_work\n", __func__);
 	tabla->hs_detect_work_stop = true;
 	wmb();
 	TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
 	if (cancel_work_sync(correct_plug_work)) {
 		pr_debug("%s: hs_correct_plug_work is canceled\n", __func__);
-		wcd9xxx_unlock_sleep(tabla->codec->control_data);
+		wcd9xxx_unlock_sleep(core_res);
 	}
 	TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
 }
@@ -7470,9 +7478,13 @@
 	bool correction = false;
 	enum tabla_mbhc_plug_type plug_type = PLUG_TYPE_INVALID;
 	unsigned long timeout;
+	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	tabla = container_of(work, struct tabla_priv, hs_correct_plug_work);
 	codec = tabla->codec;
+	core = tabla->codec->control_data;
+	core_res = &core->core_res;
 
 	pr_debug("%s: enter\n", __func__);
 	tabla->mbhc_cfg.mclk_cb_fn(codec, 1, false);
@@ -7581,7 +7593,7 @@
 	pr_debug("%s: leave current_plug(%d)\n",
 		 __func__, tabla->current_plug);
 	/* unlock sleep */
-	wcd9xxx_unlock_sleep(tabla->codec->control_data);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 /* called under codec_resource_lock acquisition */
@@ -7738,6 +7750,7 @@
 	int ret;
 	struct snd_soc_codec *codec = priv->codec;
 	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
 	/* Cancel possibly running hs_detect_work */
@@ -7766,12 +7779,12 @@
 	} else if (is_mb_trigger && !is_removal) {
 		pr_debug("%s: Waiting for Headphone left trigger\n",
 			__func__);
-		wcd9xxx_lock_sleep(core);
+		wcd9xxx_lock_sleep(core_res);
 		if (schedule_delayed_work(&priv->mbhc_insert_dwork,
 					  usecs_to_jiffies(1000000)) == 0) {
 			pr_err("%s: mbhc_insert_dwork is already scheduled\n",
 			       __func__);
-			wcd9xxx_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core_res);
 		}
 		tabla_codec_enable_hs_detect(codec, 1, MBHC_USE_HPHL_TRIGGER,
 					     false);
@@ -7781,7 +7794,7 @@
 			pr_debug("%s: Complete plug insertion, Detecting plug "
 				 "type\n", __func__);
 			tabla_codec_detect_plug_type(codec);
-			wcd9xxx_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core_res);
 		} else {
 			wcd9xxx_enable_irq(codec->control_data,
 					   WCD9XXX_IRQ_MBHC_INSERTION);
@@ -8058,11 +8071,13 @@
 	struct tabla_priv *tabla;
 	struct snd_soc_codec *codec;
 	struct wcd9xxx *tabla_core;
+	struct wcd9xxx_core_resource *core_res;
 
 	dwork = to_delayed_work(work);
 	tabla = container_of(dwork, struct tabla_priv, mbhc_insert_dwork);
 	codec = tabla->codec;
 	tabla_core = dev_get_drvdata(codec->dev->parent);
+	core_res = &tabla_core->core_res;
 
 	pr_debug("%s:\n", __func__);
 
@@ -8073,7 +8088,7 @@
 	wcd9xxx_disable_irq_sync(codec->control_data,
 				 WCD9XXX_IRQ_MBHC_INSERTION);
 	tabla_codec_detect_plug_type(codec);
-	wcd9xxx_unlock_sleep(tabla_core);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 static void tabla_hs_gpio_handler(struct snd_soc_codec *codec)
@@ -8090,7 +8105,7 @@
 	usleep_range(TABLA_GPIO_IRQ_DEBOUNCE_TIME_US,
 		     TABLA_GPIO_IRQ_DEBOUNCE_TIME_US);
 
-	wcd9xxx_nested_irq_lock(core);
+	wcd9xxx_nested_irq_lock(&core->core_res);
 	TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
 
 	/* cancel pending button press */
@@ -8163,7 +8178,7 @@
 
 	tabla->in_gpio_handler = false;
 	TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
-	wcd9xxx_nested_irq_unlock(core);
+	wcd9xxx_nested_irq_unlock(&core->core_res);
 	pr_debug("%s: leave\n", __func__);
 }
 
@@ -8172,8 +8187,10 @@
 	int r = IRQ_HANDLED;
 	struct snd_soc_codec *codec = data;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx *core = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &core->core_res;
 
-	if (unlikely(wcd9xxx_lock_sleep(codec->control_data) == false)) {
+	if (unlikely(wcd9xxx_lock_sleep(core_res) == false)) {
 		pr_warn("%s: failed to hold suspend\n", __func__);
 		/*
 		 * Give up this IRQ for now and resend this IRQ so IRQ can be
@@ -8186,7 +8203,7 @@
 		r = IRQ_NONE;
 	} else {
 		tabla_hs_gpio_handler(codec);
-		wcd9xxx_unlock_sleep(codec->control_data);
+		wcd9xxx_unlock_sleep(core_res);
 	}
 
 	return r;
@@ -8200,6 +8217,8 @@
 	int retry = 0;
 	enum tabla_mbhc_plug_type plug_type;
 	bool is_headset = false;
+	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	pr_debug("%s(): Poll Microphone voltage for %d seconds\n",
 			 __func__, TABLA_HS_DETECT_PLUG_TIME_MS / 1000);
@@ -8207,6 +8226,8 @@
 	tabla = container_of(work, struct tabla_priv,
 						 hs_correct_plug_work_nogpio);
 	codec = tabla->codec;
+	core = codec->control_data;
+	core_res = &core->core_res;
 
 	/* Make sure the MBHC mux is connected to MIC Path */
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
@@ -8261,7 +8282,7 @@
 		tabla_codec_cleanup_hs_polling(codec);
 		tabla_codec_enable_hs_detect(codec, 0, 0, false);
 	}
-	wcd9xxx_unlock_sleep(codec->control_data);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 static int tabla_mbhc_init_and_calibrate(struct tabla_priv *tabla)
@@ -8933,9 +8954,11 @@
 	int ret = 0;
 	int i;
 	void *ptr = NULL;
+	struct wcd9xxx_core_resource *core_res;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
+	core_res = &control->core_res;
 
 	tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL);
 	if (!tabla) {
@@ -9049,7 +9072,7 @@
 
 	snd_soc_dapm_sync(dapm);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_INSERTION,
 		tabla_hs_insert_irq, "Headset insert detect", tabla);
 	if (ret) {
@@ -9057,9 +9080,9 @@
 		       WCD9XXX_IRQ_MBHC_INSERTION);
 		goto err_insert_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_REMOVAL,
 				  tabla_hs_remove_irq,
 				  "Headset remove detect", tabla);
@@ -9069,7 +9092,7 @@
 		goto err_remove_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_MBHC_POTENTIAL,
 				  tabla_dce_handler, "DC Estimation detect",
 				  tabla);
@@ -9079,7 +9102,7 @@
 		goto err_potential_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_MBHC_RELEASE,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE,
 				  tabla_release_handler,
 				  "Button Release detect", tabla);
 	if (ret) {
@@ -9088,7 +9111,7 @@
 		goto err_release_irq;
 	}
 
-	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
 				  tabla_slimbus_irq, "SLIMBUS Slave", tabla);
 	if (ret) {
 		pr_err("%s: Failed to request irq %d\n", __func__,
@@ -9097,10 +9120,10 @@
 	}
 
 	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
-		wcd9xxx_interface_reg_write(codec->control_data,
-			TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
+		wcd9xxx_interface_reg_write(control,
+				TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
 				  tabla_hphl_ocp_irq,
 				  "HPH_L OCP detect", tabla);
@@ -9109,9 +9132,9 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 		goto err_hphl_ocp_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 
-	ret = wcd9xxx_request_irq(codec->control_data,
+	ret = wcd9xxx_request_irq(core_res,
 				  WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
 				  tabla_hphr_ocp_irq,
 				  "HPH_R OCP detect", tabla);
@@ -9120,7 +9143,7 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 		goto err_hphr_ocp_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 
 	/*
 	 * Register suspend lock and notifier to resend edge triggered
@@ -9151,19 +9174,19 @@
 	return ret;
 
 err_hphr_ocp_irq:
-	wcd9xxx_free_irq(codec->control_data,
+	wcd9xxx_free_irq(core_res,
 			WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, tabla);
 err_hphl_ocp_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, tabla);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tabla);
 err_slimbus_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_RELEASE, tabla);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, tabla);
 err_release_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL,
 			 tabla);
 err_potential_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_REMOVAL, tabla);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, tabla);
 err_remove_irq:
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION,
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION,
 			 tabla);
 err_insert_irq:
 err_pdata:
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 3602dd3..8f00dc8 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -4051,6 +4051,7 @@
 	unsigned int value)
 {
 	int ret;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
 
 	if (reg == SND_SOC_NOPM)
 		return 0;
@@ -4064,7 +4065,7 @@
 				reg, ret);
 	}
 
-	return wcd9xxx_reg_write(codec->control_data, reg, value);
+	return wcd9xxx_reg_write(&wcd9xxx->core_res, reg, value);
 }
 static unsigned int taiko_read(struct snd_soc_codec *codec,
 				unsigned int reg)
@@ -4072,6 +4073,8 @@
 	unsigned int val;
 	int ret;
 
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+
 	if (reg == SND_SOC_NOPM)
 		return 0;
 
@@ -4087,7 +4090,7 @@
 				reg, ret);
 	}
 
-	val = wcd9xxx_reg_read(codec->control_data, reg);
+	val = wcd9xxx_reg_read(&wcd9xxx->core_res, reg);
 	return val;
 }
 
@@ -6151,8 +6154,11 @@
 {
 	int ret = 0;
 	struct snd_soc_codec *codec = taiko->codec;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	struct wcd9xxx_core_resource *core_res =
+				&wcd9xxx->core_res;
 
-	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
 				  taiko_slimbus_irq, "SLIMBUS Slave", taiko);
 	if (ret)
 		pr_err("%s: Failed to request irq %d\n", __func__,
@@ -6166,8 +6172,11 @@
 static void taiko_cleanup_irqs(struct taiko_priv *taiko)
 {
 	struct snd_soc_codec *codec = taiko->codec;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	struct wcd9xxx_core_resource *core_res =
+				&wcd9xxx->core_res;
 
-	wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, taiko);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, taiko);
 }
 
 int taiko_hs_detect(struct snd_soc_codec *codec,
@@ -6180,7 +6189,7 @@
 		taiko->mbhc_started = true;
 	return rc;
 }
-EXPORT_SYMBOL_GPL(taiko_hs_detect);
+EXPORT_SYMBOL(taiko_hs_detect);
 
 void taiko_event_register(
 	int (*machine_event_cb)(struct snd_soc_codec *codec,
@@ -6190,7 +6199,7 @@
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
 	taiko->machine_codec_event_cb = machine_event_cb;
 }
-EXPORT_SYMBOL_GPL(taiko_event_register);
+EXPORT_SYMBOL(taiko_event_register);
 
 static void taiko_init_slim_slave_cfg(struct snd_soc_codec *codec)
 {
@@ -6412,6 +6421,7 @@
 	int i, rco_clk_rate;
 	void *ptr = NULL;
 	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+	struct wcd9xxx_core_resource *core_res;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
@@ -6437,8 +6447,9 @@
 
 	/* codec resmgr module init */
 	wcd9xxx = codec->control_data;
+	core_res = &wcd9xxx->core_res;
 	pdata = dev_get_platdata(codec->dev->parent);
-	ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, wcd9xxx, pdata,
+	ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, core_res, pdata,
 				  &taiko_reg_address);
 	if (ret) {
 		pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 7820cd0..3400ff2 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -20,6 +20,7 @@
 #include <linux/debugfs.h>
 #include <linux/list.h>
 #include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 #include <linux/mfd/wcd9xxx/wcd9320_registers.h>
 #include <linux/mfd/wcd9xxx/pdata.h>
@@ -452,7 +453,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_cal_btn_det_mp);
+EXPORT_SYMBOL(wcd9xxx_mbhc_cal_btn_det_mp);
 
 static void wcd9xxx_calibrate_hs_polling(struct wcd9xxx_mbhc *mbhc)
 {
@@ -556,7 +557,7 @@
 			mbhc->hphlocp_cnt = 0;
 		else
 			mbhc->hphrocp_cnt = 0;
-		wcd9xxx_enable_irq(codec->control_data, irq);
+		wcd9xxx_enable_irq(mbhc->resmgr->core_res, irq);
 	}
 }
 
@@ -685,7 +686,7 @@
 	if (r)
 		/* if scheduled mbhc.mbhc_btn_dwork is canceled from here,
 		 * we have to unlock from here instead btn_work */
-		wcd9xxx_unlock_sleep(mbhc->resmgr->core);
+		wcd9xxx_unlock_sleep(mbhc->resmgr->core_res);
 	return r;
 }
 
@@ -857,7 +858,7 @@
 	pr_debug("%s: scheduling wcd9xxx_correct_swch_plug\n", __func__);
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
 	mbhc->hs_detect_work_stop = false;
-	wcd9xxx_lock_sleep(mbhc->resmgr->core);
+	wcd9xxx_lock_sleep(mbhc->resmgr->core_res);
 	schedule_work(work);
 }
 
@@ -873,7 +874,7 @@
 	if (cancel_work_sync(work)) {
 		pr_debug("%s: correct_plug_swch is canceled\n",
 			 __func__);
-		wcd9xxx_unlock_sleep(mbhc->resmgr->core);
+		wcd9xxx_unlock_sleep(mbhc->resmgr->core_res);
 	}
 	WCD9XXX_BCL_LOCK(mbhc->resmgr);
 }
@@ -939,7 +940,7 @@
 	short bias_value;
 	struct snd_soc_codec *codec = mbhc->codec;
 
-	wcd9xxx_disable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	if (noreldetection)
 		wcd9xxx_turn_onoff_rel_detection(codec, false);
 
@@ -980,7 +981,7 @@
 
 	if (noreldetection)
 		wcd9xxx_turn_onoff_rel_detection(codec, true);
-	wcd9xxx_enable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 
 	return bias_value;
 }
@@ -1833,7 +1834,7 @@
 		snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
 				    0x3, mbhc->mbhc_cfg->micbias);
 
-	wcd9xxx_enable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
 	pr_debug("%s: leave\n", __func__);
 
@@ -2297,7 +2298,7 @@
 
 	pr_debug("%s: enter\n", __func__);
 	WCD9XXX_BCL_LOCK(mbhc->resmgr);
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 
 	is_mb_trigger = !!(snd_soc_read(codec, mbhc->mbhc_bias_regs.mbhc_reg) &
 			   0x10);
@@ -2343,7 +2344,7 @@
 			    mbhc->buttons_pressed);
 
 	pr_debug("%s: leave\n", __func__);
-	wcd9xxx_unlock_sleep(mbhc->resmgr->core);
+	wcd9xxx_unlock_sleep(mbhc->resmgr->core_res);
 }
 
 static void wcd9xxx_mbhc_insert_work(struct work_struct *work)
@@ -2351,12 +2352,12 @@
 	struct delayed_work *dwork;
 	struct wcd9xxx_mbhc *mbhc;
 	struct snd_soc_codec *codec;
-	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	dwork = to_delayed_work(work);
 	mbhc = container_of(dwork, struct wcd9xxx_mbhc, mbhc_insert_dwork);
 	codec = mbhc->codec;
-	core = mbhc->resmgr->core;
+	core_res = mbhc->resmgr->core_res;
 
 	pr_debug("%s:\n", __func__);
 
@@ -2364,9 +2365,9 @@
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
 	snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
-	wcd9xxx_disable_irq_sync(core, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq_sync(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 	wcd9xxx_mbhc_detect_plug_type(mbhc);
-	wcd9xxx_unlock_sleep(core);
+	wcd9xxx_unlock_sleep(core_res);
 }
 
 static bool wcd9xxx_mbhc_fw_validate(const struct firmware *fw)
@@ -2702,7 +2703,7 @@
 	}
 	pr_debug("%s: leave current_plug(%d)\n", __func__, mbhc->current_plug);
 	/* unlock sleep */
-	wcd9xxx_unlock_sleep(mbhc->resmgr->core);
+	wcd9xxx_unlock_sleep(mbhc->resmgr->core_res);
 }
 
 static void wcd9xxx_swch_irq_handler(struct wcd9xxx_mbhc *mbhc)
@@ -2797,13 +2798,13 @@
 	struct wcd9xxx_mbhc *mbhc = data;
 
 	pr_debug("%s: enter\n", __func__);
-	if (unlikely(wcd9xxx_lock_sleep(mbhc->resmgr->core) == false)) {
+	if (unlikely(wcd9xxx_lock_sleep(mbhc->resmgr->core_res) == false)) {
 		pr_warn("%s: failed to hold suspend\n", __func__);
 		r = IRQ_NONE;
 	} else {
 		/* Call handler */
 		wcd9xxx_swch_irq_handler(mbhc);
-		wcd9xxx_unlock_sleep(mbhc->resmgr->core);
+		wcd9xxx_unlock_sleep(mbhc->resmgr->core_res);
 	}
 
 	pr_debug("%s: leave %d\n", __func__, r);
@@ -2979,7 +2980,7 @@
 	short dce[d->n_btn_meas + 1], sta;
 	s32 mv[d->n_btn_meas + 1], mv_s[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = mbhc->codec;
-	struct wcd9xxx *core = mbhc->resmgr->core;
+	struct wcd9xxx_core_resource *core_res = mbhc->resmgr->core_res;
 	int n_btn_meas = d->n_btn_meas;
 	void *calibration = mbhc->mbhc_cfg->calibration;
 
@@ -3119,11 +3120,11 @@
 
 		mask = wcd9xxx_get_button_mask(btn);
 		mbhc->buttons_pressed |= mask;
-		wcd9xxx_lock_sleep(core);
+		wcd9xxx_lock_sleep(core_res);
 		if (schedule_delayed_work(&mbhc->mbhc_btn_dwork,
 					  msecs_to_jiffies(400)) == 0) {
 			WARN(1, "Button pressed twice without release event\n");
-			wcd9xxx_unlock_sleep(core);
+			wcd9xxx_unlock_sleep(core_res);
 		}
 	} else {
 		pr_debug("%s: bogus button press, too short press?\n",
@@ -3207,7 +3208,7 @@
 			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
 					    0x10, 0x10);
 		} else {
-			wcd9xxx_disable_irq(codec->control_data,
+			wcd9xxx_disable_irq(mbhc->resmgr->core_res,
 					  WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 			mbhc->hph_status |= SND_JACK_OC_HPHL;
 			wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
@@ -3237,7 +3238,7 @@
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
 				    0x10);
 	} else {
-		wcd9xxx_disable_irq(mbhc->resmgr->core,
+		wcd9xxx_disable_irq(mbhc->resmgr->core_res,
 				    WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 		mbhc->hph_status |= SND_JACK_OC_HPHR;
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
@@ -3318,7 +3319,7 @@
 	struct snd_soc_codec *codec = mbhc->codec;
 
 	pr_debug("%s: enter\n", __func__);
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	wcd9xxx_turn_onoff_rel_detection(codec, false);
 
 	/* t_dce and t_sta are updated by wcd9xxx_update_mbhc_clk_rate() */
@@ -3449,7 +3450,7 @@
 				    0x80, 0x80);
 	usleep_range(100, 100);
 
-	wcd9xxx_enable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
+	wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	wcd9xxx_turn_onoff_rel_detection(codec, true);
 
 	pr_debug("%s: leave\n", __func__);
@@ -3510,8 +3511,8 @@
 static int wcd9xxx_setup_jack_detect_irq(struct wcd9xxx_mbhc *mbhc)
 {
 	int ret = 0;
-	void *core = mbhc->resmgr->core;
 	struct snd_soc_codec *codec = mbhc->codec;
+	void *core_res = mbhc->resmgr->core_res;
 	int jack_irq;
 
 	if (mbhc->mbhc_cb && mbhc->mbhc_cb->jack_detect_irq)
@@ -3540,7 +3541,7 @@
 		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_RX_HPH_OCP_CTL,
 				    1 << 1, 1 << 1);
 
-		ret = wcd9xxx_request_irq(core, jack_irq,
+		ret = wcd9xxx_request_irq(core_res, jack_irq,
 					  wcd9xxx_mech_plug_detect_irq,
 					  "Jack Detect",
 					  mbhc);
@@ -3575,9 +3576,9 @@
 	if (!IS_ERR_VALUE(ret)) {
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
 				    0x10);
-		wcd9xxx_enable_irq(codec->control_data,
+		wcd9xxx_enable_irq(mbhc->resmgr->core_res,
 				   WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
-		wcd9xxx_enable_irq(codec->control_data,
+		wcd9xxx_enable_irq(mbhc->resmgr->core_res,
 				   WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 
 		/* Initialize mechanical mbhc */
@@ -3807,7 +3808,7 @@
 	pr_debug("%s: leave %d\n", __func__, rc);
 	return rc;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_start);
+EXPORT_SYMBOL(wcd9xxx_mbhc_start);
 
 static enum wcd9xxx_micbias_num
 wcd9xxx_event_to_micbias(const enum wcd9xxx_notify_event event)
@@ -4374,7 +4375,7 @@
 		      bool impedance_det_en)
 {
 	int ret;
-	void *core;
+	void *core_res;
 
 	pr_debug("%s: enter\n", __func__);
 	memset(&mbhc->mbhc_bias_regs, 0, sizeof(struct mbhc_micbias_regs));
@@ -4441,18 +4442,18 @@
 
 	wcd9xxx_init_debugfs(mbhc);
 
-	core = mbhc->resmgr->core;
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_INSERTION,
+	core_res = mbhc->resmgr->core_res;
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION,
 				  wcd9xxx_hs_insert_irq,
 				  "Headset insert detect", mbhc);
 	if (ret) {
-		pr_err("%s: Failed to request irq %d\n", __func__,
-		       WCD9XXX_IRQ_MBHC_INSERTION);
+		pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
+		       WCD9XXX_IRQ_MBHC_INSERTION, ret);
 		goto err_insert_irq;
 	}
-	wcd9xxx_disable_irq(core, WCD9XXX_IRQ_MBHC_INSERTION);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
 
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_REMOVAL,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL,
 				  wcd9xxx_hs_remove_irq,
 				  "Headset remove detect", mbhc);
 	if (ret) {
@@ -4461,7 +4462,7 @@
 		goto err_remove_irq;
 	}
 
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_POTENTIAL,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL,
 				  wcd9xxx_dce_handler, "DC Estimation detect",
 				  mbhc);
 	if (ret) {
@@ -4470,7 +4471,7 @@
 		goto err_potential_irq;
 	}
 
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_RELEASE,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE,
 				  wcd9xxx_release_handler,
 				  "Button Release detect", mbhc);
 	if (ret) {
@@ -4479,7 +4480,7 @@
 		goto err_release_irq;
 	}
 
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
 				  wcd9xxx_hphl_ocp_irq, "HPH_L OCP detect",
 				  mbhc);
 	if (ret) {
@@ -4487,9 +4488,9 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 		goto err_hphl_ocp_irq;
 	}
-	wcd9xxx_disable_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
 
-	ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
+	ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
 				  wcd9xxx_hphr_ocp_irq, "HPH_R OCP detect",
 				  mbhc);
 	if (ret) {
@@ -4497,7 +4498,7 @@
 		       WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 		goto err_hphr_ocp_irq;
 	}
-	wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+	wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
 
 	wcd9xxx_regmgr_cond_register(resmgr, 1 << WCD9XXX_COND_HPH_MIC |
 					     1 << WCD9XXX_COND_HPH);
@@ -4506,43 +4507,44 @@
 	return ret;
 
 err_hphr_ocp_irq:
-	wcd9xxx_free_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
 err_hphl_ocp_irq:
-	wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
 err_release_irq:
-	wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
 err_potential_irq:
-	wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
 err_remove_irq:
-	wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
 err_insert_irq:
 	wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
 
 	pr_debug("%s: leave ret %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_init);
+EXPORT_SYMBOL(wcd9xxx_mbhc_init);
 
 void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc)
 {
-	void *cdata = mbhc->codec->control_data;
+	struct wcd9xxx_core_resource *core_res =
+				mbhc->resmgr->core_res;
 
 	wcd9xxx_regmgr_cond_deregister(mbhc->resmgr, 1 << WCD9XXX_COND_HPH_MIC |
 						     1 << WCD9XXX_COND_HPH);
 
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
 
 	if (mbhc->mbhc_cb && mbhc->mbhc_cb->free_irq)
 		mbhc->mbhc_cb->free_irq(mbhc);
 	else
-		wcd9xxx_free_irq(cdata, WCD9320_IRQ_MBHC_JACK_SWITCH,
+		wcd9xxx_free_irq(core_res, WCD9320_IRQ_MBHC_JACK_SWITCH,
 				 mbhc);
 
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
-	wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
+	wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);
 
 	if (mbhc->mbhc_fw)
 		release_firmware(mbhc->mbhc_fw);
@@ -4551,7 +4553,7 @@
 
 	wcd9xxx_cleanup_debugfs(mbhc);
 }
-EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_deinit);
+EXPORT_SYMBOL(wcd9xxx_mbhc_deinit);
 
 MODULE_DESCRIPTION("wcd9xxx MBHC module");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 9633cc0..b8cc999 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -797,7 +797,7 @@
 
 int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
 			struct snd_soc_codec *codec,
-			struct wcd9xxx *wcd9xxx,
+			struct wcd9xxx_core_resource *core_res,
 			struct wcd9xxx_pdata *pdata,
 			struct wcd9xxx_reg_address *reg_addr)
 {
@@ -808,7 +808,7 @@
 	resmgr->bandgap_type = WCD9XXX_BANDGAP_OFF;
 	resmgr->codec = codec;
 	/* This gives access of core handle to lock/unlock suspend */
-	resmgr->core = wcd9xxx;
+	resmgr->core_res = core_res;
 	resmgr->pdata = pdata;
 	resmgr->reg_addr = reg_addr;
 
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.h b/sound/soc/codecs/wcd9xxx-resmgr.h
index e6a8f5d..4279437 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.h
+++ b/sound/soc/codecs/wcd9xxx-resmgr.h
@@ -13,6 +13,7 @@
 #define __WCD9XXX_COMMON_H__
 
 #include <linux/notifier.h>
+#include <linux/mfd/wcd9xxx/core-resource.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 
 enum wcd9xxx_bandgap_type {
@@ -102,7 +103,7 @@
 
 struct wcd9xxx_resmgr {
 	struct snd_soc_codec *codec;
-	struct wcd9xxx *core;
+	struct wcd9xxx_core_resource *core_res;
 
 	u32 rx_bias_count;
 
@@ -150,7 +151,7 @@
 
 int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
 			struct snd_soc_codec *codec,
-			struct wcd9xxx *wcd9xxx,
+			struct wcd9xxx_core_resource *core_res,
 			struct wcd9xxx_pdata *pdata,
 			struct wcd9xxx_reg_address *reg_addr);
 void wcd9xxx_resmgr_deinit(struct wcd9xxx_resmgr *resmgr);