Skip to contentSkip to conversation

1. Replace mfd_data with platform_data for 88pm860x since mfd tree is upgraded.

PATCH Superseded Haojian Zhuang 6 participants 32 messages Apr 13, 2011 – Apr 18, 2011 1 message not in the archive

Subsystems (5)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): 2011041301

#2 lore raw

PATCH 1/13 input: touchscreen: use polling mode in 88pm860x

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   82 +++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 19 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +63 -19
index b3aebc2..fe12f61 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct pm860x_touch,
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;
@@ -77,30 +94,54 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = (end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec) / 1000;
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret & PM8607_STATUS_PEN)
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
 
 static int pm860x_touch_open(struct input_dev *dev)
 {
 	struct pm860x_touch *touch = input_get_drvdata(dev);
-	int data, ret;
+	int data;
 
+	/* set debounce time with 0ms */
+	pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			PD_DEBOUNCE_0MSEC);
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
-	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
 	return 0;
-out:
-	return ret;
 }
 
 static void pm860x_touch_close(struct input_dev *dev)
@@ -152,16 +193,17 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +230,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
 	free_irq(touch->irq, touch);
@@ -202,6 +245,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
 	platform_set_drvdata(pdev, NULL);
Signature · 1 line
1.5.6.5
#3 lore raw

PATCH 2/13 input: touchscreen: move initialization in 88pm860x

Move the GPADC initialization code from mfd driver to touch driver.

---
 drivers/input/touchscreen/88pm860x-ts.c |   44 +++++++++++++++++++++-----
 drivers/mfd/88pm860x-core.c             |   51 -------------------------------
 2 files changed, 35 insertions(+), 60 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +35 -9
index fe12f61..d2e1451 100644
@@ -14,6 +14,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/input.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 
 #define MEAS_LEN		(8)
@@ -154,11 +155,40 @@ static void pm860x_touch_close(struct input_dev *dev)
 	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
 }
 
+static void __devinit pm860x_gpadc_init(struct i2c_client *i2c,
+					struct pm860x_touch_pdata *pdata)
+{
+	int data;
+
+	/* set GPADC MISC1 register */
+	data = 0;
+	data |= (pdata->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
+	data |= (pdata->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
+	data |= (pdata->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
+	data |= (pdata->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
+	if (data)
+		pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+
+	/* set tsi prebias time */
+	if (pdata->tsi_prebias) {
+		data = pdata->tsi_prebias;
+		pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+	}
+
+	/* set prebias & prechg time of pen detect */
+	data = 0;
+	data |= pdata->pen_prebias & PM8607_PD_PREBIAS_MASK;
+	data |= (pdata->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
+	if (data)
+		pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+
+	pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
+			PM8607_GPADC_EN, PM8607_GPADC_EN);
+}
+
 static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_platform_data *pm860x_pdata =		\
-				pdev->dev.parent->platform_data;
 	struct pm860x_touch_pdata *pdata = NULL;
 	struct pm860x_touch *touch;
 	int irq, ret;
@@ -169,13 +199,8 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	if (!pm860x_pdata) {
-		dev_err(&pdev->dev, "platform data is missing\n");
-		return -EINVAL;
-	}
-
-	pdata = pm860x_pdata->touch;
-	if (!pdata) {
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {
 		dev_err(&pdev->dev, "touchscreen data is missing\n");
 		return -EINVAL;
 	}
@@ -229,6 +254,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 		goto out_rg;
 	}
 
+	pm860x_gpadc_init(touch->i2c, pdata);
 	platform_set_drvdata(pdev, touch);
 	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
drivers/mfd/88pm860x-core.c +0 -51

63 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#4 lore raw

PATCH 3/13 rtc: add 88pm860x rtc

Support RTC component in 88PM860x. Also support synchronize time from 88PM860x RTC to another RTC device. It should be implemented in sync callback API.

While 88PM860x RTC is enabled, it can do RTC calibration to gurantee enough power is supplied on VRTC domain of 88PM860x.

Cc Alessandro Zummo <[email protected]>
---
 drivers/mfd/88pm860x-core.c  |   31 +++
 drivers/rtc/Kconfig          |   10 +
 drivers/rtc/Makefile         |    1 +
 drivers/rtc/rtc-88pm860x.c   |  426 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/88pm860x.h |    6 +
 5 files changed, 474 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-88pm860x.c
drivers/mfd/88pm860x-core.c +31 -0
index b03cdd3..f114ec7 100644
@@ -57,6 +57,10 @@ static struct resource regulator_resources[] __initdata = {
 	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
 };
 
+static struct resource rtc_resources[] __devinitdata = {
+	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
+};
+
 static struct resource touch_resources[] __initdata = {
 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
 };
@@ -126,6 +130,10 @@ static struct mfd_cell regulator_devs[] __initdata = {
 	{"88pm860x-regulator", 17,},
 };
 
+static struct mfd_cell rtc_devs[] = {
+	{"88pm860x-rtc", -1,},
+};
+
 static struct mfd_cell touch_devs[] __initdata = {
 	{"88pm860x-touch", -1,},
 };
@@ -148,6 +156,7 @@ static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
 static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
 static struct pm860x_touch_pdata touch_pdata;
 static struct pm860x_power_pdata power_pdata;
+static struct pm860x_rtc_pdata rtc_pdata;
 
 struct pm860x_irq_data {
 	int	reg;
@@ -588,6 +597,27 @@ out:
 	return;
 }
 
+static void __devinit device_rtc_init(struct pm860x_chip *chip,
+				      struct i2c_client *i2c,
+				      struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->rtc == NULL))
+		return;
+
+	memcpy(&rtc_pdata, pdata->rtc, sizeof(struct pm860x_rtc_pdata));
+	rtc_devs[0].platform_data = &rtc_pdata;
+	rtc_devs[0].pdata_size = sizeof(rtc_pdata);
+	rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
+	rtc_devs[0].resources = &rtc_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+			      ARRAY_SIZE(rtc_devs), &rtc_resources[0],
+			      chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add rtc subdev\n");
+}
+
 static void __devinit device_touch_init(struct pm860x_chip *chip,
 					struct i2c_client *i2c,
 					struct pm860x_platform_data *pdata)
@@ -719,6 +749,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
 		goto out;
 
 	device_regulator_init(chip, i2c, pdata);
+	device_rtc_init(chip, i2c, pdata);
 	device_onkey_init(chip, i2c, pdata);
 	device_touch_init(chip, i2c, pdata);
 	device_power_init(chip, i2c, pdata);
drivers/rtc/Kconfig +10 -0
index e187887..286f51e 100644
@@ -128,6 +128,16 @@ comment "I2C RTC drivers"
 
 if I2C
 
+config RTC_DRV_88PM860X
+	tristate "Marvell 88PM860x"
+	depends on RTC_CLASS && I2C && MFD_88PM860X
+	help
+	  If you say yes here you get support for RTC function in Marvell
+	  88PM860x chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-88pm860x.
+
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
 	help
drivers/rtc/Makefile +1 -0
index ca91c3c..e3d6fb0 100644
@@ -15,6 +15,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
 
 # Keep the list ordered.
 
+obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-88pm860x.o
 obj-$(CONFIG_RTC_DRV_AB3100)	+= rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)	+= rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
drivers/rtc/rtc-88pm860x.c new file +426 -0

426 lines not on this page · raw message

include/linux/mfd/88pm860x.h +6 -0
index 8fba797..63b4fb8 100644
@@ -330,6 +330,11 @@ struct pm860x_led_pdata {
 	unsigned long	flags;
 };
 
+struct pm860x_rtc_pdata {
+	int		(*sync)(unsigned int ticks);
+	int		vrtc;
+};
+
 struct pm860x_touch_pdata {
 	int		gpadc_prebias;
 	int		slot_cycle;
@@ -349,6 +354,7 @@ struct pm860x_power_pdata {
 struct pm860x_platform_data {
 	struct pm860x_backlight_pdata	*backlight;
 	struct pm860x_led_pdata		*led;
+	struct pm860x_rtc_pdata		*rtc;
 	struct pm860x_touch_pdata	*touch;
 	struct pm860x_power_pdata	*power;
 	struct regulator_init_data	*regulator;
Signature · 1 line
1.5.6.5
#5 lore raw

PATCH 4/13 input: set the long press detection in 88pm860x onkey

Move the long-press detection from onkey handler to probe function. Avoid unnecessary I2C operation in onkey handler.

---
 drivers/input/misc/88pm860x_onkey.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/input/misc/88pm860x_onkey.c +3 -3
index 3dca3c1..1abc77e 100644
@@ -50,9 +50,6 @@ static irqreturn_t pm860x_onkey_handler(int irq, void *data)
 	ret &= ONKEY_STATUS;
 	input_report_key(info->idev, KEY_POWER, ret);
 	input_sync(info->idev);
-
-	/* Enable 8-second long onkey detection */
-	pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
 	return IRQ_HANDLED;
 }
 
@@ -105,6 +102,9 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, info);
+
+	/* Enable 8-second long onkey detection */
+	pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
 	return 0;
 
 out_irq:
Signature · 1 line
1.5.6.5
#6 lore raw

PATCH 5/13 w1: add DS278x slave driver

Append DS278x slave driver.

Cc Evgeniy Polyakov <[email protected]>
---
 drivers/w1/slaves/Kconfig     |   13 +++
 drivers/w1/slaves/Makefile    |    1 +
 drivers/w1/slaves/w1_ds278x.c |  184 +++++++++++++++++++++++++++++++++++++++++
 drivers/w1/w1_family.h        |    3 +
 4 files changed, 201 insertions(+), 0 deletions(-)
 create mode 100644 drivers/w1/slaves/w1_ds278x.c
drivers/w1/slaves/Kconfig +13 -0
index f0c9096..d737aa9 100644
@@ -61,6 +61,19 @@ config W1_SLAVE_DS2760
 
 	  If you are unsure, say N.
 
+config W1_SLAVE_DS278x
+	tristate "Dallas 278x battery monitor chip"
+	depends on W1
+	help
+	  If you enable this you will have the DS278x battery monitor
+	  chip support.
+
+	  The battery monitor chip is used in many batteries/devices
+	  as the one who is responsible for charging/discharging/monitoring
+	  Li+ batteries.
+
+	  If you are unsure, say N.
+
 config W1_SLAVE_BQ27000
 	tristate "BQ27000 slave support"
 	depends on W1
drivers/w1/slaves/Makefile +1 -0
index 3c76350..bcc134b 100644
@@ -8,4 +8,5 @@ obj-$(CONFIG_W1_SLAVE_DS2423)	+= w1_ds2423.o
 obj-$(CONFIG_W1_SLAVE_DS2431)	+= w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2760)	+= w1_ds2760.o
+obj-$(CONFIG_W1_SLAVE_DS278x)	+= w1_ds278x.o
 obj-$(CONFIG_W1_SLAVE_BQ27000)	+= w1_bq27000.o
drivers/w1/slaves/w1_ds278x.c new file +184 -0

184 lines not on this page · raw message

drivers/w1/w1_family.h +3 -0
index f3b636d..0f0b58c 100644
@@ -36,6 +36,9 @@
 #define W1_THERM_DS18B20 	0x28
 #define W1_EEPROM_DS2431	0x2D
 #define W1_FAMILY_DS2760	0x30
+#define W1_BATTMON_DS2780	0x32
+#define W1_BATTMON_DS2781	0x3D
+#define W1_BATTMON_DS2783	0x34
 
 #define MAXNAMELEN		32
 
Signature · 1 line
1.5.6.5
#7 lore raw

PATCH 6/13 mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip

This driver provides registers and IRQ of PXA3xx chips to the ds1wm driver.

Cc Evgeniy Polyakov <[email protected]>
---
 drivers/mfd/Kconfig  |    7 ++
 drivers/mfd/Makefile |    1 +
 drivers/mfd/pxa-w1.c |  150 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/pxa-w1.c
drivers/mfd/Kconfig +7 -0
index e2fea58..b6ecf90 100644
@@ -34,6 +34,13 @@ config MFD_88PM860X
 	  select individual components like voltage regulators, RTC and
 	  battery-charger under the corresponding menus.
 
+config MFD_PXA_DS1WM
+	tristate "Support DS1WM chip on Marvell silicons"
+	select MFD_CORE
+	help
+	  This core driver provides register access for PXA_DS1WM.
+	  Actual functionality is handled by the ds1wm drivers.
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
drivers/mfd/Makefile +1 -0
index 419caa9..4f8d1d2 100644
@@ -4,6 +4,7 @@
 
 88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
 obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
+obj-$(CONFIG_MFD_PXA_DS1WM)	+= pxa-w1.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 
drivers/mfd/pxa-w1.c new file +150 -0

150 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#8 lore raw

PATCH 7/13 mfd: fix build warning on 88pm860x

WARNING: vmlinux.o(.devinit.text+0x6c4): Section mismatch in reference from the function device_onkey_init() to the (unknown reference) .init.data:(unknown)
The function __devinit device_onkey_init() references a (unknown reference)
__initdata (unknown).
If (unknown) is only used by device_onkey_init then annotate (unknown) with a matching annotation.

It's caused by using __initdata on mfd cell resources. Replace __initdata with __devinitdata.

---
 drivers/mfd/88pm860x-core.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)
drivers/mfd/88pm860x-core.c +14 -14
index f114ec7..4fbc69b 100644
@@ -21,13 +21,13 @@
 
 #define INT_STATUS_NUM			3
 
