Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2afa62ea authored by Haojian Zhuang's avatar Haojian Zhuang Committed by Samuel Ortiz
Browse files

mfd: Use genirq in 88pm860x



Use genirq to simplify IRQ handling in 88pm860x. Remove the interface of
mask/free IRQs on 88pm860x. All these work is taken by genirq. Update the
touchscreen driver of 88pm860x since IRQ handling is changed.

Signed-off-by: default avatarHaojian Zhuang <haojian.zhuang@marvell.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 7731074a
Loading
Loading
Loading
Loading
+5 −10
Original line number Original line Diff line number Diff line
@@ -54,7 +54,6 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
	int z1, z2, rt = 0;
	int z1, z2, rt = 0;
	int ret;
	int ret;


	pm860x_mask_irq(chip, irq);
	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
	if (ret < 0)
	if (ret < 0)
		goto out;
		goto out;
@@ -83,7 +82,6 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
		dev_dbg(chip->dev, "pen release\n");
		dev_dbg(chip->dev, "pen release\n");
	}
	}
	input_sync(touch->idev);
	input_sync(touch->idev);
	pm860x_unmask_irq(chip, irq);


out:
out:
	return IRQ_HANDLED;
	return IRQ_HANDLED;
@@ -92,7 +90,6 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
static int pm860x_touch_open(struct input_dev *dev)
static int pm860x_touch_open(struct input_dev *dev)
{
{
	struct pm860x_touch *touch = input_get_drvdata(dev);
	struct pm860x_touch *touch = input_get_drvdata(dev);
	struct pm860x_chip *chip = touch->chip;
	int data, ret;
	int data, ret;


	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
@@ -100,7 +97,6 @@ static int pm860x_touch_open(struct input_dev *dev)
	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
	if (ret < 0)
	if (ret < 0)
		goto out;
		goto out;
	pm860x_unmask_irq(chip, touch->irq);
	return 0;
	return 0;
out:
out:
	return ret;
	return ret;
@@ -109,13 +105,11 @@ static int pm860x_touch_open(struct input_dev *dev)
static void pm860x_touch_close(struct input_dev *dev)
static void pm860x_touch_close(struct input_dev *dev)
{
{
	struct pm860x_touch *touch = input_get_drvdata(dev);
	struct pm860x_touch *touch = input_get_drvdata(dev);
	struct pm860x_chip *chip = touch->chip;
	int data;
	int data;


	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
	pm860x_mask_irq(chip, touch->irq);
}
}


static int __devinit pm860x_touch_probe(struct platform_device *pdev)
static int __devinit pm860x_touch_probe(struct platform_device *pdev)
@@ -164,11 +158,12 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
	touch->idev->close = pm860x_touch_close;
	touch->idev->close = pm860x_touch_close;
	touch->chip = chip;
	touch->chip = chip;
	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
	touch->irq = irq;
	touch->irq = irq + chip->irq_base;
	touch->res_x = pdata->res_x;
	touch->res_x = pdata->res_x;
	input_set_drvdata(touch->idev, touch);
	input_set_drvdata(touch->idev, touch);


	ret = pm860x_request_irq(chip, irq, pm860x_touch_handler, touch);
	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
				   IRQF_ONESHOT, "touch", touch);
	if (ret < 0)
	if (ret < 0)
		goto out_irq;
		goto out_irq;


@@ -194,7 +189,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
	platform_set_drvdata(pdev, touch);
	platform_set_drvdata(pdev, touch);
	return 0;
	return 0;
out_rg:
out_rg:
	pm860x_free_irq(chip, irq);
	free_irq(touch->irq, touch);
out_irq:
out_irq:
	input_free_device(touch->idev);
	input_free_device(touch->idev);
out:
out:
@@ -207,7 +202,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
	struct pm860x_touch *touch = platform_get_drvdata(pdev);
	struct pm860x_touch *touch = platform_get_drvdata(pdev);


	input_unregister_device(touch->idev);
	input_unregister_device(touch->idev);
	pm860x_free_irq(touch->chip, touch->irq);
	free_irq(touch->irq, touch);
	platform_set_drvdata(pdev, NULL);
	platform_set_drvdata(pdev, NULL);
	kfree(touch);
	kfree(touch);
	return 0;
	return 0;
+294 −114
Original line number Original line Diff line number Diff line
@@ -12,11 +12,14 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
#include <linux/mfd/88pm860x.h>


#define INT_STATUS_NUM			3

char pm860x_backlight_name[][MFD_NAME_SIZE] = {
char pm860x_backlight_name[][MFD_NAME_SIZE] = {
	"backlight-0",
	"backlight-0",
	"backlight-1",
	"backlight-1",
@@ -119,6 +122,42 @@ static struct mfd_cell touch_devs[] = {
	.flags	= IORESOURCE_IO,			\
	.flags	= IORESOURCE_IO,			\
}
}


static struct resource power_supply_resources[] = {
	{
		.name		= "88pm860x-power",
		.start		= PM8607_IRQ_CHG,
		.end		= PM8607_IRQ_CHG,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct mfd_cell power_devs[] = {
	{
		.name		= "88pm860x-power",
		.num_resources	= 1,
		.resources	= &power_supply_resources[0],
		.id		= -1,
	},
};

static struct resource onkey_resources[] = {
	{
		.name		= "88pm860x-onkey",
		.start		= PM8607_IRQ_ONKEY,
		.end		= PM8607_IRQ_ONKEY,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct mfd_cell onkey_devs[] = {
	{
		.name		= "88pm860x-onkey",
		.num_resources	= 1,
		.resources	= &onkey_resources[0],
		.id		= -1,
	},
};

static struct resource regulator_resources[] = {
static struct resource regulator_resources[] = {
	PM8607_REG_RESOURCE(BUCK1, BUCK1),
	PM8607_REG_RESOURCE(BUCK1, BUCK1),
	PM8607_REG_RESOURCE(BUCK2, BUCK2),
	PM8607_REG_RESOURCE(BUCK2, BUCK2),
@@ -163,129 +202,224 @@ static struct mfd_cell regulator_devs[] = {
	PM8607_REG_DEVS(ldo14, LDO14),
	PM8607_REG_DEVS(ldo14, LDO14),
};
};


#define CHECK_IRQ(irq)					\
struct pm860x_irq_data {
do {							\
	int	reg;
	if ((irq < 0) || (irq >= PM860X_NUM_IRQ))	\
	int	mask_reg;
		return -EINVAL;				\
	int	enable;		/* enable or not */
} while (0)
	int	offs;		/* bit offset in mask register */

};
/* IRQs only occur on 88PM8607 */
int pm860x_mask_irq(struct pm860x_chip *chip, int irq)
{
	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
				: chip->companion;
	int offset, data, ret;

	CHECK_IRQ(irq);

	offset = (irq >> 3) + PM8607_INT_MASK_1;
	data = 1 << (irq % 8);
	ret = pm860x_set_bits(i2c, offset, data, 0);


	return ret;
static struct pm860x_irq_data pm860x_irqs[] = {
}
	[PM8607_IRQ_ONKEY] = {
EXPORT_SYMBOL(pm860x_mask_irq);
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 0,
	},
	[PM8607_IRQ_EXTON] = {
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 1,
	},
	[PM8607_IRQ_CHG] = {
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 2,
	},
	[PM8607_IRQ_BAT] = {
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 3,
	},
	[PM8607_IRQ_RTC] = {
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 4,
	},
	[PM8607_IRQ_CC] = {
		.reg		= PM8607_INT_STATUS1,
		.mask_reg	= PM8607_INT_MASK_1,
		.offs		= 1 << 5,
	},
	[PM8607_IRQ_VBAT] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 0,
	},
	[PM8607_IRQ_VCHG] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 1,
	},
	[PM8607_IRQ_VSYS] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 2,
	},
	[PM8607_IRQ_TINT] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 3,
	},
	[PM8607_IRQ_GPADC0] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 4,
	},
	[PM8607_IRQ_GPADC1] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 5,
	},
	[PM8607_IRQ_GPADC2] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 6,
	},
	[PM8607_IRQ_GPADC3] = {
		.reg		= PM8607_INT_STATUS2,
		.mask_reg	= PM8607_INT_MASK_2,
		.offs		= 1 << 7,
	},
	[PM8607_IRQ_AUDIO_SHORT] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 0,
	},
	[PM8607_IRQ_PEN] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 1,
	},
	[PM8607_IRQ_HEADSET] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 2,
	},
	[PM8607_IRQ_HOOK] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 3,
	},
	[PM8607_IRQ_MICIN] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 4,
	},
	[PM8607_IRQ_CHG_FAIL] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 5,
	},
	[PM8607_IRQ_CHG_DONE] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 6,
	},
	[PM8607_IRQ_CHG_FAULT] = {
		.reg		= PM8607_INT_STATUS3,
		.mask_reg	= PM8607_INT_MASK_3,
		.offs		= 1 << 7,
	},
};


