* [PATCH] mfd: adopt mfd_data in 88pm860x backlight
@ 2011-03-07 15:43 Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Haojian Zhuang
2011-03-14 10:56 ` [PATCH] mfd: adopt mfd_data in 88pm860x backlight Samuel Ortiz
0 siblings, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Copy 88pm860x platform data into different mfd_data structure for
backlight driver. So move the identification of device node from
backlight driver to mfd driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-core.c | 96 +++++++++++++++++---------------
drivers/video/backlight/88pm860x_bl.c | 34 +++---------
include/linux/mfd/88pm860x.h | 2 +-
3 files changed, 60 insertions(+), 72 deletions(-)
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 793300c..a88967a 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -20,12 +20,19 @@
#define INT_STATUS_NUM 3
-char pm860x_backlight_name[][MFD_NAME_SIZE] = {
- "backlight-0",
- "backlight-1",
- "backlight-2",
+static struct resource bk_resources[] __initdata = {
+ {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
+ {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
+ {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
};
-EXPORT_SYMBOL(pm860x_backlight_name);
+
+static struct mfd_cell bk_devs[] __initdata = {
+ {"88pm860x-backlight", 0,},
+ {"88pm860x-backlight", 1,},
+ {"88pm860x-backlight", 2,},
+};
+
+static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
char pm860x_led_name[][MFD_NAME_SIZE] = {
"led0-red",
@@ -37,34 +44,6 @@ char pm860x_led_name[][MFD_NAME_SIZE] = {
};
EXPORT_SYMBOL(pm860x_led_name);
-#define PM8606_BACKLIGHT_RESOURCE(_i, _x) \
-{ \
- .name = pm860x_backlight_name[_i], \
- .start = PM8606_##_x, \
- .end = PM8606_##_x, \
- .flags = IORESOURCE_IO, \
-}
-
-static struct resource backlight_resources[] = {
- PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A),
- PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A),
- PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A),
-};
-
-#define PM8606_BACKLIGHT_DEVS(_i) \
-{ \
- .name = "88pm860x-backlight", \
- .num_resources = 1, \
- .resources = &backlight_resources[_i], \
- .id = _i, \
-}
-
-static struct mfd_cell backlight_devs[] = {
- PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1),
- PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2),
- PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3),
-};
-
#define PM8606_LED_RESOURCE(_i, _x) \
{ \
.name = pm860x_led_name[_i], \
@@ -595,23 +574,49 @@ static void device_irq_exit(struct pm860x_chip *chip)
free_irq(chip->core_irq, chip);
}
+static void __devinit device_bk_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int ret;
+ int i, j, id;
+
+ if ((pdata == NULL) || (pdata->backlight == NULL))
+ return;
+
+ if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
+ pdata->num_backlights = ARRAY_SIZE(bk_devs);
+
+ for (i = 0; i < pdata->num_backlights; i++) {
+ memcpy(&bk_pdata[i], &pdata->backlight[i],
+ sizeof(struct pm860x_backlight_pdata));
+ bk_devs[i].mfd_data = &bk_pdata[i];
+
+ for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
+ id = bk_resources[j].start;
+ if (bk_pdata[i].flags != id)
+ continue;
+
+ bk_devs[i].num_resources = 1;
+ bk_devs[i].resources = &bk_resources[j];
+ ret = mfd_add_devices(chip->dev, 0,
+ &bk_devs[i], 1,
+ &bk_resources[j], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add "
+ "backlight subdev\n");
+ return;
+ }
+ }
+ }
+}
+
static void __devinit device_8606_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
int ret;
- 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->led) {
ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
ARRAY_SIZE(led_devs),
@@ -624,7 +629,6 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
}
return;
out_dev:
- mfd_remove_devices(chip->dev);
device_irq_exit(chip);
}
@@ -743,6 +747,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
switch (chip->id) {
case CHIP_PM8606:
+ device_bk_init(chip, chip->client, pdata);
device_8606_init(chip, chip->client, pdata);
break;
case CHIP_PM8607:
@@ -753,6 +758,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
if (chip->companion) {
switch (chip->id) {
case CHIP_PM8607:
+ device_bk_init(chip, chip->companion, pdata);
device_8606_init(chip, chip->companion, pdata);
break;
case CHIP_PM8606:
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index b224396..552825c 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -12,11 +12,12 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/i2c.h>
#include <linux/backlight.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
#define MAX_BRIGHTNESS (0xFF)
#define MIN_BRIGHTNESS (0)
@@ -161,32 +162,13 @@ static const struct backlight_ops pm860x_backlight_ops = {
.get_brightness = pm860x_backlight_get_brightness,
};
-static int __check_device(struct pm860x_backlight_pdata *pdata, char *name)
-{
- struct pm860x_backlight_pdata *p = pdata;
- int ret = -EINVAL;
-
- while (p && p->id) {
- if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0))
- break;
-
- if (!strncmp(name, pm860x_backlight_name[p->flags],
- MFD_NAME_SIZE)) {
- ret = (int)p->flags;
- break;
- }
- p++;
- }
- return ret;
-}
-
static int pm860x_backlight_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm860x_platform_data *pm860x_pdata;
struct pm860x_backlight_pdata *pdata = NULL;
struct pm860x_backlight_data *data;
struct backlight_device *bl;
+ struct mfd_cell *cell;
struct resource *res;
struct backlight_properties props;
unsigned char value;
@@ -199,10 +181,10 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (pdev->dev.parent->platform_data) {
- pm860x_pdata = pdev->dev.parent->platform_data;
- pdata = pm860x_pdata->backlight;
- }
+ cell = pdev->dev.platform_data;
+ if (cell == NULL)
+ return -ENODEV;
+ pdata = cell->mfd_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "platform data isn't assigned to "
"backlight\n");
@@ -219,7 +201,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
data->current_brightness = MAX_BRIGHTNESS;
data->pwm = pdata->pwm;
data->iset = pdata->iset;
- data->port = __check_device(pdata, name);
+ data->port = pdata->flags;
if (data->port < 0) {
dev_err(&pdev->dev, "wrong platform data is assigned");
kfree(data);
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index 4db1fbd..f790d37 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -356,10 +356,10 @@ struct pm860x_platform_data {
int i2c_port; /* Controlled by GI2C or PI2C */
int irq_mode; /* Clear interrupt by read/write(0/1) */
int irq_base; /* IRQ base number of 88pm860x */
+ int num_backlights;
struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
};
-extern char pm860x_backlight_name[][MFD_NAME_SIZE];
extern char pm860x_led_name[][MFD_NAME_SIZE];
extern int pm860x_reg_read(struct i2c_client *, int);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: adopt mfd_data in 88pm860x led
2011-03-07 15:43 [PATCH] mfd: adopt mfd_data in 88pm860x backlight Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
2011-03-14 11:23 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Samuel Ortiz
2011-03-14 10:56 ` [PATCH] mfd: adopt mfd_data in 88pm860x backlight Samuel Ortiz
1 sibling, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Copy 88pm860x platform data into different mfd_data structure for
led driver. So move the identification of device node from led
driver to mfd driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/leds/leds-88pm860x.c | 60 +++++++++++------------
drivers/mfd/88pm860x-core.c | 109 +++++++++++++++++++-----------------------
include/linux/mfd/88pm860x.h | 3 +-
3 files changed, 79 insertions(+), 93 deletions(-)
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index e672b44..416def8 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -17,6 +17,7 @@
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
#define LED_PWM_SHIFT (3)
@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work)
struct pm860x_led *led;
struct pm860x_chip *chip;
- int mask;
+ unsigned char buf[3];
+ int mask, ret;
led = container_of(work, struct pm860x_led, work);
chip = led->chip;
@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work)
pm860x_set_bits(led->i2c, __led_off(led->port),
LED_CURRENT_MASK, led->iset);
}
+ pm860x_set_bits(led->i2c, __blink_off(led->port),
+ LED_BLINK_MASK, LED_ON_CONTINUOUS);
mask = __blink_ctl_mask(led->port);
pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
- } else if (led->brightness == 0) {
- pm860x_set_bits(led->i2c, __led_off(led->port),
- LED_CURRENT_MASK, 0);
- mask = __blink_ctl_mask(led->port);
- pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
}
pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
led->brightness);
+
+ if (led->brightness == 0) {
+ pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
+ ret = buf[0] & LED_PWM_MASK;
+ ret |= buf[1] & LED_PWM_MASK;
+ ret |= buf[2] & LED_PWM_MASK;
+ if (ret == 0) {
+ /* unset current since no led is lighting */
+ pm860x_set_bits(led->i2c, __led_off(led->port),
+ LED_CURRENT_MASK, 0);
+ mask = __blink_ctl_mask(led->port);
+ pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+ }
+ }
led->current_brightness = led->brightness;
dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
__led_off(led->port), led->brightness);
@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev,
schedule_work(&data->work);
}
-static int __check_device(struct pm860x_led_pdata *pdata, char *name)
-{
- struct pm860x_led_pdata *p = pdata;
- int ret = -EINVAL;
-
- while (p && p->id) {
- if ((p->id != PM8606_ID_LED) || (p->flags < 0))
- break;
-
- if (!strncmp(name, pm860x_led_name[p->flags],
- MFD_NAME_SIZE)) {
- ret = (int)p->flags;
- break;
- }
- p++;
- }
- return ret;
-}
-
static int pm860x_led_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm860x_platform_data *pm860x_pdata;
struct pm860x_led_pdata *pdata;
struct pm860x_led *data;
+ struct mfd_cell *cell;
struct resource *res;
int ret;
@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (pdev->dev.parent->platform_data) {
- pm860x_pdata = pdev->dev.parent->platform_data;
- pdata = pm860x_pdata->led;
- } else {
+ cell = pdev->dev.platform_data;
+ if (cell == NULL)
+ return -ENODEV;
+ pdata = cell->mfd_data;
+ if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data!\n");
return -EINVAL;
}
@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev)
data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
- strncpy(data->name, res->name, MFD_NAME_SIZE);
+ strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
dev_set_drvdata(&pdev->dev, data);
data->chip = chip;
data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
data->iset = pdata->iset;
- data->port = __check_device(pdata, data->name);
+ data->port = pdata->flags;
if (data->port < 0) {
dev_err(&pdev->dev, "check device failed\n");
kfree(data);
@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
goto out;
}
+ pm860x_led_set(&data->cdev, 0);
return 0;
out:
kfree(data);
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index a88967a..cec375c 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -26,57 +26,32 @@ static struct resource bk_resources[] __initdata = {
{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
};
+static struct resource led_resources[] __initdata = {
+ {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,},
+ {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,},
+ {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
+ {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,},
+};
+
static struct mfd_cell bk_devs[] __initdata = {
{"88pm860x-backlight", 0,},
{"88pm860x-backlight", 1,},
{"88pm860x-backlight", 2,},
};
-static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
-
-char pm860x_led_name[][MFD_NAME_SIZE] = {
- "led0-red",
- "led0-green",
- "led0-blue",
- "led1-red",
- "led1-green",
- "led1-blue",
-};
-EXPORT_SYMBOL(pm860x_led_name);
-
-#define PM8606_LED_RESOURCE(_i, _x) \
-{ \
- .name = pm860x_led_name[_i], \
- .start = PM8606_##_x, \
- .end = PM8606_##_x, \
- .flags = IORESOURCE_IO, \
-}
-
-static struct resource led_resources[] = {
- PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B),
- PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C),
- PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D),
- PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B),
- PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C),
- PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D),
+static struct mfd_cell led_devs[] __initdata = {
+ {"88pm860x-led", 0,},
+ {"88pm860x-led", 1,},
+ {"88pm860x-led", 2,},
+ {"88pm860x-led", 3,},
+ {"88pm860x-led", 4,},
+ {"88pm860x-led", 5,},
};
-#define PM8606_LED_DEVS(_i) \
-{ \
- .name = "88pm860x-led", \
- .num_resources = 1, \
- .resources = &led_resources[_i], \
- .id = _i, \
-}
-
-static struct mfd_cell led_devs[] = {
- PM8606_LED_DEVS(PM8606_LED1_RED),
- PM8606_LED_DEVS(PM8606_LED1_GREEN),
- PM8606_LED_DEVS(PM8606_LED1_BLUE),
- PM8606_LED_DEVS(PM8606_LED2_RED),
- PM8606_LED_DEVS(PM8606_LED2_GREEN),
- PM8606_LED_DEVS(PM8606_LED2_BLUE),
-};
+static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
+static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
static struct resource touch_resources[] = {
{
@@ -611,25 +586,41 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
}
}
-static void __devinit device_8606_init(struct pm860x_chip *chip,
- struct i2c_client *i2c,
- struct pm860x_platform_data *pdata)
+static void __devinit device_led_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
{
int ret;
+ int i, j, id;
- if (pdata && pdata->led) {
- ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
- ARRAY_SIZE(led_devs),
- &led_resources[0], 0);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add led "
- "subdev\n");
- goto out_dev;
+ if ((pdata == NULL) || (pdata->led == NULL))
+ return;
+
+ if (pdata->num_leds > ARRAY_SIZE(led_devs))
+ pdata->num_leds = ARRAY_SIZE(led_devs);
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ memcpy(&led_pdata[i], &pdata->led[i],
+ sizeof(struct pm860x_led_pdata));
+ led_devs[i].mfd_data = &led_pdata[i];
+
+ for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
+ id = led_resources[j].start;
+ if (led_pdata[i].flags != id)
+ continue;
+
+ led_devs[i].num_resources = 1;
+ led_devs[i].resources = &led_resources[j],
+ ret = mfd_add_devices(chip->dev, 0,
+ &led_devs[i], 1,
+ &led_resources[j], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add "
+ "led subdev\n");
+ return;
+ }
}
}
- return;
-out_dev:
- device_irq_exit(chip);
}
static void __devinit device_8607_init(struct pm860x_chip *chip,
@@ -748,7 +739,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
switch (chip->id) {
case CHIP_PM8606:
device_bk_init(chip, chip->client, pdata);
- device_8606_init(chip, chip->client, pdata);
+ device_led_init(chip, chip->client, pdata);
break;
case CHIP_PM8607:
device_8607_init(chip, chip->client, pdata);
@@ -759,7 +750,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
switch (chip->id) {
case CHIP_PM8607:
device_bk_init(chip, chip->companion, pdata);
- device_8606_init(chip, chip->companion, pdata);
+ device_led_init(chip, chip->companion, pdata);
break;
case CHIP_PM8606:
device_8607_init(chip, chip->companion, pdata);
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index f790d37..ff60614 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -356,12 +356,11 @@ struct pm860x_platform_data {
int i2c_port; /* Controlled by GI2C or PI2C */
int irq_mode; /* Clear interrupt by read/write(0/1) */
int irq_base; /* IRQ base number of 88pm860x */
+ int num_leds;
int num_backlights;
struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
};
-extern char pm860x_led_name[][MFD_NAME_SIZE];
-
extern int pm860x_reg_read(struct i2c_client *, int);
extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: adopt mfd_data in 88pm860x regulator
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
` (2 more replies)
2011-03-14 11:23 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Samuel Ortiz
1 sibling, 3 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Copy 88pm860x platform data into different mfd_data structure for
regulator driver. So move the identification of device node from
regulator driver to mfd driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-core.c | 165 ++++++++++++++++++++++++++----------------
drivers/regulator/88pm8607.c | 46 ++++++------
include/linux/mfd/88pm860x.h | 7 +-
3 files changed, 132 insertions(+), 86 deletions(-)
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index cec375c..96ea0c6 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
+#include <linux/regulator/machine.h>
#define INT_STATUS_NUM 3
@@ -35,6 +36,27 @@ static struct resource led_resources[] __initdata = {
{PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,},
};
+static struct resource regulator_resources[] __initdata = {
+ {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,},
+ {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,},
+ {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,},
+ {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,},
+ {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,},
+ {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,},
+ {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,},
+ {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,},
+ {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,},
+ {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,},
+ {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
+ {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
+ {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
+ {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
+ {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
+ {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
+};
+
static struct mfd_cell bk_devs[] __initdata = {
{"88pm860x-backlight", 0,},
{"88pm860x-backlight", 1,},
@@ -50,8 +72,30 @@ static struct mfd_cell led_devs[] __initdata = {
{"88pm860x-led", 5,},
};
+static struct mfd_cell regulator_devs[] __initdata = {
+ {"88pm860x-regulator", 0,},
+ {"88pm860x-regulator", 1,},
+ {"88pm860x-regulator", 2,},
+ {"88pm860x-regulator", 3,},
+ {"88pm860x-regulator", 4,},
+ {"88pm860x-regulator", 5,},
+ {"88pm860x-regulator", 6,},
+ {"88pm860x-regulator", 7,},
+ {"88pm860x-regulator", 8,},
+ {"88pm860x-regulator", 9,},
+ {"88pm860x-regulator", 10,},
+ {"88pm860x-regulator", 11,},
+ {"88pm860x-regulator", 12,},
+ {"88pm860x-regulator", 13,},
+ {"88pm860x-regulator", 14,},
+ {"88pm860x-regulator", 15,},
+ {"88pm860x-regulator", 16,},
+ {"88pm860x-regulator", 17,},
+};
+
static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
+static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
static struct resource touch_resources[] = {
{
@@ -69,13 +113,6 @@ static struct mfd_cell touch_devs[] = {
},
};
-#define PM8607_REG_RESOURCE(_start, _end) \
-{ \
- .start = PM8607_##_start, \
- .end = PM8607_##_end, \
- .flags = IORESOURCE_IO, \
-}
-
static struct resource power_supply_resources[] = {
{
.name = "88pm860x-power",
@@ -149,52 +186,6 @@ static struct mfd_cell codec_devs[] = {
},
};
-static struct resource regulator_resources[] = {
- PM8607_REG_RESOURCE(BUCK1, BUCK1),
- PM8607_REG_RESOURCE(BUCK2, BUCK2),
- PM8607_REG_RESOURCE(BUCK3, BUCK3),
- PM8607_REG_RESOURCE(LDO1, LDO1),
- PM8607_REG_RESOURCE(LDO2, LDO2),
- PM8607_REG_RESOURCE(LDO3, LDO3),
- PM8607_REG_RESOURCE(LDO4, LDO4),
- PM8607_REG_RESOURCE(LDO5, LDO5),
- PM8607_REG_RESOURCE(LDO6, LDO6),
- PM8607_REG_RESOURCE(LDO7, LDO7),
- PM8607_REG_RESOURCE(LDO8, LDO8),
- PM8607_REG_RESOURCE(LDO9, LDO9),
- PM8607_REG_RESOURCE(LDO10, LDO10),
- PM8607_REG_RESOURCE(LDO12, LDO12),
- PM8607_REG_RESOURCE(VIBRATOR_SET, VIBRATOR_SET),
- PM8607_REG_RESOURCE(LDO14, LDO14),
-};
-
-#define PM8607_REG_DEVS(_id) \
-{ \
- .name = "88pm860x-regulator", \
- .num_resources = 1, \
- .resources = ®ulator_resources[PM8607_ID_##_id], \
- .id = PM8607_ID_##_id, \
-}
-
-static struct mfd_cell regulator_devs[] = {
- PM8607_REG_DEVS(BUCK1),
- PM8607_REG_DEVS(BUCK2),
- PM8607_REG_DEVS(BUCK3),
- PM8607_REG_DEVS(LDO1),
- PM8607_REG_DEVS(LDO2),
- PM8607_REG_DEVS(LDO3),
- PM8607_REG_DEVS(LDO4),
- PM8607_REG_DEVS(LDO5),
- PM8607_REG_DEVS(LDO6),
- PM8607_REG_DEVS(LDO7),
- PM8607_REG_DEVS(LDO8),
- PM8607_REG_DEVS(LDO9),
- PM8607_REG_DEVS(LDO10),
- PM8607_REG_DEVS(LDO12),
- PM8607_REG_DEVS(LDO13),
- PM8607_REG_DEVS(LDO14),
-};
-
struct pm860x_irq_data {
int reg;
int mask_reg;
@@ -623,6 +614,64 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
}
}
+static void __devinit device_regulator_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ struct regulator_init_data *initdata;
+ int ret;
+ int 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, "BUCK")) {
+ sscanf(initdata->constraints.name, "BUCK%d", &j);
+ /* BUCK1 ~ BUCK3 */
+ if ((j < 1) || (j > 3)) {
+ dev_err(chip->dev, "Failed to add constraint "
+ "(%s)\n", initdata->constraints.name);
+ goto out;
+ }
+ j = (j - 1) + PM8607_ID_BUCK1;
+ }
+ if (strstr(initdata->constraints.name, "LDO")) {
+ sscanf(initdata->constraints.name, "LDO%d", &j);
+ /* LDO1 ~ LDO15 */
+ if ((j < 1) || (j > 15)) {
+ dev_err(chip->dev, "Failed to add constraint "
+ "(%s)\n", initdata->constraints.name);
+ goto out;
+ }
+ j = (j - 1) + PM8607_ID_LDO1;
+ }
+ if (j == -1) {
+ dev_err(chip->dev, "Failed to add constraint (%s)\n",
+ initdata->constraints.name);
+ goto out;
+ }
+ memcpy(®ulator_pdata[i], &pdata->regulator[i],
+ sizeof(struct regulator_init_data));
+ regulator_devs[i].mfd_data = ®ulator_pdata[i];
+ regulator_devs[i].num_resources = 1;
+ regulator_devs[i].resources = ®ulator_resources[j];
+
+ ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1,
+ ®ulator_resources[j], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add regulator subdev\n");
+ goto out;
+ }
+ }
+out:
+ return;
+}
+
static void __devinit device_8607_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
@@ -678,14 +727,6 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
if (ret < 0)
goto out;
- ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0],
- ARRAY_SIZE(regulator_devs),
- ®ulator_resources[0], 0);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add regulator subdev\n");
- goto out_dev;
- }
-
if (pdata && pdata->touch) {
ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
ARRAY_SIZE(touch_devs),
@@ -723,6 +764,8 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add codec subdev\n");
goto out_dev;
}
+
+ device_regulator_init(chip, i2c, pdata);
return;
out_dev:
mfd_remove_devices(chip->dev);
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index dd63084..8592512 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
struct pm8607_regulator_info {
@@ -394,47 +395,48 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6),
};
-static inline struct pm8607_regulator_info *find_regulator_info(int id)
+static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
- struct pm8607_regulator_info *info;
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm8607_regulator_info *info = NULL;
+ struct regulator_init_data *pdata;
+ struct mfd_cell *cell;
int i;
+ cell = pdev->dev.platform_data;
+ if (cell == NULL)
+ return -ENODEV;
+ pdata = cell->mfd_data;
+ if (pdata == NULL)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
info = &pm8607_regulator_info[i];
- if (info->desc.id == id)
- return info;
+ if (!strcmp(info->desc.name, pdata->constraints.name))
+ break;
}
- return NULL;
-}
-
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
-{
- struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm860x_platform_data *pdata = chip->dev->platform_data;
- struct pm8607_regulator_info *info = NULL;
-
- info = find_regulator_info(pdev->id);
- if (info == NULL) {
- dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ if (i > ARRAY_SIZE(pm8607_regulator_info)) {
+ dev_err(&pdev->dev, "Failed to find regulator %s\n",
+ pdata->constraints.name);
return -EINVAL;
}
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->chip = chip;
+ /* check DVC ramp slope double */
+ if (!strcmp(info->desc.name, "BUCK3"))
+ if (info->chip->buck3_double)
+ info->slope_double = 1;
+
info->regulator = regulator_register(&info->desc, &pdev->dev,
- pdata->regulator[pdev->id], info);
+ pdata, info);
if (IS_ERR(info->regulator)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
return PTR_ERR(info->regulator);
}
- /* check DVC ramp slope double */
- if (info->desc.id == PM8607_ID_BUCK3)
- if (info->chip->buck3_double)
- info->slope_double = 1;
-
platform_set_drvdata(pdev, info);
return 0;
}
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index ff60614..a6f6f81 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -131,9 +131,11 @@ enum {
PM8607_ID_LDO8,
PM8607_ID_LDO9,
PM8607_ID_LDO10,
+ PM8607_ID_LDO11,
PM8607_ID_LDO12,
PM8607_ID_LDO13,
PM8607_ID_LDO14,
+ PM8607_ID_LDO15,
PM8607_ID_RG_MAX,
};
@@ -310,8 +312,6 @@ struct pm860x_chip {
};
-#define PM8607_MAX_REGULATOR PM8607_ID_RG_MAX /* 3 Bucks, 13 LDOs */
-
enum {
GI2C_PORT = 0,
PI2C_PORT,
@@ -351,6 +351,7 @@ struct pm860x_platform_data {
struct pm860x_led_pdata *led;
struct pm860x_touch_pdata *touch;
struct pm860x_power_pdata *power;
+ struct regulator_init_data *regulator;
unsigned short companion_addr; /* I2C address of companion chip */
int i2c_port; /* Controlled by GI2C or PI2C */
@@ -358,7 +359,7 @@ struct pm860x_platform_data {
int irq_base; /* IRQ base number of 88pm860x */
int num_leds;
int num_backlights;
- struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
+ int num_regulators;
};
extern int pm860x_reg_read(struct i2c_client *, int);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: adopt mfd_data in 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: add workqueue thread into 88pm860x Haojian Zhuang
2011-03-14 11:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x Samuel Ortiz
2011-03-08 23:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Mark Brown
2011-03-14 11:23 ` Samuel Ortiz
2 siblings, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Copy 88pm860x platform data into different mfd_data structure for
onkey/touch/codec/power driver. So move the identification of
device node from those drivers to mfd driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/input/misc/88pm860x_onkey.c | 2 +-
drivers/mfd/88pm860x-core.c | 251 ++++++++++++++++++-----------------
2 files changed, 127 insertions(+), 126 deletions(-)
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
index 4cc8282..3dca3c1 100644
--- a/drivers/input/misc/88pm860x_onkey.c
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -74,7 +74,7 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
info->chip = chip;
info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->dev = &pdev->dev;
- info->irq = irq + chip->irq_base;
+ info->irq = irq;
info->idev = input_allocate_device();
if (!info->idev) {
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 96ea0c6..9c511c1 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -57,6 +57,39 @@ static struct resource regulator_resources[] __initdata = {
{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
};
+static struct resource touch_resources[] __initdata = {
+ {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
+};
+
+static struct resource onkey_resources[] __initdata = {
+ {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
+};
+
+static struct resource codec_resources[] __initdata = {
+ /* Headset microphone insertion or removal */
+ {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,},
+ /* Hook-switch press or release */
+ {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,},
+ /* Headset insertion or removal */
+ {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
+ /* Audio short */
+ {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
+};
+
+static struct resource battery_resources[] __initdata = {
+ {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 = {
+ {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,},
+ {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,},
+ {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
+ {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
+};
+
static struct mfd_cell bk_devs[] __initdata = {
{"88pm860x-backlight", 0,},
{"88pm860x-backlight", 1,},
@@ -93,98 +126,28 @@ static struct mfd_cell regulator_devs[] __initdata = {
{"88pm860x-regulator", 17,},
};
-static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
-static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
-static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
-
-static struct resource touch_resources[] = {
- {
- .start = PM8607_IRQ_PEN,
- .end = PM8607_IRQ_PEN,
- .flags = IORESOURCE_IRQ,
- },
+static struct mfd_cell touch_devs[] __initdata = {
+ {"88pm860x-touch", -1,},
};
-static struct mfd_cell touch_devs[] = {
- {
- .name = "88pm860x-touch",
- .num_resources = 1,
- .resources = &touch_resources[0],
- },
+static struct mfd_cell onkey_devs[] __initdata = {
+ {"88pm860x-onkey", -1,},
};
-static struct resource power_supply_resources[] = {
- {
- .name = "88pm860x-power",
- .start = PM8607_IRQ_CHG,
- .end = PM8607_IRQ_CHG,
- .flags = IORESOURCE_IRQ,
- },
+static struct mfd_cell codec_devs[] __initdata = {
+ {"88pm860x-codec", -1,},
};
static struct mfd_cell power_devs[] = {
- {
- .name = "88pm860x-power",
- .num_resources = 1,
- .resources = &power_supply_resources[0],
- .id = -1,
- },
-};
-
-static struct resource onkey_resources[] = {
- {
- .name = "88pm860x-onkey",
- .start = PM8607_IRQ_ONKEY,
- .end = PM8607_IRQ_ONKEY,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mfd_cell onkey_devs[] = {
- {
- .name = "88pm860x-onkey",
- .num_resources = 1,
- .resources = &onkey_resources[0],
- .id = -1,
- },
-};
-
-static struct resource codec_resources[] = {
- {
- /* Headset microphone insertion or removal */
- .name = "micin",
- .start = PM8607_IRQ_MICIN,
- .end = PM8607_IRQ_MICIN,
- .flags = IORESOURCE_IRQ,
- }, {
- /* Hook-switch press or release */
- .name = "hook",
- .start = PM8607_IRQ_HOOK,
- .end = PM8607_IRQ_HOOK,
- .flags = IORESOURCE_IRQ,
- }, {
- /* Headset insertion or removal */
- .name = "headset",
- .start = PM8607_IRQ_HEADSET,
- .end = PM8607_IRQ_HEADSET,
- .flags = IORESOURCE_IRQ,
- }, {
- /* Audio short */
- .name = "audio-short",
- .start = PM8607_IRQ_AUDIO_SHORT,
- .end = PM8607_IRQ_AUDIO_SHORT,
- .flags = IORESOURCE_IRQ,
- },
+ {"88pm860x-battery", -1,},
+ {"88pm860x-charger", -1,},
};
-static struct mfd_cell codec_devs[] = {
- {
- .name = "88pm860x-codec",
- .num_resources = ARRAY_SIZE(codec_resources),
- .resources = &codec_resources[0],
- .id = -1,
- },
-};
+static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
+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;
struct pm860x_irq_data {
int reg;
@@ -672,6 +635,82 @@ out:
return;
}
+static void __devinit device_touch_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int ret;
+
+ if ((pdata == NULL) || (pdata->touch == NULL))
+ return;
+
+ memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata));
+ touch_devs[0].mfd_data = &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 pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int ret;
+
+ if ((pdata == NULL) || (pdata->power == NULL))
+ return;
+
+ memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata));
+ power_devs[0].mfd_data = &power_pdata;
+ power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
+ power_devs[0].resources = &battery_resources[0],
+ ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
+ &battery_resources[0], chip->irq_base);
+ if (ret < 0)
+ dev_err(chip->dev, "Failed to add battery subdev\n");
+
+ power_devs[1].mfd_data = &power_pdata;
+ power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
+ power_devs[1].resources = &charger_resources[0],
+ ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
+ &charger_resources[0], chip->irq_base);
+ if (ret < 0)
+ dev_err(chip->dev, "Failed to add charger subdev\n");
+}
+
+static void __devinit device_onkey_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_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_codec_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int ret;
+
+ codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
+ codec_devs[0].resources = &codec_resources[0],
+ ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
+ ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+ if (ret < 0)
+ dev_err(chip->dev, "Failed to add codec subdev\n");
+}
+
static void __devinit device_8607_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
@@ -727,49 +766,11 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
if (ret < 0)
goto out;
- 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;
- }
- }
-
- if (pdata && pdata->power) {
- ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
- ARRAY_SIZE(power_devs),
- &power_supply_resources[0], 0);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add power supply "
- "subdev\n");
- goto out_dev;
- }
- }
-
- ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
- ARRAY_SIZE(onkey_devs),
- &onkey_resources[0], 0);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add onkey subdev\n");
- goto out_dev;
- }
-
- ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
- ARRAY_SIZE(codec_devs),
- &codec_resources[0], 0);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add codec subdev\n");
- goto out_dev;
- }
-
device_regulator_init(chip, i2c, pdata);
- return;
-out_dev:
- mfd_remove_devices(chip->dev);
- device_irq_exit(chip);
+ device_onkey_init(chip, i2c, pdata);
+ device_touch_init(chip, i2c, pdata);
+ device_power_init(chip, i2c, pdata);
+ device_codec_init(chip, i2c, pdata);
out:
return;
}
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: add workqueue thread into 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Haojian Zhuang
2011-03-13 6:38 ` [PATCH] mfd: add workqueue thread into 88pm860x Dmitry Torokhov
2011-03-14 11:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x Samuel Ortiz
1 sibling, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Create workqueue thread in 88pm860x driver since 88pm860x driver
needs to handle event in workqueue.
Avoid to use system workqueue since i2c operation cost a lot of
time. It would impact system performance.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-core.c | 12 ++++++++++++
include/linux/mfd/88pm860x.h | 1 +
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 9c511c1..42c4fa2 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -766,11 +766,21 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
if (ret < 0)
goto out;
+ chip->monitor_wqueue = create_singlethread_workqueue("88pm860x");
+ if (!chip->monitor_wqueue) {
+ ret = -ESRCH;
+ goto out_work;
+ }
+
device_regulator_init(chip, i2c, pdata);
device_onkey_init(chip, i2c, pdata);
device_touch_init(chip, i2c, pdata);
device_power_init(chip, i2c, pdata);
device_codec_init(chip, i2c, pdata);
+ return;
+
+out_work:
+ device_irq_exit(chip);
out:
return;
}
@@ -807,6 +817,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
void __devexit pm860x_device_exit(struct pm860x_chip *chip)
{
+ flush_workqueue(chip->monitor_wqueue);
+ destroy_workqueue(chip->monitor_wqueue);
device_irq_exit(chip);
mfd_remove_devices(chip->dev);
}
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index a6f6f81..87df510 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -301,6 +301,7 @@ struct pm860x_chip {
struct mutex irq_lock;
struct i2c_client *client;
struct i2c_client *companion; /* companion chip client */
+ struct workqueue_struct *monitor_wqueue;
int buck3_double; /* DVC ramp slope double */
unsigned short companion_addr;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] input: touchscreen: use polling mode in 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: add workqueue thread into 88pm860x Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: move initialization " Haojian Zhuang
2011-03-13 6:44 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Dmitry Torokhov
2011-03-13 6:38 ` [PATCH] mfd: add workqueue thread into 88pm860x Dmitry Torokhov
1 sibling, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: 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.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/input/touchscreen/88pm860x-ts.c | 77 +++++++++++++++++++++++-------
1 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index b3aebc2..7d481cc 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -19,6 +19,18 @@
#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,26 @@
#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;
+
+ 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,6 +93,15 @@ 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;
+ queue_delayed_work(touch->chip->monitor_wqueue,
+ &touch->poll_work,
+ msecs_to_jiffies(interval));
} else {
input_report_abs(touch->idev, ABS_PRESSURE, 0);
input_report_key(touch->idev, BTN_TOUCH, 0);
@@ -85,22 +110,36 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
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;
+
+ 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,14 +191,14 @@ 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);
@@ -188,6 +227,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 +242,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
{
struct pm860x_touch *touch = platform_get_drvdata(pdev);
+ flush_workqueue(touch->chip->monitor_wqueue);
input_unregister_device(touch->idev);
free_irq(touch->irq, touch);
platform_set_drvdata(pdev, NULL);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] input: touchscreen: move initialization in 88pm860x
2011-03-07 15:43 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: append additional read write on 88pm860x Haojian Zhuang
2011-03-13 6:44 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Dmitry Torokhov
1 sibling, 1 reply; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Move the GPADC initialization code from mfd driver to touch driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/input/touchscreen/88pm860x-ts.c | 50 ++++++++++++++++++++++++------
drivers/mfd/88pm860x-core.c | 51 -------------------------------
2 files changed, 40 insertions(+), 61 deletions(-)
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index 7d481cc..aa8fe1a 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -11,10 +11,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
#define MEAS_LEN (8)
#define ACCURATE_BIT (12)
@@ -152,13 +153,43 @@ 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;
+ struct mfd_cell *cell;
int irq, ret;
irq = platform_get_irq(pdev, 0);
@@ -167,13 +198,11 @@ 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) {
+ cell = pdev->dev.platform_data;
+ if (cell == NULL)
+ return -ENODEV;
+ pdata = cell->mfd_data;
+ if (pdata == NULL) {
dev_err(&pdev->dev, "touchscreen data is missing\n");
return -EINVAL;
}
@@ -226,6 +255,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;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 42c4fa2..7879569 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -362,53 +362,6 @@ static struct irq_chip pm860x_irq_chip = {
.irq_disable = pm860x_irq_disable,
};
-static int __devinit device_gpadc_init(struct pm860x_chip *chip,
- struct pm860x_platform_data *pdata)
-{
- struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
- : chip->companion;
- int data;
- int ret;
-
- /* initialize GPADC without activating it */
-
- if (!pdata || !pdata->touch)
- return -EINVAL;
-
- /* set GPADC MISC1 register */
- data = 0;
- data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
- data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
- data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
- data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
- if (data) {
- ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
- if (ret < 0)
- goto out;
- }
- /* set tsi prebias time */
- if (pdata->touch->tsi_prebias) {
- data = pdata->touch->tsi_prebias;
- ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
- if (ret < 0)
- goto out;
- }
- /* set prebias & prechg time of pen detect */
- data = 0;
- data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
- data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
- if (data) {
- ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
- if (ret < 0)
- goto out;
- }
-
- ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
- PM8607_GPADC_EN, PM8607_GPADC_EN);
-out:
- return ret;
-}
-
static int __devinit device_irq_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
@@ -758,10 +711,6 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
goto out;
}
- ret = device_gpadc_init(chip, pdata);
- if (ret < 0)
- goto out;
-
ret = device_irq_init(chip, pdata);
if (ret < 0)
goto out;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: append additional read write on 88pm860x
2011-03-07 15:43 ` [PATCH] input: touchscreen: move initialization " Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] rtc: add 88pm860x rtc Haojian Zhuang
2011-03-14 11:25 ` [PATCH] mfd: append additional read write on 88pm860x Samuel Ortiz
0 siblings, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Append the additional read/write operation on 88pm860x for accessing
test page in 88PM860x.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-i2c.c | 103 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/88pm860x.h | 8 +++
2 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index bc02e6b..e017dc8 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -126,6 +126,109 @@ out:
}
EXPORT_SYMBOL(pm860x_set_bits);
+int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char zero = 0;
+ unsigned char data;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ pm860x_write_device(i2c, 0xFA, 0, &zero);
+ pm860x_write_device(i2c, 0xFB, 0, &zero);
+ pm860x_write_device(i2c, 0xFF, 0, &zero);
+ ret = pm860x_read_device(i2c, reg, 1, &data);
+ if (ret >= 0)
+ ret = (int)data;
+ pm860x_write_device(i2c, 0xFE, 0, &zero);
+ pm860x_write_device(i2c, 0xFC, 0, &zero);
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_page_reg_read);
+
+int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
+ unsigned char data)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char zero;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ pm860x_write_device(i2c, 0xFA, 0, &zero);
+ pm860x_write_device(i2c, 0xFB, 0, &zero);
+ pm860x_write_device(i2c, 0xFF, 0, &zero);
+ ret = pm860x_write_device(i2c, reg, 1, &data);
+ pm860x_write_device(i2c, 0xFE, 0, &zero);
+ pm860x_write_device(i2c, 0xFC, 0, &zero);
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_page_reg_write);
+
+int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char zero = 0;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ pm860x_write_device(i2c, 0xFA, 0, &zero);
+ pm860x_write_device(i2c, 0xFB, 0, &zero);
+ pm860x_write_device(i2c, 0xFF, 0, &zero);
+ ret = pm860x_read_device(i2c, reg, count, buf);
+ pm860x_write_device(i2c, 0xFE, 0, &zero);
+ pm860x_write_device(i2c, 0xFC, 0, &zero);
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_page_bulk_read);
+
+int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char zero = 0;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ pm860x_write_device(i2c, 0xFA, 0, &zero);
+ pm860x_write_device(i2c, 0xFB, 0, &zero);
+ pm860x_write_device(i2c, 0xFF, 0, &zero);
+ ret = pm860x_write_device(i2c, reg, count, buf);
+ pm860x_write_device(i2c, 0xFE, 0, &zero);
+ pm860x_write_device(i2c, 0xFC, 0, &zero);
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_page_bulk_write);
+
+int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
+ unsigned char mask, unsigned char data)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char zero;
+ unsigned char value;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ pm860x_write_device(i2c, 0xFA, 0, &zero);
+ pm860x_write_device(i2c, 0xFB, 0, &zero);
+ pm860x_write_device(i2c, 0xFF, 0, &zero);
+ ret = pm860x_read_device(i2c, reg, 1, &value);
+ if (ret < 0)
+ goto out;
+ value &= ~mask;
+ value |= data;
+ ret = pm860x_write_device(i2c, reg, 1, &value);
+out:
+ pm860x_write_device(i2c, 0xFE, 0, &zero);
+ pm860x_write_device(i2c, 0xFC, 0, &zero);
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_page_set_bits);
static const struct i2c_device_id pm860x_id_table[] = {
{ "88PM860x", 0 },
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index 87df510..05f8677 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -369,6 +369,14 @@ extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *);
extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
unsigned char);
+extern int pm860x_page_reg_read(struct i2c_client *, int);
+extern int pm860x_page_reg_write(struct i2c_client *, int, unsigned char);
+extern int pm860x_page_bulk_read(struct i2c_client *, int, int,
+ unsigned char *);
+extern int pm860x_page_bulk_write(struct i2c_client *, int, int,
+ unsigned char *);
+extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char,
+ unsigned char);
extern int pm860x_device_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata) __devinit ;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] rtc: add 88pm860x rtc
2011-03-07 15:43 ` [PATCH] mfd: append additional read write on 88pm860x Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: set the long press detection in 88pm860x onkey Haojian Zhuang
2011-03-14 10:51 ` [PATCH] rtc: add 88pm860x rtc Samuel Ortiz
2011-03-14 11:25 ` [PATCH] mfd: append additional read write on 88pm860x Samuel Ortiz
1 sibling, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Support RTC component in 88PM860x. Also support synchronize time
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.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-core.c | 30 ++++++++++++++++++++++++++++++
drivers/rtc/Kconfig | 10 ++++++++++
drivers/rtc/Makefile | 1 +
include/linux/mfd/88pm860x.h | 6 ++++++
4 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 7879569..864e6a3 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -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[] __initdata = {
+ {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[] __initdata = {
+ {"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,26 @@ 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].mfd_data = &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)
@@ -722,6 +751,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
}
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);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4941cad..4f7b9f4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -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
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 2afdaf3..edc9325 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -17,6 +17,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
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index 05f8677..318aba8 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -331,6 +331,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;
@@ -350,6 +355,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;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] input: set the long press detection in 88pm860x onkey
2011-03-07 15:43 ` [PATCH] rtc: add 88pm860x rtc Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] w1: add DS278x slave driver Haojian Zhuang
2011-03-13 6:45 ` [PATCH] input: set the long press detection in 88pm860x onkey Dmitry Torokhov
2011-03-14 10:51 ` [PATCH] rtc: add 88pm860x rtc Samuel Ortiz
1 sibling, 2 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Move the long-press detection from onkey handler to probe function. Avoid
unnecessary I2C operation in onkey handler.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/input/misc/88pm860x_onkey.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
index 3dca3c1..1abc77e 100644
--- a/drivers/input/misc/88pm860x_onkey.c
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -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:
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] w1: add DS278x slave driver
2011-03-07 15:43 ` [PATCH] input: set the long press detection in 88pm860x onkey Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip Haojian Zhuang
2011-03-13 6:45 ` [PATCH] input: set the long press detection in 88pm860x onkey Dmitry Torokhov
1 sibling, 1 reply; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
Append DS278x slave driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
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
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index f0c9096..d737aa9 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -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
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 3c76350..bcc134b 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -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
diff --git a/drivers/w1/slaves/w1_ds278x.c b/drivers/w1/slaves/w1_ds278x.c
new file mode 100644
index 0000000..9da94bb
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds278x.c
@@ -0,0 +1,184 @@
+/*
+ * w1_ds278x.c - w1 family 27 (DS2780/DS2781) driver
+ *
+ * Copyright (c) Intel 2006 Stanley Cai <stanley.cai@intel.com>
+ * Copyright (c) Marvell 2007 Paul Shen <bo.a.shen@marvell.com>
+ *
+ * Modified from w1_ds2433 driver
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+
+#define W1_REG_SIZE 256
+
+#define W1_F27_READ_REG 0x69
+#define W1_F27_WRITE_REG 0x6C
+#define W1_F27_COPY_REG 0x48
+#define W1_F27_RECALL_REG 0xB8
+#define W1_F27_LOCK_REG 0x6A
+
+struct w1_f27_data {
+ u8 memory[W1_REG_SIZE];
+ u32 validcrc;
+};
+
+/**
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f27_fix_count(loff_t off, size_t count,
+ size_t size)
+{
+ if (off > size)
+ return 0;
+
+ if ((off + count) > size)
+ return (size - off);
+
+ return count;
+}
+
+static ssize_t w1_f27_read_bin(struct file *fp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ u8 wrbuf[2];
+
+ count = w1_f27_fix_count(off, count, W1_REG_SIZE);
+ if (count == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ mutex_lock(&sl->master->mutex);
+
+ /* read directly from the REG */
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_mutex_unlock;
+ }
+
+ wrbuf[0] = W1_F27_READ_REG;
+ wrbuf[1] = off & 0xff;
+ w1_write_block(sl->master, wrbuf, 2);
+ w1_read_block(sl->master, buf, count);
+
+out_mutex_unlock:
+ mutex_unlock(&sl->master->mutex);
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static ssize_t w1_f27_write_bin(struct file *fp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct w1_slave *sl = kobj_to_w1_slave(kobj);
+ char wrbuf[2];
+
+ count = w1_f27_fix_count(off, count, W1_REG_SIZE);
+ if (count == 0)
+ return 0;
+
+ atomic_inc(&sl->refcnt);
+ mutex_lock(&sl->master->mutex);
+
+ if (w1_reset_select_slave(sl)) {
+ count = -EIO;
+ goto out_mutex_unlock;
+ }
+
+ wrbuf[0] = W1_F27_WRITE_REG;
+ wrbuf[1] = off & 0xff;
+ w1_write_block(sl->master, wrbuf, 2);
+ w1_write_block(sl->master, buf, count);
+
+out_mutex_unlock:
+ mutex_unlock(&sl->master->mutex);
+ atomic_dec(&sl->refcnt);
+
+ return count;
+}
+
+static struct bin_attribute w1_f27_bin_attr = {
+ .attr = {
+ .name = "registers",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = W1_REG_SIZE,
+ .read = w1_f27_read_bin,
+ .write = w1_f27_write_bin,
+};
+
+static int w1_f27_add_slave(struct w1_slave *sl)
+{
+ int err;
+
+ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f27_bin_attr);
+
+ return err;
+}
+
+static void w1_f27_remove_slave(struct w1_slave *sl)
+{
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f27_bin_attr);
+}
+
+static struct w1_family_ops w1_f27_fops = {
+ .add_slave = w1_f27_add_slave,
+ .remove_slave = w1_f27_remove_slave,
+};
+
+static struct w1_family w1_family_2780 = {
+ .fid = W1_BATTMON_DS2780,
+ .fops = &w1_f27_fops,
+};
+
+static struct w1_family w1_family_2781 = {
+ .fid = W1_BATTMON_DS2781,
+ .fops = &w1_f27_fops,
+};
+
+static struct w1_family w1_family_2783 = {
+ .fid = W1_BATTMON_DS2783,
+ .fops = &w1_f27_fops,
+};
+
+
+static int __init w1_f27_init(void)
+{
+ pr_info("1-Wire driver for the DS278x battery monitor...\n");
+ return (w1_register_family(&w1_family_2780) |
+ w1_register_family(&w1_family_2781) |
+ w1_register_family(&w1_family_2783));
+}
+
+static void __exit w1_f27_fini(void)
+{
+ w1_unregister_family(&w1_family_2781);
+ w1_unregister_family(&w1_family_2780);
+ w1_unregister_family(&w1_family_2783);
+}
+
+module_init(w1_f27_init);
+module_exit(w1_f27_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Shen <bo.a.shen@marvell.com>");
+MODULE_DESCRIPTION("w1 family 27 driver for DS2780 & DS2781,"
+ " Stand-Alone Fuel Gauge IC");
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index f3b636d..0f0b58c 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -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
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip
2011-03-07 15:43 ` [PATCH] w1: add DS278x slave driver Haojian Zhuang
@ 2011-03-07 15:43 ` Haojian Zhuang
2011-03-14 11:28 ` Samuel Ortiz
0 siblings, 1 reply; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-07 15:43 UTC (permalink / raw)
To: johnpol, sameo, a.zummo, lrg, broonie, dmitry.torokhov, dtor,
rpurdie, linux-kernel
Cc: Haojian Zhuang
This driver provides registers and IRQ of PXA3xx chips to the ds1wm driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/Kconfig | 7 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/pxa-w1.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/pxa-w1.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 5309534..1bb0ebd 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -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---
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c7e99df..3d1648f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -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
obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
diff --git a/drivers/mfd/pxa-w1.c b/drivers/mfd/pxa-w1.c
new file mode 100644
index 0000000..1fb380f
--- /dev/null
+++ b/drivers/mfd/pxa-w1.c
@@ -0,0 +1,149 @@
+/*
+ * Core driver for PXA DS1WM chip.
+ *
+ * Copyright (C) 2010 Marvell <jtzhou@marvell.com>
+ *
+ * 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[] __initdata = {
+ {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 __initdata = {
+ .name = "ds1wm",
+ .enable = ds1wm_enable,
+ .disable = ds1wm_disable,
+ .mfd_data = &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;
+
+ info = kzalloc(sizeof(struct pxa_w1_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (r == NULL) {
+ 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) {
+ 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)
+{
+ platform_driver_unregister(&pxa_w1_driver);
+}
+
+module_init(pxa_w1_base_init);
+module_exit(pxa_w1_base_exit);
+
+MODULE_AUTHOR("Jett Zhou <jtzhou@marvell.com>");
+MODULE_DESCRIPTION("one wire driver for PXA");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-w1");
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: adopt mfd_data in 88pm860x regulator
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
@ 2011-03-08 23:24 ` Mark Brown
2011-03-14 11:23 ` Samuel Ortiz
2 siblings, 0 replies; 28+ messages in thread
From: Mark Brown @ 2011-03-08 23:24 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, sameo, a.zummo, lrg, dmitry.torokhov, dtor, rpurdie,
linux-kernel
On Mon, Mar 07, 2011 at 11:43:11PM +0800, Haojian Zhuang wrote:
> Copy 88pm860x platform data into different mfd_data structure for
> regulator driver. So move the identification of device node from
> regulator driver to mfd driver.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
but if there's any in-tree users of the device I'd expect they need
their platform data updated?
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: add workqueue thread into 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: add workqueue thread into 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Haojian Zhuang
@ 2011-03-13 6:38 ` Dmitry Torokhov
1 sibling, 0 replies; 28+ messages in thread
From: Dmitry Torokhov @ 2011-03-13 6:38 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, sameo, a.zummo, lrg, broonie, rpurdie, linux-kernel
On Mon, Mar 07, 2011 at 11:43:13PM +0800, Haojian Zhuang wrote:
> Create workqueue thread in 88pm860x driver since 88pm860x driver
> needs to handle event in workqueue.
>
> Avoid to use system workqueue since i2c operation cost a lot of
> time. It would impact system performance.
No, not anymore - the concurrency managed workqueues implemented by
Tejun allow scheduling longer-running jobs on the system workqueue
without impacting other users.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] input: touchscreen: use polling mode in 88pm860x
2011-03-07 15:43 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: move initialization " Haojian Zhuang
@ 2011-03-13 6:44 ` Dmitry Torokhov
2011-03-14 12:41 ` Haojian Zhuang
1 sibling, 1 reply; 28+ messages in thread
From: Dmitry Torokhov @ 2011-03-13 6:44 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, sameo, a.zummo, lrg, broonie, rpurdie, linux-kernel
On Mon, Mar 07, 2011 at 11:43:14PM +0800, Haojian Zhuang wrote:
> 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.
>
Instead of scheduling work you could stay in the interrupt handler
(which is a separate thread) and poll from it. Or is it a nested
interrupt and it is sharing the interrupt thread?
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] input: set the long press detection in 88pm860x onkey
2011-03-07 15:43 ` [PATCH] input: set the long press detection in 88pm860x onkey Haojian Zhuang
2011-03-07 15:43 ` [PATCH] w1: add DS278x slave driver Haojian Zhuang
@ 2011-03-13 6:45 ` Dmitry Torokhov
1 sibling, 0 replies; 28+ messages in thread
From: Dmitry Torokhov @ 2011-03-13 6:45 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, sameo, a.zummo, lrg, broonie, rpurdie, linux-kernel
On Mon, Mar 07, 2011 at 11:43:18PM +0800, Haojian Zhuang wrote:
> Move the long-press detection from onkey handler to probe function. Avoid
> unnecessary I2C operation in onkey handler.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
> ---
> drivers/input/misc/88pm860x_onkey.c | 6 +++---
> 1 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
> index 3dca3c1..1abc77e 100644
> --- a/drivers/input/misc/88pm860x_onkey.c
> +++ b/drivers/input/misc/88pm860x_onkey.c
> @@ -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:
> --
> 1.5.6.5
>
--
Dmitry
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] rtc: add 88pm860x rtc
2011-03-07 15:43 ` [PATCH] rtc: add 88pm860x rtc Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: set the long press detection in 88pm860x onkey Haojian Zhuang
@ 2011-03-14 10:51 ` Samuel Ortiz
2011-03-14 13:09 ` Haojian Zhuang
1 sibling, 1 reply; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 10:51 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:17PM +0800, Haojian Zhuang wrote:
> Support RTC component in 88PM860x. Also support synchronize time
> 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.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
> ---
> drivers/mfd/88pm860x-core.c | 30 ++++++++++++++++++++++++++++++
> drivers/rtc/Kconfig | 10 ++++++++++
> drivers/rtc/Makefile | 1 +
> include/linux/mfd/88pm860x.h | 6 ++++++
rtc-88pm860x.c is missing from this patch.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: adopt mfd_data in 88pm860x backlight
2011-03-07 15:43 [PATCH] mfd: adopt mfd_data in 88pm860x backlight Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Haojian Zhuang
@ 2011-03-14 10:56 ` Samuel Ortiz
1 sibling, 0 replies; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 10:56 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:09PM +0800, Haojian Zhuang wrote:
> Copy 88pm860x platform data into different mfd_data structure for
> backlight driver. So move the identification of device node from
> backlight driver to mfd driver.
Patch applied, thanks.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: adopt mfd_data in 88pm860x led
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
@ 2011-03-14 11:23 ` Samuel Ortiz
1 sibling, 0 replies; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 11:23 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:10PM +0800, Haojian Zhuang wrote:
> Copy 88pm860x platform data into different mfd_data structure for
> led driver. So move the identification of device node from led
> driver to mfd driver.
Patch applied, thanks.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: adopt mfd_data in 88pm860x regulator
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
2011-03-08 23:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Mark Brown
@ 2011-03-14 11:23 ` Samuel Ortiz
2 siblings, 0 replies; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 11:23 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:11PM +0800, Haojian Zhuang wrote:
> Copy 88pm860x platform data into different mfd_data structure for
> regulator driver. So move the identification of device node from
> regulator driver to mfd driver.
Patch applied as well, thanks.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: adopt mfd_data in 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: add workqueue thread into 88pm860x Haojian Zhuang
@ 2011-03-14 11:24 ` Samuel Ortiz
1 sibling, 0 replies; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 11:24 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:12PM +0800, Haojian Zhuang wrote:
> Copy 88pm860x platform data into different mfd_data structure for
> onkey/touch/codec/power driver. So move the identification of
> device node from those drivers to mfd driver.
I applied this patch too.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: append additional read write on 88pm860x
2011-03-07 15:43 ` [PATCH] mfd: append additional read write on 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] rtc: add 88pm860x rtc Haojian Zhuang
@ 2011-03-14 11:25 ` Samuel Ortiz
1 sibling, 0 replies; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 11:25 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:16PM +0800, Haojian Zhuang wrote:
> Append the additional read/write operation on 88pm860x for accessing
> test page in 88PM860x.
Patch applied, thanks.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip
2011-03-07 15:43 ` [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip Haojian Zhuang
@ 2011-03-14 11:28 ` Samuel Ortiz
2011-03-14 12:34 ` Haojian Zhuang
0 siblings, 1 reply; 28+ messages in thread
From: Samuel Ortiz @ 2011-03-14 11:28 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol, a.zummo, lrg, broonie, dmitry.torokhov, dtor, rpurdie,
linux-kernel
Hi Haojian,
On Mon, Mar 07, 2011 at 11:43:20PM +0800, Haojian Zhuang wrote:
> This driver provides registers and IRQ of PXA3xx chips to the ds1wm driver.
Why is this an MFD driver ?
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 28+ messages in thread
* RE: [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip
2011-03-14 11:28 ` Samuel Ortiz
@ 2011-03-14 12:34 ` Haojian Zhuang
2011-03-14 19:55 ` Jean-Francois Dagenais
0 siblings, 1 reply; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-14 12:34 UTC (permalink / raw)
To: Samuel Ortiz
Cc: johnpol@2ka.mipt.ru, a.zummo@towertech.it, lrg@slimlogic.co.uk,
broonie@opensource.wolfsonmicro.com, dmitry.torokhov@gmail.com,
dtor@mail.ru, rpurdie@rpsys.net, linux-kernel@vger.kernel.org
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1066 bytes --]
>-----Original Message-----
>From: Samuel Ortiz [mailto:sameo@linux.intel.com]
>Sent: 2011Äê3ÔÂ14ÈÕ 7:29 PM
>To: Haojian Zhuang
>Cc: johnpol@2ka.mipt.ru; a.zummo@towertech.it; lrg@slimlogic.co.uk;
>broonie@opensource.wolfsonmicro.com; dmitry.torokhov@gmail.com;
>dtor@mail.ru; rpurdie@rpsys.net; linux-kernel@vger.kernel.org
>Subject: Re: [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control +
>DS1WM chip
>
>Hi Haojian,
>
>On Mon, Mar 07, 2011 at 11:43:20PM +0800, Haojian Zhuang wrote:
>> This driver provides registers and IRQ of PXA3xx chips to the ds1wm
>driver.
>Why is this an MFD driver ?
>
>Cheers,
>Samuel.
>
>--
>Intel Open Source Technology Centre
>http://oss.intel.com/
Hi Samuel,
Because there's already a DS1WM driver in drivers/w1/masters/ds1wm.c. In PXA silicons, W1 controler is compatible with this driver. So we implement it as MFD driver, like htc-pasic3.c.
Best Regards
Haojian
ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
^ permalink raw reply [flat|nested] 28+ messages in thread
* RE: [PATCH] input: touchscreen: use polling mode in 88pm860x
2011-03-13 6:44 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Dmitry Torokhov
@ 2011-03-14 12:41 ` Haojian Zhuang
2011-03-15 5:02 ` Dmitry Torokhov
0 siblings, 1 reply; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-14 12:41 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: johnpol@2ka.mipt.ru, sameo@linux.intel.com, a.zummo@towertech.it,
lrg@slimlogic.co.uk, broonie@opensource.wolfsonmicro.com,
rpurdie@rpsys.net, linux-kernel@vger.kernel.org
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1164 bytes --]
>-----Original Message-----
>From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
>Sent: 2011Äê3ÔÂ13ÈÕ 2:44 PM
>To: Haojian Zhuang
>Cc: johnpol@2ka.mipt.ru; sameo@linux.intel.com; a.zummo@towertech.it;
>lrg@slimlogic.co.uk; broonie@opensource.wolfsonmicro.com;
>rpurdie@rpsys.net; linux-kernel@vger.kernel.org
>Subject: Re: [PATCH] input: touchscreen: use polling mode in 88pm860x
>
>On Mon, Mar 07, 2011 at 11:43:14PM +0800, Haojian Zhuang wrote:
>> 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.
>>
>
>Instead of scheduling work you could stay in the interrupt handler
>(which is a separate thread) and poll from it. Or is it a nested
>interrupt and it is sharing the interrupt thread?
>
>Thanks.
>
>--
>Dmitry
I'm using a nested interrupt. Do you mean that I should keep polling in the nested interrupt handler?
Thanks
Haojian
ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
^ permalink raw reply [flat|nested] 28+ messages in thread
* RE: [PATCH] rtc: add 88pm860x rtc
2011-03-14 10:51 ` [PATCH] rtc: add 88pm860x rtc Samuel Ortiz
@ 2011-03-14 13:09 ` Haojian Zhuang
0 siblings, 0 replies; 28+ messages in thread
From: Haojian Zhuang @ 2011-03-14 13:09 UTC (permalink / raw)
To: Samuel Ortiz
Cc: johnpol@2ka.mipt.ru, a.zummo@towertech.it, lrg@slimlogic.co.uk,
broonie@opensource.wolfsonmicro.com, dmitry.torokhov@gmail.com,
dtor@mail.ru, rpurdie@rpsys.net, linux-kernel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 1310 bytes --]
>-----Original Message-----
>From: Samuel Ortiz [mailto:sameo@linux.intel.com]
>Sent: 2011年3月14日 6:51 PM
>To: Haojian Zhuang
>Cc: johnpol@2ka.mipt.ru; a.zummo@towertech.it; lrg@slimlogic.co.uk;
>broonie@opensource.wolfsonmicro.com; dmitry.torokhov@gmail.com;
>dtor@mail.ru; rpurdie@rpsys.net; linux-kernel@vger.kernel.org
>Subject: Re: [PATCH] rtc: add 88pm860x rtc
>
>Hi Haojian,
>
>On Mon, Mar 07, 2011 at 11:43:17PM +0800, Haojian Zhuang wrote:
>> Support RTC component in 88PM860x. Also support synchronize time
>> 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.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
>> ---
>> drivers/mfd/88pm860x-core.c | 30 ++++++++++++++++++++++++++++++
>> drivers/rtc/Kconfig | 10 ++++++++++
>> drivers/rtc/Makefile | 1 +
>> include/linux/mfd/88pm860x.h | 6 ++++++
>rtc-88pm860x.c is missing from this patch.
>
>Cheers,
>Samuel.
>
>--
>Intel Open Source Technology Centre
>http://oss.intel.com/
Hi Samuel,
I'm sorry on missing the rtc file. Now I attach it in mail. I'm sorry on inconvient.
Thanks
Haojian
[-- Attachment #2: 0001-rtc-add-88pm860x-rtc.patch --]
[-- Type: application/octet-stream, Size: 17691 bytes --]
From 339df576239a38fa10a3f0a62d3957cd6bf6cc30 Mon Sep 17 00:00:00 2001
From: Haojian Zhuang <haojian.zhuang@marvell.com>
Date: Tue, 1 Mar 2011 21:55:36 +0800
Subject: [PATCH] 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.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
drivers/mfd/88pm860x-core.c | 30 +++
drivers/rtc/Kconfig | 10 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-88pm860x.c | 432 ++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/88pm860x.h | 6 +
5 files changed, 479 insertions(+), 0 deletions(-)
create mode 100644 drivers/rtc/rtc-88pm860x.c
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 7879569..864e6a3 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -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[] __initdata = {
+ {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[] __initdata = {
+ {"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,26 @@ 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].mfd_data = &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)
@@ -722,6 +751,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
}
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);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4941cad..4f7b9f4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -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
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 2afdaf3..edc9325 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -17,6 +17,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
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
new file mode 100644
index 0000000..6ad507b
--- /dev/null
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -0,0 +1,432 @@
+/*
+ * Real Time Clock driver for Marvell 88PM860x PMIC
+ *
+ * Copyright (c) 2010 Marvell International Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/88pm860x.h>
+
+#define VRTC_CALIBRATION
+
+struct pm860x_rtc_info {
+ struct pm860x_chip *chip;
+ struct i2c_client *i2c;
+ struct rtc_device *rtc_dev;
+ struct device *dev;
+ struct delayed_work calib_work;
+
+ int irq;
+ int vrtc;
+ int (*sync)(unsigned int ticks);
+};
+
+#define REG_VRTC_MEAS1 0x7D
+
+#define REG0_ADDR 0xB0
+#define REG1_ADDR 0xB2
+#define REG2_ADDR 0xB4
+#define REG3_ADDR 0xB6
+
+#define REG0_DATA 0xB1
+#define REG1_DATA 0xB3
+#define REG2_DATA 0xB5
+#define REG3_DATA 0xB7
+
+/* bit definitions of Measurement Enable Register 2 (0x51) */
+#define MEAS2_VRTC (1 << 0)
+
+/* bit definitions of RTC Register 1 (0xA0) */
+#define ALARM_EN (1 << 3)
+#define ALARM_WAKEUP (1 << 4)
+#define ALARM (1 << 5)
+#define RTC1_USE_XO (1 << 7)
+
+#define VRTC_CALIB_INTERVAL (HZ * 60 * 10) /* 10 minutes */
+
+static irqreturn_t rtc_update_handler(int irq, void *data)
+{
+ struct pm860x_rtc_info *info = (struct pm860x_rtc_info *)data;
+ int mask;
+
+ mask = ALARM | ALARM_WAKEUP;
+ pm860x_set_bits(info->i2c, PM8607_RTC1, mask | ALARM_EN, mask);
+ rtc_update_irq(info->rtc_dev, 1, RTC_AF);
+ return IRQ_HANDLED;
+}
+
+static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct pm860x_rtc_info *info = dev_get_drvdata(dev);
+
+ if (enabled)
+ pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM);
+ else
+ pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0);
+ return 0;
+}
+
+/*
+ * Calculate the next alarm time given the requested alarm time mask
+ * and the current time.
+ */
+static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
+ struct rtc_time *alrm)
+{
+ unsigned long next_time;
+ unsigned long now_time;
+
+ next->tm_year = now->tm_year;
+ next->tm_mon = now->tm_mon;
+ next->tm_mday = now->tm_mday;
+ next->tm_hour = alrm->tm_hour;
+ next->tm_min = alrm->tm_min;
+ next->tm_sec = alrm->tm_sec;
+
+ rtc_tm_to_time(now, &now_time);
+ rtc_tm_to_time(next, &next_time);
+
+ if (next_time < now_time) {
+ /* Advance one day */
+ next_time += 60 * 60 * 24;
+ rtc_time_to_tm(next_time, next);
+ }
+}
+
+static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pm860x_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[8];
+ unsigned long ticks, base, data;
+
+ pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
+ dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
+ buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+ base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
+
+ /* load 32-bit read-only counter */
+ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
+ data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ ticks = base + data;
+ dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
+ base, data, ticks);
+
+ rtc_time_to_tm(ticks, tm);
+
+ return 0;
+}
+
+static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pm860x_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[4];
+ unsigned long ticks, base, data;
+
+ if ((tm->tm_year < 70) || (tm->tm_year > 138)) {
+ dev_dbg(info->dev, "Set time %d out of range. "
+ "Please set time between 1970 to 2038.\n",
+ 1900 + tm->tm_year);
+ return -EINVAL;
+ }
+ rtc_tm_to_time(tm, &ticks);
+
+ /* load 32-bit read-only counter */
+ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
+ data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ base = ticks - data;
+ dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
+ base, data, ticks);
+
+ pm860x_page_reg_write(info->i2c, REG0_DATA, (base >> 24) & 0xFF);
+ pm860x_page_reg_write(info->i2c, REG1_DATA, (base >> 16) & 0xFF);
+ pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF);
+ pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF);
+
+ if (info->sync)
+ info->sync(ticks);
+ return 0;
+}
+
+static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pm860x_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[8];
+ unsigned long ticks, base, data;
+ int ret;
+
+ pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
+ dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
+ buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+ base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
+
+ pm860x_bulk_read(info->i2c, PM8607_RTC_EXPIRE1, 4, buf);
+ data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ ticks = base + data;
+ dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
+ base, data, ticks);
+
+ rtc_time_to_tm(ticks, &alrm->time);
+ ret = pm860x_reg_read(info->i2c, PM8607_RTC1);
+ alrm->enabled = (ret & ALARM_EN) ? 1 : 0;
+ alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0;
+ return 0;
+}
+
+static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pm860x_rtc_info *info = dev_get_drvdata(dev);
+ struct rtc_time now_tm, alarm_tm;
+ unsigned long ticks, base, data;
+ unsigned char buf[8];
+ int mask;
+
+ pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0);
+
+ pm860x_page_bulk_read(info->i2c, REG0_ADDR, 8, buf);
+ dev_dbg(info->dev, "%x-%x-%x-%x-%x-%x-%x-%x\n", buf[0], buf[1],
+ buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+ base = (buf[1] << 24) | (buf[3] << 16) | (buf[5] << 8) | buf[7];
+
+ /* load 32-bit read-only counter */
+ pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
+ data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ ticks = base + data;
+ dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
+ base, data, ticks);
+
+ rtc_time_to_tm(ticks, &now_tm);
+ rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
+ /* get new ticks for alarm in 24 hours */
+ rtc_tm_to_time(&alarm_tm, &ticks);
+ data = ticks - base;
+
+ buf[0] = data & 0xff;
+ buf[1] = (data >> 8) & 0xff;
+ buf[2] = (data >> 16) & 0xff;
+ buf[3] = (data >> 24) & 0xff;
+ pm860x_bulk_write(info->i2c, PM8607_RTC_EXPIRE1, 4, buf);
+ if (alrm->enabled) {
+ mask = ALARM | ALARM_WAKEUP | ALARM_EN;
+ pm860x_set_bits(info->i2c, PM8607_RTC1, mask, mask);
+ } else {
+ mask = ALARM | ALARM_WAKEUP | ALARM_EN;
+ pm860x_set_bits(info->i2c, PM8607_RTC1, mask,
+ ALARM | ALARM_WAKEUP);
+ }
+ return 0;
+}
+
+static const struct rtc_class_ops pm860x_rtc_ops = {
+ .read_time = pm860x_rtc_read_time,
+ .set_time = pm860x_rtc_set_time,
+ .read_alarm = pm860x_rtc_read_alarm,
+ .set_alarm = pm860x_rtc_set_alarm,
+ .alarm_irq_enable = pm860x_rtc_alarm_irq_enable,
+};
+
+#ifdef VRTC_CALIBRATION
+static void calibrate_vrtc_work(struct work_struct *work)
+{
+ struct pm860x_rtc_info *info = container_of(work,
+ struct pm860x_rtc_info, calib_work.work);
+ unsigned char buf[2];
+ unsigned int sum, data, mean, vrtc_set;
+ int i;
+
+ for (i = 0, sum = 0; i < 16; i++) {
+ msleep(100);
+ pm860x_bulk_read(info->i2c, REG_VRTC_MEAS1, 2, buf);
+ data = (buf[0] << 4) | buf[1];
+ data = (data * 5400) >> 12; /* convert to mv */
+ sum += data;
+ }
+ mean = sum >> 4;
+ vrtc_set = 2700 + (info->vrtc & 0x3) * 200;
+ dev_dbg(info->dev, "mean:%d, vrtc_set:%d\n", mean, vrtc_set);
+
+ sum = pm860x_reg_read(info->i2c, PM8607_RTC_MISC1);
+ data = sum & 0x3;
+ if ((mean + 200) < vrtc_set) {
+ /* try higher voltage */
+ if (++data == 4)
+ goto out;
+ data = (sum & 0xf8) | (data & 0x3);
+ pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data);
+ } else if ((mean - 200) > vrtc_set) {
+ /* try lower voltage */
+ if (data-- == 0)
+ goto out;
+ data = (sum & 0xf8) | (data & 0x3);
+ pm860x_reg_write(info->i2c, PM8607_RTC_MISC1, data);
+ } else
+ goto out;
+ dev_dbg(info->dev, "set 0x%x to RTC_MISC1\n", data);
+ /* trigger next calibration since VRTC is updated */
+ queue_delayed_work(info->chip->monitor_wqueue, &info->calib_work,
+ VRTC_CALIB_INTERVAL);
+ return;
+out:
+ /* disable measurement */
+ pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0);
+ dev_dbg(info->dev, "finish VRTC calibration\n");
+ return;
+}
+#endif
+
+static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_rtc_pdata *pdata = NULL;
+ struct pm860x_rtc_info *info;
+ struct mfd_cell *cell;
+ struct rtc_time tm;
+ unsigned long ticks = 0;
+ int ret;
+
+ cell = pdev->dev.platform_data;
+ if (cell == NULL)
+ return -ENODEV;
+ pdata = cell->mfd_data;
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "No platform data!\n");
+ return -EINVAL;
+ }
+
+ info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->irq = platform_get_irq(pdev, 0);
+ if (info->irq < 0) {
+ dev_err(&pdev->dev, "No IRQ resource!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ info->chip = chip;
+ info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+ info->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, info);
+
+ ret = request_threaded_irq(info->irq, NULL, rtc_update_handler,
+ IRQF_ONESHOT, "rtc", info);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+ info->irq, ret);
+ goto out;
+ }
+
+ /* set addresses of 32-bit base value for RTC time */
+ pm860x_page_reg_write(info->i2c, REG0_ADDR, REG0_DATA);
+ pm860x_page_reg_write(info->i2c, REG1_ADDR, REG1_DATA);
+ pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA);
+ pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA);
+
+ ret = pm860x_rtc_read_time(&pdev->dev, &tm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to read initial time.\n");
+ goto out_rtc;
+ }
+ if ((tm.tm_year < 70) || (tm.tm_year > 138)) {
+ tm.tm_year = 70;
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ ret = pm860x_rtc_set_time(&pdev->dev, &tm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to set initial time.\n");
+ goto out_rtc;
+ }
+ }
+ rtc_tm_to_time(&tm, &ticks);
+ if (pdata->sync) {
+ pdata->sync(ticks);
+ info->sync = pdata->sync;
+ }
+
+ info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev,
+ &pm860x_rtc_ops, THIS_MODULE);
+ ret = PTR_ERR(info->rtc_dev);
+ if (IS_ERR(info->rtc_dev)) {
+ dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+ goto out_rtc;
+ }
+
+ /*
+ * enable internal XO instead of internal 3.25MHz clock since it can
+ * free running in PMIC power-down state.
+ */
+ pm860x_set_bits(info->i2c, PM8607_RTC1, RTC1_USE_XO, RTC1_USE_XO);
+
+#ifdef VRTC_CALIBRATION
+ /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
+ info->vrtc = pdata->vrtc & 0x3;
+ pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
+
+ /* calibrate VRTC */
+ INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work);
+ queue_delayed_work(chip->monitor_wqueue, &info->calib_work,
+ VRTC_CALIB_INTERVAL);
+#endif /* VRTC_CALIBRATION */
+ return 0;
+out_rtc:
+ free_irq(info->irq, info);
+out:
+ kfree(info);
+ return ret;
+}
+
+static int __devexit pm860x_rtc_remove(struct platform_device *pdev)
+{
+ struct pm860x_rtc_info *info = platform_get_drvdata(pdev);
+
+#ifdef VRTC_CALIBRATION
+ flush_workqueue(info->chip->monitor_wqueue);
+ /* disable measurement */
+ pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0);
+#endif /* VRTC_CALIBRATION */
+
+ platform_set_drvdata(pdev, NULL);
+ rtc_device_unregister(info->rtc_dev);
+ free_irq(info->irq, info);
+ kfree(info);
+ return 0;
+}
+
+static struct platform_driver pm860x_rtc_driver = {
+ .driver = {
+ .name = "88pm860x-rtc",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_rtc_probe,
+ .remove = __devexit_p(pm860x_rtc_remove),
+};
+
+static int __init pm860x_rtc_init(void)
+{
+ return platform_driver_register(&pm860x_rtc_driver);
+}
+module_init(pm860x_rtc_init);
+
+static void __exit pm860x_rtc_exit(void)
+{
+ platform_driver_unregister(&pm860x_rtc_driver);
+}
+module_exit(pm860x_rtc_exit);
+
+MODULE_DESCRIPTION("Marvell 88PM860x RTC driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
index 05f8677..318aba8 100644
--- a/include/linux/mfd/88pm860x.h
+++ b/include/linux/mfd/88pm860x.h
@@ -331,6 +331,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;
@@ -350,6 +355,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;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip
2011-03-14 12:34 ` Haojian Zhuang
@ 2011-03-14 19:55 ` Jean-Francois Dagenais
0 siblings, 0 replies; 28+ messages in thread
From: Jean-Francois Dagenais @ 2011-03-14 19:55 UTC (permalink / raw)
To: Haojian Zhuang
Cc: Samuel Ortiz, johnpol@2ka.mipt.ru, a.zummo@towertech.it,
lrg@slimlogic.co.uk, broonie@opensource.wolfsonmicro.com,
dmitry.torokhov@gmail.com, dtor@mail.ru, rpurdie@rpsys.net,
linux-kernel@vger.kernel.org
On Mar 14, 2011, at 8:34, Haojian Zhuang wrote:
>
>
>> -----Original Message-----
>> From: Samuel Ortiz [mailto:sameo@linux.intel.com]
>> Sent: 2011年3月14日 7:29 PM
>> To: Haojian Zhuang
>> Cc: johnpol@2ka.mipt.ru; a.zummo@towertech.it; lrg@slimlogic.co.uk;
>> broonie@opensource.wolfsonmicro.com; dmitry.torokhov@gmail.com;
>> dtor@mail.ru; rpurdie@rpsys.net; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control +
>> DS1WM chip
>>
>> Hi Haojian,
>>
>> On Mon, Mar 07, 2011 at 11:43:20PM +0800, Haojian Zhuang wrote:
>>> This driver provides registers and IRQ of PXA3xx chips to the ds1wm
>> driver.
>> Why is this an MFD driver ?
>>
>> Cheers,
>> Samuel.
>>
>> --
>> Intel Open Source Technology Centre
>> http://oss.intel.com/
>
> Hi Samuel,
>
> Because there's already a DS1WM driver in drivers/w1/masters/ds1wm.c. In PXA silicons, W1 controler is compatible with this driver. So we implement it as MFD driver, like htc-pasic3.c.
>
> Best Regards
> Haojian--
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
I successfully made this driver work with a ds1wm core inside a virtex5 interfaced through PCI express. The base address of the ds1wm is at a certain offset in the BAR0 of the virtex5. We used a shared interrupt for the ds1wm and the other function our virtex5 does. This is on a x86 platform. I posted a couple of patches last week which added multi-slave search support to the existing ds1wm driver.
look for [w1 PATCHES 3/3] Complete the 1-wire (w1) ds1wm driver search algo
I declare the presence of the ds1wm from my pci_probe of the FPGA device.
static int ds1wm_enable(struct platform_device *pdev)
{
struct MYSTRUCT* pMyDevStruct = dev_get_drvdata(pdev->dev.parent);
u32* address = pHudDev->bar0KernAddr + REG_OFFSET_RESET;
... custom stuff you need to do to make the ds1wm power up
return 0;
}
static int ds1wm_disable(struct platform_device *pdev)
{
... undo what you did in enable.
return 0;
}
#define REG_1_WIRE_BASE 0xXX
static struct ds1wm_driver_data ds1wm_pdata = {
.active_high = 1,
.clock_rate = 125000000 // PCIe transaction clock
};
static struct resource ds1wm_resources[] = {
[0] = {
.start = REG_1_WIRE_BASE,
.end = REG_1_WIRE_BASE + (5*sizeof(int)), // that's 5 registers each on a 32 bit address, we omit the 6th one, i.e. control reg
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0, // cell define as offset from parent base resource, i.e. 0 means same
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell ds1wm_cell = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
.driver_data = &ds1wm_pdata,
.num_resources = 2,
.resources = ds1wm_resources,
};
[...] in my pci_probe() [...]
ds1wm_cell.platform_data = &ds1wm_cell;
ds1wm_cell.data_size = sizeof(ds1wm_cell);
PDEBUG( "adding ds1wm core in mfd subsys, irq: %d\n", pPciDev->irq);
if(0 > mfd_add_devices(&pPciDev->dev, 0, &ds1wm_cell, 1, &pPciDev->resource[0], pPciDev->irq))
{
printk(KERN_CRIT PRINTK_ID "%s failed to add ds1wm \n", pHudDev->hwDeviceName);
goto cancel_and_exit;
}
PDEBUG( "ds1wm core added to mfd subsys\n");
GOOD LUCK!
FYI, here's the intro I had for these patches:
===================
The first patch add generic functionnality to w1_io for Resume Command [A5h]
lots of slaves support. I found it useful for multi-commands/reset workflows
with the same slave on a multi-slave bus.
This DS2408 w1 slave driver is not complete for all the
features of the chip, but its sufficient if you use it as
a simple IO expander. Enjoy!
The ds1wm had Kconfig dependencies towards ARM && HAVE_CLK. I took them
out since I was using the ds1wm on an x86_64 platform (ds1wm in a FPGA through
pcie) and found them irrelevant.
The clock freq/divisors at the top of ds1wm.c did not have the MSB set to 1.
This bit is CLK_EN which turns the whole prescaler and dividers on. The driver
never mentionned this bit either, so I just included this bit right in the table
entries. I also took the liberty to add a couple of entries to the table. The
spec doesn't explicitely mentions these possibilities but the description and
examination of the core shows the prescalers & dividers can be used for more
than the table explicitely shows. The table I enlarged still doesn't cover all
possibilities, but it's a good start.
I also made a few tweaks to a couple of the read and write algorithms which
made sense while I had my head very deep in the ds1wm documentation. We stressed
it a lot with 10+ slaves on the bus, many ds2408, ds2431 and ds2433 at the same
time doing extensive interaction. It proved quite stable in our production
environment.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] input: touchscreen: use polling mode in 88pm860x
2011-03-14 12:41 ` Haojian Zhuang
@ 2011-03-15 5:02 ` Dmitry Torokhov
0 siblings, 0 replies; 28+ messages in thread
From: Dmitry Torokhov @ 2011-03-15 5:02 UTC (permalink / raw)
To: Haojian Zhuang
Cc: johnpol@2ka.mipt.ru, sameo@linux.intel.com, a.zummo@towertech.it,
lrg@slimlogic.co.uk, broonie@opensource.wolfsonmicro.com,
rpurdie@rpsys.net, linux-kernel@vger.kernel.org
On Mon, Mar 14, 2011 at 05:41:35AM -0700, Haojian Zhuang wrote:
>
>
> >-----Original Message-----
> >From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> >Sent: 2011年3月13日 2:44 PM
> >To: Haojian Zhuang
> >Cc: johnpol@2ka.mipt.ru; sameo@linux.intel.com; a.zummo@towertech.it;
> >lrg@slimlogic.co.uk; broonie@opensource.wolfsonmicro.com;
> >rpurdie@rpsys.net; linux-kernel@vger.kernel.org
> >Subject: Re: [PATCH] input: touchscreen: use polling mode in 88pm860x
> >
> >On Mon, Mar 07, 2011 at 11:43:14PM +0800, Haojian Zhuang wrote:
> >> 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.
> >>
> >
> >Instead of scheduling work you could stay in the interrupt handler
> >(which is a separate thread) and poll from it. Or is it a nested
> >interrupt and it is sharing the interrupt thread?
> >
> >Thanks.
> >
> >--
> >Dmitry
>
> I'm using a nested interrupt. Do you mean that I should keep polling in the nested interrupt handler?
>
No, I do not believe you can poll from the nested handler since I
believe it shares the thread with other interrupts. In non-nested case
you could though.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2011-03-15 5:02 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-07 15:43 [PATCH] mfd: adopt mfd_data in 88pm860x backlight Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: adopt mfd_data in 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: add workqueue thread into 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: touchscreen: move initialization " Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: append additional read write on 88pm860x Haojian Zhuang
2011-03-07 15:43 ` [PATCH] rtc: add 88pm860x rtc Haojian Zhuang
2011-03-07 15:43 ` [PATCH] input: set the long press detection in 88pm860x onkey Haojian Zhuang
2011-03-07 15:43 ` [PATCH] w1: add DS278x slave driver Haojian Zhuang
2011-03-07 15:43 ` [PATCH] mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip Haojian Zhuang
2011-03-14 11:28 ` Samuel Ortiz
2011-03-14 12:34 ` Haojian Zhuang
2011-03-14 19:55 ` Jean-Francois Dagenais
2011-03-13 6:45 ` [PATCH] input: set the long press detection in 88pm860x onkey Dmitry Torokhov
2011-03-14 10:51 ` [PATCH] rtc: add 88pm860x rtc Samuel Ortiz
2011-03-14 13:09 ` Haojian Zhuang
2011-03-14 11:25 ` [PATCH] mfd: append additional read write on 88pm860x Samuel Ortiz
2011-03-13 6:44 ` [PATCH] input: touchscreen: use polling mode in 88pm860x Dmitry Torokhov
2011-03-14 12:41 ` Haojian Zhuang
2011-03-15 5:02 ` Dmitry Torokhov
2011-03-13 6:38 ` [PATCH] mfd: add workqueue thread into 88pm860x Dmitry Torokhov
2011-03-14 11:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x Samuel Ortiz
2011-03-08 23:24 ` [PATCH] mfd: adopt mfd_data in 88pm860x regulator Mark Brown
2011-03-14 11:23 ` Samuel Ortiz
2011-03-14 11:23 ` [PATCH] mfd: adopt mfd_data in 88pm860x led Samuel Ortiz
2011-03-14 10:56 ` [PATCH] mfd: adopt mfd_data in 88pm860x backlight Samuel Ortiz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox