From 780da55e2ad7f9d934e7452fba4340a5f9575a32 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Mon, 27 Dec 2010 21:48:40 +0100
Subject: [PATCH 39/69] MFD: pcf50633: Use the genirq for irq handling

---
 drivers/input/misc/pcf50633-input.c |   64 +++++++++++---
 drivers/mfd/pcf50633-adc.c          |   34 ++++++-
 drivers/mfd/pcf50633-core.c         |  149 ++++++++++++++++++++++++++++---
 drivers/mfd/pcf50633-irq.c          |  168 +++++++++++++++++------------------
 drivers/power/pcf50633-charger.c    |  160 +++++++++++++++++++++++----------
 drivers/rtc/rtc-pcf50633.c          |   71 +++++++++------
 include/linux/mfd/pcf50633/core.h   |   23 +----
 7 files changed, 460 insertions(+), 209 deletions(-)

diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
index 9556273..983d5c8 100644
--- a/drivers/input/misc/pcf50633-input.c
+++ b/drivers/input/misc/pcf50633-input.c
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 
 #include <linux/mfd/pcf50633/core.h>
@@ -31,26 +32,27 @@
 struct pcf50633_input {
 	struct pcf50633 *pcf;
 	struct input_dev *input_dev;
+	int irq_pressed;
+	int irq_released;
 };
 
-static void
-pcf50633_input_irq(int irq, void *data)
+static irqreturn_t pcf50633_input_irq(int irq, void *data)
 {
-	struct pcf50633_input *input;
+	struct pcf50633_input *input = data;
 	int onkey_released;
 
-	input = data;
-
 	/* We report only one event depending on the key press status */
 	onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
 						& PCF50633_OOCSTAT_ONKEY;
 
-	if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
+	if (irq == input->irq_pressed && !onkey_released)
 		input_report_key(input->input_dev, KEY_POWER, 1);
-	else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
+	else if (irq == input->irq_released && onkey_released)
 		input_report_key(input->input_dev, KEY_POWER, 0);
 
 	input_sync(input->input_dev);
+
+	return IRQ_HANDLED;
 }
 
 static int __devinit pcf50633_input_probe(struct platform_device *pdev)
@@ -58,7 +60,22 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev)
 	struct pcf50633_input *input;
 	struct input_dev *input_dev;
 	int ret;
+	int irq_released;
+	int irq_pressed;
+
+	irq_released = platform_get_irq_byname(pdev, "ONKEYR");
+	if (irq_released <= 0) {
+		dev_err(&pdev->dev, "Failed to get released irq: %d\n",
+			irq_released);
+		return irq_released ?: -EINVAL;
+	}
 
+	irq_pressed = platform_get_irq_byname(pdev, "ONKEYF");
+	if (irq_pressed <= 0) {
+		dev_err(&pdev->dev, "Failed to get pressed irq: %d\n",
+			irq_pressed);
+		return irq_pressed ?: -EINVAL;
+	}
 
 	input = kzalloc(sizeof(*input), GFP_KERNEL);
 	if (!input)
@@ -85,20 +102,41 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev)
 		kfree(input);
 		return ret;
 	}
-	pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,
-				pcf50633_input_irq, input);
-	pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,
-				pcf50633_input_irq, input);
+
+	ret = request_threaded_irq(irq_released, NULL, pcf50633_input_irq, 0,
+			"onkey released", input);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request released irq: %d\n", ret);
+		goto err_input_unregister;
+	}
+	ret = request_threaded_irq(irq_pressed, NULL, pcf50633_input_irq, 0,
+			"onkey pressed", input);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request pressed irq: %d\n", ret);
+		goto err_free_irq;
+	}
+
+	input->irq_released = irq_released;
+	input->irq_pressed = irq_pressed;
+
 
 	return 0;
+
+err_free_irq:
+	free_irq(irq_pressed, input);
+err_input_unregister:
+	input_unregister_device(input->input_dev);
+	kfree(input);
+
+	return ret;
 }
 
 static int __devexit pcf50633_input_remove(struct platform_device *pdev)
 {
 	struct pcf50633_input *input  = platform_get_drvdata(pdev);
 
-	pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
-	pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
+	free_irq(input->irq_released, input);
+	free_irq(input->irq_pressed, input);
 
 	input_unregister_device(input->input_dev);
 	kfree(input);
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index bf77c8f..54a78c1 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -24,6 +24,8 @@
 #include <linux/platform_device.h>
 #include <linux/completion.h>
 
+#include <linux/interrupt.h>
+
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/adc.h>
 
@@ -49,6 +51,7 @@ struct pcf50633_adc {
 	int queue_head;
 	int queue_tail;
 	struct mutex queue_mutex;
+	int irq;
 };
 
 static void adc_setup(struct pcf50633 *pcf, int channel, int avg)
@@ -165,7 +168,7 @@ static int adc_result(struct pcf50633 *pcf)
 	return result;
 }
 