int pm860x_unmask_irq(struct pm860x_chip *chip, int irq)
static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
						    int irq)
{
{
	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
	return &pm860x_irqs[irq - chip->irq_base];
				: chip->companion;
	int offset, data, ret;

	CHECK_IRQ(irq);

	offset = (irq >> 3) + PM8607_INT_MASK_1;
	data = 1 << (irq % 8);
	ret = pm860x_set_bits(i2c, offset, data, data);

	return ret;
}
}
EXPORT_SYMBOL(pm860x_unmask_irq);

#define INT_STATUS_NUM		(3)


static irqreturn_t pm8607_irq_thread(int irq, void *data)
static irqreturn_t pm860x_irq(int irq, void *data)
{
{
	DECLARE_BITMAP(irq_status, PM860X_NUM_IRQ);
	struct pm860x_chip *chip = data;
	struct pm860x_chip *chip = data;
	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
	struct pm860x_irq_data *irq_data;
				: chip->companion;
	struct i2c_client *i2c;
	unsigned char status_buf[INT_STATUS_NUM << 1];
	int read_reg = -1, value = 0;
	unsigned long value;
	int i;
	int i, ret;

	irq_status[0] = 0;


	/* read out status register */
	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
	ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
				INT_STATUS_NUM << 1, status_buf);
		irq_data = &pm860x_irqs[i];
	if (ret < 0)
		if (read_reg != irq_data->reg) {
		goto out;
			read_reg = irq_data->reg;
	if (chip->irq_mode) {
			value = pm860x_reg_read(i2c, irq_data->reg);
		/* 0, clear by read. 1, clear by write */
		ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
					INT_STATUS_NUM, status_buf);
		if (ret < 0)
			goto out;
		}
		}

		if (value & irq_data->enable)
	/* clear masked interrupt status */
			handle_nested_irq(chip->irq_base + i);
	for (i = 0, value = 0; i < INT_STATUS_NUM; i++) {
	}
		status_buf[i] &= status_buf[i + INT_STATUS_NUM];
	return IRQ_HANDLED;
		irq_status[0] |= status_buf[i] << (i * 8);
}
}


	while (!bitmap_empty(irq_status, PM860X_NUM_IRQ)) {
static void pm860x_irq_lock(unsigned int irq)
		irq = find_first_bit(irq_status, PM860X_NUM_IRQ);
{
		clear_bit(irq, irq_status);
	struct pm860x_chip *chip = get_irq_chip_data(irq);
		dev_dbg(chip->dev, "Servicing IRQ #%d\n", irq);


	mutex_lock(&chip->irq_lock);
	mutex_lock(&chip->irq_lock);
		if (chip->irq[irq].handler)
			chip->irq[irq].handler(irq, chip->irq[irq].data);
		else {
			pm860x_mask_irq(chip, irq);
			dev_err(chip->dev, "Nobody cares IRQ %d. "
				"Now mask it.\n", irq);
			for (i = 0; i < (INT_STATUS_NUM << 1); i++) {
				dev_err(chip->dev, "status[%d]:%x\n", i,
					status_buf[i]);
}
}

static void pm860x_irq_sync_unlock(unsigned int irq)
{
	struct pm860x_chip *chip = get_irq_chip_data(irq);
	struct pm860x_irq_data *irq_data;
	struct i2c_client *i2c;
	static unsigned char cached[3] = {0x0, 0x0, 0x0};
	unsigned char mask[3];
	int i;

	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
	/* Load cached value. In initial, all IRQs are masked */
	for (i = 0; i < 3; i++)
		mask[i] = cached[i];
	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
		irq_data = &pm860x_irqs[i];
		switch (irq_data->mask_reg) {
		case PM8607_INT_MASK_1:
			mask[0] &= ~irq_data->offs;
			mask[0] |= irq_data->enable;
			break;
		case PM8607_INT_MASK_2:
			mask[1] &= ~irq_data->offs;
			mask[1] |= irq_data->enable;
			break;
		case PM8607_INT_MASK_3:
			mask[2] &= ~irq_data->offs;
			mask[2] |= irq_data->enable;
			break;
		default:
			dev_err(chip->dev, "wrong IRQ\n");
			break;
		}
		}
		mutex_unlock(&chip->irq_lock);
	}
	}
out:
	/* update mask into registers */
	return IRQ_HANDLED;
	for (i = 0; i < 3; i++) {
		if (mask[i] != cached[i]) {
			cached[i] = mask[i];
			pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
		}
	}
	}


int pm860x_request_irq(struct pm860x_chip *chip, int irq,
		       irq_handler_t handler, void *data)
{
	CHECK_IRQ(irq);
	if (!handler)
		return -EINVAL;

	mutex_lock(&chip->irq_lock);
	chip->irq[irq].handler = handler;
	chip->irq[irq].data = data;
	mutex_unlock(&chip->irq_lock);
	mutex_unlock(&chip->irq_lock);

	return 0;
}
}
EXPORT_SYMBOL(pm860x_request_irq);


int pm860x_free_irq(struct pm860x_chip *chip, int irq)
static void pm860x_irq_enable(unsigned int irq)
{
{
	CHECK_IRQ(irq);
	struct pm860x_chip *chip = get_irq_chip_data(irq);

	pm860x_irqs[irq - chip->irq_base].enable
	mutex_lock(&chip->irq_lock);
		= pm860x_irqs[irq - chip->irq_base].offs;
	chip->irq[irq].handler = NULL;
}
	chip->irq[irq].data = NULL;
	mutex_unlock(&chip->irq_lock);


	return 0;
static void pm860x_irq_disable(unsigned int irq)
{
	struct pm860x_chip *chip = get_irq_chip_data(irq);
	pm860x_irqs[irq - chip->irq_base].enable = 0;
}
}
EXPORT_SYMBOL(pm860x_free_irq);

