2013-06-14 05:23:51

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 0/9] mfd: 88pm80x: bug fixes and enhancement

The patch set fixes some bugs in the 88pm800/88pm805 driver, and it add
regulator device into 88pm800.

The patches are tested based on Marvell pxa988 platform.

V2->V1:
add more fixes patches.
Below patches are same almost same as V1
mfd: 88pm800: fix NULL pointer errorm
mfd: 88pm800/88pm805: remove "IRQF_TRIGGER_FALLING" flag
Other patches are new.

Chao Xie (7):
mfd: 88pm80x: fix driver name for 88pm800 and 88pm805
mfd: 88pm800: fix for mask_invert
mfd: 88pm800: remove the power and gpadc page addr from platform data
mfd: 88pm800: fixes error handling for sub pages probe/remove
mfd: 88pm80x: Changes chip id definition and detection
mfd: 88pm800: enhance sub devices initialization
mfd: 88pm800: add regulator sub device

Yi Zhang (2):
mfd: 88pm800: fix NULL pointer error
mfd: 88pm800/88pm805: remove "IRQF_TRIGGER_FALLING" flag

drivers/mfd/88pm800.c | 237 +++++++++++++++++++++++++------------------
drivers/mfd/88pm805.c | 20 +---
drivers/mfd/88pm80x.c | 47 +++++++--
include/linux/mfd/88pm80x.h | 17 ++--
4 files changed, 193 insertions(+), 128 deletions(-)

--
1.7.4.1


2013-06-14 05:23:32

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 3/9] mfd: 88pm800: fix for mask_invert

mask_invert must be set. Or interrupt cannot be cleared.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 0801049..cca63f2 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -362,6 +362,7 @@ static struct regmap_irq_chip pm800_irq_chip = {
.status_base = PM800_INT_STATUS1,
.mask_base = PM800_INT_ENA_1,
.ack_base = PM800_INT_STATUS1,
+ .mask_invert = 1,
};

static int pm800_pages_init(struct pm80x_chip *chip)
--
1.7.4.1

2013-06-14 05:23:38

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 5/9] mfd: 88pm800: remove the power and gpadc page addr from platform data

88pm800 has two addtional pages - power and gpadc.
The address of the pages depends on the address of 88pm800.
So do not need pass the address of the power and gpadc in
platform data.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 5 +++--
include/linux/mfd/88pm80x.h | 2 --
2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index d2951d7..6b607ad 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -525,8 +525,9 @@ static int pm800_probe(struct i2c_client *client,
goto err_subchip_alloc;
}

- subchip->power_page_addr = pdata->power_page_addr;
- subchip->gpadc_page_addr = pdata->gpadc_page_addr;
+ /* pm800 has 2 addtional pages to support power and gpadc. */
+ subchip->power_page_addr = client->addr + 1;
+ subchip->gpadc_page_addr = client->addr + 2;
chip->subchip = subchip;