-static void pcf50633_adc_irq(int irq, void *data)
+static irqreturn_t pcf50633_adc_irq(int irq, void *data)
 {
 	struct pcf50633_adc *adc = data;
 	struct pcf50633 *pcf = adc->pcf;
@@ -179,7 +182,7 @@ static void pcf50633_adc_irq(int irq, void *data)
 	if (WARN_ON(!req)) {
 		dev_err(pcf->dev, "pcf50633-adc irq: ADC queue empty!\n");
 		mutex_unlock(&adc->queue_mutex);
-		return;
+		return IRQ_HANDLED;
 	}
 	adc->queue[head] = NULL;
 	adc->queue_head = (head + 1) &
@@ -192,12 +195,16 @@ static void pcf50633_adc_irq(int irq, void *data)
 
 	req->callback(pcf, req->callback_param, res);
 	kfree(req);
+
+	return IRQ_HANDLED;
 }
 
 static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
 {
 	struct pcf50633 *pcf = dev_to_pcf50633(pdev->dev.parent);
 	struct pcf50633_adc *adc;
+	int irq;
+	int ret;
 
 	adc = kzalloc(sizeof(*adc), GFP_KERNEL);
 	if (!adc)
@@ -206,14 +213,31 @@ static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
 	adc->pcf = pcf;
 	platform_set_drvdata(pdev, adc);
 
-	pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY,
-					pcf50633_adc_irq, adc);
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		ret = irq;
+		dev_err(&pdev->dev, "Failed to get irq: %d\n", ret);
+		goto err_free;
+	}
 
 	mutex_init(&adc->queue_mutex);
 
+	ret = request_threaded_irq(irq, NULL, pcf50633_adc_irq, 0,
+				dev_name(&pdev->dev), adc);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+		goto err_free;
+	}
+
+	adc->irq = irq;
+
 	pcf->adc = adc;
 
 	return 0;
+
+err_free:
+	kfree(adc);
+	return ret;
 }
 
 static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
@@ -223,7 +247,7 @@ static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
 
 	adc->pcf->adc = NULL;
 
-	pcf50633_free_irq(adc->pcf, PCF50633_IRQ_ADCRDY);
+	free_irq(adc->irq, adc);
 
 	mutex_lock(&adc->queue_mutex);
 	head = adc->queue_head;
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 07a018d..165a3f3 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -53,7 +53,7 @@ static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
 
 }
 
-/* Read a block of up to 32 regs  */
+/* Read a block of upto 32 regs  */
 int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
 					int nr_regs, u8 *data)
 {
@@ -67,7 +67,7 @@ int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
 }
 EXPORT_SYMBOL_GPL(pcf50633_read_block);
 
-/* Write a block of up to 32 regs  */
+/* Write a block of upto 32 regs  */
 int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
 					int nr_regs, u8 *data)
 {
@@ -211,8 +211,8 @@ static struct attribute_group pcf_attr_group = {
 	.attrs	= pcf_sysfs_entries,
 };
 
-#ifdef CONFIG_PM_SLEEP
 
+#ifdef CONFIG_PM_SLEEP
 static int pcf50633_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -238,17 +238,139 @@ static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
 		.id = -1, \
 	} \
 
+#define PCF50633_CELL_RESOURCES(_name, _resources) \
+	{ \
+		.name = _name, \
+		.num_resources = ARRAY_SIZE(_resources), \
+		.resources = _resources, \
+		.id = -1, \
+	} \
+
 #define PCF50633_CELL_ID(_name, _id) \
 	{ \
 		.name = _name, \
 		.id = _id, \
 	} \
 
+static struct resource pcf50633_adc_resources[] = {
+	{
+		.start = PCF50633_IRQ_ADCRDY,
+		.end = PCF50633_IRQ_ADCRDY,
+		.flags = IORESOURCE_IRQ,
+		.name = "ADCRDY",
+	}
+};
+
+static struct resource pcf50633_input_resources[] = {
+	{
+		.start = PCF50633_IRQ_ONKEYR,
+		.end = PCF50633_IRQ_ONKEYR,
+		.flags = IORESOURCE_IRQ,
+		.name = "ONKEYR",
+	},
+	{
+		.start = PCF50633_IRQ_ONKEYF,
+		.end = PCF50633_IRQ_ONKEYF,
+		.flags = IORESOURCE_IRQ,
+		.name = "ONKEYF",
+	}
+};
+
+static struct resource pcf50633_rtc_resources[] = {
+	{
+		.start = PCF50633_IRQ_ALARM,
+		.end = PCF50633_IRQ_ALARM,
+		.flags = IORESOURCE_IRQ,
+		.name = "ALARM",
+	},
+	{
+		.start = PCF50633_IRQ_SECOND,
+		.end = PCF50633_IRQ_SECOND,
+		.flags = IORESOURCE_IRQ,
+		.name = "SECOND",
+	}
+};
+
+static struct resource pcf50633_mbc_resources[] = {
+	{
+		.start = PCF50633_IRQ_ADPINS,
+		.end = PCF50633_IRQ_ADPINS,
+		.flags = IORESOURCE_IRQ,
+		.name = "ADPINS",
+	},
+	{
+		.start = PCF50633_IRQ_ADPREM,
+		.end = PCF50633_IRQ_ADPREM,
+		.flags = IORESOURCE_IRQ,
+		.name = "ADPREM",
+	},
+	{
+		.start = PCF50633_IRQ_USBINS,
+		.end = PCF50633_IRQ_USBINS,
+		.flags = IORESOURCE_IRQ,
+		.name = "USBINS",
+	},
+	{
+		.start = PCF50633_IRQ_USBREM,
+		.end = PCF50633_IRQ_USBREM,
+		.flags = IORESOURCE_IRQ,
+		.name = "USBREM",
+	},
+	{
+		.start = PCF50633_IRQ_BATFULL,
+		.end = PCF50633_IRQ_BATFULL,
+		.flags = IORESOURCE_IRQ,
+		.name = "BATFULL",
+	},
+	{
+		.start = PCF50633_IRQ_CHGHALT,
+		.end = PCF50633_IRQ_CHGHALT,
+		.flags = IORESOURCE_IRQ,
+		.name = "CHGHALT",
+	},
+	{
+		.start = PCF50633_IRQ_THLIMON,
+		.end = PCF50633_IRQ_THLIMON,
+		.flags = IORESOURCE_IRQ,
+		.name = "THLIMON",
+	},
+	{
+		.start = PCF50633_IRQ_THLIMOFF,
+		.end = PCF50633_IRQ_THLIMOFF,
+		.flags = IORESOURCE_IRQ,
+		.name = "THLIMOFF",
+	},
+	{
+		.start = PCF50633_IRQ_USBLIMON,
+		.end = PCF50633_IRQ_USBLIMON,
+		.flags = IORESOURCE_IRQ,
+		.name = "USBLIMON",
+	},
+	{
+		.start = PCF50633_IRQ_USBLIMOFF,
+		.end = PCF50633_IRQ_USBLIMOFF,
+		.flags = IORESOURCE_IRQ,
+		.name = "USBLIMOFF",
+	},
+	{
+		.start = PCF50633_IRQ_LOWSYS,
+		.end = PCF50633_IRQ_LOWSYS,
+		.flags = IORESOURCE_IRQ,
+		.name = "LOWSYS",
+	},
+	{
+		.start = PCF50633_IRQ_LOWBAT,
+		.end = PCF50633_IRQ_LOWBAT,
+		.flags = IORESOURCE_IRQ,
+		.name = "LOWBAT",
+	},
+};
+
 static struct mfd_cell pcf50633_cells[] = {
-	PCF50633_CELL("pcf50633-input"),
-	PCF50633_CELL("pcf50633-rtc"),
-	PCF50633_CELL("pcf50633-mbc"),
-	PCF50633_CELL("pcf50633-adc"),
+	PCF50633_CELL_RESOURCES("pcf50633-input", pcf50633_input_resources),
+	PCF50633_CELL_RESOURCES("pcf50633-rtc", pcf50633_rtc_resources),
+	PCF50633_CELL_RESOURCES("pcf50633-mbc", pcf50633_mbc_resources),
+	PCF50633_CELL_RESOURCES("pcf50633-adc", pcf50633_adc_resources),
 	PCF50633_CELL("pcf50633-backlight"),
 	PCF50633_CELL("pcf50633-gpio"),
 	PCF50633_CELL_ID("pcf50633-regltr", 0),
@@ -300,13 +422,15 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 	dev_info(pcf->dev, "Probed device version %d variant %d\n",
 							version, variant);
 
-	pcf50633_irq_init(pcf, client->irq);
+	ret = pcf50633_irq_init(pcf, client->irq);
+	if (ret)
+		goto err_free;
 
 	ret = mfd_add_devices(pcf->dev, 0, pcf50633_cells,
-			ARRAY_SIZE(pcf50633_cells), NULL, 0);
+			ARRAY_SIZE(pcf50633_cells), NULL, pcf->irq_base);
 	if (ret) {
 		dev_err(pcf->dev, "Failed to add mfd cells.\n");
-		goto err_free;
+		goto err_irq_free;
 	}
 
 	ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
@@ -318,6 +442,8 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 
 	return 0;
 
+err_irq_free:
+	pcf50633_irq_free(pcf);
 err_free:
 	kfree(pcf);
 
@@ -329,10 +455,11 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
 	struct pcf50633 *pcf = i2c_get_clientdata(client);
 
 	sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
-	pcf50633_irq_free(pcf);
 
 	mfd_remove_devices(pcf->dev);
 
+	pcf50633_irq_free(pcf);
+
 	kfree(pcf);
 
 	return 0;
diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c
index 1b0192f..4b8269c 100644
--- a/drivers/mfd/pcf50633-irq.c
+++ b/drivers/mfd/pcf50633-irq.c
@@ -2,7 +2,7 @@
  *
  * (C) 2006-2008 by Openmoko, Inc.
  * Author: Harald Welte <laforge@openmoko.org>
- * 	   Balaji Rao <balajirrao@openmoko.org>
+ * 		Balaji Rao <balajirrao@openmoko.org>
  * All rights reserved.
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
@@ -25,92 +26,63 @@
 #define PCF50633_MBCS1_USBPRES 		0x01
 #define PCF50633_MBCS1_ADAPTPRES	0x01
 
-int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
-			void (*handler) (int, void *), void *data)
+static void pcf50633_irq_lock(struct irq_data *data)
 {
-	if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
-		return -EINVAL;
+	struct pcf50633 *pcf = irq_data_get_irq_chip_data(data);
 
-	if (WARN_ON(pcf->irq_handler[irq].handler))
-		return -EBUSY;
-
-	mutex_lock(&pcf->lock);
-	pcf->irq_handler[irq].handler = handler;
-	pcf->irq_handler[irq].data = data;
-	mutex_unlock(&pcf->lock);
-
-	return 0;
+	mutex_lock(&pcf->irq_lock);
 }
-EXPORT_SYMBOL_GPL(pcf50633_register_irq);
 
-int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
+static void pcf50633_irq_sync_unlock(struct irq_data *data)
 {
-	if (irq < 0 || irq >= PCF50633_NUM_IRQ)
-		return -EINVAL;
+	struct pcf50633 *pcf = irq_data_get_irq_chip_data(data);
+	unsigned int i;
 
-	mutex_lock(&pcf->lock);
-	pcf->irq_handler[irq].handler = NULL;
-	mutex_unlock(&pcf->lock);
+	for (i = 0; i < ARRAY_SIZE(pcf->mask_regs); ++i) {
+		if (pcf->mask_regs[i] == pcf->mask_regs_cur[i])
+			continue;
 
-	return 0;
+		pcf->mask_regs[i] = pcf->mask_regs_cur[i];
+		pcf50633_reg_write(pcf, PCF50633_REG_INT1M + i,
+				pcf->mask_regs[i]);
+	}
+
+	mutex_unlock(&pcf->irq_lock);
 }
-EXPORT_SYMBOL_GPL(pcf50633_free_irq);
 
-static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
+static void pcf50633_irq_mask(struct irq_data *data)
 {
-	u8 reg, bit;
-	int ret = 0, idx;
+	struct pcf50633 *pcf = irq_data_get_irq_chip_data(data);
+	int irq = data->irq;
+	u8 bit;
+	int idx;
 
 	idx = irq >> 3;
-	reg = PCF50633_REG_INT1M + idx;
 	bit = 1 << (irq & 0x07);
 
-	pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
-
-	mutex_lock(&pcf->lock);
-
-	if (mask)
-		pcf->mask_regs[idx] |= bit;
-	else
-		pcf->mask_regs[idx] &= ~bit;
-
-	mutex_unlock(&pcf->lock);
-
-	return ret;
+	pcf->mask_regs[idx] |= bit;
 }
 
-int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
+static void pcf50633_irq_unmask(struct irq_data *data)
 {
-	dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
+	struct pcf50633 *pcf = irq_data_get_irq_chip_data(data);
+	int irq = data->irq;
+	u8 bit;
+	int idx;
 
-	return __pcf50633_irq_mask_set(pcf, irq, 1);
-}
-EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
-
-int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
-{
-	dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
+	idx = irq >> 3;
+	bit = 1 << (irq & 0x07);
 
-	return __pcf50633_irq_mask_set(pcf, irq, 0);
+	pcf->mask_regs[idx] &= ~bit;
 }
-EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
 
-int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
-{
-	u8 reg, bits;
-
-	reg =  irq >> 3;
-	bits = 1 << (irq & 0x07);
-
-	return pcf->mask_regs[reg] & bits;
-}
-EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
-
-static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
-{
-	if (pcf->irq_handler[irq].handler)
-		pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
-}
+static struct irq_chip pcf50633_irq_chip = {
+	.name = "pcf50633-irq",
+	.irq_mask = pcf50633_irq_mask,
+	.irq_unmask = pcf50633_irq_unmask,
+	.irq_bus_lock = pcf50633_irq_lock,
+	.irq_bus_sync_unlock = pcf50633_irq_sync_unlock,
+};
 
 /* Maximum amount of time ONKEY is held before emergency action is taken */
 #define PCF50633_ONKEY1S_TIMEOUT 8
@@ -214,13 +186,16 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
 		pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
 	}
 
+	irq = pcf->irq_base;
 	for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
 		/* Unset masked interrupts */
 		pcf_int[i] &= ~pcf->mask_regs[i];
 
-		for (j = 0; j < 8 ; j++)
+		for (j = 0; j < 8 ; j++) {
 			if (pcf_int[i] & (1 << j))
-				pcf50633_irq_call_handler(pcf, (i * 8) + j);
+				handle_nested_irq(irq);
+			++irq;
+		}
 	}
 
 out:
@@ -240,15 +215,6 @@ int pcf50633_irq_suspend(struct pcf50633 *pcf)
 	 * henceforth */
 	disable_irq(pcf->irq);
 
-	/* Save the masks */
-	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
-				ARRAY_SIZE(pcf->suspend_irq_masks),
-					pcf->suspend_irq_masks);
-	if (ret < 0) {
-		dev_err(pcf->dev, "error saving irq masks\n");
-		goto out;
-	}
-
 	/* Write wakeup irq masks */
 	for (i = 0; i < ARRAY_SIZE(res); i++)
 		res[i] = ~pcf->pdata->resumers[i];