static struct irq_chip pm860x_irq_chip = {
	.name		= "88pm860x",
	.bus_lock	= pm860x_irq_lock,
	.bus_sync_unlock = pm860x_irq_sync_unlock,
	.enable		= pm860x_irq_enable,
	.disable	= pm860x_irq_disable,
};


static int __devinit device_gpadc_init(struct pm860x_chip *chip,
static int __devinit device_gpadc_init(struct pm860x_chip *chip,
				       struct pm860x_platform_data *pdata)
				       struct pm860x_platform_data *pdata)
@@ -348,9 +482,15 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
				: chip->companion;
				: chip->companion;
	unsigned char status_buf[INT_STATUS_NUM];
	unsigned char status_buf[INT_STATUS_NUM];
	int data, mask, ret = -EINVAL;
	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
	struct irq_desc *desc;
	int i, data, mask, ret = -EINVAL;
	int __irq;


	mutex_init(&chip->irq_lock);
	if (!pdata || !pdata->irq_base) {
		dev_warn(chip->dev, "No interrupt support on IRQ base\n");
		return -EINVAL;
	}


	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
		| PM8607_B0_MISC1_INT_MASK;
		| PM8607_B0_MISC1_INT_MASK;
@@ -389,25 +529,45 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
	if (ret < 0)
	if (ret < 0)
		goto out;
		goto out;


	memset(chip->irq, 0, sizeof(struct pm860x_irq) * PM860X_NUM_IRQ);
	mutex_init(&chip->irq_lock);

	chip->irq_base = pdata->irq_base;
	ret = request_threaded_irq(i2c->irq, NULL, pm8607_irq_thread,
	chip->core_irq = i2c->irq;
				IRQF_ONESHOT | IRQF_TRIGGER_LOW,
	if (!chip->core_irq)
				"88PM8607", chip);
	if (ret < 0) {
		dev_err(chip->dev, "Failed to request IRQ #%d.\n", i2c->irq);
		goto out;
		goto out;

	desc = irq_to_desc(chip->core_irq);

	/* register IRQ by genirq */
	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
		__irq = i + chip->irq_base;
		set_irq_chip_data(__irq, chip);
		set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
					 handle_edge_irq);
		set_irq_nested_thread(__irq, 1);