-static struct resource bk_resources[] __initdata = {
+static struct resource bk_resources[] __devinitdata = {
 	{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
 	{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
 	{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
 };
 
-static struct resource led_resources[] __initdata = {
+static struct resource led_resources[] __devinitdata = {
 	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
 	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
 	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
@@ -36,7 +36,7 @@ static struct resource led_resources[] __initdata = {
 	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
 };
 
-static struct resource regulator_resources[] __initdata = {
+static struct resource regulator_resources[] __devinitdata = {
 	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
 	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
 	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
@@ -61,15 +61,15 @@ static struct resource rtc_resources[] __devinitdata = {
 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
 };
 
-static struct resource touch_resources[] __initdata = {
+static struct resource touch_resources[] __devinitdata = {
 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
 };
 
-static struct resource onkey_resources[] __initdata = {
+static struct resource onkey_resources[] __devinitdata = {
 	{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
 };
 
-static struct resource codec_resources[] __initdata = {
+static struct resource codec_resources[] __devinitdata = {
 	/* Headset microphone insertion or removal */
 	{PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
 	/* Hook-switch press or release */
@@ -80,12 +80,12 @@ static struct resource codec_resources[] __initdata = {
 	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
 };
 
-static struct resource battery_resources[] __initdata = {
+static struct resource battery_resources[] __devinitdata = {
 	{PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
 	{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
 };
 
-static struct resource charger_resources[] __initdata = {
+static struct resource charger_resources[] __devinitdata = {
 	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
 	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
 	{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout",    IORESOURCE_IRQ,},
@@ -94,13 +94,13 @@ static struct resource charger_resources[] __initdata = {
 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell bk_devs[] __initdata = {
+static struct mfd_cell bk_devs[] = {
 	{"88pm860x-backlight", 0,},
 	{"88pm860x-backlight", 1,},
 	{"88pm860x-backlight", 2,},
 };
 
-static struct mfd_cell led_devs[] __initdata = {
+static struct mfd_cell led_devs[] = {
 	{"88pm860x-led", 0,},
 	{"88pm860x-led", 1,},
 	{"88pm860x-led", 2,},
@@ -109,7 +109,7 @@ static struct mfd_cell led_devs[] __initdata = {
 	{"88pm860x-led", 5,},
 };
 
-static struct mfd_cell regulator_devs[] __initdata = {
+static struct mfd_cell regulator_devs[] = {
 	{"88pm860x-regulator", 0,},
 	{"88pm860x-regulator", 1,},
 	{"88pm860x-regulator", 2,},
@@ -134,15 +134,15 @@ static struct mfd_cell rtc_devs[] = {
 	{"88pm860x-rtc", -1,},
 };
 
-static struct mfd_cell touch_devs[] __initdata = {
+static struct mfd_cell touch_devs[] = {
 	{"88pm860x-touch", -1,},
 };
 
-static struct mfd_cell onkey_devs[] __initdata = {
+static struct mfd_cell onkey_devs[] = {
 	{"88pm860x-onkey", -1,},
 };
 
-static struct mfd_cell codec_devs[] __initdata = {
+static struct mfd_cell codec_devs[] = {
 	{"88pm860x-codec", -1,},
 };
 
Signature · 1 line
1.5.6.5
#9 lore raw

PATCH 8/13 mfd: use platform_data in max8925

Use platform_data to pass parameters to client driver.

---
 drivers/mfd/max8925-core.c  |  467 +++++++++++++++++++++++++------------------
 include/linux/mfd/max8925.h |    9 +-
 2 files changed, 274 insertions(+), 202 deletions(-)
drivers/mfd/max8925-core.c +269 -198
index 58cc5fd..044801c 100644
@@ -17,169 +17,141 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
+#include <linux/regulator/machine.h>
 
-static struct resource backlight_resources[] = {
-	{
-		.name	= "max8925-backlight",
-		.start	= MAX8925_WLED_MODE_CNTL,
-		.end	= MAX8925_WLED_CNTL,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource bk_resources[] __devinitdata = {
+	{0, 0, "max8925-backlight", IORESOURCE_IO,},
 };
 
-static struct mfd_cell backlight_devs[] = {
-	{
-		.name		= "max8925-backlight",
-		.num_resources	= 1,
-		.resources	= &backlight_resources[0],
-		.id		= -1,
-	},
+static struct resource touch_resources[] __devinitdata = {
+	{MAX8925_IRQ_TSC_STICK,  MAX8925_IRQ_TSC_STICK,  "touch stick",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_TSC_NSTICK, MAX8925_IRQ_TSC_NSTICK, "touch nstick",
+	 IORESOURCE_IRQ,},
 };
 
-static struct resource touch_resources[] = {
-	{
-		.name	= "max8925-tsc",
-		.start	= MAX8925_TSC_IRQ,
-		.end	= MAX8925_ADC_RES_END,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource power_resources[] __devinitdata = {
+	{MAX8925_IRQ_VCHG_DC_OVP,    MAX8925_IRQ_VCHG_DC_OVP,		\
+	 "dc overvoltage",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DC_F,      MAX8925_IRQ_VCHG_DC_F,		\
+	 "dc falling",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DC_R,      MAX8925_IRQ_VCHG_DC_R,		\
+	 "dc rising",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_OVP,   MAX8925_IRQ_VCHG_USB_OVP,		\
+	 "usb overvoltage",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_F,     MAX8925_IRQ_VCHG_USB_F,		\
+	 "usb falling",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_R,     MAX8925_IRQ_VCHG_USB_R,		\
+	 "usb rising",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_THM_OK_R,  MAX8925_IRQ_VCHG_THM_OK_R,		\
+	 "bat temp valid",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_THM_OK_F,  MAX8925_IRQ_VCHG_THM_OK_F,		\
+	 "bat temp invalid",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_SYSLOW_F, MAX8925_IRQ_VCHG_SYSLOW_F,		\
+	 "VSYSLOW falling",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_SYSLOW_R, MAX8925_IRQ_VCHG_SYSLOW_R,		\
+	 "VSYSLOW rising", IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_RST,       MAX8925_IRQ_VCHG_RST,		\
+	 "charger restart",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DONE,      MAX8925_IRQ_VCHG_DONE,		\
+	 "charger done",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_TOPOFF,    MAX8925_IRQ_VCHG_TOPOFF,		\
+	 "charger topoff",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_TMR_FAULT, MAX8925_IRQ_VCHG_TMR_FAULT,	\
+	 "charger expire",	IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell touch_devs[] = {
-	{
-		.name		= "max8925-touch",
-		.num_resources	= 1,
-		.resources	= &touch_resources[0],
-		.id		= -1,
-	},
+static struct resource rtc_resources[] __devinitdata = {
+	{MAX8925_IRQ_RTC_ALARM0, MAX8925_IRQ_RTC_ALARM0, "rtc-alarm0",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_RTC_ALARM1, MAX8925_IRQ_RTC_ALARM1, "rtc-alarm1",
+	 IORESOURCE_IRQ,},
 };
 
-static struct resource power_supply_resources[] = {
-	{
-		.name	= "max8925-power",
-		.start	= MAX8925_CHG_IRQ1,
-		.end	= MAX8925_CHG_IRQ1_MASK,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource onkey_resources[] __devinitdata = {
+	{MAX8925_IRQ_GPM_SW_R, MAX8925_IRQ_GPM_SW_R, "onkey R",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_GPM_SW_F, MAX8925_IRQ_GPM_SW_F, "onkey F",
+	 IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell power_devs[] = {
-	{
-		.name		= "max8925-power",
-		.num_resources	= 1,
-		.resources	= &power_supply_resources[0],
-		.id		= -1,
-	},
+static struct resource regulator_resources[] __devinitdata = {
+	{MAX8925_ID_SD1,   MAX8925_ID_SD1,   "SD1",   IORESOURCE_IO,},
+	{MAX8925_ID_SD2,   MAX8925_ID_SD2,   "SD2",   IORESOURCE_IO,},
+	{MAX8925_ID_SD3,   MAX8925_ID_SD3,   "SD3",   IORESOURCE_IO,},
+	{MAX8925_ID_LDO1,  MAX8925_ID_LDO1,  "LDO01", IORESOURCE_IO,},
+	{MAX8925_ID_LDO2,  MAX8925_ID_LDO2,  "LDO02", IORESOURCE_IO,},
+	{MAX8925_ID_LDO3,  MAX8925_ID_LDO3,  "LDO03", IORESOURCE_IO,},
+	{MAX8925_ID_LDO4,  MAX8925_ID_LDO4,  "LDO04", IORESOURCE_IO,},
+	{MAX8925_ID_LDO5,  MAX8925_ID_LDO5,  "LDO05", IORESOURCE_IO,},
+	{MAX8925_ID_LDO6,  MAX8925_ID_LDO6,  "LDO06", IORESOURCE_IO,},
+	{MAX8925_ID_LDO7,  MAX8925_ID_LDO7,  "LDO07", IORESOURCE_IO,},
+	{MAX8925_ID_LDO8,  MAX8925_ID_LDO8,  "LDO08", IORESOURCE_IO,},
+	{MAX8925_ID_LDO9,  MAX8925_ID_LDO9,  "LDO09", IORESOURCE_IO,},
+	{MAX8925_ID_LDO10, MAX8925_ID_LDO10, "LDO10", IORESOURCE_IO,},
+	{MAX8925_ID_LDO11, MAX8925_ID_LDO11, "LDO11", IORESOURCE_IO,},
+	{MAX8925_ID_LDO12, MAX8925_ID_LDO12, "LDO12", IORESOURCE_IO,},
+	{MAX8925_ID_LDO13, MAX8925_ID_LDO13, "LDO13", IORESOURCE_IO,},
+	{MAX8925_ID_LDO14, MAX8925_ID_LDO14, "LDO14", IORESOURCE_IO,},
+	{MAX8925_ID_LDO15, MAX8925_ID_LDO15, "LDO15", IORESOURCE_IO,},
+	{MAX8925_ID_LDO16, MAX8925_ID_LDO16, "LDO16", IORESOURCE_IO,},
+	{MAX8925_ID_LDO17, MAX8925_ID_LDO17, "LDO17", IORESOURCE_IO,},
+	{MAX8925_ID_LDO18, MAX8925_ID_LDO18, "LDO18", IORESOURCE_IO,},
+	{MAX8925_ID_LDO19, MAX8925_ID_LDO19, "LDO19", IORESOURCE_IO,},
+	{MAX8925_ID_LDO20, MAX8925_ID_LDO20, "LDO20", IORESOURCE_IO,},
 };
 
-static struct resource rtc_resources[] = {
-	{
-		.name	= "max8925-rtc",
-		.start	= MAX8925_RTC_IRQ,
-		.end	= MAX8925_RTC_IRQ_MASK,
-		.flags	= IORESOURCE_IO,
-	},
+static struct mfd_cell bk_devs[] = {
+	{"max8925-backlight", -1,},
 };
 
-static struct mfd_cell rtc_devs[] = {
-	{
-		.name		= "max8925-rtc",
-		.num_resources	= 1,
-		.resources	= &rtc_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell touch_devs[] = {
+	{"max8925-touch", -1,},
 };
 
-static struct resource onkey_resources[] = {
-	{
-		.name	= "max8925-onkey",
-		.start	= MAX8925_IRQ_GPM_SW_R,
-		.end	= MAX8925_IRQ_GPM_SW_R,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.name	= "max8925-onkey",
-		.start	= MAX8925_IRQ_GPM_SW_F,
-		.end	= MAX8925_IRQ_GPM_SW_F,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct mfd_cell power_devs[] = {
+	{"max8925-power", -1,},
 };
 
-static struct mfd_cell onkey_devs[] = {
-	{
-		.name		= "max8925-onkey",
-		.num_resources	= 2,
-		.resources	= &onkey_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell rtc_devs[] = {
+	{"max8925-rtc", -1,},
 };
 
-#define MAX8925_REG_RESOURCE(_start, _end)	\
-{						\
-	.start	= MAX8925_##_start,		\
-	.end	= MAX8925_##_end,		\
-	.flags	= IORESOURCE_IO,		\
-}
-
-static struct resource regulator_resources[] = {
-	MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
-	MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
-	MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
-	MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
-	MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
-	MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
-	MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
-	MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
-	MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
-	MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
-	MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
-	MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
-	MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
-	MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
-	MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
-	MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
-	MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
-	MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
-	MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
-	MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
-	MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
+static struct mfd_cell onkey_devs[] = {
+	{"max8925-onkey", -1,},
 };
 
-#define MAX8925_REG_DEVS(_id)						\
-{									\
-	.name		= "max8925-regulator",				\
-	.num_resources	= 1,						\
-	.resources	= &regulator_resources[MAX8925_ID_##_id],	\
-	.id		= MAX8925_ID_##_id,				\
-}
-
 static struct mfd_cell regulator_devs[] = {
-	MAX8925_REG_DEVS(SD1),
-	MAX8925_REG_DEVS(SD2),
-	MAX8925_REG_DEVS(SD3),
-	MAX8925_REG_DEVS(LDO1),
-	MAX8925_REG_DEVS(LDO2),
-	MAX8925_REG_DEVS(LDO3),
-	MAX8925_REG_DEVS(LDO4),
-	MAX8925_REG_DEVS(LDO5),
-	MAX8925_REG_DEVS(LDO6),
-	MAX8925_REG_DEVS(LDO7),
-	MAX8925_REG_DEVS(LDO8),
-	MAX8925_REG_DEVS(LDO9),
-	MAX8925_REG_DEVS(LDO10),
-	MAX8925_REG_DEVS(LDO11),
-	MAX8925_REG_DEVS(LDO12),
-	MAX8925_REG_DEVS(LDO13),
-	MAX8925_REG_DEVS(LDO14),
-	MAX8925_REG_DEVS(LDO15),
-	MAX8925_REG_DEVS(LDO16),
-	MAX8925_REG_DEVS(LDO17),
-	MAX8925_REG_DEVS(LDO18),
-	MAX8925_REG_DEVS(LDO19),
-	MAX8925_REG_DEVS(LDO20),
+	{"max8925-regulator", 0,},
+	{"max8925-regulator", 1,},
+	{"max8925-regulator", 2,},
+	{"max8925-regulator", 3,},
+	{"max8925-regulator", 4,},
+	{"max8925-regulator", 5,},
+	{"max8925-regulator", 6,},
+	{"max8925-regulator", 7,},
+	{"max8925-regulator", 8,},
+	{"max8925-regulator", 9,},
+	{"max8925-regulator", 10,},
+	{"max8925-regulator", 11,},
+	{"max8925-regulator", 12,},
+	{"max8925-regulator", 13,},
+	{"max8925-regulator", 14,},
+	{"max8925-regulator", 15,},
+	{"max8925-regulator", 16,},
+	{"max8925-regulator", 17,},
+	{"max8925-regulator", 18,},
+	{"max8925-regulator", 19,},
+	{"max8925-regulator", 20,},
+	{"max8925-regulator", 21,},
+	{"max8925-regulator", 22,},
 };
 
+static struct max8925_backlight_pdata bk_pdata;
+static struct max8925_touch_pdata touch_pdata;
+static struct max8925_power_pdata power_pdata;
+static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
+
 enum {
 	FLAGS_ADC = 1,	/* register in ADC component */
 	FLAGS_RTC,	/* register in RTC component */
@@ -588,6 +560,159 @@ tsc_irq:
 	return 0;
 }
 
+static void __devinit device_bk_init(struct max8925_chip *chip,
+				     struct i2c_client *i2c,
+				     struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->backlight == NULL))
+		return;
+
+	memcpy(&bk_pdata, pdata->backlight,
+		sizeof(struct max8925_backlight_pdata));
+	bk_devs[0].platform_data = &bk_pdata;
+	bk_devs[0].pdata_size = sizeof(bk_pdata);
+
+	bk_devs[0].num_resources = 1;
+	bk_devs[0].resources = &bk_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &bk_devs[0], 1,
+			      &bk_resources[0], 0);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add backlight subdev\n");
+}
+
+static void __devinit device_rtc_init(struct max8925_chip *chip,
+				      struct i2c_client *i2c,
+				      struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
+	rtc_devs[0].resources = &rtc_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 1,
+			      &rtc_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add rtc subdev\n");
+}
+
+static void __devinit device_touch_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->touch == NULL))
+		return;
+
+	memcpy(&touch_pdata, pdata->touch,
+		sizeof(struct max8925_touch_pdata));
+	touch_devs[0].platform_data = &touch_pdata;
+	touch_devs[0].pdata_size = sizeof(touch_pdata);
+	touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
+	touch_devs[0].resources = &touch_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+			      ARRAY_SIZE(touch_devs),
+			      &touch_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add touch subdev\n");
+}
+
+static void __devinit device_power_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->power == NULL))
+		return;
+
+	memcpy(&power_pdata, pdata->power,
+		sizeof(struct max8925_power_pdata));
+	power_devs[0].platform_data = &power_pdata;
+	power_devs[0].pdata_size = sizeof(power_pdata);
+	power_devs[0].num_resources = ARRAY_SIZE(power_resources);
+	power_devs[0].resources = &power_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+				ARRAY_SIZE(power_devs),
+				&power_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add power supply subdev\n");
+}
+
+static void __devinit device_onkey_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources);
+	onkey_devs[0].resources = &onkey_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+			      ARRAY_SIZE(onkey_devs),
+			      &onkey_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add onkey subdev\n");
+}
+
+static void __devinit device_regulator_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	struct regulator_init_data *initdata;
+	int ret, i, j;
+
+	if ((pdata == NULL) || (pdata->regulator == NULL))
+		return;
+
+	if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
+		pdata->num_regulators = ARRAY_SIZE(regulator_devs);
+
+	for (i = 0, j = -1; i < pdata->num_regulators; i++) {
+		initdata = &pdata->regulator[i];
+		if (strstr(initdata->constraints.name, "SD")) {
+			sscanf(initdata->constraints.name, "SD%d", &j);
+			/* SD1 ~ SD3 */
+			if ((j < 1) || (j > 3)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + MAX8925_ID_SD1;
+		}
+		if (strstr(initdata->constraints.name, "LDO")) {
+			sscanf(initdata->constraints.name, "LDO%d", &j);
+			/* LDO01 ~ LDO20 */
+			if ((j < 1) || (j > 20)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + MAX8925_ID_LDO1;
+		}
+		if (j == -1) {
+			dev_err(chip->dev, "Failed to add constraint (%s)\n",
+				initdata->constraints.name);
+			goto out;
+		}
+		memcpy(&regulator_pdata[i], &pdata->regulator[i],
+			sizeof(struct regulator_init_data));
+		regulator_devs[i].platform_data = &regulator_pdata[i];
+		regulator_devs[i].pdata_size = sizeof(regulator_pdata[i]);
+		regulator_devs[i].num_resources = 1;
+		regulator_devs[i].resources = &regulator_resources[j];
+
+		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
+				      &regulator_resources[j], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add regulator subdev\n");
+			goto out;
+		}
+	}
+out:
+	return;
+}
+
 int __devinit max8925_device_init(struct max8925_chip *chip,
 				  struct max8925_platform_data *pdata)
 {
@@ -604,75 +729,21 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
 		do {
 			ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
 		} while (ret & MAX8925_NREF_OK);
-		/* enaable ADC scheduler, interval is 1 second */
+		/* enable ADC scheduler, interval is 1 second */
 		max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
 	}
 
 	/* enable Momentary Power Loss */
 	max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
 
-	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
-			      ARRAY_SIZE(rtc_devs),
-			      &rtc_resources[0], 0);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to add rtc subdev\n");
-		goto out;
-	}
-
-	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;
-	}
-
-	if (pdata && pdata->regulator[0]) {
-		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
-				      ARRAY_SIZE(regulator_devs),
-				      &regulator_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add regulator subdev\n");
-			goto out_dev;
-		}
-	}
-
-	if (pdata && pdata->backlight) {
-		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
-				      ARRAY_SIZE(backlight_devs),
-				      &backlight_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add backlight subdev\n");
-			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;
-		}
-	}
-
-	if (pdata && pdata->touch) {
-		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
-				      ARRAY_SIZE(touch_devs),
-				      &touch_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add touch subdev\n");
-			goto out_dev;
-		}
-	}
+	device_bk_init(chip, chip->i2c, pdata);
+	device_rtc_init(chip, chip->rtc, pdata);
+	device_touch_init(chip, chip->adc, pdata);
+	device_power_init(chip, chip->adc, pdata);
+	device_onkey_init(chip, chip->i2c, pdata);
+	device_regulator_init(chip, chip->i2c, pdata);
 
 	return 0;
-out_dev:
-	mfd_remove_devices(chip->dev);
-out:
-	return ret;
 }
 
 void __devexit max8925_device_exit(struct max8925_chip *chip)
include/linux/mfd/max8925.h +5 -4
index 5259dfe..51578e2 100644
@@ -209,9 +209,9 @@ struct max8925_chip {
 };
 
 struct max8925_backlight_pdata {
-	int	lxw_scl;	/* 0/1 -- 0.8Ohm/0.4Ohm */
-	int	lxw_freq;	/* 700KHz ~ 1400KHz */
-	int	dual_string;	/* 0/1 -- single/dual string */
+	int		lxw_scl;	/* 0/1 -- 0.8Ohm/0.4Ohm */
+	int		lxw_freq;	/* 700KHz ~ 1400KHz */
+	int		dual_string;	/* 0/1 -- single/dual string */
 };
 
 struct max8925_touch_pdata {
@@ -233,10 +233,11 @@ struct max8925_platform_data {
 	struct max8925_backlight_pdata	*backlight;
 	struct max8925_touch_pdata	*touch;
 	struct max8925_power_pdata	*power;
-	struct regulator_init_data	*regulator[MAX8925_MAX_REGULATOR];
+	struct regulator_init_data	*regulator;
 
 	int		irq_base;
 	int		tsc_irq;
+	int		num_regulators;
 };
 
 extern int max8925_reg_read(struct i2c_client *, int);
Signature · 1 line
1.5.6.5
#10 lore raw

PATCH 9/13 input: get irq from resource in max8925 onkey

Avoid to use hardcoding irq numbers in max8925 onkey driver. Get irq from resources instead.

---
 drivers/input/misc/max8925_onkey.c |   36 ++++++++++++++++--------------------
 1 files changed, 16 insertions(+), 20 deletions(-)
drivers/input/misc/max8925_onkey.c +16 -20
index 7de0ded..835cc2a 100644
@@ -69,18 +69,7 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_onkey_info *info;
-	int irq[2], error;
-
-	irq[0] = platform_get_irq(pdev, 0);
-	if (irq[0] < 0) {
-		dev_err(&pdev->dev, "No IRQ resource!\n");
-		return -EINVAL;
-	}
-	irq[1] = platform_get_irq(pdev, 1);
-	if (irq[1] < 0) {
-		dev_err(&pdev->dev, "No IRQ resource!\n");
-		return -EINVAL;
-	}
+	int error = -EINVAL;
 
 	info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL);
 	if (!info)
@@ -88,21 +77,30 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
 
 	info->i2c = chip->i2c;
 	info->dev = &pdev->dev;
-	irq[0] += chip->irq_base;
-	irq[1] += chip->irq_base;
 
-	error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler,
+	info->irq[0] = platform_get_irq(pdev, 0);
+	if (info->irq[0] < 0) {
+		dev_err(&pdev->dev, "No IRQ resource!\n");
+		goto out;
+	}
+	info->irq[1] = platform_get_irq(pdev, 1);
+	if (info->irq[1] < 0) {
+		dev_err(&pdev->dev, "No IRQ resource!\n");
+		goto out;
+	}
+
+	error = request_threaded_irq(info->irq[0], NULL, max8925_onkey_handler,
 				     IRQF_ONESHOT, "onkey-down", info);
 	if (error < 0) {
 		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
-			irq[0], error);
+			info->irq[0], error);
 		goto out;
 	}
-	error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler,
+	error = request_threaded_irq(info->irq[1], NULL, max8925_onkey_handler,
 				     IRQF_ONESHOT, "onkey-up", info);
 	if (error < 0) {
 		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
-			irq[1], error);
+			info->irq[1], error);
 		goto out_irq;
 	}
 
@@ -117,8 +115,6 @@ static int __devinit max8925_onkey_probe(struct platform_device *pdev)
 	info->idev->phys = "max8925_on/input0";
 	info->idev->id.bustype = BUS_I2C;
 	info->idev->dev.parent = &pdev->dev;
-	info->irq[0] = irq[0];
-	info->irq[1] = irq[1];
 	info->idev->evbit[0] = BIT_MASK(EV_KEY);
 	info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
 
Signature · 1 line
1.5.6.5
#11 lore raw

PATCH 10/13 rtc: avoid to use hardcoding irq number in max8925

Avoid to use hardcoding irq number in max8925 rtc driver. Use irq number from resources instead.

Cc Alessandro Zummo <[email protected]>
---
 drivers/rtc/rtc-max8925.c |   22 +++++++++++++---------
 1 files changed, 13 insertions(+), 9 deletions(-)
drivers/rtc/rtc-max8925.c +13 -9
index 174036d..c460152 100644
@@ -69,6 +69,7 @@ struct max8925_rtc_info {
 	struct max8925_chip	*chip;
 	struct i2c_client	*rtc;
 	struct device		*dev;
+	int			irq;
 };
 
 static irqreturn_t rtc_update_handler(int irq, void *data)
@@ -239,7 +240,7 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_rtc_info *info;
-	int irq, ret;
+	int ret = -EINVAL;
 
 	info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL);
 	if (!info)
@@ -247,16 +248,22 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
 	info->chip = chip;
 	info->rtc = chip->rtc;
 	info->dev = &pdev->dev;
-	irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0;
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		dev_err(chip->dev, "Failed to get IRQ resource\n");
+		goto out_irq;
+	}
 
-	ret = request_threaded_irq(irq, NULL, rtc_update_handler,
+	ret = request_threaded_irq(info->irq, NULL, rtc_update_handler,
 				   IRQF_ONESHOT, "rtc-alarm0", info);
 	if (ret < 0) {
 		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
-			irq, ret);
+			info->irq, ret);
 		goto out_irq;
 	}
 
+	dev_set_drvdata(&pdev->dev, info);
+	platform_set_drvdata(pdev, info);
 	info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
 					&max8925_rtc_ops, THIS_MODULE);
 	ret = PTR_ERR(info->rtc_dev);
@@ -265,12 +272,9 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
 		goto out_rtc;
 	}
 
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
-
 	return 0;
 out_rtc:
-	free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+	free_irq(info->irq, info);
 out_irq:
 	kfree(info);
 	return ret;
@@ -281,7 +285,7 @@ static int __devexit max8925_rtc_remove(struct platform_device *pdev)
 	struct max8925_rtc_info *info = platform_get_drvdata(pdev);
 
 	if (info) {
-		free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+		free_irq(info->irq, info);
 		rtc_device_unregister(info->rtc_dev);
 		kfree(info);
 	}
Signature · 1 line
1.5.6.5
#12 lore raw

PATCH 11/13 power_supply: max8925: use platform_data from cell

Avoid to get platform_data from parent device. Get it from mfd cell device instead.

Cc Anton Vorontsov <[email protected]>
Cc David Woodhouse <[email protected]>
---
 drivers/power/max8925_power.c |   16 +++++-----------
 1 files changed, 5 insertions(+), 11 deletions(-)
drivers/power/max8925_power.c +5 -11
index 8e5aec2..359c53c 100644
@@ -425,21 +425,16 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
 static __devinit int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *max8925_pdata;
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
-	int ret;
-
-	if (pdev->dev.parent->platform_data) {
-		max8925_pdata = pdev->dev.parent->platform_data;
-		pdata = max8925_pdata->power;
-	}
+	int ret = -EINVAL;
 
-	if (!pdata) {
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {
 		dev_err(&pdev->dev, "platform data isn't assigned to "
 			"power supply\n");
 		return -EINVAL;
-	}
+	};
 
 	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
 	if (!info)
@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->chip = chip;
 	info->gpm = chip->i2c;
 	info->adc = chip->adc;
+	dev_set_drvdata(&pdev->dev, info);
 
 	info->ac.name = "max8925-ac";
 	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->topoff_threshold = pdata->topoff_threshold;
 	info->fast_charge = pdata->fast_charge;
 	info->set_charger = pdata->set_charger;
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
 
 	max8925_init_charger(chip, info);
 	return 0;
Signature · 1 line
1.5.6.5
#13 lore raw

PATCH 11/13 power_supply: max8925: use platform_data from cell

Avoid to get platform_data from parent device. Get it from mfd cell device instead.

Cc Anton Vorontsov <[email protected]>
Cc David Woodhouse <[email protected]>
---
 drivers/power/max8925_power.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)
drivers/power/max8925_power.c +2 -8
index 8e5aec2..a70e16d 100644
@@ -425,16 +425,11 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
 static __devinit int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *max8925_pdata;
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
 	int ret;
 
-	if (pdev->dev.parent->platform_data) {
-		max8925_pdata = pdev->dev.parent->platform_data;
-		pdata = max8925_pdata->power;
-	}
-
+	pdata = pdev->dev.platform_data;
 	if (!pdata) {
 		dev_err(&pdev->dev, "platform data isn't assigned to "
 			"power supply\n");
@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->chip = chip;
 	info->gpm = chip->i2c;
 	info->adc = chip->adc;
+	platform_set_drvdata(pdev, info);
 
 	info->ac.name = "max8925-ac";
 	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->topoff_threshold = pdata->topoff_threshold;
 	info->fast_charge = pdata->fast_charge;
 	info->set_charger = pdata->set_charger;
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
 
 	max8925_init_charger(chip, info);
 	return 0;
Signature · 1 line
1.5.6.5
#14 lore raw

Re: [PATCH 11/13] power_supply: max8925: use platform_data from cell

In reply to Haojian Zhuang
Quoted 7 lines · Haojian Zhuang

Avoid to get platform_data from parent device. Get it from mfd cell device instead.

Cc Anton Vorontsov <[email protected]>
Cc David Woodhouse <[email protected]>

---

I don't see the whole series, but I hope the patch doesn't break any existing in-tree users of that driver?

Quoted 11 lines
 drivers/power/max8925_power.c |   16 +++++-----------
 1 files changed, 5 insertions(+), 11 deletions(-)
drivers/power/max8925_power.c +0 -0
index 8e5aec2..359c53c 100644
@@ -425,21 +425,16 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
 static __devinit int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 430

Quoted 10 lines
drivers/power/max8925_power.c +1 -7
-	struct max8925_platform_data *max8925_pdata;
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
-	int ret;
-
-	if (pdev->dev.parent->platform_data) {
-		max8925_pdata = pdev->dev.parent->platform_data;
-		pdata = max8925_pdata->power;
-	}
+	int ret = -EINVAL;

I guess you don't need the initializer.

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 433

Quoted 4 lines
drivers/power/max8925_power.c +2 -1
-	if (!pdata) {
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {

I'd prefer to keep '!pdata'.

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 437

Quoted 5 lines
drivers/power/max8925_power.c +1 -1
 		dev_err(&pdev->dev, "platform data isn't assigned to "
 			"power supply\n");
 		return -EINVAL;
-	}
+	};

No need for the semicolon.

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct platform_device *pdev) · line 445

Quoted 8 lines
drivers/power/max8925_power.c +1 -0
 	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
 	if (!info)
@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->chip = chip;
 	info->gpm = chip->i2c;
 	info->adc = chip->adc;
+	dev_set_drvdata(&pdev->dev, info);

As this is a platform driver, you'd better do platform_set_drvdata(pdev, info), not dev_set_drvdata(). In the end, it's the same thing.

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct platform_device *pdev) · line 483

Quoted 12 lines
drivers/power/max8925_power.c +0 -2
 	info->ac.name = "max8925-ac";
 	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
 	info->topoff_threshold = pdata->topoff_threshold;
 	info->fast_charge = pdata->fast_charge;
 	info->set_charger = pdata->set_charger;
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
 
 	max8925_init_charger(chip, info);
 	return 0;

Thanks,

Signature · 2 lines
Anton Vorontsov
Email: [email protected]
#15 lore raw

RE: [PATCH 11/13] power_supply: max8925: use platform_data from cell

Quoted 15 lines

-----Original Message-----
From: Anton Vorontsov [mailto:[email protected]]
Sent: 2011年4月13日 11:03 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; David Woodhouse
Subject: Re: [PATCH 11/13] power_supply: max8925: use platform_data from cell

Quoted 3 lines · Haojian Zhuang

Avoid to get platform_data from parent device. Get it from mfd cell device instead.

Quoted 8 lines
Quoted 4 lines
Cc Anton Vorontsov <[email protected]>
Cc David Woodhouse <[email protected]>

---

I don't see the whole series, but I hope the patch doesn't break any existing in-tree users of that driver?

Excuse me for not include you in the whole series. I checked that it won't break existing code.

The fix for this patch is already sent. Please help to review.

Quoted 10 lines

Review

Quoted 4 lines
 drivers/power/max8925_power.c |   16 +++++-----------
 1 files changed, 5 insertions(+), 11 deletions(-)
(quoted diff) +0 -0

b/drivers/power/max8925_power.c

drivers/power/max8925_power.c static __devexit int

Quoted 4 lines

index 8e5aec2..359c53c 100644

drivers/power/max8925_power.c +0 -0
@@ -425,21 +425,16 @@ static __devexit int

max8925_deinit_charger(struct max8925_power_info *info)

Quoted 16 lines

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 430

Quoted 13 lines
drivers/power/max8925_power.c +1 -7
 static __devinit int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *max8925_pdata;
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
-	int ret;
-
-	if (pdev->dev.parent->platform_data) {
-		max8925_pdata = pdev->dev.parent->platform_data;
-		pdata = max8925_pdata->power;
-	}
+	int ret = -EINVAL;

I guess you don't need the initializer.

OK

Quoted 7 lines

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 433

Quoted 4 lines
drivers/power/max8925_power.c +2 -1
-	if (!pdata) {
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {

I'd prefer to keep '!pdata'.

OK

Quoted 7 lines

drivers/power/max8925_power.c static __devexit int max8925_deinit_charger(struct max8925_power_info *info) · line 437

Quoted 5 lines
drivers/power/max8925_power.c +1 -1
 		dev_err(&pdev->dev, "platform data isn't assigned to "
 			"power supply\n");
 		return -EINVAL;
-	}
+	};

No need for the semicolon.

OK

Quoted 6 lines

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct

Quoted 5 lines
drivers/power/max8925_power.c +0 -0
 	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
 	if (!info)
@@ -447,6 +442,7 @@ static __devinit int max8925_power_probe(struct

platform_device *pdev)

Quoted 9 lines

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct platform_device *pdev) · line 445

Quoted 4 lines
drivers/power/max8925_power.c +1 -0
 	info->chip = chip;
 	info->gpm = chip->i2c;
 	info->adc = chip->adc;
+	dev_set_drvdata(&pdev->dev, info);

As this is a platform driver, you'd better do platform_set_drvdata(pdev, info),
not dev_set_drvdata(). In the end, it's the same thing.

Got it.

Quoted 11 lines

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct

Quoted 4 lines
drivers/power/max8925_power.c +0 -0
 	info->ac.name = "max8925-ac";
 	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
@@ -482,8 +478,6 @@ static __devinit int max8925_power_probe(struct

platform_device *pdev)

Quoted 6 lines
drivers/power/max8925_power.c +0 -2
 	info->topoff_threshold = pdata->topoff_threshold;
 	info->fast_charge = pdata->fast_charge;
 	info->set_charger = pdata->set_charger;
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
 
Quoted 8 lines

drivers/power/max8925_power.c static __devinit int max8925_power_probe(struct platform_device *pdev) · line 483

Quoted 2 lines
drivers/power/max8925_power.c +0 -0
 	max8925_init_charger(chip, info);
 	return 0;

Thanks,

--
Anton Vorontsov
Email: [email protected]

���{.n�+�������+%�����ݶ��w��{.n�+����{��G�����{ay�ʇڙ�,j��f���h��������z_�(�階�ݢj"���m������G������?����&���~��iO��z��v�^�m���� ������?�I�

#16 lore raw

PATCH 12/13 regulator: check name in initialization of max8925

In reply to Haojian Zhuang

Check name in initialization of max8925 regulator driver.

Cc Liam Girdwood <[email protected]>
Cc Mark Brown <[email protected]>
---
 drivers/regulator/max8925-regulator.c |   37 +++++++++++++++-----------------
 1 files changed, 17 insertions(+), 20 deletions(-)
drivers/regulator/max8925-regulator.c +17 -20
index 8ae1475..ce821e4 100644
@@ -169,7 +169,7 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
 #define MAX8925_SDV(_id, min, max, step)			\
 {								\
 	.desc	= {						\
-		.name	= "SDV" #_id,				\
+		.name	= "SD" #_id,				\
 		.ops	= &max8925_regulator_sdv_ops,		\
 		.type	= REGULATOR_VOLTAGE,			\
 		.id	= MAX8925_ID_SD##_id,			\
@@ -231,39 +231,36 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
 	MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static struct max8925_regulator_info * __devinit find_regulator_info(int id)
+static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 {
-	struct max8925_regulator_info *ri;
+	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct max8925_regulator_info *ri = NULL;
+	struct regulator_init_data *pdata;
+	struct regulator_dev *rdev;
 	int i;
 
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL)
+		return -EINVAL;
+
 	for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
 		ri = &max8925_regulator_info[i];
-		if (ri->desc.id == id)
-			return ri;
+		if (!strcmp(ri->desc.name, pdata->constraints.name))
+			break;
 	}
-	return NULL;
-}
-
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
-{
-	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *pdata = chip->dev->platform_data;
-	struct max8925_regulator_info *ri;
-	struct regulator_dev *rdev;
-
-	ri = find_regulator_info(pdev->id);
-	if (ri == NULL) {
-		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+	if (i > ARRAY_SIZE(max8925_regulator_info)) {
+		dev_err(&pdev->dev, "Failed to find regulator %s\n",
+			pdata->constraints.name);
 		return -EINVAL;
 	}
 	ri->i2c = chip->i2c;
 	ri->chip = chip;
 
 	rdev = regulator_register(&ri->desc, &pdev->dev,
-				  pdata->regulator[pdev->id], ri);
+				  pdata, ri);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
-				ri->desc.name);
+			ri->desc.name);
 		return PTR_ERR(rdev);
 	}
 
Signature · 1 line
1.5.6.5
#17 lore raw

PATCH 13/13 regulator: max8925: enable i2c sequence for control

Force to enable i2c as power up/down sequence. Otherwise, SD/LDO can't be enabled or disabled via accessing i2c bus.

Cc Liam Girdwood <[email protected]>
Cc Mark Brown <[email protected]>
---
 drivers/regulator/max8925-regulator.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)
drivers/regulator/max8925-regulator.c +8 -3
index ce821e4..2dd2fd9 100644
@@ -23,6 +23,10 @@
 #define SD1_DVM_SHIFT		5		/* SDCTL1 bit5 */
 #define SD1_DVM_EN		6		/* SDV1 bit 6 */
 
+/* bit definitions in SD & LDO control registers */
+#define OUT_ENABLE   		0x1f		/* Power U/D sequence as I2C */
+#define OUT_DISABLE		0x1e		/* Power U/D sequence as I2C */
+
 struct max8925_regulator_info {
 	struct regulator_desc	desc;
 	struct regulator_dev	*regulator;
@@ -93,8 +97,8 @@ static int max8925_enable(struct regulator_dev *rdev)
 	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
 
 	return max8925_set_bits(info->i2c, info->enable_reg,
-				1 << info->enable_bit,
-				1 << info->enable_bit);
+				OUT_ENABLE << info->enable_bit,
+				OUT_ENABLE << info->enable_bit);
 }
 
 static int max8925_disable(struct regulator_dev *rdev)
@@ -102,7 +106,8 @@ static int max8925_disable(struct regulator_dev *rdev)
 	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
 
 	return max8925_set_bits(info->i2c, info->enable_reg,
-				1 << info->enable_bit, 0);
+				OUT_ENABLE << info->enable_bit,
+				OUT_DISABLE << info->enable_bit);
 }
 
 static int max8925_is_enabled(struct regulator_dev *rdev)
Signature · 1 line
1.5.6.5
Acked-by on v1 13/13
#18 lore raw

Re: [PATCH 13/13] regulator: max8925: enable i2c sequence for control

Quoted 2 lines · Haojian Zhuang

Force to enable i2c as power up/down sequence. Otherwise, SD/LDO can't be enabled or disabled via accessing i2c bus.

#19 lore raw

Re: [PATCH 12/13] regulator: check name in initialization of max8925

In reply to Haojian Zhuang

drivers/regulator/max8925-regulator.c static struct max8925_regulator_info max8925_regulator_info[] = { · line 249

Quoted 4 lines · Haojian Zhuang

Check name in initialization of max8925 regulator driver.

drivers/regulator/max8925-regulator.c +2 -0
+		if (!strcmp(ri->desc.name, pdata->constraints.name))
+			break;

This isn't a good change - the whole point of the name in the constraints is that it allows the user to assign an arbatrary string which is useful for the board. The driver should never be looking inside the constraints at all, the core will apply the constraints for you.

#20 lore raw

RE: [PATCH 12/13] regulator: check name in initialization of max8925

Quoted 14 lines

-----Original Message-----
From: Mark Brown [mailto:[email protected]]
Sent: 2011年4月17日 2:02 AM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Liam Girdwood
Subject: Re: [PATCH 12/13] regulator: check name in initialization of max8925

Quoted 1 line · Haojian Zhuang

Check name in initialization of max8925 regulator driver.

Quoted 8 lines

drivers/regulator/max8925-regulator.c static struct max8925_regulator_info max8925_regulator_info[] = { · line 249

Quoted 2 lines
drivers/regulator/max8925-regulator.c +2 -0
+		if (!strcmp(ri->desc.name, pdata->constraints.name))
+			break;

This isn't a good change - the whole point of the name in the constraints is that it allows the user to assign an arbatrary string which is useful for the board. The driver should never be looking inside the constraints at all, the core will apply the constraints for you.

I'll move the name of regulator into regulator_init_data->driver_data.

Thanks
Haojian �翳簕.n�+壏煯壄�+%娝�遍荻w�簕.n�+壏{炳G珴�妠ay�蕠跈�,jf"穐殢飦�戧鐉_璁(殠娸"濟�m���G珴�⒏?櫒璀�&x忈秈O曟瑉窔v豝�m��� �鹅�⒏?朓�

Acked-by on v1 10/13
#21 lore raw

Re: [PATCH 10/13] rtc: avoid to use hardcoding irq number in max8925

In reply to Haojian Zhuang
Quoted 4 lines · Haojian Zhuang

Avoid to use hardcoding irq number in max8925 rtc driver. Use irq number from resources instead.

Quoted 78 lines
Cc Alessandro Zummo <[email protected]>
---
 drivers/rtc/rtc-max8925.c |   22 +++++++++++++---------
 1 files changed, 13 insertions(+), 9 deletions(-)
drivers/rtc/rtc-max8925.c +2 -1
index 174036d..c460152 100644
@@ -69,6 +69,7 @@ struct max8925_rtc_info {
 	struct max8925_chip	*chip;
 	struct i2c_client	*rtc;
 	struct device		*dev;
+	int			irq;
 };
 
 static irqreturn_t rtc_update_handler(int irq, void *data)
@@ -239,7 +240,7 @@ static int __devinit max8925_rtc_probe(struct
 platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_rtc_info *info;
-	int irq, ret;
+	int ret = -EINVAL;
 
 	info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL);
drivers/rtc/rtc-max8925.c +9 -3
 	if (!info)
@@ -247,16 +248,22 @@ static int __devinit max8925_rtc_probe(struct
 platform_device *pdev)
 	info->chip = chip;
 	info->rtc = chip->rtc;
 	info->dev = &pdev->dev;
-	irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0;
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		dev_err(chip->dev, "Failed to get IRQ resource\n");
+		goto out_irq;
+	}
 
-	ret = request_threaded_irq(irq, NULL, rtc_update_handler,
+	ret = request_threaded_irq(info->irq, NULL, rtc_update_handler,
 				   IRQF_ONESHOT, "rtc-alarm0", info);
 	if (ret < 0) {
 		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
-			irq, ret);
+			info->irq, ret);
 		goto out_irq;
 	}
 
+	dev_set_drvdata(&pdev->dev, info);
+	platform_set_drvdata(pdev, info);
 	info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
 					&max8925_rtc_ops, THIS_MODULE);
drivers/rtc/rtc-max8925.c +1 -4
 	ret = PTR_ERR(info->rtc_dev);
@@ -265,12 +272,9 @@ static int __devinit max8925_rtc_probe(struct
 platform_device *pdev)
 		goto out_rtc;
 	}
 
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
-
 	return 0;
 out_rtc:
-	free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+	free_irq(info->irq, info);
 out_irq:
 	kfree(info);
drivers/rtc/rtc-max8925.c +1 -1
 	return ret;
@@ -281,7 +285,7 @@ static int __devexit max8925_rtc_remove(struct
 platform_device *pdev)
 	struct max8925_rtc_info *info = platform_get_drvdata(pdev);
 
 	if (info) {
-		free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+		free_irq(info->irq, info);
 		rtc_device_unregister(info->rtc_dev);
 		kfree(info);
Quoted 1 line

}

Added the irq to the info , Hmm.........,seems like all good to me . Thanks
Best regards

Quoted 9 lines

--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Acked-by on v1 8/13
#22 lore raw

Re: [PATCH 08/13] mfd: use platform_data in max8925

In reply to Haojian Zhuang
Quoted 3 lines · Haojian Zhuang

Use platform_data to pass parameters to client driver.

Quoted 554 lines
---
 drivers/mfd/max8925-core.c  |  467
+++++++++++++++++++++++++------------------
 include/linux/mfd/max8925.h |    9 +-
 2 files changed, 274 insertions(+), 202 deletions(-)
drivers/mfd/max8925-core.c +109 -137
index 58cc5fd..044801c 100644
@@ -17,169 +17,141 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
+#include <linux/regulator/machine.h>
 
-static struct resource backlight_resources[] = {
-	{
-		.name	= "max8925-backlight",
-		.start	= MAX8925_WLED_MODE_CNTL,
-		.end	= MAX8925_WLED_CNTL,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource bk_resources[] __devinitdata = {
+	{0, 0, "max8925-backlight", IORESOURCE_IO,},
 };
 
-static struct mfd_cell backlight_devs[] = {
-	{
-		.name		= "max8925-backlight",
-		.num_resources	= 1,
-		.resources	= &backlight_resources[0],
-		.id		= -1,
-	},
+static struct resource touch_resources[] __devinitdata = {
+	{MAX8925_IRQ_TSC_STICK,  MAX8925_IRQ_TSC_STICK,  "touch stick",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_TSC_NSTICK, MAX8925_IRQ_TSC_NSTICK, "touch nstick",
+	 IORESOURCE_IRQ,},
 };
 
-static struct resource touch_resources[] = {
-	{
-		.name	= "max8925-tsc",
-		.start	= MAX8925_TSC_IRQ,
-		.end	= MAX8925_ADC_RES_END,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource power_resources[] __devinitdata = {
+	{MAX8925_IRQ_VCHG_DC_OVP,    MAX8925_IRQ_VCHG_DC_OVP,		\
+	 "dc overvoltage",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DC_F,      MAX8925_IRQ_VCHG_DC_F,		\
+	 "dc falling",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DC_R,      MAX8925_IRQ_VCHG_DC_R,		\
+	 "dc rising",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_OVP,   MAX8925_IRQ_VCHG_USB_OVP,		\
+	 "usb overvoltage",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_F,     MAX8925_IRQ_VCHG_USB_F,		\
+	 "usb falling",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_USB_R,     MAX8925_IRQ_VCHG_USB_R,		\
+	 "usb rising",		IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_THM_OK_R,  MAX8925_IRQ_VCHG_THM_OK_R,		\
+	 "bat temp valid",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_THM_OK_F,  MAX8925_IRQ_VCHG_THM_OK_F,		\
+	 "bat temp invalid",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_SYSLOW_F, MAX8925_IRQ_VCHG_SYSLOW_F,		\
+	 "VSYSLOW falling",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_SYSLOW_R, MAX8925_IRQ_VCHG_SYSLOW_R,		\
+	 "VSYSLOW rising", IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_RST,       MAX8925_IRQ_VCHG_RST,		\
+	 "charger restart",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_DONE,      MAX8925_IRQ_VCHG_DONE,		\
+	 "charger done",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_TOPOFF,    MAX8925_IRQ_VCHG_TOPOFF,		\
+	 "charger topoff",	IORESOURCE_IRQ,},
+	{MAX8925_IRQ_VCHG_TMR_FAULT, MAX8925_IRQ_VCHG_TMR_FAULT,	\
+	 "charger expire",	IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell touch_devs[] = {
-	{
-		.name		= "max8925-touch",
-		.num_resources	= 1,
-		.resources	= &touch_resources[0],
-		.id		= -1,
-	},
+static struct resource rtc_resources[] __devinitdata = {
+	{MAX8925_IRQ_RTC_ALARM0, MAX8925_IRQ_RTC_ALARM0, "rtc-alarm0",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_RTC_ALARM1, MAX8925_IRQ_RTC_ALARM1, "rtc-alarm1",
+	 IORESOURCE_IRQ,},
 };
 
-static struct resource power_supply_resources[] = {
-	{
-		.name	= "max8925-power",
-		.start	= MAX8925_CHG_IRQ1,
-		.end	= MAX8925_CHG_IRQ1_MASK,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource onkey_resources[] __devinitdata = {
+	{MAX8925_IRQ_GPM_SW_R, MAX8925_IRQ_GPM_SW_R, "onkey R",
+	 IORESOURCE_IRQ,},
+	{MAX8925_IRQ_GPM_SW_F, MAX8925_IRQ_GPM_SW_F, "onkey F",
+	 IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell power_devs[] = {
-	{
-		.name		= "max8925-power",
-		.num_resources	= 1,
-		.resources	= &power_supply_resources[0],
-		.id		= -1,
-	},
+static struct resource regulator_resources[] __devinitdata = {
+	{MAX8925_ID_SD1,   MAX8925_ID_SD1,   "SD1",   IORESOURCE_IO,},
+	{MAX8925_ID_SD2,   MAX8925_ID_SD2,   "SD2",   IORESOURCE_IO,},
+	{MAX8925_ID_SD3,   MAX8925_ID_SD3,   "SD3",   IORESOURCE_IO,},
+	{MAX8925_ID_LDO1,  MAX8925_ID_LDO1,  "LDO01", IORESOURCE_IO,},
+	{MAX8925_ID_LDO2,  MAX8925_ID_LDO2,  "LDO02", IORESOURCE_IO,},
+	{MAX8925_ID_LDO3,  MAX8925_ID_LDO3,  "LDO03", IORESOURCE_IO,},
+	{MAX8925_ID_LDO4,  MAX8925_ID_LDO4,  "LDO04", IORESOURCE_IO,},
+	{MAX8925_ID_LDO5,  MAX8925_ID_LDO5,  "LDO05", IORESOURCE_IO,},
+	{MAX8925_ID_LDO6,  MAX8925_ID_LDO6,  "LDO06", IORESOURCE_IO,},
+	{MAX8925_ID_LDO7,  MAX8925_ID_LDO7,  "LDO07", IORESOURCE_IO,},
+	{MAX8925_ID_LDO8,  MAX8925_ID_LDO8,  "LDO08", IORESOURCE_IO,},
+	{MAX8925_ID_LDO9,  MAX8925_ID_LDO9,  "LDO09", IORESOURCE_IO,},
+	{MAX8925_ID_LDO10, MAX8925_ID_LDO10, "LDO10", IORESOURCE_IO,},
+	{MAX8925_ID_LDO11, MAX8925_ID_LDO11, "LDO11", IORESOURCE_IO,},
+	{MAX8925_ID_LDO12, MAX8925_ID_LDO12, "LDO12", IORESOURCE_IO,},
+	{MAX8925_ID_LDO13, MAX8925_ID_LDO13, "LDO13", IORESOURCE_IO,},
+	{MAX8925_ID_LDO14, MAX8925_ID_LDO14, "LDO14", IORESOURCE_IO,},
+	{MAX8925_ID_LDO15, MAX8925_ID_LDO15, "LDO15", IORESOURCE_IO,},
+	{MAX8925_ID_LDO16, MAX8925_ID_LDO16, "LDO16", IORESOURCE_IO,},
+	{MAX8925_ID_LDO17, MAX8925_ID_LDO17, "LDO17", IORESOURCE_IO,},
+	{MAX8925_ID_LDO18, MAX8925_ID_LDO18, "LDO18", IORESOURCE_IO,},
+	{MAX8925_ID_LDO19, MAX8925_ID_LDO19, "LDO19", IORESOURCE_IO,},
+	{MAX8925_ID_LDO20, MAX8925_ID_LDO20, "LDO20", IORESOURCE_IO,},
 };
 
-static struct resource rtc_resources[] = {
-	{
-		.name	= "max8925-rtc",
-		.start	= MAX8925_RTC_IRQ,
-		.end	= MAX8925_RTC_IRQ_MASK,
-		.flags	= IORESOURCE_IO,
-	},
+static struct mfd_cell bk_devs[] = {
+	{"max8925-backlight", -1,},
 };
 
-static struct mfd_cell rtc_devs[] = {
-	{
-		.name		= "max8925-rtc",
-		.num_resources	= 1,
-		.resources	= &rtc_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell touch_devs[] = {
+	{"max8925-touch", -1,},
 };
 
-static struct resource onkey_resources[] = {
-	{
-		.name	= "max8925-onkey",
-		.start	= MAX8925_IRQ_GPM_SW_R,
-		.end	= MAX8925_IRQ_GPM_SW_R,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.name	= "max8925-onkey",
-		.start	= MAX8925_IRQ_GPM_SW_F,
-		.end	= MAX8925_IRQ_GPM_SW_F,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct mfd_cell power_devs[] = {
+	{"max8925-power", -1,},
 };
 
-static struct mfd_cell onkey_devs[] = {
-	{
-		.name		= "max8925-onkey",
-		.num_resources	= 2,
-		.resources	= &onkey_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell rtc_devs[] = {
+	{"max8925-rtc", -1,},
 };
 
-#define MAX8925_REG_RESOURCE(_start, _end)	\
-{						\
-	.start	= MAX8925_##_start,		\
-	.end	= MAX8925_##_end,		\
-	.flags	= IORESOURCE_IO,		\
-}
-
-static struct resource regulator_resources[] = {
-	MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
-	MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
-	MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
-	MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
-	MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
-	MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
-	MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
-	MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
-	MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
-	MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
-	MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
-	MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
-	MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
-	MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
-	MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
-	MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
-	MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
-	MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
-	MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
-	MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
-	MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
+static struct mfd_cell onkey_devs[] = {
+	{"max8925-onkey", -1,},
 };
 
-#define MAX8925_REG_DEVS(_id)						\
-{									\
-	.name		= "max8925-regulator",				\
-	.num_resources	= 1,						\
-	.resources	= &regulator_resources[MAX8925_ID_##_id],	\
-	.id		= MAX8925_ID_##_id,				\
-}
-
 static struct mfd_cell regulator_devs[] = {
-	MAX8925_REG_DEVS(SD1),
-	MAX8925_REG_DEVS(SD2),
-	MAX8925_REG_DEVS(SD3),
-	MAX8925_REG_DEVS(LDO1),
-	MAX8925_REG_DEVS(LDO2),
-	MAX8925_REG_DEVS(LDO3),
-	MAX8925_REG_DEVS(LDO4),
-	MAX8925_REG_DEVS(LDO5),
-	MAX8925_REG_DEVS(LDO6),
-	MAX8925_REG_DEVS(LDO7),
-	MAX8925_REG_DEVS(LDO8),
-	MAX8925_REG_DEVS(LDO9),
-	MAX8925_REG_DEVS(LDO10),
-	MAX8925_REG_DEVS(LDO11),
-	MAX8925_REG_DEVS(LDO12),
-	MAX8925_REG_DEVS(LDO13),
-	MAX8925_REG_DEVS(LDO14),
-	MAX8925_REG_DEVS(LDO15),
-	MAX8925_REG_DEVS(LDO16),
-	MAX8925_REG_DEVS(LDO17),
-	MAX8925_REG_DEVS(LDO18),
-	MAX8925_REG_DEVS(LDO19),
-	MAX8925_REG_DEVS(LDO20),
+	{"max8925-regulator", 0,},
+	{"max8925-regulator", 1,},
+	{"max8925-regulator", 2,},
+	{"max8925-regulator", 3,},
+	{"max8925-regulator", 4,},
+	{"max8925-regulator", 5,},
+	{"max8925-regulator", 6,},
+	{"max8925-regulator", 7,},
+	{"max8925-regulator", 8,},
+	{"max8925-regulator", 9,},
+	{"max8925-regulator", 10,},
+	{"max8925-regulator", 11,},
+	{"max8925-regulator", 12,},
+	{"max8925-regulator", 13,},
+	{"max8925-regulator", 14,},
+	{"max8925-regulator", 15,},
+	{"max8925-regulator", 16,},
+	{"max8925-regulator", 17,},
+	{"max8925-regulator", 18,},
+	{"max8925-regulator", 19,},
+	{"max8925-regulator", 20,},
+	{"max8925-regulator", 21,},
+	{"max8925-regulator", 22,},
 };
 
+static struct max8925_backlight_pdata bk_pdata;
+static struct max8925_touch_pdata touch_pdata;
+static struct max8925_power_pdata power_pdata;
+static struct regulator_init_data
 regulator_pdata[ARRAY_SIZE(regulator_devs)];
+
 enum {
 	FLAGS_ADC = 1,	/* register in ADC component */
drivers/mfd/max8925-core.c +160 -61
 	FLAGS_RTC,	/* register in RTC component */
@@ -588,6 +560,159 @@ tsc_irq:
 	return 0;
 }
 
+static void __devinit device_bk_init(struct max8925_chip *chip,
+				     struct i2c_client *i2c,
+				     struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->backlight == NULL))
+		return;
+
+	memcpy(&bk_pdata, pdata->backlight,
+		sizeof(struct max8925_backlight_pdata));
+	bk_devs[0].platform_data = &bk_pdata;
+	bk_devs[0].pdata_size = sizeof(bk_pdata);
+
+	bk_devs[0].num_resources = 1;
+	bk_devs[0].resources = &bk_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &bk_devs[0], 1,
+			      &bk_resources[0], 0);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add backlight subdev\n");
+}
+
+static void __devinit device_rtc_init(struct max8925_chip *chip,
+				      struct i2c_client *i2c,
+				      struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
+	rtc_devs[0].resources = &rtc_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 1,
+			      &rtc_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add rtc subdev\n");
+}
+
+static void __devinit device_touch_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->touch == NULL))
+		return;
+
+	memcpy(&touch_pdata, pdata->touch,
+		sizeof(struct max8925_touch_pdata));
+	touch_devs[0].platform_data = &touch_pdata;
+	touch_devs[0].pdata_size = sizeof(touch_pdata);
+	touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
+	touch_devs[0].resources = &touch_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+			      ARRAY_SIZE(touch_devs),
+			      &touch_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add touch subdev\n");
+}
+
+static void __devinit device_power_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->power == NULL))
+		return;
+
+	memcpy(&power_pdata, pdata->power,
+		sizeof(struct max8925_power_pdata));
+	power_devs[0].platform_data = &power_pdata;
+	power_devs[0].pdata_size = sizeof(power_pdata);
+	power_devs[0].num_resources = ARRAY_SIZE(power_resources);
+	power_devs[0].resources = &power_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+				ARRAY_SIZE(power_devs),
+				&power_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add power supply subdev\n");
+}
+
+static void __devinit device_onkey_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources);
+	onkey_devs[0].resources = &onkey_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+			      ARRAY_SIZE(onkey_devs),
+			      &onkey_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add onkey subdev\n");
+}
+
+static void __devinit device_regulator_init(struct max8925_chip *chip,
+					struct i2c_client *i2c,
+					struct max8925_platform_data *pdata)
+{
+	struct regulator_init_data *initdata;
+	int ret, i, j;
+
+	if ((pdata == NULL) || (pdata->regulator == NULL))
+		return;
+
+	if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
+		pdata->num_regulators = ARRAY_SIZE(regulator_devs);
+
+	for (i = 0, j = -1; i < pdata->num_regulators; i++) {
+		initdata = &pdata->regulator[i];
+		if (strstr(initdata->constraints.name, "SD")) {
+			sscanf(initdata->constraints.name, "SD%d", &j);
+			/* SD1 ~ SD3 */
+			if ((j < 1) || (j > 3)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + MAX8925_ID_SD1;
+		}
+		if (strstr(initdata->constraints.name, "LDO")) {
+			sscanf(initdata->constraints.name, "LDO%d", &j);
+			/* LDO01 ~ LDO20 */
+			if ((j < 1) || (j > 20)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + MAX8925_ID_LDO1;
+		}
+		if (j == -1) {
+			dev_err(chip->dev, "Failed to add constraint (%s)\n",
+				initdata->constraints.name);
+			goto out;
+		}
+		memcpy(&regulator_pdata[i], &pdata->regulator[i],
+			sizeof(struct regulator_init_data));
+		regulator_devs[i].platform_data = &regulator_pdata[i];
+		regulator_devs[i].pdata_size = sizeof(regulator_pdata[i]);
+		regulator_devs[i].num_resources = 1;
+		regulator_devs[i].resources = &regulator_resources[j];
+
+		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
+				      &regulator_resources[j], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add regulator subdev\n");
+			goto out;
+		}
+	}
+out:
+	return;
+}
+
 int __devinit max8925_device_init(struct max8925_chip *chip,
 				  struct max8925_platform_data *pdata)
 {
@@ -604,75 +729,21 @@ int __devinit max8925_device_init(struct max8925_chip
 *chip,
 		do {
 			ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
 		} while (ret & MAX8925_NREF_OK);
-		/* enaable ADC scheduler, interval is 1 second */
+		/* enable ADC scheduler, interval is 1 second */
 		max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
 	}
 
 	/* enable Momentary Power Loss */
 	max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
 
-	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
-			      ARRAY_SIZE(rtc_devs),
-			      &rtc_resources[0], 0);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to add rtc subdev\n");
-		goto out;
-	}
-
-	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;
-	}
-
-	if (pdata && pdata->regulator[0]) {
-		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
-				      ARRAY_SIZE(regulator_devs),
-				      &regulator_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add regulator subdev\n");
-			goto out_dev;
-		}
-	}
-
-	if (pdata && pdata->backlight) {
-		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
-				      ARRAY_SIZE(backlight_devs),
-				      &backlight_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add backlight subdev\n");
-			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;
-		}
-	}
-
-	if (pdata && pdata->touch) {
-		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
-				      ARRAY_SIZE(touch_devs),
-				      &touch_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add touch subdev\n");
-			goto out_dev;
-		}
-	}
+	device_bk_init(chip, chip->i2c, pdata);
+	device_rtc_init(chip, chip->rtc, pdata);
+	device_touch_init(chip, chip->adc, pdata);
+	device_power_init(chip, chip->adc, pdata);
+	device_onkey_init(chip, chip->i2c, pdata);
+	device_regulator_init(chip, chip->i2c, pdata);
 
 	return 0;
-out_dev:
-	mfd_remove_devices(chip->dev);
-out:
-	return ret;
 }
 

void __devexit max8925_device_exit(struct max8925_chip *chip)

include/linux/mfd/max8925.h +3 -3
index 5259dfe..51578e2 100644
@@ -209,9 +209,9 @@ struct max8925_chip {
 };
 
 struct max8925_backlight_pdata {
-	int	lxw_scl;	/* 0/1 -- 0.8Ohm/0.4Ohm */
-	int	lxw_freq;	/* 700KHz ~ 1400KHz */
-	int	dual_string;	/* 0/1 -- single/dual string */
+	int		lxw_scl;	/* 0/1 -- 0.8Ohm/0.4Ohm */
+	int		lxw_freq;	/* 700KHz ~ 1400KHz */
+	int		dual_string;	/* 0/1 -- single/dual string */
 };
 
 struct max8925_touch_pdata {
@@ -233,10 +233,11 @@ struct max8925_platform_data {
 	struct max8925_backlight_pdata	*backlight;
 	struct max8925_touch_pdata	*touch;

include/linux/mfd/max8925.h struct max8925_platform_data { · line 243

Quoted 10 lines
include/linux/mfd/max8925.h +2 -1
 	struct max8925_power_pdata	*power;
-	struct regulator_init_data	*regulator[MAX8925_MAX_REGULATOR];
+	struct regulator_init_data	*regulator;
 
 	int		irq_base;
 	int		tsc_irq;
+	int		num_regulators;
 };
 
 extern int max8925_reg_read(struct i2c_client *, int);

More nice code than before to me .
Cheers
Best regards .

Quoted 9 lines

--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#23 lore raw

Re: [PATCH 06/13] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip

In reply to Haojian Zhuang
Quoted 115 lines · Haojian Zhuang

This driver provides registers and IRQ of PXA3xx chips to the ds1wm driver.

Cc Evgeniy Polyakov <[email protected]>
---
 drivers/mfd/Kconfig  |    7 ++
 drivers/mfd/Makefile |    1 +
 drivers/mfd/pxa-w1.c |  150
++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/pxa-w1.c
drivers/mfd/Kconfig +7 -0
index e2fea58..b6ecf90 100644
@@ -34,6 +34,13 @@ config MFD_88PM860X
 	  select individual components like voltage regulators, RTC and
 	  battery-charger under the corresponding menus.
 
+config MFD_PXA_DS1WM
+	tristate "Support DS1WM chip on Marvell silicons"
+	select MFD_CORE
+	help
+	  This core driver provides register access for PXA_DS1WM.
+	  Actual functionality is handled by the ds1wm drivers.
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
drivers/mfd/Makefile +1 -0
index 419caa9..4f8d1d2 100644
@@ -4,6 +4,7 @@
 
 88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
 obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
+obj-$(CONFIG_MFD_PXA_DS1WM)	+= pxa-w1.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 
drivers/mfd/pxa-w1.c new file +67 -0
new file mode 100644
index 0000000..98074ff
@@ -0,0 +1,150 @@
+/*
+ * Core driver for PXA DS1WM chip.
+ *
+ * Copyright (C) 2010 Marvell  <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ds1wm.h>
+
+struct pxa_w1_info {
+	struct clk *clk;
+};
+
+static int ds1wm_enable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_enable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (active)\n");
+	return 0;
+}
+
+static int ds1wm_disable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_disable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (in-active)\n");
+	return 0;
+}
+
+static struct resource ds1wm_resources[] __devinitdata = {
+	{0, 0, "ds1wm-mem", IORESOURCE_MEM,},
+	{0, 0, "ds1wm-irq", IORESOURCE_IRQ,},
+};
+
+static struct ds1wm_driver_data ds1wm_pdata;
+
+static struct mfd_cell ds1wm_cell __devinitdata = {
+	.name		= "ds1wm",
+	.enable		= ds1wm_enable,
+	.disable	= ds1wm_disable,
+	.platform_data	= &ds1wm_pdata,
+	.pdata_size	= sizeof(ds1wm_pdata),
+	.num_resources	= ARRAY_SIZE(ds1wm_resources),
+	.resources	= ds1wm_resources,
+};
+
+static int __devinit pxa_w1_probe(struct platform_device *pdev)
+{
+	struct ds1wm_driver_data *pdata = pdev->dev.platform_data;

drivers/mfd/pxa-w1.c line 77

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+	struct pxa_w1_info *info;
+	struct resource *r;
+	int ret, irq;
+
+	info = kzalloc(sizeof(struct pxa_w1_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {

Prefer to (!r) ?

drivers/mfd/pxa-w1.c line 90

Quoted 13 lines
drivers/mfd/pxa-w1.c new file +13 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	irq = r->start;
+	if (pdata)
+		ds1wm_pdata.active_high = pdata->active_high;
+	if (ds1wm_pdata.active_high)
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_HIGHEDGE;
+	else
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_LOWEDGE;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {

The same ?

Quoted 50 lines
drivers/mfd/pxa-w1.c new file +50 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	ds1wm_resources[0].end = resource_size(r) - 1;
+
+	info->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(info->clk)) {
+		ret = PTR_ERR(info->clk);
+		goto out;
+	}
+	platform_set_drvdata(pdev, info);
+
+	ds1wm_pdata.clock_rate = clk_get_rate(info->clk);
+	ret = mfd_add_devices(&pdev->dev, pdev->id, &ds1wm_cell, 1, r, irq);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to register pxa DS1WM\n");
+
+	return 0;
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit pxa_w1_remove(struct platform_device *pdev)
+{
+	struct pxa_w1_info *info = platform_get_drvdata(pdev);
+
+	mfd_remove_devices(&pdev->dev);
+	clk_put(info->clk);
+	kfree(info);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver pxa_w1_driver = {
+	.driver = {
+		   .name	= "pxa3xx-w1",
+		   .owner	= THIS_MODULE,
+	},
+	.probe		= pxa_w1_probe,
+	.remove		= __devexit_p(pxa_w1_remove),
+};
+
+static int __init pxa_w1_base_init(void)
+{
+	return platform_driver_register(&pxa_w1_driver);
+}
+
+static void __exit pxa_w1_base_exit(void)
+{

drivers/mfd/pxa-w1.c line 150

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+	platform_driver_unregister(&pxa_w1_driver);
+}
+
+module_init(pxa_w1_base_init);
+module_exit(pxa_w1_base_exit);
+
+MODULE_AUTHOR("Jett Zhou <[email protected]>");
+MODULE_DESCRIPTION("one wire driver for PXA");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-w1");

Best regards ,
Thanks

Quoted 9 lines

--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#24 lore raw

RE: [PATCH 06/13] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip

Quoted 134 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Wanlong Gao
Sent: 2011年4月14日 10:18 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Evgeniy Polyakov
Subject: Re: [PATCH 06/13] mfd: pxa-w1: MFD driver for PXA 1wire control
+ DS1WM chip

Quoted 1 line · Haojian Zhuang

This driver provides registers and IRQ of PXA3xx chips to the ds1wm

driver.

Quoted 47 lines
Cc Evgeniy Polyakov <[email protected]>
---
 drivers/mfd/Kconfig  |    7 ++
 drivers/mfd/Makefile |    1 +
 drivers/mfd/pxa-w1.c |  150
++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/pxa-w1.c
drivers/mfd/Kconfig +7 -0
index e2fea58..b6ecf90 100644
@@ -34,6 +34,13 @@ config MFD_88PM860X
 	  select individual components like voltage regulators, RTC and
 	  battery-charger under the corresponding menus.
 
+config MFD_PXA_DS1WM
+	tristate "Support DS1WM chip on Marvell silicons"
+	select MFD_CORE
+	help
+	  This core driver provides register access for PXA_DS1WM.
+	  Actual functionality is handled by the ds1wm drivers.
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
drivers/mfd/Makefile +1 -0
index 419caa9..4f8d1d2 100644
@@ -4,6 +4,7 @@
 
 88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
 obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
+obj-$(CONFIG_MFD_PXA_DS1WM)	+= pxa-w1.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 
drivers/mfd/pxa-w1.c new file +0 -0
new file mode 100644
index 0000000..98074ff

drivers/mfd/pxa-w1.c line 6

Quoted 6 lines
drivers/mfd/pxa-w1.c new file +6 -0
@@ -0,0 +1,150 @@
+/*
+ * Core driver for PXA DS1WM chip.
+ *
+ * Copyright (C) 2010 Marvell  <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or

modify

drivers/mfd/pxa-w1.c line 7

Quoted 1 line
drivers/mfd/pxa-w1.c new file +1 -0
+ * it under the terms of the GNU General Public License as published

by

Quoted 63 lines
drivers/mfd/pxa-w1.c new file +63 -0
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ds1wm.h>
+
+struct pxa_w1_info {
+	struct clk *clk;
+};
+
+static int ds1wm_enable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_enable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (active)\n");
+	return 0;
+}
+
+static int ds1wm_disable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_disable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (in-active)\n");
+	return 0;
+}
+
+static struct resource ds1wm_resources[] __devinitdata = {
+	{0, 0, "ds1wm-mem", IORESOURCE_MEM,},
+	{0, 0, "ds1wm-irq", IORESOURCE_IRQ,},
+};
+
+static struct ds1wm_driver_data ds1wm_pdata;
+
+static struct mfd_cell ds1wm_cell __devinitdata = {
+	.name		= "ds1wm",
+	.enable		= ds1wm_enable,
+	.disable	= ds1wm_disable,
+	.platform_data	= &ds1wm_pdata,
+	.pdata_size	= sizeof(ds1wm_pdata),
+	.num_resources	= ARRAY_SIZE(ds1wm_resources),
+	.resources	= ds1wm_resources,
+};
+
+static int __devinit pxa_w1_probe(struct platform_device *pdev)
+{
+	struct ds1wm_driver_data *pdata = pdev->dev.platform_data;
+	struct pxa_w1_info *info;
+	struct resource *r;
+	int ret, irq;
Quoted 8 lines

drivers/mfd/pxa-w1.c line 77

Quoted 7 lines
drivers/mfd/pxa-w1.c new file +7 -0
+
+	info = kzalloc(sizeof(struct pxa_w1_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {

Prefer to (!r) ?

Why do you always stick to use !r? I like to use NULL since it's clear to me.

Quoted 78 lines

drivers/mfd/pxa-w1.c line 90

Quoted 13 lines
drivers/mfd/pxa-w1.c new file +13 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	irq = r->start;
+	if (pdata)
+		ds1wm_pdata.active_high = pdata->active_high;
+	if (ds1wm_pdata.active_high)
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_HIGHEDGE;
+	else
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_LOWEDGE;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {

The same ?

Quoted 4 lines
drivers/mfd/pxa-w1.c new file +4 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	ds1wm_resources[0].end = resource_size(r) - 1;

drivers/mfd/pxa-w1.c

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+
+	info->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(info->clk)) {
+		ret = PTR_ERR(info->clk);
+		goto out;
+	}
+	platform_set_drvdata(pdev, info);
+
+	ds1wm_pdata.clock_rate = clk_get_rate(info->clk);
+	ret = mfd_add_devices(&pdev->dev, pdev->id, &ds1wm_cell, 1, r,

irq);

Quoted 36 lines
drivers/mfd/pxa-w1.c new file +36 -0
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to register pxa DS1WM\n");
+
+	return 0;
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit pxa_w1_remove(struct platform_device *pdev)
+{
+	struct pxa_w1_info *info = platform_get_drvdata(pdev);
+
+	mfd_remove_devices(&pdev->dev);
+	clk_put(info->clk);
+	kfree(info);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver pxa_w1_driver = {
+	.driver = {
+		   .name	= "pxa3xx-w1",
+		   .owner	= THIS_MODULE,
+	},
+	.probe		= pxa_w1_probe,
+	.remove		= __devexit_p(pxa_w1_remove),
+};
+
+static int __init pxa_w1_base_init(void)
+{
+	return platform_driver_register(&pxa_w1_driver);
+}
+
+static void __exit pxa_w1_base_exit(void)
+{

drivers/mfd/pxa-w1.c line 150

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+	platform_driver_unregister(&pxa_w1_driver);
+}
+
+module_init(pxa_w1_base_init);
+module_exit(pxa_w1_base_exit);
+
+MODULE_AUTHOR("Jett Zhou <[email protected]>");
+MODULE_DESCRIPTION("one wire driver for PXA");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-w1");

Best regards ,
Thanks

Quoted 10 lines
Quoted 5 lines

--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-

kernel" in

Quoted 4 lines

the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

�翳簕.n�+壏煯壄�+%娝�遍荻w�簕.n�+壏{炳G珴�妠ay�蕠跈�,jf"穐殢飦�戧鐉_璁(殠娸"濟�m���G珴�⒏?櫒璀�&x忈秈O曟瑉窔v豝�m��� �鹅�⒏?朓�

#25 lore raw

Re: [PATCH 06/13] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip

Quoted 143 lines · Haojian Zhuang
Quoted 134 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Wanlong Gao
Sent: 2011年4月14日 10:18 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Evgeniy Polyakov
Subject: Re: [PATCH 06/13] mfd: pxa-w1: MFD driver for PXA 1wire control
+ DS1WM chip

Quoted 1 line · Haojian Zhuang

This driver provides registers and IRQ of PXA3xx chips to the ds1wm

driver.

Quoted 47 lines
Cc Evgeniy Polyakov<[email protected]>
---
  drivers/mfd/Kconfig  |    7 ++
  drivers/mfd/Makefile |    1 +
  drivers/mfd/pxa-w1.c |  150
++++++++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 158 insertions(+), 0 deletions(-)

create mode 100644 drivers/mfd/pxa-w1.c

drivers/mfd/Kconfig +7 -0
index e2fea58..b6ecf90 100644
@@ -34,6 +34,13 @@ config MFD_88PM860X
  	  select individual components like voltage regulators, RTC and
  	  battery-charger under the corresponding menus.
 
+config MFD_PXA_DS1WM
+	tristate "Support DS1WM chip on Marvell silicons"
+	select MFD_CORE
+	help
+	  This core driver provides register access for PXA_DS1WM.
+	  Actual functionality is handled by the ds1wm drivers.
+
  config MFD_SM501
  	tristate "Support for Silicon Motion SM501"
  	 ---help---
drivers/mfd/Makefile +1 -0
index 419caa9..4f8d1d2 100644
@@ -4,6 +4,7 @@
 
  88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
  obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
+obj-$(CONFIG_MFD_PXA_DS1WM)	+= pxa-w1.o
  obj-$(CONFIG_MFD_SM501)		+= sm501.o
  obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 
drivers/mfd/pxa-w1.c new file +0 -0
new file mode 100644
index 0000000..98074ff

drivers/mfd/pxa-w1.c line 6

Quoted 6 lines
drivers/mfd/pxa-w1.c new file +6 -0
@@ -0,0 +1,150 @@
+/*
+ * Core driver for PXA DS1WM chip.
+ *
+ * Copyright (C) 2010 Marvell<[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or

modify

drivers/mfd/pxa-w1.c line 7

Quoted 1 line
drivers/mfd/pxa-w1.c new file +1 -0
+ * it under the terms of the GNU General Public License as published

by

Quoted 63 lines
drivers/mfd/pxa-w1.c new file +63 -0
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include<linux/init.h>
+#include<linux/module.h>
+#include<linux/slab.h>
+#include<linux/platform_device.h>
+#include<linux/gpio.h>
+#include<linux/io.h>
+#include<linux/irq.h>
+#include<linux/clk.h>
+#include<linux/err.h>
+#include<linux/interrupt.h>
+#include<linux/mfd/core.h>
+#include<linux/mfd/ds1wm.h>
+
+struct pxa_w1_info {
+	struct clk *clk;
+};
+
+static int ds1wm_enable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_enable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (active)\n");
+	return 0;
+}
+
+static int ds1wm_disable(struct platform_device *pdev)
+{
+	struct device *dev = pdev->dev.parent;
+	struct pxa_w1_info *info = dev_get_drvdata(dev);
+
+	clk_disable(info->clk);
+	dev_dbg(dev, "pxa DS1WM clk (in-active)\n");
+	return 0;
+}
+
+static struct resource ds1wm_resources[] __devinitdata = {
+	{0, 0, "ds1wm-mem", IORESOURCE_MEM,},
+	{0, 0, "ds1wm-irq", IORESOURCE_IRQ,},
+};
+
+static struct ds1wm_driver_data ds1wm_pdata;
+
+static struct mfd_cell ds1wm_cell __devinitdata = {
+	.name		= "ds1wm",
+	.enable		= ds1wm_enable,
+	.disable	= ds1wm_disable,
+	.platform_data	=&ds1wm_pdata,
+	.pdata_size	= sizeof(ds1wm_pdata),
+	.num_resources	= ARRAY_SIZE(ds1wm_resources),
+	.resources	= ds1wm_resources,
+};
+
+static int __devinit pxa_w1_probe(struct platform_device *pdev)
+{
+	struct ds1wm_driver_data *pdata = pdev->dev.platform_data;
+	struct pxa_w1_info *info;
+	struct resource *r;
+	int ret, irq;
Quoted 8 lines

drivers/mfd/pxa-w1.c line 77

Quoted 7 lines
drivers/mfd/pxa-w1.c new file +7 -0
+
+	info = kzalloc(sizeof(struct pxa_w1_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {

Prefer to (!r) ?

Quoted 2 lines

Why do you always stick to use !r? I like to use NULL since it's clear to me.

Use your habits and I just make a noise .
Thanks

Quoted 88 lines
Quoted 88 lines

drivers/mfd/pxa-w1.c line 90

Quoted 13 lines
drivers/mfd/pxa-w1.c new file +13 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	irq = r->start;
+	if (pdata)
+		ds1wm_pdata.active_high = pdata->active_high;
+	if (ds1wm_pdata.active_high)
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_HIGHEDGE;
+	else
+		ds1wm_resources[1].flags |= IORESOURCE_IRQ_LOWEDGE;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {

The same ?

Quoted 4 lines
drivers/mfd/pxa-w1.c new file +4 -0
+		ret = -ENXIO;
+		goto out;
+	}
+	ds1wm_resources[0].end = resource_size(r) - 1;

drivers/mfd/pxa-w1.c

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+
+	info->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(info->clk)) {
+		ret = PTR_ERR(info->clk);
+		goto out;
+	}
+	platform_set_drvdata(pdev, info);
+
+	ds1wm_pdata.clock_rate = clk_get_rate(info->clk);
+	ret = mfd_add_devices(&pdev->dev, pdev->id,&ds1wm_cell, 1, r,

irq);

Quoted 36 lines
drivers/mfd/pxa-w1.c new file +36 -0
+	if (ret<  0)
+		dev_err(&pdev->dev, "failed to register pxa DS1WM\n");
+
+	return 0;
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit pxa_w1_remove(struct platform_device *pdev)
+{
+	struct pxa_w1_info *info = platform_get_drvdata(pdev);
+
+	mfd_remove_devices(&pdev->dev);
+	clk_put(info->clk);
+	kfree(info);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver pxa_w1_driver = {
+	.driver = {
+		   .name	= "pxa3xx-w1",
+		   .owner	= THIS_MODULE,
+	},
+	.probe		= pxa_w1_probe,
+	.remove		= __devexit_p(pxa_w1_remove),
+};
+
+static int __init pxa_w1_base_init(void)
+{
+	return platform_driver_register(&pxa_w1_driver);
+}
+
+static void __exit pxa_w1_base_exit(void)
+{

drivers/mfd/pxa-w1.c line 150

Quoted 10 lines
drivers/mfd/pxa-w1.c new file +10 -0
+	platform_driver_unregister(&pxa_w1_driver);
+}
+
+module_init(pxa_w1_base_init);
+module_exit(pxa_w1_base_exit);
+
+MODULE_AUTHOR("Jett Zhou<[email protected]>");
+MODULE_DESCRIPTION("one wire driver for PXA");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-w1");

Best regards ,
Thanks

Quoted 5 lines

--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-

kernel" in

Quoted 4 lines

the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#26 lore raw

Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

In reply to Haojian Zhuang
Quoted 82 lines · Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   82
+++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 19 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +28 -11
index b3aebc2..fe12f61 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct pm860x_touch,
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void · line 101

Quoted 8 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -0
@@ -77,30 +94,54 @@ static irqreturn_t pm860x_touch_handler(int irq, void
 *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = (end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec) / 1000;

Is the interval you calibrated right ?

Quoted 15 lines
drivers/input/touchscreen/88pm860x-ts.c +7 -0
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:
+	return;
+}

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 125

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +10 -0
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret & PM8607_STATUS_PEN)
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)

prefer to !(ret & PM8607_STATUS_PEN) ?

Quoted 12 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -1
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
 
 static int pm860x_touch_open(struct input_dev *dev)
 {
 	struct pm860x_touch *touch = input_get_drvdata(dev);
-	int data, ret;
+	int data;

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 143

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -3
 
+	/* set debounce time with 0ms */
+	pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			PD_DEBOUNCE_0MSEC);
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
-	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);

Why not check the return value now ?

Quoted 44 lines
drivers/input/touchscreen/88pm860x-ts.c +0 -2
 	return 0;
-out:
-	return ret;
 }
 

static void pm860x_touch_close(struct input_dev *dev)

drivers/input/touchscreen/88pm860x-ts.c +3 -2
@@ -152,16 +193,17 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +230,7 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 	free_irq(touch->irq, touch);
@@ -202,6 +245,7 @@ static int __devexit pm860x_touch_remove(struct
 platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
Quoted 4 lines

platform_set_drvdata(pdev, NULL);
--
1.5.6.5

Best regards
Thanks

Quoted 6 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#27 lore raw

RE: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 98 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Wanlong Gao
Sent: 2011年4月14日 10:02 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Dmitry Torokhov
Subject: Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 20 lines · Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   82
+++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 19 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +0 -0
index b3aebc2..fe12f61 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>

drivers/input/touchscreen/88pm860x-ts.c line 23

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +3 -1
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign

HZ

Quoted 27 lines
drivers/input/touchscreen/88pm860x-ts.c +15 -5
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;

drivers/input/touchscreen/88pm860x-ts.c line 66

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -2
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct

pm860x_touch,

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq,

Quoted 15 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -3
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;
@@ -77,30 +94,54 @@ static irqreturn_t pm860x_touch_handler(int irq,

void

Quoted 9 lines

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 100

Quoted 8 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -0
 *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = (end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec) / 1000;

Is the interval you calibrated right ?

Good catch. I'll fix it.

Quoted 40 lines
Quoted 13 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -0
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data)

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +10 -0
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret &

PM8607_STATUS_PEN)

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 125

Quoted 2 lines
drivers/input/touchscreen/88pm860x-ts.c +2 -0
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)

prefer to !(ret & PM8607_STATUS_PEN) ?

Quoted 13 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -1
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
 
 static int pm860x_touch_open(struct input_dev *dev)
 {
 	struct pm860x_touch *touch = input_get_drvdata(dev);
-	int data, ret;
+	int data;
 
Quoted 10 lines

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 143

Quoted 9 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -3
+	/* set debounce time with 0ms */
+	pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			PD_DEBOUNCE_0MSEC);
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
-	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);

Why not check the return value now ?

Seems checking is better in open(). I'll fix it.

Quoted 51 lines
Quoted 45 lines
drivers/input/touchscreen/88pm860x-ts.c +0 -2
 	return 0;
-out:
-	return ret;
 }
 

static void pm860x_touch_close(struct input_dev *dev)

drivers/input/touchscreen/88pm860x-ts.c +3 -2
@@ -152,16 +193,17 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip-
 companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +230,7 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 	free_irq(touch->irq, touch);
@@ -202,6 +245,7 @@ static int __devexit pm860x_touch_remove(struct
 platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
Quoted 4 lines

platform_set_drvdata(pdev, NULL);
--
1.5.6.5

Best regards
Thanks

Quoted 7 lines
Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

kernel" in

Quoted 4 lines

the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

�翳簕.n�+壏煯壄�+%娝�遍荻w�簕.n�+壏{炳G珴�妠ay�蕠跈�,jf"穐殢飦�戧鐉_璁(殠娸"濟�m���G珴�⒏?櫒璀�&x忈秈O曟瑉窔v豝�m��� �鹅�⒏?朓�

Reviewed-by
#28 lore raw

Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

2011-4-14 22:41, Haojian Zhuang wroted:

Quoted 12 lines
Quoted 12 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Wanlong Gao
Sent: 2011年4月14日 10:02 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Dmitry Torokhov
Subject: Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 6 lines
Quoted 6 lines · Haojian Zhuang
Quoted 5 lines

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

Quoted 90 lines
Quoted 80 lines
Quoted 15 lines
Cc Dmitry Torokhov<[email protected]>
---
  drivers/input/touchscreen/88pm860x-ts.c |   82
+++++++++++++++++++++++-------
  1 files changed, 63 insertions(+), 19 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +0 -0
index b3aebc2..fe12f61 100644
@@ -12,13 +12,25 @@
  #include<linux/module.h>
  #include<linux/platform_device.h>
  #include<linux/i2c.h>

drivers/input/touchscreen/88pm860x-ts.c line 23

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +3 -1
+#include<linux/slab.h>
  #include<linux/input.h>
  #include<linux/mfd/88pm860x.h>
-#include<linux/slab.h>
 
  #define MEAS_LEN		(8)
  #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign

HZ

Quoted 27 lines
drivers/input/touchscreen/88pm860x-ts.c +15 -5
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
  /* touch register */
  #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
  #define MEAS_TSIZ2_EN		(1<<  7)
 
  struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;

drivers/input/touchscreen/88pm860x-ts.c line 66

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -2
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
  };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
  {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct

pm860x_touch,

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq,

Quoted 15 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -3
+						  poll_work.work);
  	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
  	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
  	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
  	if (ret<  0)
  		goto out;
@@ -77,30 +94,54 @@ static irqreturn_t pm860x_touch_handler(int irq,

void

Quoted 9 lines

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 100

Quoted 8 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -0
 *data)
  		input_report_abs(touch->idev, ABS_PRESSURE, rt);
  		input_report_key(touch->idev, BTN_TOUCH, 1);
  		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = (end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec) / 1000;

Is the interval you calibrated right ?

Quoted 1 line

Good catch. I'll fix it.

Glad.

Quoted 52 lines
Quoted 41 lines
Quoted 14 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -0
+		interval = (interval<  MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
  	} else {
  		input_report_abs(touch->idev, ABS_PRESSURE, 0);
  		input_report_key(touch->idev, BTN_TOUCH, 0);
  		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
  	}
  	input_sync(touch->idev);
 
  out:

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data)

Quoted 10 lines
drivers/input/touchscreen/88pm860x-ts.c +10 -0
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret&

PM8607_STATUS_PEN)

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, · line 126

Quoted 2 lines
drivers/input/touchscreen/88pm860x-ts.c +2 -0
+		? 1 : 0);
+	if ((ret&  PM8607_STATUS_PEN) == 0)

prefer to !(ret& PM8607_STATUS_PEN) ?

Quoted 13 lines
drivers/input/touchscreen/88pm860x-ts.c +5 -1
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
  	return IRQ_HANDLED;
  }
 
  static int pm860x_touch_open(struct input_dev *dev)
  {
  	struct pm860x_touch *touch = input_get_drvdata(dev);
-	int data, ret;
+	int data;
 
Quoted 10 lines

drivers/input/touchscreen/88pm860x-ts.c static irqreturn_t pm860x_touch_handler(int irq, void *data) · line 143

Quoted 9 lines
drivers/input/touchscreen/88pm860x-ts.c +4 -3
+	/* set debounce time with 0ms */
+	pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			PD_DEBOUNCE_0MSEC);
  	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
  		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
-	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret<  0)
-		goto out;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);

Why not check the return value now ?

Quoted 1 line

Seems checking is better in open(). I'll fix it.

Glad.

Quoted 59 lines
Quoted 59 lines
Quoted 46 lines
drivers/input/touchscreen/88pm860x-ts.c +0 -2
  	return 0;
-out:
-	return ret;
  }
 

static void pm860x_touch_close(struct input_dev *dev)

drivers/input/touchscreen/88pm860x-ts.c +3 -2
@@ -152,16 +193,17 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
  	}
 
  	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
  	touch->idev->id.bustype = BUS_I2C;
  	touch->idev->dev.parent =&pdev->dev;
  	touch->idev->open = pm860x_touch_open;
  	touch->idev->close = pm860x_touch_close;
  	touch->chip = chip;
  	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip-
 companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
  	touch->res_x = pdata->res_x;
  	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 

ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
IRQF_ONESHOT, "touch", touch);

drivers/input/touchscreen/88pm860x-ts.c +1 -0
@@ -188,6 +230,7 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
  	}
 
  	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
  	return 0;
  out_rg:
  	free_irq(touch->irq, touch);
drivers/input/touchscreen/88pm860x-ts.c +1 -0
@@ -202,6 +245,7 @@ static int __devexit pm860x_touch_remove(struct
 platform_device *pdev)
  {
  	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
  	input_unregister_device(touch->idev);
  	free_irq(touch->irq, touch);
Quoted 4 lines

platform_set_drvdata(pdev, NULL);
--
1.5.6.5

Best regards
Thanks

Quoted 2 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-

kernel" in

Quoted 4 lines

the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#29 lore raw

PATCH 1/13 input: touchscreen: use polling mode in 88pm860x

In reply to Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   79 ++++++++++++++++++++++++------
 1 files changed, 63 insertions(+), 16 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +63 -16
index b3aebc2..dbb3435 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct pm860x_touch,
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;
@@ -77,14 +94,39 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = ((end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec)) / 1000;
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret & PM8607_STATUS_PEN)
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
 
@@ -93,12 +135,14 @@ static int pm860x_touch_open(struct input_dev *dev)
 	struct pm860x_touch *touch = input_get_drvdata(dev);
 	int data, ret;
 
+	/* set debounce time with 0ms */
+	ret = pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			      PD_DEBOUNCE_0MSEC);
+	if (ret < 0)
+		goto out;
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
 	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
-	return 0;
 out:
 	return ret;
 }
@@ -152,16 +196,17 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +233,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
 	free_irq(touch->irq, touch);
@@ -202,6 +248,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
 	platform_set_drvdata(pdev, NULL);
Signature · 1 line
1.5.6.5
#30 lore raw

Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 179 lines · Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   79
++++++++++++++++++++++++------
 1 files changed, 63 insertions(+), 16 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +61 -16
index b3aebc2..dbb3435 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct pm860x_touch,
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;
@@ -77,14 +94,39 @@ static irqreturn_t pm860x_touch_handler(int irq, void
 *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = ((end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec)) / 1000;
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret & PM8607_STATUS_PEN)
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
@@ -93,12 +135,14 @@ static int pm860x_touch_open(struct input_dev *dev)
 	struct pm860x_touch *touch = input_get_drvdata(dev);
 	int data, ret;
 
+	/* set debounce time with 0ms */
+	ret = pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			      PD_DEBOUNCE_0MSEC);
+	if (ret < 0)
+		goto out;
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
 	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
-	return 0;
 out:
 	return ret;
 }
@@ -152,16 +196,17 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-	touch->irq = irq + chip->irq_base;
+	touch->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +233,7 @@ static int __devinit pm860x_touch_probe(struct
 platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
drivers/input/touchscreen/88pm860x-ts.c +1 -0
 	free_irq(touch->irq, touch);
@@ -202,6 +248,7 @@ static int __devexit pm860x_touch_remove(struct
 platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
Quoted 4 lines

platform_set_drvdata(pdev, NULL);
--
1.5.6.5

It looks all good to me now .
Thanks for your great work .

Best regards .

Quoted 6 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#31 lore raw

Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

In reply to Haojian Zhuang

drivers/input/touchscreen/88pm860x-ts.c line 26

Quoted 11 lines · Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

 drivers/input/touchscreen/88pm860x-ts.c |   79 ++++++++++++++++++++++++------
drivers/input/touchscreen/88pm860x-ts.c +5 -0
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)

Is it guaranteed that this hardware part will only ever be used on systems where this is true? How big a bug would it be if somebody tried to glue this touchscreen into some random embedded-ARM where HZ was something else, and should this be computed as a function of HZ instead of hardcoding 7?

It *looks* like the intent of the schedule_delayed_work() call is "let's run this once a tick when we're awake *anyhow*" - but looking at the code, I can't convince myself a rounding error in computing 'interval' won't schedule 1ms before or after the next tick would have been. Isn't there a better API with slack timers or something that would do a better "next tick" job?

#32 lore raw

RE: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 26 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: 2011年4月16日 10:17 PM
To: Haojian Zhuang
Cc: [email protected]; [email protected]; linux- [email protected]; Dmitry Torokhov
Subject: Re: [PATCH 01/13] input: touchscreen: use polling mode in 88pm860x

Quoted 5 lines · Haojian Zhuang

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

 drivers/input/touchscreen/88pm860x-ts.c |   79

++++++++++++++++++++++++------

Quoted 2 lines

+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign

HZ

Quoted 3 lines

+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS (7)

Quoted 7 lines

Is it guaranteed that this hardware part will only ever be used on systems
where this is true? How big a bug would it be if somebody tried to glue this
touchscreen into some random embedded-ARM where HZ was something else, and
should this be computed as a function of HZ instead of hardcoding 7?

It's 7msec whatever you choose any silicon. So it's not a problem.

Quoted 12 lines

It *looks* like the intent of the schedule_delayed_work() call is "let's run
this once a tick when we're awake *anyhow*" - but looking at the code, I can't
convince myself a rounding error in computing 'interval' won't schedule 1ms
before or after the next tick would have been. Isn't there a better API with
slack timers or something that would do a better "next tick" job?

�翳簕.n�+壏煯壄�+%娝�遍荻w�簕.n�+壏{炳G珴�妠ay�蕠跈�,jf"穐殢飦�戧鐉_璁(殠娸"濟�m���G珴�⒏?櫒璀�&x忈秈O曟瑉窔v豝�m��� �鹅�⒏?朓