ret = pm800_pages_init(chip);
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index e94537b..023e639 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -309,8 +309,6 @@ struct pm80x_chip {

struct pm80x_platform_data {
struct pm80x_rtc_pdata *rtc;
- unsigned short power_page_addr; /* power page I2C address */
- unsigned short gpadc_page_addr; /* gpadc page I2C address */
int irq_mode; /* Clear interrupt by read/write(0/1) */
int batt_det; /* enable/disable */
int (*plat_config)(struct pm80x_chip *chip,
--
1.7.4.1

2013-06-14 05:23:54

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 4/9] mfd: 88pm800/88pm805: remove "IRQF_TRIGGER_FALLING" flag

From: Yi Zhang <[email protected]>

88pm800/88pm805 interrupt is asserted low if the events happened.
So remove IRQF_TRIGGER_FALLING for irq request.
How the interrupt is connected to SOC chip depends on the board design.
So do not set IRQF_TRIGGER flags.

Signed-off-by: Yi Zhang <[email protected]>
Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 2 +-
drivers/mfd/88pm805.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index cca63f2..d2951d7 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -318,7 +318,7 @@ out:
static int device_irq_init_800(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
- unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ unsigned long flags = IRQF_ONESHOT;
int data, mask, ret = -EINVAL;

if (!map || !chip->irq) {
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index d32b544..0e82c2a 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -138,7 +138,7 @@ static struct regmap_irq pm805_irqs[] = {
static int device_irq_init_805(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
- unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ unsigned long flags = IRQF_ONESHOT;
int data, mask, ret = -EINVAL;

if (!map || !chip->irq) {
--
1.7.4.1

2013-06-14 05:23:59

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 7/9] mfd: 88pm80x: Changes chip id definition and detection

Change the chip id definition and detection.
It brings the benefits
1. do not need add PM800_CHIP_XXX for the coming revision.
2. do not need pass driver_data in i2c_device_id because we
can distinguish the chips by CHIP_ID register.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 42 +++++--------------------------------
drivers/mfd/88pm805.c | 16 ++-----------
drivers/mfd/88pm80x.c | 47 ++++++++++++++++++++++++++++++++++++------
include/linux/mfd/88pm80x.h | 7 +----
4 files changed, 51 insertions(+), 61 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 932ebe8..16faad6 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -27,8 +27,6 @@
#include <linux/mfd/88pm80x.h>
#include <linux/slab.h>

-#define PM800_CHIP_ID (0x00)
-
/* Interrupt Registers */
#define PM800_INT_STATUS1 (0x05)
#define PM800_ONKEY_INT_STS1 (1 << 0)
@@ -113,20 +111,11 @@ enum {
PM800_MAX_IRQ,
};

-enum {
- /* Procida */
- PM800_CHIP_A0 = 0x60,
- PM800_CHIP_A1 = 0x61,
- PM800_CHIP_B0 = 0x62,
- PM800_CHIP_C0 = 0x63,
- PM800_CHIP_END = PM800_CHIP_C0,
-
- /* Make sure to update this to the last stepping */
- PM8XXX_CHIP_END = PM800_CHIP_END
-};
+/* PM800: generation identification number */
+#define PM800_CHIP_GEN_ID_NUM 0x3

static const struct i2c_device_id pm80x_id_table[] = {
- {"88PM800", CHIP_PM800},
+ {"88PM800", 0},
{} /* NULL terminated */
};
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
@@ -433,28 +422,9 @@ static void pm800_pages_exit(struct pm80x_chip *chip)
static int device_800_init(struct pm80x_chip *chip,
struct pm80x_platform_data *pdata)
{
- int ret, pmic_id;
+ int ret;
unsigned int val;

- ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
- goto out;
- }
-
- pmic_id = val & PM80X_VERSION_MASK;
-
- if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) {
- chip->version = val;
- dev_info(chip->dev,
- "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val);
- } else {
- dev_err(chip->dev,
- "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
- ret = -EINVAL;
- goto out;
- }
-
/*
* alarm wake up bit will be clear in device_irq_init(),
* read before that
@@ -522,7 +492,7 @@ static int pm800_probe(struct i2c_client *client,
struct pm80x_platform_data *pdata = client->dev.platform_data;
struct pm80x_subchip *subchip;

- ret = pm80x_init(client, id);
+ ret = pm80x_init(client);
if (ret) {
dev_err(&client->dev, "pm800_init fail\n");
goto out_init;
@@ -552,7 +522,7 @@ static int pm800_probe(struct i2c_client *client,

ret = device_800_init(chip, pdata);
if (ret) {
- dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
+ dev_err(chip->dev, "Failed to initialize 88pm800 devices\n");
goto err_device_init;
}

diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 0e82c2a..5216022 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -29,10 +29,8 @@
#include <linux/slab.h>
#include <linux/delay.h>

-#define PM805_CHIP_ID (0x00)
-
static const struct i2c_device_id pm80x_id_table[] = {
- {"88PM805", CHIP_PM805},
+ {"88PM805", 0},
{} /* NULL terminated */
};
MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
@@ -192,7 +190,6 @@ static struct regmap_irq_chip pm805_irq_chip = {
static int device_805_init(struct pm80x_chip *chip)
{
int ret = 0;
- unsigned int val;
struct regmap *map = chip->regmap;

if (!map) {
@@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip)
return -EINVAL;
}

- ret = regmap_read(map, PM805_CHIP_ID, &val);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
- goto out_irq_init;
- }
- chip->version = val;
-
chip->regmap_irq_chip = &pm805_irq_chip;

ret = device_irq_init_805(chip);
@@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client,
struct pm80x_chip *chip;
struct pm80x_platform_data *pdata = client->dev.platform_data;

- ret = pm80x_init(client, id);
+ ret = pm80x_init(client);
if (ret) {
dev_err(&client->dev, "pm805_init fail!\n");
goto out_init;
@@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client,

ret = device_805_init(chip);
if (ret) {
- dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
+ dev_err(chip->dev, "Failed to initialize 88pm805 devices\n");
goto err_805_init;
}

diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index f736a46..5e72f65 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -18,6 +18,23 @@
#include <linux/uaccess.h>
#include <linux/err.h>

+/* 88pm80x chips have same definition for chip id register. */
+#define PM80X_CHIP_ID (0x00)
+#define PM80X_CHIP_ID_NUM(x) (((x) >> 5) & 0x7)
+#define PM80X_CHIP_ID_REVISION(x) ((x) & 0x1F)
+
+struct pm80x_chip_mapping {
+ unsigned int id;
+ int type;
+};
+
+static struct pm80x_chip_mapping chip_mapping[] = {
+ /* 88PM800 chip id number */
+ {0x3, CHIP_PM800},
+ /* 88PM805 chip id number */
+ {0x0, CHIP_PM805},
+};
+
/*
* workaround: some registers needed by pm805 are defined in pm800, so
* need to use this global variable to maintain the relation between
@@ -31,12 +48,13 @@ const struct regmap_config pm80x_regmap_config = {
};
EXPORT_SYMBOL_GPL(pm80x_regmap_config);

-int pm80x_init(struct i2c_client *client,
- const struct i2c_device_id *id)
+
+int pm80x_init(struct i2c_client *client)
{
struct pm80x_chip *chip;
struct regmap *map;
- int ret = 0;
+ unsigned int val;
+ int i, ret = 0;

chip =
devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
@@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client,
return ret;
}

- chip->id = id->driver_data;
- if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805)
- return -EINVAL;
-
chip->client = client;
chip->regmap = map;

@@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client,
dev_set_drvdata(chip->dev, chip);
i2c_set_clientdata(chip->client, chip);

+ ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(chip_mapping); i++) {
+ if (chip_mapping[i].id == PM80X_CHIP_ID_NUM(val)) {
+ chip->type = chip_mapping[i].type;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(chip_mapping)) {
+ dev_err(chip->dev,
+ "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
+ return -EINVAL;
+ }
+
device_init_wakeup(&client->dev, 1);

/*
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index 023e639..4a66a56 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -17,7 +17,6 @@
#include <linux/regmap.h>
#include <linux/atomic.h>

-#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */
enum {
CHIP_INVALID = 0,
CHIP_PM800,
@@ -299,8 +298,7 @@ struct pm80x_chip {
struct regmap *regmap;
struct regmap_irq_chip *regmap_irq_chip;
struct regmap_irq_chip_data *irq_data;
- unsigned char version;
- int id;
+ int type;
int irq;
int irq_mode;
unsigned long wu_flag;
@@ -361,7 +359,6 @@ static inline int pm80x_dev_resume(struct device *dev)
}
#endif

-extern int pm80x_init(struct i2c_client *client,
- const struct i2c_device_id *id);
+extern int pm80x_init(struct i2c_client *client);
extern int pm80x_deinit(void);
#endif /* __LINUX_MFD_88PM80X_H */
--
1.7.4.1

2013-06-14 05:24:08

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 1/9] mfd: 88pm800: fix NULL pointer error

From: Yi Zhang <[email protected]>

move "device_800_init" to fix NULL pointer error when
calling "device_gpadc_init"

for "device_gpadc_init" needs "subchip->regmap_gpadc"
to set registers via regmap interface

Signed-off-by: Yi Zhang <[email protected]>
Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 18 ++++++++++--------
1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 582bda5..b2f9f0f 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -528,24 +528,26 @@ static int pm800_probe(struct i2c_client *client,
subchip->gpadc_page_addr = pdata->gpadc_page_addr;
chip->subchip = subchip;

- ret = device_800_init(chip, pdata);
- if (ret) {
- dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
- goto err_subchip_alloc;
- }
-
ret = pm800_pages_init(chip);
if (ret) {
dev_err(&client->dev, "pm800_pages_init failed!\n");
goto err_page_init;
}

+ ret = device_800_init(chip, pdata);
+ if (ret) {
+ dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
+ goto err_device_init;
+ }
+
if (pdata->plat_config)
pdata->plat_config(chip, pdata);

+ return 0;
+
+err_device_init:
+ pm800_pages_exit(chip);
err_page_init:
- mfd_remove_devices(chip->dev);
- device_irq_exit_800(chip);
err_subchip_alloc:
pm80x_deinit();
out_init:
--
1.7.4.1

2013-06-14 05:23:53

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 6/9] mfd: 88pm800: fixes error handling for sub pages probe/remove

pm800_pages_init and pm800_pages_exit are called by pm800_probe.
Change the code to enhance error handling and remove unused code at
pm800_pages_init/exit and pm800_probe.

Signed-off-by: Yi Zhang <[email protected]>
Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 80 ++++++++++++++++++++++++++++--------------------
1 files changed, 47 insertions(+), 33 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 6b607ad..932ebe8 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -370,50 +370,64 @@ static int pm800_pages_init(struct pm80x_chip *chip)
struct pm80x_subchip *subchip;
struct i2c_client *client = chip->client;

+ int ret = 0;
+
subchip = chip->subchip;
- /* PM800 block power: i2c addr 0x31 */
- if (subchip->power_page_addr) {
- subchip->power_page =
- i2c_new_dummy(client->adapter, subchip->power_page_addr);
- subchip->regmap_power =
- devm_regmap_init_i2c(subchip->power_page,
- &pm80x_regmap_config);
- i2c_set_clientdata(subchip->power_page, chip);
- } else
- dev_info(chip->dev,
- "PM800 block power 0x31: No power_page_addr\n");
-
- /* PM800 block GPADC: i2c addr 0x32 */
- if (subchip->gpadc_page_addr) {
- subchip->gpadc_page = i2c_new_dummy(client->adapter,
- subchip->gpadc_page_addr);
- subchip->regmap_gpadc =
- devm_regmap_init_i2c(subchip->gpadc_page,
- &pm80x_regmap_config);
- i2c_set_clientdata(subchip->gpadc_page, chip);
- } else
- dev_info(chip->dev,
- "PM800 block GPADC 0x32: No gpadc_page_addr\n");
+ if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr)
+ return -ENODEV;
+
+ /* PM800 block power page */
+ subchip->power_page = i2c_new_dummy(client->adapter,
+ subchip->power_page_addr);
+ if (subchip->power_page == NULL) {
+ ret = -ENODEV;
+ goto out;
+ }

- return 0;
+ subchip->regmap_power = devm_regmap_init_i2c(subchip->power_page,
+ &pm80x_regmap_config);
+ if (IS_ERR(subchip->regmap_power)) {
+ ret = PTR_ERR(subchip->regmap_power);
+ dev_err(chip->dev,
+ "Failed to allocate regmap_power: %d\n", ret);
+ goto out;
+ }
+
+ i2c_set_clientdata(subchip->power_page, chip);
+
+ /* PM800 block GPADC */
+ subchip->gpadc_page = i2c_new_dummy(client->adapter,
+ subchip->gpadc_page_addr);
+ if (subchip->gpadc_page == NULL) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ subchip->regmap_gpadc = devm_regmap_init_i2c(subchip->gpadc_page,
+ &pm80x_regmap_config);
+ if (IS_ERR(subchip->regmap_gpadc)) {
+ ret = PTR_ERR(subchip->regmap_gpadc);
+ dev_err(chip->dev,
+ "Failed to allocate regmap_gpadc: %d\n", ret);
+ goto out;
+ }
+ i2c_set_clientdata(subchip->gpadc_page, chip);
+
+out:
+ return ret;
}

static void pm800_pages_exit(struct pm80x_chip *chip)
{
struct pm80x_subchip *subchip;

- regmap_exit(chip->regmap);
- i2c_unregister_device(chip->client);
-
subchip = chip->subchip;
- if (subchip->power_page) {
- regmap_exit(subchip->regmap_power);
+
+ if (subchip && subchip->power_page)
i2c_unregister_device(subchip->power_page);
- }
- if (subchip->gpadc_page) {
- regmap_exit(subchip->regmap_gpadc);
+
+ if (subchip && subchip->gpadc_page)
i2c_unregister_device(subchip->gpadc_page);
- }
}

static int device_800_init(struct pm80x_chip *chip,
--
1.7.4.1

2013-06-14 05:25:00

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 8/9] mfd: 88pm800: enhance sub devices initialization

Separate the devices initialization into different functions.
It makes the probe function clearly.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 61 +++++++++++++++++++++++++++++++++---------------
1 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 16faad6..35c7fe8 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -304,6 +304,40 @@ out:
return ret;
}

+static int device_onkey_init(struct pm80x_chip *chip,
+ struct pm80x_platform_data *pdata)
+{
+ int ret;
+
+ ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+ ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
+ NULL);
+ if (ret) {
+ dev_err(chip->dev, "Failed to add onkey subdev\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int device_rtc_init(struct pm80x_chip *chip,
+ struct pm80x_platform_data *pdata)
+{
+ int ret;
+
+ rtc_devs[0].platform_data = pdata->rtc;
+ rtc_devs[0].pdata_size =
+ pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+ ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+ ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
+ if (ret) {
+ dev_err(chip->dev, "Failed to add rtc subdev\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int device_irq_init_800(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
@@ -453,27 +487,16 @@ static int device_800_init(struct pm80x_chip *chip,
goto out;
}

- ret =
- mfd_add_devices(chip->dev, 0, &onkey_devs[0],
- ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
- NULL);
- if (ret < 0) {
+ ret = device_onkey_init(chip, pdata);
+ if (ret) {
dev_err(chip->dev, "Failed to add onkey subdev\n");
goto out_dev;
- } else
- dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__);
-
- if (pdata && pdata->rtc) {
- rtc_devs[0].platform_data = pdata->rtc;
- rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
- ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
- ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to add rtc subdev\n");
- goto out_dev;
- } else
- dev_info(chip->dev,
- "[%s]:Added mfd rtc_devs\n", __func__);
+ }
+
+ ret = device_rtc_init(chip, pdata);
+ if (ret) {
+ dev_err(chip->dev, "Failed to add rtc subdev\n");
+ goto out;
}

return 0;
--
1.7.4.1

2013-06-14 05:24:58

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 2/9] mfd: 88pm80x: fix driver name for 88pm800 and 88pm805

88pm800 has same driver name as 88pm805. Fix it.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 2 +-
drivers/mfd/88pm805.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index b2f9f0f..0801049 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -569,7 +569,7 @@ static int pm800_remove(struct i2c_client *client)

static struct i2c_driver pm800_driver = {
.driver = {
- .name = "88PM80X",
+ .name = "88PM800",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
},
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 65d7ac09..d32b544 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -276,7 +276,7 @@ static int pm805_remove(struct i2c_client *client)

static struct i2c_driver pm805_driver = {
.driver = {
- .name = "88PM80X",
+ .name = "88PM805",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
},
--
1.7.4.1

2013-06-14 05:23:37

by Chao Xie

[permalink] [raw]
Subject: [PATCH V2 9/9] mfd: 88pm800: add regulator sub device

Signed-off-by: Chao Xie <[email protected]>
---
drivers/mfd/88pm800.c | 28 ++++++++++++++++++++++++++++
include/linux/mfd/88pm80x.h | 8 ++++++++
2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 35c7fe8..ec9d815 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -156,6 +156,13 @@ static struct mfd_cell onkey_devs[] = {
},
};

+static struct mfd_cell regulator_devs[] = {
+ {
+ .name = "88pm80x-regulator",
+ .id = -1,
+ },
+};
+
static const struct regmap_irq pm800_irqs[] = {
/* INT0 */
[PM800_IRQ_ONKEY] = {
@@ -338,6 +345,21 @@ static int device_rtc_init(struct pm80x_chip *chip,
return 0;
}

+static int device_regulator_init(struct pm80x_chip *chip,
+ struct pm80x_platform_data *pdata)
+{
+ int ret;
+
+ ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+ ARRAY_SIZE(regulator_devs), NULL, 0, NULL);
+ if (ret) {
+ dev_err(chip->dev, "Failed to add regulator subdev\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int device_irq_init_800(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
@@ -499,6 +521,12 @@ static int device_800_init(struct pm80x_chip *chip,
goto out;
}

+ ret = device_regulator_init(chip, pdata);
+ if (ret) {
+ dev_err(chip->dev, "Failed to add regulators subdev\n");
+ goto out;
+ }
+
return 0;
out_dev:
mfd_remove_devices(chip->dev);
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index 4a66a56..97cb283 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -307,6 +307,14 @@ struct pm80x_chip {

struct pm80x_platform_data {
struct pm80x_rtc_pdata *rtc;
+ /*
+ * For the regulator not defined, set regulators[not_defined] to be
+ * NULL. num_regulators are the number of regulators supposed to be
+ * initialized. If all regulators are not defined, set num_regulators
+ * to be 0.
+ */
+ struct regulator_init_data *regulators[PM800_ID_RG_MAX];
+ unsigned int num_regulators;
int irq_mode; /* Clear interrupt by read/write(0/1) */
int batt_det; /* enable/disable */
int (*plat_config)(struct pm80x_chip *chip,
--
1.7.4.1

2013-06-17 23:08:01

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH V2 0/9] mfd: 88pm80x: bug fixes and enhancement

Hi Chao,

On Fri, Jun 14, 2013 at 01:21:44AM -0400, Chao Xie wrote:
> The patch set fixes some bugs in the 88pm800/88pm805 driver, and it add
> regulator device into 88pm800.
>
> The patches are tested based on Marvell pxa988 platform.
>
> V2->V1:
> add more fixes patches.
> Below patches are same almost same as V1
> mfd: 88pm800: fix NULL pointer errorm
> mfd: 88pm800/88pm805: remove "IRQF_TRIGGER_FALLING" flag
> Other patches are new.
>
> Chao Xie (7):
> mfd: 88pm80x: fix driver name for 88pm800 and 88pm805
> mfd: 88pm800: fix for mask_invert
> mfd: 88pm800: remove the power and gpadc page addr from platform data
> mfd: 88pm800: fixes error handling for sub pages probe/remove
> mfd: 88pm80x: Changes chip id definition and detection
> mfd: 88pm800: enhance sub devices initialization
> mfd: 88pm800: add regulator sub device
>
> Yi Zhang (2):
> mfd: 88pm800: fix NULL pointer error
> mfd: 88pm800/88pm805: remove "IRQF_TRIGGER_FALLING" flag
>
> drivers/mfd/88pm800.c | 237 +++++++++++++++++++++++++------------------
> drivers/mfd/88pm805.c | 20 +---
> drivers/mfd/88pm80x.c | 47 +++++++--
> include/linux/mfd/88pm80x.h | 17 ++--
> 4 files changed, 193 insertions(+), 128 deletions(-)
All 9 patches applied, thanks.

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/