#ifdef CONFIG_ARM
		set_irq_flags(__irq, IRQF_VALID);
#else
		set_irq_noprobe(__irq);
#endif
	}

	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
				   "88pm860x", chip);
	if (ret) {
		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
		chip->core_irq = 0;
	}
	}
	chip->chip_irq = i2c->irq;

	return 0;
	return 0;
out:
out:
	chip->core_irq = 0;
	return ret;
	return ret;
}
}


static void __devexit device_irq_exit(struct pm860x_chip *chip)
static void __devexit device_irq_exit(struct pm860x_chip *chip)
{
{
	if (chip->chip_irq >= 0)
	if (chip->core_irq)
		free_irq(chip->chip_irq, chip);
		free_irq(chip->core_irq, chip);
}
}


static void __devinit device_8606_init(struct pm860x_chip *chip,
static void __devinit device_8606_init(struct pm860x_chip *chip,
@@ -513,6 +673,26 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
			goto out_dev;
			goto out_dev;
		}
		}
	}
	}

	if (pdata && pdata->power) {
		ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
				      ARRAY_SIZE(power_devs),
				      &power_supply_resources[0], 0);
		if (ret < 0) {
			dev_err(chip->dev, "Failed to add power supply "
				"subdev\n");
			goto out_dev;
		}
	}

	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
			      ARRAY_SIZE(onkey_devs),
			      &onkey_resources[0], 0);
	if (ret < 0) {
		dev_err(chip->dev, "Failed to add onkey subdev\n");
		goto out_dev;
	}

	return;
	return;
out_dev:
out_dev:
	mfd_remove_devices(chip->dev);
	mfd_remove_devices(chip->dev);