@@ -272,8 +238,8 @@ int pcf50633_irq_resume(struct pcf50633 *pcf)
 
 	/* Write the saved mask registers */
 	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
-				ARRAY_SIZE(pcf->suspend_irq_masks),
-					pcf->suspend_irq_masks);
+				ARRAY_SIZE(pcf->mask_regs),
+					pcf->mask_regs);
 	if (ret < 0)
 		dev_err(pcf->dev, "Error restoring saved suspend masks\n");
 
@@ -286,33 +252,61 @@ int pcf50633_irq_resume(struct pcf50633 *pcf)
 
 int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
 {
+	int irq_base;
 	int ret;
+	int i;
 
+	irq_base = irq_alloc_descs(-1, 0, PCF50633_NUM_IRQ, 0);
+	if (irq_base < 0) {
+		dev_err(pcf->dev, "Failed to allocate irq descs: %d\n", irq_base);
+		return irq_base;
+	}
+
+	mutex_init(&pcf->irq_lock);
 	pcf->irq = irq;
+	pcf->irq_base = irq_base;
+
+	/* Mask all irqs */
+	for (i = 0; i < 5; ++i)
+		pcf->mask_regs[i] = 0xff;
 
-	/* Enable all interrupts except RTC SECOND */
-	pcf->mask_regs[0] = 0x80;
-	pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
-	pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
-	pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
-	pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
-	pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
+	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
+					ARRAY_SIZE(pcf->mask_regs), pcf->mask_regs);
+	if (ret < 0)
+		goto err_irq_free_descs;
+
+
+	for (i = irq_base; i < irq_base + PCF50633_NUM_IRQ; ++i) {
+		irq_set_chip_data(i, pcf);
+		irq_set_nested_thread(i, 1);
+		irq_set_chip_and_handler(i, &pcf50633_irq_chip, handle_simple_irq);
+		irq_modify_status(i, IRQ_NOREQUEST, IRQ_NOPROBE);
+	}
 
 	ret = request_threaded_irq(irq, NULL, pcf50633_irq,
 					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 					"pcf50633", pcf);
 
-	if (ret)
+	if (ret) {
 		dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
+		goto err_irq_free_descs;
+	}
 
 	if (enable_irq_wake(irq) < 0)
 		dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
 			"in this hardware revision", irq);
 
+
+	return 0;
+
+err_irq_free_descs:
+	irq_free_descs(pcf->irq_base, PCF50633_NUM_IRQ);
+
 	return ret;
 }
 
 void pcf50633_irq_free(struct pcf50633 *pcf)
 {
 	free_irq(pcf->irq, pcf);
+	irq_free_descs(pcf->irq_base, PCF50633_NUM_IRQ);
 }
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 3699611..97dbcb2 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -24,9 +24,27 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 
+#include <linux/interrupt.h>
+
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/mbc.h>
 
+enum pcf50633_mbc_irqs {
+	PCF50633_MBC_IRQ_ADPINS,
+	PCF50633_MBC_IRQ_ADPREM,
+	PCF50633_MBC_IRQ_USBINS,
+	PCF50633_MBC_IRQ_USBREM,
+	PCF50633_MBC_IRQ_BATFULL,
+	PCF50633_MBC_IRQ_CHGHALT,
+	PCF50633_MBC_IRQ_THLIMON,
+	PCF50633_MBC_IRQ_THLIMOFF,
+	PCF50633_MBC_IRQ_USBLIMON,
+	PCF50633_MBC_IRQ_USBLIMOFF,
+	PCF50633_MBC_IRQ_LOWSYS,
+	PCF50633_MBC_IRQ_LOWBAT,
+	PCF50633_MBC_NUM_IRQS,
+};
+
 struct pcf50633_mbc {
 	struct pcf50633 *pcf;
 
@@ -36,11 +54,13 @@ struct pcf50633_mbc {
 	struct power_supply usb;
 	struct power_supply adapter;
 	struct power_supply ac;
+
+	int irqs[PCF50633_MBC_NUM_IRQS];
 };
 
-int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
+static int __pcf50633_mbc_usb_curlim_set(struct pcf50633_mbc *mbc, int ma)
 {
-	struct pcf50633_mbc *mbc = pcf->mbc;
+	struct pcf50633 *pcf = mbc->pcf;
 	int ret = 0;
 	u8 bits;
 	int charging_start = 1;
@@ -80,14 +100,14 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
 	 * gets reset to the wrong thing
 	 */
 
-	if (mbc->pcf->pdata->charger_reference_current_ma) {
-		mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma;
+	if (pcf->pdata->charger_reference_current_ma) {
+		mbcc5 = (ma << 8) / pcf->pdata->charger_reference_current_ma;
 		if (mbcc5 > 255)
 			mbcc5 = 255;
-		pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
+		pcf50633_reg_write(pcf, PCF50633_REG_MBCC5, mbcc5);
 	}
 
-	mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
+	mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
 	chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
 
 	/* If chgmod == BATFULL, setting chgena has no effect.
@@ -108,8 +128,19 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
 
 	return ret;
 }
+
+int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
+{
+	struct pcf50633_mbc *mbc = pcf->mbc;
+
+	if (!mbc)
+		return -ENODEV;
+
+	return __pcf50633_mbc_usb_curlim_set(mbc, ma);
+}
 EXPORT_SYMBOL_GPL(pcf50633_mbc_usb_curlim_set);
 
+
 int pcf50633_mbc_get_status(struct pcf50633 *pcf)
 {
 	struct pcf50633_mbc *mbc = pcf->mbc;
@@ -119,7 +150,7 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf)
 	if (!mbc)
 		return 0;
 
-	chgmod = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2)
+	chgmod = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2)
 		& PCF50633_MBCS2_MBC_MASK;
 
 	if (mbc->usb_online)
@@ -195,7 +226,7 @@ static ssize_t set_usblim(struct device *dev,
 	if (ret)
 		return -EINVAL;
 
-	pcf50633_mbc_usb_curlim_set(mbc->pcf, ma);
+	__pcf50633_mbc_usb_curlim_set(mbc, ma);
 
 	return count;
 }
@@ -259,31 +290,34 @@ static struct attribute_group mbc_attr_group = {
 	.attrs	= pcf50633_mbc_sysfs_entries,
 };
 
-static void
-pcf50633_mbc_irq_handler(int irq, void *data)
+static irqreturn_t pcf50633_mbc_irq_handler(int irq, void *data)
 {
 	struct pcf50633_mbc *mbc = data;
 
 	/* USB */
-	if (irq == PCF50633_IRQ_USBINS) {
+	if (irq == mbc->irqs[PCF50633_MBC_IRQ_USBINS]) {
 		mbc->usb_online = 1;
-	} else if (irq == PCF50633_IRQ_USBREM) {
+	} else if (irq == mbc->irqs[PCF50633_MBC_IRQ_USBREM]) {
 		mbc->usb_online = 0;
-		pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
+		__pcf50633_mbc_usb_curlim_set(mbc, 0);
 	}
 
 	/* Adapter */
-	if (irq == PCF50633_IRQ_ADPINS)
+	if (irq == mbc->irqs[PCF50633_MBC_IRQ_ADPINS])
 		mbc->adapter_online = 1;
-	else if (irq == PCF50633_IRQ_ADPREM)
+	else if (irq == mbc->irqs[PCF50633_MBC_IRQ_ADPREM])
 		mbc->adapter_online = 0;
 
 	power_supply_changed(&mbc->ac);
 	power_supply_changed(&mbc->usb);
 	power_supply_changed(&mbc->adapter);
 
-	if (mbc->pcf->pdata->mbc_event_callback)
+	if (mbc->pcf->pdata->mbc_event_callback) {
+		irq -= mbc->pcf->irq_base;
 		mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
+	}
+
+	return IRQ_HANDLED;
 }
 
 static int adapter_get_property(struct power_supply *psy,
@@ -351,19 +385,19 @@ static enum power_supply_property power_props[] = {
 	POWER_SUPPLY_PROP_ONLINE,
 };
 
-static const u8 mbc_irq_handlers[] = {
-	PCF50633_IRQ_ADPINS,
-	PCF50633_IRQ_ADPREM,
-	PCF50633_IRQ_USBINS,
-	PCF50633_IRQ_USBREM,
-	PCF50633_IRQ_BATFULL,
-	PCF50633_IRQ_CHGHALT,
-	PCF50633_IRQ_THLIMON,
-	PCF50633_IRQ_THLIMOFF,
-	PCF50633_IRQ_USBLIMON,
-	PCF50633_IRQ_USBLIMOFF,
-	PCF50633_IRQ_LOWSYS,
-	PCF50633_IRQ_LOWBAT,
+static const char *pcf50633_mbc_irq_names[PCF50633_MBC_NUM_IRQS] = {
+	"ADPINS",
+	"ADPREM",
+	"USBINS",
+	"USBREM",
+	"BATFULL",
+	"CHGHALT",
+	"THLIMON",
+	"THLIMOFF",
+	"USBLIMON",
+	"USBLIMOFF",
+	"LOWSYS",
+	"LOWBAT",
 };
 
 static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
@@ -371,6 +405,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
 	struct pcf50633 *pcf = dev_to_pcf50633(pdev->dev.parent);
 	struct pcf50633_mbc *mbc;
 	int ret;
+	int irq;
 	int i;
 	u8 mbcs1;
 
@@ -378,14 +413,20 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
 	if (!mbc)
 		return -ENOMEM;
 
+	for (i = 0; i < PCF50633_MBC_NUM_IRQS; ++i) {
+		irq = platform_get_irq_byname(pdev, pcf50633_mbc_irq_names[i]);
+		if (irq <= 0) {
+			dev_err(&pdev->dev, "Failed to get %s irq: %d\n",
+					pcf50633_mbc_irq_names[i], irq);
+			ret = irq ?: -EINVAL;
+			goto err_free;
+		}
+		mbc->irqs[i] = irq;
+	}
+
 	platform_set_drvdata(pdev, mbc);
 	mbc->pcf = pcf;
 
-	/* Set up IRQ handlers */
-	for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
-		pcf50633_register_irq(mbc->pcf, mbc_irq_handlers[i],
-					pcf50633_mbc_irq_handler, mbc);
-
 	/* Create power supplies */
 	mbc->adapter.name		= "adapter";
 	mbc->adapter.type		= POWER_SUPPLY_TYPE_MAINS;
@@ -414,40 +455,63 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
 	ret = power_supply_register(&pdev->dev, &mbc->adapter);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register adapter\n");
-		kfree(mbc);
-		return ret;
+		goto err_free;
 	}
 
 	ret = power_supply_register(&pdev->dev, &mbc->usb);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register usb\n");
-		power_supply_unregister(&mbc->adapter);
-		kfree(mbc);
-		return ret;
+		goto err_unregister_adapter;
 	}
 
 	ret = power_supply_register(&pdev->dev, &mbc->ac);
 	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to register ac\n");
-		power_supply_unregister(&mbc->adapter);
-		power_supply_unregister(&mbc->usb);
-		kfree(mbc);
-		return ret;
+		goto err_unregister_usb;
 	}
 
 	ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
-	if (ret)
+	if (ret) {
 		dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
+		goto err_unregister_ac;
+	}
+
+	/* Set up IRQ handlers */
+	for (i = 0; i < PCF50633_MBC_NUM_IRQS; ++i) {
+		ret = request_threaded_irq(mbc->irqs[i], NULL,
+				pcf50633_mbc_irq_handler, 0,
+				pcf50633_mbc_irq_names[i], mbc);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request %s irq: %d\n",
+						pcf50633_mbc_irq_names[i], ret);
+			goto err_free_irq;
+		}
+	}
 
 	mbcs1 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS1);
 	if (mbcs1 & PCF50633_MBCS1_USBPRES)