@@ -524,7 +704,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
int pm860x_device_init(struct pm860x_chip *chip,
int pm860x_device_init(struct pm860x_chip *chip,
		       struct pm860x_platform_data *pdata)
		       struct pm860x_platform_data *pdata)
{
{
	chip->chip_irq = -EINVAL;
	chip->core_irq = 0;


	switch (chip->id) {
	switch (chip->id) {
	case CHIP_PM8606:
	case CHIP_PM8606:
+12 −18
Original line number Original line Diff line number Diff line
@@ -262,12 +262,13 @@ enum {


/* Interrupt Number in 88PM8607 */
/* Interrupt Number in 88PM8607 */
enum {
enum {
	PM8607_IRQ_ONKEY = 0,
	PM8607_IRQ_ONKEY,
	PM8607_IRQ_EXTON,
	PM8607_IRQ_EXTON,
	PM8607_IRQ_CHG,
	PM8607_IRQ_CHG,
	PM8607_IRQ_BAT,
	PM8607_IRQ_BAT,
	PM8607_IRQ_RTC,
	PM8607_IRQ_RTC,
	PM8607_IRQ_VBAT = 8,
	PM8607_IRQ_CC,
	PM8607_IRQ_VBAT,
	PM8607_IRQ_VCHG,
	PM8607_IRQ_VCHG,
	PM8607_IRQ_VSYS,
	PM8607_IRQ_VSYS,
	PM8607_IRQ_TINT,
	PM8607_IRQ_TINT,
@@ -275,7 +276,7 @@ enum {
	PM8607_IRQ_GPADC1,
	PM8607_IRQ_GPADC1,
	PM8607_IRQ_GPADC2,
	PM8607_IRQ_GPADC2,
	PM8607_IRQ_GPADC3,
	PM8607_IRQ_GPADC3,
	PM8607_IRQ_AUDIO_SHORT = 16,
	PM8607_IRQ_AUDIO_SHORT,
	PM8607_IRQ_PEN,
	PM8607_IRQ_PEN,
	PM8607_IRQ_HEADSET,
	PM8607_IRQ_HEADSET,
	PM8607_IRQ_HOOK,
	PM8607_IRQ_HOOK,
@@ -291,26 +292,19 @@ enum {
	PM8607_CHIP_B0 = 0x48,
	PM8607_CHIP_B0 = 0x48,
};
};


#define PM860X_NUM_IRQ		24

struct pm860x_irq {
	irq_handler_t		handler;
	void			*data;
};

struct pm860x_chip {
struct pm860x_chip {
	struct device		*dev;
	struct device		*dev;
	struct mutex		io_lock;
	struct mutex		io_lock;
	struct mutex		irq_lock;
	struct mutex		irq_lock;
	struct i2c_client	*client;
	struct i2c_client	*client;
	struct i2c_client	*companion;	/* companion chip client */
	struct i2c_client	*companion;	/* companion chip client */
	struct pm860x_irq	irq[PM860X_NUM_IRQ];


	int			buck3_double;	/* DVC ramp slope double */
	int			buck3_double;	/* DVC ramp slope double */
	unsigned short		companion_addr;
	unsigned short		companion_addr;
	int			id;
	int			id;
	int			irq_mode;
	int			irq_mode;
	int			chip_irq;
	int			irq_base;
	int			core_irq;
	unsigned char		chip_version;
	unsigned char		chip_version;


};
};
@@ -347,14 +341,20 @@ struct pm860x_touch_pdata {
	unsigned long	flags;
	unsigned long	flags;
};
};


struct pm860x_power_pdata {
	unsigned	fast_charge;	/* charge current */
};

struct pm860x_platform_data {
struct pm860x_platform_data {
	struct pm860x_backlight_pdata	*backlight;
	struct pm860x_backlight_pdata	*backlight;
	struct pm860x_led_pdata		*led;
	struct pm860x_led_pdata		*led;
	struct pm860x_touch_pdata	*touch;
	struct pm860x_touch_pdata	*touch;
	struct pm860x_power_pdata	*power;


	unsigned short	companion_addr;	/* I2C address of companion chip */
	unsigned short	companion_addr;	/* I2C address of companion chip */
	int		i2c_port;	/* Controlled by GI2C or PI2C */
	int		i2c_port;	/* Controlled by GI2C or PI2C */
	int		irq_mode;	/* Clear interrupt by read/write(0/1) */
	int		irq_mode;	/* Clear interrupt by read/write(0/1) */
	int		irq_base;	/* IRQ base number of 88pm860x */
	struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
	struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
};
};


@@ -368,12 +368,6 @@ extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *);
extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
			   unsigned char);
			   unsigned char);


extern int pm860x_mask_irq(struct pm860x_chip *, int);
extern int pm860x_unmask_irq(struct pm860x_chip *, int);
extern int pm860x_request_irq(struct pm860x_chip *, int,
			      irq_handler_t handler, void *);
extern int pm860x_free_irq(struct pm860x_chip *, int);

extern int pm860x_device_init(struct pm860x_chip *chip,
extern int pm860x_device_init(struct pm860x_chip *chip,
			      struct pm860x_platform_data *pdata);
			      struct pm860x_platform_data *pdata);
extern void pm860x_device_exit(struct pm860x_chip *chip);
extern void pm860x_device_exit(struct pm860x_chip *chip);