-		pcf50633_mbc_irq_handler(PCF50633_IRQ_USBINS, mbc);
+		pcf50633_mbc_irq_handler(mbc->irqs[PCF50633_MBC_IRQ_USBINS], mbc);
 	if (mbcs1 & PCF50633_MBCS1_ADAPTPRES)
-		pcf50633_mbc_irq_handler(PCF50633_IRQ_ADPINS, mbc);
+		pcf50633_mbc_irq_handler(mbc->irqs[PCF50633_MBC_IRQ_ADPINS], mbc);
 
 	pcf->mbc = mbc;
 
 	return 0;
+
+err_free_irq:
+	for (--i; i >= 0; --i)
+		free_irq(mbc->irqs[i], mbc);
+	sysfs_remove_group(&pdev->dev.kobj, &mbc_attr_group);
+err_unregister_ac:
+	power_supply_unregister(&mbc->ac);
+err_unregister_usb:
+	power_supply_unregister(&mbc->usb);
+err_unregister_adapter:
+	power_supply_unregister(&mbc->adapter);
+err_free:
+	kfree(mbc);
+
+	return ret;
 }
 
 static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
@@ -458,8 +522,8 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
 	mbc->pcf->mbc = NULL;
 
 	/* Remove IRQ handlers */
-	for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
-		pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
+	for (i = PCF50633_MBC_NUM_IRQS - 1; i >= 0; --i)
+		free_irq(mbc->irqs[i], mbc);
 
 	sysfs_remove_group(&pdev->dev.kobj, &mbc_attr_group);
 	power_supply_unregister(&mbc->usb);
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 0c42389..b0dc8c2 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -62,6 +62,8 @@ struct pcf50633_rtc {
 
 	struct pcf50633 *pcf;
 	struct rtc_device *rtc_dev;
+
+	int irq_alarm;
 };
 
 static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
@@ -90,15 +92,11 @@ static int
 pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
-	int err;
-
-	if (enabled)
-		err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
-	else
-		err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
 
-	if (err < 0)
-		return err;
+	if (enabled && !rtc->alarm_enabled)
+		enable_irq(rtc->irq_alarm);
+	else if (!enabled && rtc->alarm_enabled)
+		disable_irq(rtc->irq_alarm);
 
 	rtc->alarm_enabled = enabled;
 
@@ -142,7 +140,7 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pcf50633_rtc *rtc;
 	struct pcf50633_time pcf_tm;
-	int alarm_masked, ret = 0;
+	int ret = 0;
 
 	rtc = dev_get_drvdata(dev);
 
@@ -161,18 +159,16 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
 		pcf_tm.time[PCF50633_TI_SEC]);
 
 
-	alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
-
-	if (!alarm_masked)
-		pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+	if (rtc->alarm_enabled)
+		disable_irq(rtc->irq_alarm);
 
 	/* Returns 0 on success */
 	ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC,
 					     PCF50633_TI_EXTENT,
 					     &pcf_tm.time[0]);
 
-	if (!alarm_masked)
-		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+	if (rtc->alarm_enabled)
+		enable_irq(rtc->irq_alarm);
 
 	return ret;
 }
@@ -204,7 +200,7 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct pcf50633_rtc *rtc;
 	struct pcf50633_time pcf_tm;
-	int alarm_masked, ret = 0;
+	int ret = 0;
 
 	rtc = dev_get_drvdata(dev);
 
@@ -213,11 +209,9 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	/* do like mktime does and ignore tm_wday */
 	pcf_tm.time[PCF50633_TI_WKDAY] = 7;
 
-	alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
-
 	/* disable alarm interrupt */
-	if (!alarm_masked)
-		pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+	if (rtc->alarm_enabled)
+		disable_irq(rtc->irq_alarm);
 
 	/* Returns 0 on success */
 	ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
@@ -225,8 +219,8 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (!alrm->enabled)
 		rtc->alarm_pending = 0;
 
-	if (!alarm_masked || alrm->enabled)
-		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+	if (!rtc->alarm_enabled && alrm->enabled)
+		enable_irq(rtc->irq_alarm);
 	rtc->alarm_enabled = alrm->enabled;
 
 	return ret;
@@ -240,17 +234,26 @@ static struct rtc_class_ops pcf50633_rtc_ops = {
 	.alarm_irq_enable	= pcf50633_rtc_alarm_irq_enable,
 };
 
-static void pcf50633_rtc_irq(int irq, void *data)
+static irqreturn_t pcf50633_rtc_alarm_irq(int irq, void *data)
 {
 	struct pcf50633_rtc *rtc = data;
-
 	rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
 	rtc->alarm_pending = 1;
+
+	return IRQ_HANDLED;
 }
 
 static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
 {
 	struct pcf50633_rtc *rtc;
+	int irq_alarm;
+	int ret;
+
+	irq_alarm = platform_get_irq_byname(pdev, "ALARM");
+	if (irq_alarm <= 0) {
+		dev_err(&pdev->dev, "Failed to get alarm irq: %d\n", irq_alarm);
+		return irq_alarm ?: -EINVAL;
+	}
 
 	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
 	if (!rtc)
@@ -267,9 +270,23 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
-					pcf50633_rtc_irq, rtc);
+	ret = request_threaded_irq(irq_alarm, NULL, pcf50633_rtc_alarm_irq, 0,
+			"pcf50633-rtc alarm", rtc);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request alarm irq: %d\n", ret);
+		goto err_free;
+	}
+	disable_irq(irq_alarm);
+
+	rtc->irq_alarm = irq_alarm;
+
 	return 0;
+
+err_free_irq:
+	free_irq(irq_alarm, rtc);
+err_free:
+	kfree(rtc);
+	return ret;
 }
 
 static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
@@ -278,7 +295,7 @@ static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
 
 	rtc = platform_get_drvdata(pdev);
 
-	pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM);
+	free_irq(rtc->irq_alarm, rtc);
 
 	rtc_device_unregister(rtc->rtc_dev);
 	kfree(rtc);
diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h
index 5f486f9..bec3cb7 100644
--- a/include/linux/mfd/pcf50633/core.h
+++ b/include/linux/mfd/pcf50633/core.h
@@ -1,4 +1,5 @@
 /*
+
  * core.h  -- Core driver for NXP PCF50633
  *
  * (C) 2006-2008 by Openmoko, Inc.
@@ -14,12 +15,10 @@
 #define __LINUX_MFD_PCF50633_CORE_H
 
 #include <linux/i2c.h>
-#include <linux/workqueue.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/power_supply.h>
 #include <linux/mfd/pcf50633/backlight.h>
-#include <linux/gpio.h>
 
 struct pcf50633;
 
@@ -51,19 +50,6 @@ struct pcf50633_platform_data {
 	int gpio_base;
 };
 
-struct pcf50633_irq {
-	void (*handler) (int, void *);
-	void *data;
-};
-
-int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
-			void (*handler) (int, void *), void *data);
-int pcf50633_free_irq(struct pcf50633 *pcf, int irq);
-
-int pcf50633_irq_mask(struct pcf50633 *pcf, int irq);
-int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq);
-int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq);
-
 int pcf50633_read_block(struct pcf50633 *, u8 reg,
 					int nr_regs, u8 *data);
 int pcf50633_write_block(struct pcf50633 *pcf, u8 reg,
@@ -141,12 +127,11 @@ struct pcf50633 {
 
 	struct pcf50633_platform_data *pdata;
 	int irq;
-	struct pcf50633_irq irq_handler[PCF50633_NUM_IRQ];
-	struct work_struct irq_work;
-	struct workqueue_struct *work_queue;
 	struct mutex lock;
+	struct mutex irq_lock;
 
 	u8 mask_regs[5];
+	u8 mask_regs_cur[5];
 
 	u8 suspend_irq_masks[5];
 	u8 resume_reason[5];
@@ -154,6 +139,8 @@ struct pcf50633 {
 
 	int onkey1s_held;
 
+	unsigned int irq_base;
+
 	struct pcf50633_mbc *mbc;
 	struct pcf50633_adc *adc;
 	struct pcf50633_bl *bl;
-- 
1.7.2.5

