2011-02-18 03:07:55

by Andres Salomon

[permalink] [raw]
Subject: MFD sharing support (v3, full)

Here's all of my third attempt at MFD cell sharing. This includes all
parts; some of the patches from v2 are being resent without changes. I
apologize for the noise, but since I screwed up the threading in the first
batch and people were having trouble finding some of the patches, I figured
I'd resend everything together. There are some changes in there as well;
they've been marked in commit messages.

This whole set does the following things:
- make mfd_cell structs always accessible to platform devices
- adjust the mfd_cell API to (hopefully) be cleaner, replacing platform_data
and driver_data with mfd_data
- add wrapper functions to access mfd cell and data fields
- adjust all mfd clients/drivers to use the new API
- add a reference counting wrapper for mfd_cell's enable/disable hooks
- add platform device sharing wrappers to allow mfd clients to create
new platform devices (at the same time as platform drivers are being
registered)
- update the cs5535-mfd driver (and clients) to make use of the new
sharing code

This effectively provides the ability for mfd clients to share a single
mfd_cell, and provide the framework for mfd-core be handle shared hardware
resources.


2011-02-18 03:08:01

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 04/29] ab3550: mfd_cell is now implicitly available to drivers

No clients (in mainline kernel, I'm told that drivers exist in external
trees that are planned for mainline inclusion) make use of this, nor
do they make use of platform_data, so nothing really had to change here.

The .data_size field is unused, so its usage gets removed.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/ab3550-core.c | 4 +---
include/linux/mfd/abx500.h | 1 -
2 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
index 5fbca34..d849087 100644
--- a/drivers/mfd/ab3550-core.c
+++ b/drivers/mfd/ab3550-core.c
@@ -1320,10 +1320,8 @@ static int __init ab3550_probe(struct i2c_client *client,
goto exit_no_ops;

/* Set up and register the platform devices. */
- for (i = 0; i < AB3550_NUM_DEVICES; i++) {
+ for (i = 0; i < AB3550_NUM_DEVICES; i++)
ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
- ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i];
- }

err = mfd_add_devices(&client->dev, 0, ab3550_devs,
ARRAY_SIZE(ab3550_devs), NULL,
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 67bd6f7..7d9b6ae 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -186,7 +186,6 @@ struct abx500_init_settings {
struct ab3550_platform_data {
struct {unsigned int base; unsigned int count; } irq;
void *dev_data[AB3550_NUM_DEVICES];
- size_t dev_data_sz[AB3550_NUM_DEVICES];
struct abx500_init_settings *init_settings;
unsigned int init_settings_sz;
};
--
1.7.2.3

2011-02-18 03:08:31

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 29/29] cs5535-mfd: add sharing for acpi/pms cells

This enables sharing of cs5535-mfd cells via the new mfd_shared_* API.
Hooks for enable/disble of resources are added, with refcounting of
resources being automatically handled so that cs5535_mfd_res_enable/disable
are only called when necessary.

Clients of cs5535-mfd (in this case, olpc-xo1.c) are also modified to
use the mfd_shared API. The platform drivers are also renamed to
olpc-xo1-{pms,acpi}, and resource enabling/disabling is replaced
with mfd_shared API calls.

Signed-off-by: Andres Salomon <[email protected]>
---
arch/x86/platform/olpc/olpc-xo1.c | 42 +++++++++++++++++-------------------
drivers/mfd/cs5535-mfd.c | 37 ++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c
index 1277756..f415535 100644
--- a/arch/x86/platform/olpc/olpc-xo1.c
+++ b/arch/x86/platform/olpc/olpc-xo1.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/mfd/core.h>

#include <asm/io.h>
#include <asm/olpc.h>
@@ -56,25 +57,24 @@ static void xo1_power_off(void)
static int __devinit olpc_xo1_probe(struct platform_device *pdev)
{
struct resource *res;
+ int err;

/* don't run on non-XOs */
if (!machine_is_olpc())
return -ENODEV;

+ err = mfd_shared_cell_enable(pdev);
+ if (err)
+ return err;
+
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
return -EIO;
}
-
- if (!request_region(res->start, resource_size(res), DRV_NAME)) {
- dev_err(&pdev->dev, "can't request region\n");
- return -EIO;
- }
-
- if (strcmp(pdev->name, "cs5535-pms") == 0)
+ if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
pms_base = res->start;
- else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+ else if (strcmp(pdev->name, "olpc-xo1-ac-acpi") == 0)
acpi_base = res->start;

/* If we have both addresses, we can override the poweroff hook */
@@ -88,14 +88,11 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev)

static int __devexit olpc_xo1_remove(struct platform_device *pdev)
{
- struct resource *r;
-
- r = platform_get_resource(pdev, IORESOURCE_IO, 0);
- release_region(r->start, resource_size(r));
+ mfd_shared_cell_disable(pdev);

- if (strcmp(pdev->name, "cs5535-pms") == 0)
+ if (strcmp(pdev->name, "olpc-xo1-pms") == 0)
pms_base = 0;
- else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+ else if (strcmp(pdev->name, "olpc-xo1-acpi") == 0)
acpi_base = 0;

pm_power_off = NULL;
@@ -104,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)

static struct platform_driver cs5535_pms_drv = {
.driver = {
- .name = "cs5535-pms",
+ .name = "olpc-xo1-pms",
.owner = THIS_MODULE,
},
.probe = olpc_xo1_probe,
@@ -113,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = {

static struct platform_driver cs5535_acpi_drv = {
.driver = {
- .name = "cs5535-acpi",
+ .name = "olpc-xo1-acpi",
.owner = THIS_MODULE,
},
.probe = olpc_xo1_probe,
@@ -124,26 +121,27 @@ static int __init olpc_xo1_init(void)
{
int r;

- r = platform_driver_register(&cs5535_pms_drv);
+ r = mfd_shared_platform_driver_register(&cs5535_pms_drv, "cs5535-pms");
if (r)
return r;

- r = platform_driver_register(&cs5535_acpi_drv);
+ r = mfd_shared_platform_driver_register(&cs5535_acpi_drv,
+ "cs5535-acpi");
if (r)
- platform_driver_unregister(&cs5535_pms_drv);
+ mfd_shared_platform_driver_unregister(&cs5535_pms_drv);

return r;
}

static void __exit olpc_xo1_exit(void)
{
- platform_driver_unregister(&cs5535_acpi_drv);
- platform_driver_unregister(&cs5535_pms_drv);
+ mfd_shared_platform_driver_unregister(&cs5535_acpi_drv);
+ mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
}

MODULE_AUTHOR("Daniel Drake <[email protected]>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:olpc-xo1");
+MODULE_ALIAS("platform:cs5535-pms");

module_init(olpc_xo1_init);
module_exit(olpc_xo1_exit);
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 59ca6f1..886a068 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -39,6 +39,37 @@ enum cs5535_mfd_bars {
NR_BARS,
};

+static int cs5535_mfd_res_enable(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return -EIO;
+ }
+
+ if (!request_region(res->start, resource_size(res), DRV_NAME)) {
+ dev_err(&pdev->dev, "can't request region\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int cs5535_mfd_res_disable(struct platform_device *pdev)
+{
+ struct resource *res;
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return -EIO;
+ }
+
+ release_region(res->start, resource_size(res));
+ return 0;
+}
+
static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];

static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
@@ -65,12 +96,18 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
.name = "cs5535-pms",
.num_resources = 1,
.resources = &cs5535_mfd_resources[PMS_BAR],
+
+ .enable = cs5535_mfd_res_enable,
+ .disable = cs5535_mfd_res_disable,
},
{
.id = ACPI_BAR,
.name = "cs5535-acpi",
.num_resources = 1,
.resources = &cs5535_mfd_resources[ACPI_BAR],
+
+ .enable = cs5535_mfd_res_enable,
+ .disable = cs5535_mfd_res_disable,
},
};

--
1.7.2.3

2011-02-18 03:08:27

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 24/29] tmio-fb: use mfd_data instead of driver_data

Use mfd_data for passing information from mfd drivers to mfd
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data(). This changes tmio-fb only; mfd drivers with
other cells are not modified.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/tc6393xb.c | 2 +-
drivers/video/tmiofb.c | 15 +++++++--------
2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index ecb045b..3d62ded 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -694,7 +694,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
}

tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
- tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
+ tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data;

ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index 6302882..7e57d3b 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -250,8 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
*/
static int tmiofb_hw_stop(struct platform_device *dev)
{
- struct mfd_cell *cell = mfd_get_cell(dev);
- struct tmio_fb_data *data = cell->driver_data;
+ struct tmio_fb_data *data = mfd_get_data(dev);
struct fb_info *info = platform_get_drvdata(dev);
struct tmiofb_par *par = info->par;

@@ -313,7 +312,7 @@ static int tmiofb_hw_init(struct platform_device *dev)
static void tmiofb_hw_mode(struct platform_device *dev)
{
struct mfd_cell *cell = mfd_get_cell(dev);
- struct tmio_fb_data *data = cell->driver_data;
+ struct tmio_fb_data *data = mfd_get_data(dev);
struct fb_info *info = platform_get_drvdata(dev);
struct fb_videomode *mode = info->mode;
struct tmiofb_par *par = info->par;
@@ -559,8 +558,8 @@ static int tmiofb_ioctl(struct fb_info *fbi,
static struct fb_videomode *
tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
{
- struct mfd_cell *cell = mfd_get_cell(to_platform_device(info->device));
- struct tmio_fb_data *data = cell->driver_data;
+ struct tmio_fb_data *data =
+ mfd_get_data(to_platform_device(info->device));
struct fb_videomode *best = NULL;
int i;

@@ -580,8 +579,8 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{

struct fb_videomode *mode;
- struct mfd_cell *cell = mfd_get_cell(to_platform_device(info->device));
- struct tmio_fb_data *data = cell->driver_data;
+ struct tmio_fb_data *data =
+ mfd_get_data(to_platform_device(info->device));

mode = tmiofb_find_mode(info, var);
if (!mode || var->bits_per_pixel > 16)
@@ -682,7 +681,7 @@ static struct fb_ops tmiofb_ops = {
static int __devinit tmiofb_probe(struct platform_device *dev)
{
struct mfd_cell *cell = mfd_get_cell(dev);
- struct tmio_fb_data *data = cell->driver_data;
+ struct tmio_fb_data *data = mfd_get_data(dev);
struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
--
1.7.2.3

2011-02-18 03:08:29

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 25/29] rdc321x-southbridge: use mfd_data instead of driver_data (v2)

Use mfd_data for passing information from mfd drivers to soc
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data().

v2: add some missing mfd/core.h includes

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/gpio/rdc321x-gpio.c | 3 ++-
drivers/mfd/rdc321x-southbridge.c | 4 ++--
drivers/watchdog/rdc321x_wdt.c | 3 ++-
3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c
index 897e057..a9bda88 100644
--- a/drivers/gpio/rdc321x-gpio.c
+++ b/drivers/gpio/rdc321x-gpio.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/mfd/rdc321x.h>
+#include <linux/mfd/core.h>
#include <linux/slab.h>

struct rdc321x_gpio {
@@ -135,7 +136,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
struct rdc321x_gpio *rdc321x_gpio_dev;
struct rdc321x_gpio_pdata *pdata;

- pdata = platform_get_drvdata(pdev);
+ pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index 5092297..193c940 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -61,12 +61,12 @@ static struct mfd_cell rdc321x_sb_cells[] = {
.name = "rdc321x-wdt",
.resources = rdc321x_wdt_resource,
.num_resources = ARRAY_SIZE(rdc321x_wdt_resource),
- .driver_data = &rdc321x_wdt_pdata,
+ .mfd_data = &rdc321x_wdt_pdata,
}, {
.name = "rdc321x-gpio",
.resources = rdc321x_gpio_resources,
.num_resources = ARRAY_SIZE(rdc321x_gpio_resources),
- .driver_data = &rdc321x_gpio_pdata,
+ .mfd_data = &rdc321x_gpio_pdata,
},
};

diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 3939e53..d8e7250 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -37,6 +37,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/mfd/rdc321x.h>
+#include <linux/mfd/core.h>

#define RDC_WDT_MASK 0x80000000 /* Mask */
#define RDC_WDT_EN 0x00800000 /* Enable bit */
@@ -231,7 +232,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
struct resource *r;
struct rdc321x_wdt_pdata *pdata;

- pdata = platform_get_drvdata(pdev);
+ pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data supplied\n");
return -ENODEV;
--
1.7.2.3

2011-02-18 03:08:23

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 18/29] mfd-core: rename platform_data field of mfd_cell to mfd_data

Rename the platform_data variable to imply a distinction between
common platform_data driver usage (typically accessed via
pdev->dev.platform_data) and the way MFD passes data down to
clients (using a wrapper named mfd_get_data).

All clients have already been changed to use the wrapper function,
so this can be a quick single-commit change that only touches things
in drivers/mfd.

Signed-off-by: Andres Salomon <[email protected]>
Acked-by: Linus Walleij <[email protected]>
---
drivers/mfd/ab3100-core.c | 2 +-
drivers/mfd/ab3550-core.c | 2 +-
drivers/mfd/janz-cmodio.c | 2 +-
drivers/mfd/mc13xxx-core.c | 2 +-
drivers/mfd/timberdale.c | 54 +++++++++++++++++++++---------------------
drivers/mfd/twl4030-codec.c | 4 +-
drivers/mfd/wl1273-core.c | 4 +-
include/linux/mfd/core.h | 8 +++---
8 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index b44c3d9..865251e 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -950,7 +950,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,

/* Set up and register the platform devices. */
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++)
- ab3100_devs[i].platform_data = ab3100_plf_data;
+ ab3100_devs[i].mfd_data = ab3100_plf_data;

err = mfd_add_devices(&client->dev, 0, ab3100_devs,
ARRAY_SIZE(ab3100_devs), NULL, 0);
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
index d849087..f4c12a4 100644
--- a/drivers/mfd/ab3550-core.c
+++ b/drivers/mfd/ab3550-core.c
@@ -1321,7 +1321,7 @@ static int __init ab3550_probe(struct i2c_client *client,

/* Set up and register the platform devices. */
for (i = 0; i < AB3550_NUM_DEVICES; i++)
- ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
+ ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i];

err = mfd_add_devices(&client->dev, 0, ab3550_devs,
ARRAY_SIZE(ab3550_devs), NULL,
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 58de1e2..fc41911 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -86,7 +86,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,

/* Add platform data */
pdata->modno = modno;
- cell->platform_data = pdata;
+ cell->mfd_data = pdata;

/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
res->flags = IORESOURCE_MEM;
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 00c5490..b19b50a 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -689,7 +689,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
const char *name = mc13xxx_get_chipname(mc13xxx);

struct mfd_cell cell = {
- .platform_data = pdata,
+ .mfd_data = pdata,
};

/* there is no asnprintf in the kernel :-( */
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 6353921..94c6c8a 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -384,7 +384,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
- .platform_data = &timb_dma_platform_data,
+ .mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
@@ -395,37 +395,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
- .platform_data = &timberdale_xiic_platform_data,
+ .mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
- .platform_data = &timberdale_gpio_platform_data,
+ .mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
- .platform_data = &timberdale_video_platform_data,
+ .mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
- .platform_data = &timberdale_radio_platform_data,
+ .mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
- .platform_data = &timberdale_xspi_platform_data,
+ .mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
- .platform_data = &timberdale_ks8842_platform_data,
+ .mfd_data = &timberdale_ks8842_platform_data,
},
};

@@ -434,7 +434,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
- .platform_data = &timb_dma_platform_data,
+ .mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
@@ -450,13 +450,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
- .platform_data = &timberdale_xiic_platform_data,
+ .mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
- .platform_data = &timberdale_gpio_platform_data,
+ .mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-mlogicore",
@@ -467,25 +467,25 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
- .platform_data = &timberdale_video_platform_data,
+ .mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
- .platform_data = &timberdale_radio_platform_data,
+ .mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
- .platform_data = &timberdale_xspi_platform_data,
+ .mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
- .platform_data = &timberdale_ks8842_platform_data,
+ .mfd_data = &timberdale_ks8842_platform_data,
},
};

@@ -494,7 +494,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
- .platform_data = &timb_dma_platform_data,
+ .mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
@@ -505,31 +505,31 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.name = "xiic-i2c",
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
- .platform_data = &timberdale_xiic_platform_data,
+ .mfd_data = &timberdale_xiic_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
- .platform_data = &timberdale_gpio_platform_data,
+ .mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
- .platform_data = &timberdale_video_platform_data,
+ .mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
- .platform_data = &timberdale_radio_platform_data,
+ .mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
- .platform_data = &timberdale_xspi_platform_data,
+ .mfd_data = &timberdale_xspi_platform_data,
},
};

@@ -538,7 +538,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
- .platform_data = &timb_dma_platform_data,
+ .mfd_data = &timb_dma_platform_data,
},
{
.name = "timb-uart",
@@ -549,37 +549,37 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.name = "ocores-i2c",
.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
.resources = timberdale_ocores_resources,
- .platform_data = &timberdale_ocores_platform_data,
+ .mfd_data = &timberdale_ocores_platform_data,
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
- .platform_data = &timberdale_gpio_platform_data,
+ .mfd_data = &timberdale_gpio_platform_data,
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
- .platform_data = &timberdale_video_platform_data,
+ .mfd_data = &timberdale_video_platform_data,
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
- .platform_data = &timberdale_radio_platform_data,
+ .mfd_data = &timberdale_radio_platform_data,
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
- .platform_data = &timberdale_xspi_platform_data,
+ .mfd_data = &timberdale_xspi_platform_data,
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
- .platform_data = &timberdale_ks8842_platform_data,
+ .mfd_data = &timberdale_ks8842_platform_data,
},
};

diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
index 0f57426..c02fded 100644
--- a/drivers/mfd/twl4030-codec.c
+++ b/drivers/mfd/twl4030-codec.c
@@ -208,13 +208,13 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
if (pdata->audio) {
cell = &codec->cells[childs];
cell->name = "twl4030-codec";
- cell->platform_data = pdata->audio;
+ cell->mfd_data = pdata->audio;
childs++;
}
if (pdata->vibra) {
cell = &codec->cells[childs];
cell->name = "twl4030-vibra";
- cell->platform_data = pdata->vibra;
+ cell->mfd_data = pdata->vibra;
childs++;
}

diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index 703085e..f49e04e 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -79,7 +79,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,

cell = &core->cells[children];
cell->name = "wl1273_fm_radio";
- cell->platform_data = &core;
+ cell->mfd_data = &core;
children++;

if (pdata->children & WL1273_CODEC_CHILD) {
@@ -87,7 +87,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,

dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
cell->name = "wl1273-codec";
- cell->platform_data = &core;
+ cell->mfd_data = &core;
children++;
}

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 923ec25..f317fe4 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -33,8 +33,8 @@ struct mfd_cell {
/* driver-specific data for MFD-aware "cell" drivers */
void *driver_data;

- /* platform_data can be used to pass data to "generic" drivers */
- void *platform_data;
+ /* mfd_data can be used to pass data to client drivers */
+ void *mfd_data;

/*
* These resources can be specified relative to the parent device.
@@ -64,11 +64,11 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)

/*
* Given a platform device that's been created by mfd_add_devices(), fetch
- * the .platform_data entry from the mfd_cell that created it.
+ * the .mfd_data entry from the mfd_cell that created it.
*/
static inline void *mfd_get_data(struct platform_device *pdev)
{
- return mfd_get_cell(pdev)->platform_data;
+ return mfd_get_cell(pdev)->mfd_data;
}

extern int mfd_add_devices(struct device *parent, int id,
--
1.7.2.3

2011-02-18 03:08:24

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 17/29] mfd-core: drop data_size from mfd_cell struct

Now that there are no more users of this, drop it.

Signed-off-by: Andres Salomon <[email protected]>
---
include/linux/mfd/core.h | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index aefc378..923ec25 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -36,9 +36,6 @@ struct mfd_cell {
/* platform_data can be used to pass data to "generic" drivers */
void *platform_data;

- /* unused */
- size_t data_size;
-
/*
* These resources can be specified relative to the parent device.
* For accessing hardware you should use resources from the platform dev
--
1.7.2.3

2011-02-18 03:09:33

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 26/29] mfd-core: remove driver_data field from mfd_cell

All users of this have now been switched over to using mfd_data;
it can go away now.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/mfd-core.c | 1 -
include/linux/mfd/core.h | 3 ---
2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 21a39dc..01115f6 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -37,7 +37,6 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_device;

pdev->dev.parent = parent;
- platform_set_drvdata(pdev, cell->driver_data);

ret = platform_device_add_data(pdev, cell, sizeof(*cell));
if (ret)
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index f317fe4..71cd1f9 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -30,9 +30,6 @@ struct mfd_cell {
int (*suspend)(struct platform_device *dev);
int (*resume)(struct platform_device *dev);

- /* driver-specific data for MFD-aware "cell" drivers */
- void *driver_data;
-
/* mfd_data can be used to pass data to client drivers */
void *mfd_data;

--
1.7.2.3

2011-02-18 03:08:21

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 19/29] davinci_voicecodec: use mfd_data instead of driver_data

Use mfd_data for passing information from mfd drivers to soc
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data().

Signed-off-by: Andres Salomon <[email protected]>
Acked-by: Mark Brown <[email protected]>
---
drivers/mfd/davinci_voicecodec.c | 4 ++--
sound/soc/codecs/cq93vc.c | 3 ++-
sound/soc/davinci/davinci-vcif.c | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
index 33c923d..f946c0b 100644
--- a/drivers/mfd/davinci_voicecodec.c
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -119,12 +119,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
/* Voice codec interface client */
cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
cell->name = "davinci_vcif";
- cell->driver_data = davinci_vc;
+ cell->mfd_data = davinci_vc;

/* Voice codec CQ93VC client */
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
cell->name = "cq93vc";
- cell->driver_data = davinci_vc;
+ cell->mfd_data = davinci_vc;

ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
DAVINCI_VC_CELLS, NULL, 0);
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 46dbfd0..b8066ef 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -153,7 +153,8 @@ static int cq93vc_resume(struct snd_soc_codec *codec)

static int cq93vc_probe(struct snd_soc_codec *codec)
{
- struct davinci_vc *davinci_vc = codec->dev->platform_data;
+ struct davinci_vc *davinci_vc =
+ mfd_get_data(to_platform_device(codec->dev));

davinci_vc->cq93vc.codec = codec;
codec->control_data = davinci_vc;
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 9d2afcc..13e05a3 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -205,7 +205,7 @@ static struct snd_soc_dai_driver davinci_vcif_dai = {

static int davinci_vcif_probe(struct platform_device *pdev)
{
- struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
+ struct davinci_vc *davinci_vc = mfd_get_data(pdev);
struct davinci_vcif_dev *davinci_vcif_dev;
int ret;

--
1.7.2.3

2011-02-18 03:08:20

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 12/29] tc6393xb: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Modify clients to use mfd_get_cell helper function instead of
accessing platform_data directly.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/tc6393xb.c | 19 -------------------
drivers/usb/host/ohci-tmio.c | 8 ++++----
drivers/video/tmiofb.c | 20 +++++++++-----------
3 files changed, 13 insertions(+), 34 deletions(-)

diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 9a23863..a71ff5c 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -694,26 +694,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
}

tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
- tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
- &tc6393xb_cells[TC6393XB_CELL_NAND];
- tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
- sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
-
- tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
- &tc6393xb_cells[TC6393XB_CELL_MMC];
- tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
- sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
-
- tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
- &tc6393xb_cells[TC6393XB_CELL_OHCI];
- tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
- sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
-
tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
- tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
- &tc6393xb_cells[TC6393XB_CELL_FB];
- tc6393xb_cells[TC6393XB_CELL_FB].data_size =
- sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);

ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 8dabe8e..eeed164 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -185,7 +185,7 @@ static struct platform_driver ohci_hcd_tmio_driver;

static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1);
struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2);
@@ -274,7 +274,7 @@ static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct tmio_hcd *tmio = hcd_to_tmio(hcd);
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);

usb_remove_hcd(hcd);
tmio_stop_hc(dev);
@@ -293,7 +293,7 @@ static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t state)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct tmio_hcd *tmio = hcd_to_tmio(hcd);
@@ -326,7 +326,7 @@ static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t s

static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct tmio_hcd *tmio = hcd_to_tmio(hcd);
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index dfef88c..6302882 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -250,7 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
*/
static int tmiofb_hw_stop(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_fb_data *data = cell->driver_data;
struct fb_info *info = platform_get_drvdata(dev);
struct tmiofb_par *par = info->par;
@@ -268,7 +268,7 @@ static int tmiofb_hw_stop(struct platform_device *dev)
*/
static int tmiofb_hw_init(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct fb_info *info = platform_get_drvdata(dev);
struct tmiofb_par *par = info->par;
const struct resource *nlcr = &cell->resources[0];
@@ -312,7 +312,7 @@ static int tmiofb_hw_init(struct platform_device *dev)
*/
static void tmiofb_hw_mode(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_fb_data *data = cell->driver_data;
struct fb_info *info = platform_get_drvdata(dev);
struct fb_videomode *mode = info->mode;
@@ -559,8 +559,7 @@ static int tmiofb_ioctl(struct fb_info *fbi,
static struct fb_videomode *
tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
{
- struct mfd_cell *cell =
- info->device->platform_data;
+ struct mfd_cell *cell = mfd_get_cell(to_platform_device(info->device));
struct tmio_fb_data *data = cell->driver_data;
struct fb_videomode *best = NULL;
int i;
@@ -581,8 +580,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{

struct fb_videomode *mode;
- struct mfd_cell *cell =
- info->device->platform_data;
+ struct mfd_cell *cell = mfd_get_cell(to_platform_device(info->device));
struct tmio_fb_data *data = cell->driver_data;

mode = tmiofb_find_mode(info, var);
@@ -683,7 +681,7 @@ static struct fb_ops tmiofb_ops = {

static int __devinit tmiofb_probe(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_fb_data *data = cell->driver_data;
struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -811,7 +809,7 @@ err_ioremap_ccr:

static int __devexit tmiofb_remove(struct platform_device *dev)
{
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct fb_info *info = platform_get_drvdata(dev);
int irq = platform_get_irq(dev, 0);
struct tmiofb_par *par;
@@ -941,7 +939,7 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
#ifdef CONFIG_FB_TMIO_ACCELL
struct tmiofb_par *par = info->par;
#endif
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
int retval = 0;

console_lock();
@@ -973,7 +971,7 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
static int tmiofb_resume(struct platform_device *dev)
{
struct fb_info *info = platform_get_drvdata(dev);
- struct mfd_cell *cell = dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
int retval = 0;

console_lock();
--
1.7.2.3

2011-02-18 03:10:06

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 28/29] mfd-core: add platform_device sharing support for mfd (v2)

This adds functions to enable platform_device sharing for mfd clients.

Each platform driver (mfd client) that wants to share an mfd_cell's
platform_device uses the mfd_shared_platform_driver_{un,}register()
functions instead of platform_driver_{un,}register(). Along with
registering the platform driver, these also register a new platform
device with the same characteristics as the original cell, but a different
name. Given an mfd_cell with the name "foo", drivers that want to
share access to its resources can call mfd_shared_platform_driver_register
with platform drivers named (for example) "bar" and "baz". This
will register two platform devices and drivers named "bar" and "baz"
that share the same cell as the platform device "foo". The drivers
can then call "foo" cell's enable hooks (or mfd_shared_cell_enable)
to enable resources, and obtain platform resources as they normally
would.

This deals with platform handling only; mfd driver-specific details,
hardware handling, refcounting, etc are all dealt with separately.

v2: Drop the randomized names, and instead let drivers specify
their own names. This gets rid of a bunch of code, and ensures
that userspace will know where platform drivers/devices will show
up in sysfs.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/mfd-core.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/core.h | 9 +++++++
2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index ca789f8..bb2264c 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -184,5 +184,66 @@ void mfd_remove_devices(struct device *parent)
}
EXPORT_SYMBOL(mfd_remove_devices);

+static int add_shared_platform_device(const char *cell, const char *name)
+{
+ struct mfd_cell cell_entry;
+ struct device *dev;
+ struct platform_device *pdev;
+ int err;
+
+ /* check if we've already registered a device (don't fail if we have) */
+ if (bus_find_device_by_name(&platform_bus_type, NULL, name))
+ return 0;
+
+ /* fetch the parent cell's device (should already be registered!) */
+ dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
+ if (!dev) {
+ printk(KERN_ERR "failed to find device for cell %s\n", cell);
+ return -ENODEV;
+ }
+ pdev = to_platform_device(dev);
+ memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry));
+
+ WARN_ON(!cell_entry.enable);
+
+ cell_entry.name = name;
+ err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0);
+ if (err)
+ dev_err(dev, "MFD add devices failed: %d\n", err);
+ return err;
+}
+
+int mfd_shared_platform_driver_register(struct platform_driver *drv,
+ const char *cellname)
+{
+ int err;
+
+ err = add_shared_platform_device(cellname, drv->driver.name);
+ if (err)
+ printk(KERN_ERR "failed to add platform device %s\n",
+ drv->driver.name);
+
+ err = platform_driver_register(drv);
+ if (err)
+ printk(KERN_ERR "failed to add platform driver %s\n",
+ drv->driver.name);
+
+ return err;
+}
+EXPORT_SYMBOL(mfd_shared_platform_driver_register);
+
+void mfd_shared_platform_driver_unregister(struct platform_driver *drv)
+{
+ struct device *dev;
+
+ dev = bus_find_device_by_name(&platform_bus_type, NULL,
+ drv->driver.name);
+ if (dev)
+ platform_device_unregister(to_platform_device(dev));
+
+ platform_driver_unregister(drv);
+}
+EXPORT_SYMBOL(mfd_shared_platform_driver_unregister);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 22a2f5e..ed99704 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -87,4 +87,13 @@ extern int mfd_add_devices(struct device *parent, int id,

extern void mfd_remove_devices(struct device *parent);

+/*
+ * For MFD drivers with clients sharing access to resources, these create
+ * multiple platform devices per cell. Contention handling must still be
+ * handled via drivers (ie, with enable/disable hooks).
+ */
+extern int mfd_shared_platform_driver_register(struct platform_driver *drv,
+ const char *cellname);
+extern void mfd_shared_platform_driver_unregister(struct platform_driver *drv);
+
#endif
--
1.7.2.3

2011-02-18 03:10:22

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 27/29] mfd-core: add refcounting support to mfd_cells (v2)

This provides convenience functions for sharing of cells across
multiple mfd clients. Mfd drivers can provide enable/disable hooks
to actually tweak the hardware, and clients can call
mfd_shared_cell_{en,dis}able without having to worry about whether
or not another client happens to have enabled or disabled the
cell/hardware.

Note that this is purely optional; drivers can continue to use
the mfd_cell's enable/disable hooks for their own purposes, if
desired.

v2: modify mfd_shared_cell_enable/disable to only modify refcount
if the hook call succeeds.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/mfd-core.c | 64 +++++++++++++++++++++++++++++++++++++++++++---
include/linux/mfd/core.h | 14 +++++++++-
2 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 01115f6..ca789f8 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -18,6 +18,43 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>

+int mfd_shared_cell_enable(struct platform_device *pdev)
+{
+ const struct mfd_cell *cell = mfd_get_cell(pdev);
+ int err = 0;
+
+ /* only call enable hook if the cell wasn't previously enabled */
+ if (atomic_inc_return(cell->usage_count) == 1)
+ err = cell->enable(pdev);
+
+ /* if the enable hook failed, decrement counter to allow retries */
+ if (err)
+ atomic_dec(cell->usage_count);
+
+ return err;
+}
+EXPORT_SYMBOL(mfd_shared_cell_enable);
+
+int mfd_shared_cell_disable(struct platform_device *pdev)
+{
+ const struct mfd_cell *cell = mfd_get_cell(pdev);
+ int err = 0;
+
+ /* only disable if no other clients are using it */
+ if (atomic_dec_return(cell->usage_count) == 0)
+ err = cell->disable(pdev);
+
+ /* if the disable hook failed, increment to allow retries */
+ if (err)
+ atomic_inc(cell->usage_count);
+
+ /* sanity check; did someone call disable too many times? */
+ WARN_ON(atomic_read(cell->usage_count) < 0);
+
+ return err;
+}
+EXPORT_SYMBOL(mfd_shared_cell_disable);
+
static int mfd_add_device(struct device *parent, int id,
const struct mfd_cell *cell,
struct resource *mem_base,
@@ -96,14 +133,22 @@ fail_alloc:
}

int mfd_add_devices(struct device *parent, int id,
- const struct mfd_cell *cells, int n_devs,
+ struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
int irq_base)
{
int i;
int ret = 0;
+ atomic_t *cnts;
+
+ /* initialize reference counting for all cells */
+ cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL);
+ if (!cnts)
+ return -ENOMEM;

for (i = 0; i < n_devs; i++) {
+ atomic_set(&cnts[i], 0);
+ cells[i].usage_count = &cnts[i];
ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
if (ret)
break;
@@ -116,15 +161,26 @@ int mfd_add_devices(struct device *parent, int id,
}
EXPORT_SYMBOL(mfd_add_devices);

-static int mfd_remove_devices_fn(struct device *dev, void *unused)
+static int mfd_remove_devices_fn(struct device *dev, void *c)
{
- platform_device_unregister(to_platform_device(dev));
+ struct platform_device *pdev = to_platform_device(dev);
+ const struct mfd_cell *cell = mfd_get_cell(pdev);
+ atomic_t **usage_count = c;
+
+ /* find the base address of usage_count pointers (for freeing) */
+ if (!*usage_count || (cell->usage_count < *usage_count))
+ *usage_count = cell->usage_count;
+
+ platform_device_unregister(pdev);
return 0;
}

void mfd_remove_devices(struct device *parent)
{
- device_for_each_child(parent, NULL, mfd_remove_devices_fn);
+ atomic_t *cnts = NULL;
+
+ device_for_each_child(parent, &cnts, mfd_remove_devices_fn);
+ kfree(cnts);
}
EXPORT_SYMBOL(mfd_remove_devices);

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 71cd1f9..22a2f5e 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -25,8 +25,11 @@ struct mfd_cell {
const char *name;
int id;

+ /* refcounting for multiple drivers to use a single cell */
+ atomic_t *usage_count;
int (*enable)(struct platform_device *dev);
int (*disable)(struct platform_device *dev);
+
int (*suspend)(struct platform_device *dev);
int (*resume)(struct platform_device *dev);

@@ -51,6 +54,15 @@ struct mfd_cell {
};

/*
+ * Convenience functions for clients using shared cells. Refcounting
+ * happens automatically, with the cell's enable/disable callbacks
+ * being called only when a device is first being enabled or no other
+ * clients are making use of it.
+ */
+extern int mfd_shared_cell_enable(struct platform_device *pdev);
+extern int mfd_shared_cell_disable(struct platform_device *pdev);
+
+/*
* Given a platform device that's been created by mfd_add_devices(), fetch
* the mfd_cell that created it.
*/
@@ -69,7 +81,7 @@ static inline void *mfd_get_data(struct platform_device *pdev)
}

extern int mfd_add_devices(struct device *parent, int id,
- const struct mfd_cell *cells, int n_devs,
+ struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
int irq_base);

--
1.7.2.3

2011-02-18 03:08:16

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 09/29] t7166xb: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Modify clients to use mfd_get_cell helper function instead of
accessing platform_data directly.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/t7l66xb.c | 9 ---------
drivers/mtd/nand/tmio_nand.c | 10 +++++-----
2 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 9caeb4a..b9c1e4c 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -384,15 +384,6 @@ static int t7l66xb_probe(struct platform_device *dev)
t7l66xb_attach_irq(dev);

t7l66xb_cells[T7L66XB_CELL_NAND].driver_data = pdata->nand_data;
- t7l66xb_cells[T7L66XB_CELL_NAND].platform_data =
- &t7l66xb_cells[T7L66XB_CELL_NAND];
- t7l66xb_cells[T7L66XB_CELL_NAND].data_size =
- sizeof(t7l66xb_cells[T7L66XB_CELL_NAND]);
-
- t7l66xb_cells[T7L66XB_CELL_MMC].platform_data =
- &t7l66xb_cells[T7L66XB_CELL_MMC];
- t7l66xb_cells[T7L66XB_CELL_MMC].data_size =
- sizeof(t7l66xb_cells[T7L66XB_CELL_MMC]);

ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 3041d1f..5bf63e3 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -319,7 +319,7 @@ static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf,

static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
{
- struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+ struct mfd_cell *cell = mfd_get_cell(dev);
int ret;

if (cell->enable) {
@@ -363,7 +363,7 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)

static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
{
- struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+ struct mfd_cell *cell = mfd_get_cell(dev);

tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE);
if (cell->disable)
@@ -372,7 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)

static int tmio_probe(struct platform_device *dev)
{
- struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_nand_data *data = cell->driver_data;
struct resource *fcr = platform_get_resource(dev,
IORESOURCE_MEM, 0);
@@ -516,7 +516,7 @@ static int tmio_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int tmio_suspend(struct platform_device *dev, pm_message_t state)
{
- struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+ struct mfd_cell *cell = mfd_get_cell(dev);

if (cell->suspend)
cell->suspend(dev);
@@ -527,7 +527,7 @@ static int tmio_suspend(struct platform_device *dev, pm_message_t state)

static int tmio_resume(struct platform_device *dev)
{
- struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+ struct mfd_cell *cell = mfd_get_cell(dev);

/* FIXME - is this required or merely another attack of the broken
* SHARP platform? Looks suspicious.
--
1.7.2.3

2011-02-18 03:10:50

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 23/29] tmio-nand: use mfd_data instead of driver_data

Use mfd_data for passing information from mfd drivers to mfd
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data(). This changes tmio-nand only; mfd drivers with
other cells are not modified.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/t7l66xb.c | 2 +-
drivers/mfd/tc6393xb.c | 2 +-
drivers/mtd/nand/tmio_nand.c | 3 +--
3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 3c9e389..af57fc7 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -383,7 +383,7 @@ static int t7l66xb_probe(struct platform_device *dev)

t7l66xb_attach_irq(dev);

- t7l66xb_cells[T7L66XB_CELL_NAND].driver_data = pdata->nand_data;
+ t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data;

ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 7f7b9fa..ecb045b 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -693,7 +693,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
goto err_setup;
}

- tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
+ tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;

ret = mfd_add_devices(&dev->dev, dev->id,
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 5bf63e3..2383b8f 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -372,8 +372,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)

static int tmio_probe(struct platform_device *dev)
{
- struct mfd_cell *cell = mfd_get_cell(dev);
- struct tmio_nand_data *data = cell->driver_data;
+ struct tmio_nand_data *data = mfd_get_data(dev);
struct resource *fcr = platform_get_resource(dev,
IORESOURCE_MEM, 0);
struct resource *ccr = platform_get_resource(dev,
--
1.7.2.3

2011-02-18 03:10:54

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 22/29] tmio-mmc: use mfd_data instead of driver_data

Use mfd_data for passing information from mfd drivers to mfd
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data(). This changes tmio-mmc only; mfd drivers with
other cells are not modified.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/asic3.c | 2 +-
drivers/mfd/sh_mobile_sdhi.c | 2 +-
drivers/mfd/t7l66xb.c | 2 +-
drivers/mfd/tc6387xb.c | 2 +-
drivers/mfd/tc6393xb.c | 2 +-
drivers/mmc/host/tmio_mmc.c | 26 +++++++++-----------------
6 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 549d14d..d0d247d 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -783,7 +783,7 @@ static struct mfd_cell asic3_cell_mmc = {
.name = "tmio-mmc",
.enable = asic3_mmc_enable,
.disable = asic3_mmc_disable,
- .driver_data = &asic3_mmc_data,
+ .mfd_data = &asic3_mmc_data,
.num_resources = ARRAY_SIZE(asic3_mmc_resources),
.resources = asic3_mmc_resources,
};
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
index b511e74..53a6302 100644
--- a/drivers/mfd/sh_mobile_sdhi.c
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -146,7 +146,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
}

memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
- priv->cell_mmc.driver_data = mmc_data;
+ priv->cell_mmc.mfd_data = mmc_data;

platform_set_drvdata(pdev, priv);

diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index b9c1e4c..3c9e389 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -170,7 +170,7 @@ static struct mfd_cell t7l66xb_cells[] = {
.name = "tmio-mmc",
.enable = t7l66xb_mmc_enable,
.disable = t7l66xb_mmc_disable,
- .driver_data = &t7166xb_mmc_data,
+ .mfd_data = &t7166xb_mmc_data,
.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
.resources = t7l66xb_mmc_resources,
},
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 6bf1775..b006f7c 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -131,7 +131,7 @@ static struct mfd_cell tc6387xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6387xb_mmc_enable,
.disable = tc6387xb_mmc_disable,
- .driver_data = &tc6387xb_mmc_data,
+ .mfd_data = &tc6387xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
.resources = tc6387xb_mmc_resources,
},
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index a71ff5c..7f7b9fa 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -393,7 +393,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume,
- .driver_data = &tc6393xb_mmc_data,
+ .mfd_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
},
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 816fb74..f7d3fa9 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -300,8 +300,7 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)

static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
{
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);

/*
* Testing on sh-mobile showed that SDIO IRQs are unmasked when
@@ -324,8 +323,7 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)

static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
{
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);

sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
@@ -666,8 +664,7 @@ out:
static irqreturn_t tmio_mmc_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
unsigned int ireg, irq_mask, status;
unsigned int sdio_ireg, sdio_irq_mask, sdio_status;

@@ -796,8 +793,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_rx;
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
dma_cookie_t cookie;
int ret, i;
bool aligned = true, multiple = true;
@@ -873,8 +869,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_tx;
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);
dma_cookie_t cookie;
int ret, i;
bool aligned = true, multiple = true;
@@ -1071,8 +1066,7 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
static int tmio_mmc_start_data(struct tmio_mmc_host *host,
struct mmc_data *data)
{
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);

pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n",
data->blksz, data->blocks);
@@ -1177,8 +1171,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int tmio_mmc_get_ro(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);

return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1;
@@ -1187,8 +1180,7 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
static int tmio_mmc_get_cd(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- struct mfd_cell *cell = mfd_get_cell(host->pdev);
- struct tmio_mmc_data *pdata = cell->driver_data;
+ struct tmio_mmc_data *pdata = mfd_get_data(host->pdev);

if (!pdata->get_cd)
return -ENOSYS;
@@ -1260,7 +1252,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (!res_ctl)
goto out;

- pdata = cell->driver_data;
+ pdata = mfd_get_data(dev);
if (!pdata || !pdata->hclk)
goto out;

--
1.7.2.3

2011-02-18 03:10:57

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 16/29] mc13xxx: mfd_cell is now implicitly available to drivers (v2)

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

Note that mfd-core no longer makes a copy of platform_data, but the
mc13xxx-core driver creates the pdata structures on the stack. In
order to get around that, the various ARM mach types that set the
pdata have been changed to hold the variable in static (global) memory.
Also note that __initdata references in aforementioned pdata structs
have been dropped.

v2: add some missing mfd/core.h includes.
v2: embed regulators struct inside of mc13xxx_platform_data rather than
using a pointer.

Signed-off-by: Andres Salomon <[email protected]>
---
arch/arm/mach-imx/mach-mx27_3ds.c | 9 ++++++---
arch/arm/mach-imx/mach-pcm038.c | 6 ++++--
arch/arm/mach-mx3/mach-mx31_3ds.c | 8 +++++---
arch/arm/mach-mx3/mach-mx31moboard.c | 6 ++++--
drivers/leds/leds-mc13783.c | 7 ++++---
drivers/mfd/mc13xxx-core.c | 18 +++++-------------
drivers/regulator/mc13783-regulator.c | 7 +++----
drivers/regulator/mc13892-regulator.c | 7 +++----
include/linux/mfd/mc13xxx.h | 3 +--
9 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 1643315..4bf1962 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -227,9 +227,12 @@ static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
};

/* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
- .regulators = mx27_3ds_regulators,
- .num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
+static struct mc13783_platform_data mc13783_pdata = {
+ .regulators = {
+ .regulators = mx27_3ds_regulators,
+ .num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
+
+ },
.flags = MC13783_USE_REGULATOR,
};

diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 5056148..c4c8fb1 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -263,8 +263,10 @@ static struct mc13783_regulator_init_data pcm038_regulators[] = {
};

static struct mc13783_platform_data pcm038_pmic = {
- .regulators = pcm038_regulators,
- .num_regulators = ARRAY_SIZE(pcm038_regulators),
+ .regulators = {
+ .regulators = pcm038_regulators,
+ .num_regulators = ARRAY_SIZE(pcm038_regulators),
+ },
.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
MC13783_USE_TOUCHSCREEN,
};
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 0d65db8..88516af 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -156,9 +156,11 @@ static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
};

/* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
- .regulators = mx31_3ds_regulators,
- .num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
+static struct mc13783_platform_data mc13783_pdata = {
+ .regulators = {
+ .regulators = mx31_3ds_regulators,
+ .num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
+ },
.flags = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
};

diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 1aa8d65..3a9c589 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -268,8 +268,10 @@ static struct mc13783_leds_platform_data moboard_leds = {
};

static struct mc13783_platform_data moboard_pmic = {
- .regulators = moboard_regulators,
- .num_regulators = ARRAY_SIZE(moboard_regulators),
+ .regulators = {
+ .regulators = moboard_regulators,
+ .num_regulators = ARRAY_SIZE(moboard_regulators),
+ },
.leds = &moboard_leds,
.flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
MC13783_USE_ADC | MC13783_USE_LED,
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index f05bb08..06a5bb4 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -22,6 +22,7 @@
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <linux/mfd/mc13783.h>
+#include <linux/mfd/core.h>
#include <linux/slab.h>

struct mc13783_led {
@@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)

static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
{
- struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int ret = 0;
int reg = 0;
@@ -264,7 +265,7 @@ out:

static int __devinit mc13783_led_probe(struct platform_device *pdev)
{
- struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_led_platform_data *led_cur;
struct mc13783_led *led, *led_dat;
int ret, i;
@@ -351,7 +352,7 @@ err_free:

static int __devexit mc13783_led_remove(struct platform_device *pdev)
{
- struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_led *led = platform_get_drvdata(pdev);
struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
int i;
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index b9fcaf0..30807d3 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -683,14 +683,13 @@ out:
EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);

static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
- const char *format, void *pdata, size_t pdata_size)
+ const char *format, void *pdata)
{
char buf[30];
const char *name = mc13xxx_get_chipname(mc13xxx);

struct mfd_cell cell = {
.platform_data = pdata,
- .data_size = pdata_size,
};

/* there is no asnprintf in the kernel :-( */
@@ -706,7 +705,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,

static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
{
- return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
+ return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL);
}

static int mc13xxx_probe(struct spi_device *spi)
@@ -764,13 +763,8 @@ err_revision:
mc13xxx_add_subdevice(mc13xxx, "%s-codec");

if (pdata->flags & MC13XXX_USE_REGULATOR) {
- struct mc13xxx_regulator_platform_data regulator_pdata = {
- .num_regulators = pdata->num_regulators,
- .regulators = pdata->regulators,
- };
-
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
- &regulator_pdata, sizeof(regulator_pdata));
+ &pdata->regulators);
}

if (pdata->flags & MC13XXX_USE_RTC)
@@ -779,10 +773,8 @@ err_revision:
if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");

- if (pdata->flags & MC13XXX_USE_LED) {
- mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
- pdata->leds, sizeof(*pdata->leds));
- }
+ if (pdata->flags & MC13XXX_USE_LED)
+ mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds);

return 0;
}
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 3e5d0c3..23249cb 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -15,6 +15,7 @@
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
+#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
@@ -336,8 +337,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
- struct mc13783_regulator_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
+ struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13783_regulator_init_data *init_data;
int i, ret;

@@ -381,8 +381,7 @@ err:
static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
- struct mc13783_regulator_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
+ struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
int i;

platform_set_drvdata(pdev, NULL);
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 1b8f739..6f15168 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -15,6 +15,7 @@
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
+#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
@@ -520,8 +521,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv;
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
- struct mc13xxx_regulator_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
+ struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
struct mc13xxx_regulator_init_data *init_data;
int i, ret;
u32 val;
@@ -595,8 +595,7 @@ err_free:
static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
- struct mc13xxx_regulator_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
+ struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
int i;

platform_set_drvdata(pdev, NULL);
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index a1d391b..c064bea 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -146,8 +146,7 @@ struct mc13xxx_platform_data {
#define MC13XXX_USE_LED (1 << 5)
unsigned int flags;

- int num_regulators;
- struct mc13xxx_regulator_init_data *regulators;
+ struct mc13xxx_regulator_platform_data regulators;
struct mc13xxx_leds_platform_data *leds;
};

--
1.7.2.3

2011-02-18 03:11:01

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 21/29] ds1wm: use mfd_data instead of driver_data

Use mfd_data for passing information from mfd drivers to mfd
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data(). This changes ds1wm only; mfd drivers with
other cells are not modified, with the exception of led_cell.

The led_cell.driver_data line is dropped from htc-pasic3.c in this
patch as well. It's not used in mainline (there's no leds-pasic3
platform driver), so it should be safe to take care of that here.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/asic3.c | 2 +-
drivers/mfd/htc-pasic3.c | 3 +--
drivers/w1/masters/ds1wm.c | 4 ++--
3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 71d2901..549d14d 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -682,7 +682,7 @@ static struct mfd_cell asic3_cell_ds1wm = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
- .driver_data = &ds1wm_pdata,
+ .mfd_data = &ds1wm_pdata,
.num_resources = ARRAY_SIZE(ds1wm_resources),
.resources = ds1wm_resources,
};
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 079d396..fb9770b 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -117,7 +117,7 @@ static struct mfd_cell ds1wm_cell __initdata = {
.name = "ds1wm",
.enable = ds1wm_enable,
.disable = ds1wm_disable,
- .driver_data = &ds1wm_pdata,
+ .mfd_data = &ds1wm_pdata,
.num_resources = 2,
.resources = ds1wm_resources,
};
@@ -172,7 +172,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
}

if (pdata && pdata->led_pdata) {
- led_cell.driver_data = pdata->led_pdata;
ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
if (ret < 0)
dev_warn(dev, "failed to register LED device\n");
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 94f55d8..22fc726 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -216,7 +216,7 @@ static int ds1wm_find_divisor(int gclk)
static void ds1wm_up(struct ds1wm_data *ds1wm_data)
{
int divisor;
- struct ds1wm_driver_data *plat = ds1wm_data->cell->driver_data;
+ struct ds1wm_driver_data *plat = mfd_get_data(ds1wm_data->pdev);

if (ds1wm_data->cell->enable)
ds1wm_data->cell->enable(ds1wm_data->pdev);
@@ -356,7 +356,7 @@ static int ds1wm_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err0;
}
- plat = cell->driver_data;
+ plat = mfd_get_data(pdev);

/* calculate bus shift from mem resource */
ds1wm_data->bus_shift = resource_size(res) >> 3;
--
1.7.2.3

2011-02-18 03:08:13

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 11/29] sh_mobile_sdhi: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/sh_mobile_sdhi.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
index 0a7df44..b511e74 100644
--- a/drivers/mfd/sh_mobile_sdhi.c
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -147,8 +147,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)

memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
priv->cell_mmc.driver_data = mmc_data;
- priv->cell_mmc.platform_data = &priv->cell_mmc;
- priv->cell_mmc.data_size = sizeof(priv->cell_mmc);

platform_set_drvdata(pdev, priv);

--
1.7.2.3

2011-02-18 03:11:44

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 20/29] wm8400-codec: use mfd_data instead of driver_data (v2)

Use mfd_data for passing information from mfd drivers to soc
clients. The mfd_cell's driver_data field is being phased out.

Clients that were using driver_data now access .mfd_data
via mfd_get_data().

v2: add some missing mfd/core.h includes.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/wm8400-core.c | 2 +-
sound/soc/codecs/wm8400.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 1bfef48..3a6e78c 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -245,7 +245,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
{
struct mfd_cell cell = {
.name = "wm8400-codec",
- .driver_data = wm8400,
+ .mfd_data = wm8400,
};

return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 3c3bc07..736b785 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -22,6 +22,7 @@
#include <linux/regulator/consumer.h>
#include <linux/mfd/wm8400-audio.h>
#include <linux/mfd/wm8400-private.h>
+#include <linux/mfd/core.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -1377,7 +1378,7 @@ static void wm8400_probe_deferred(struct work_struct *work)

static int wm8400_codec_probe(struct snd_soc_codec *codec)
{
- struct wm8400 *wm8400 = dev_get_platdata(codec->dev);
+ struct wm8400 *wm8400 = mfd_get_data(to_platform_device(codec->dev));
struct wm8400_priv *priv;
int ret;
u16 reg;
--
1.7.2.3

2011-02-18 03:11:46

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 15/29] janz: mfd_cell is now implicitly available to drivers (v2)

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

v2: add some missing mfd/core.h includes.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/gpio/janz-ttl.c | 3 ++-
drivers/mfd/janz-cmodio.c | 1 -
drivers/net/can/janz-ican3.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c
index 813ac07..2514fb0 100644
--- a/drivers/gpio/janz-ttl.c
+++ b/drivers/gpio/janz-ttl.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -149,7 +150,7 @@ static int __devinit ttl_probe(struct platform_device *pdev)
struct resource *res;
int ret;

- pdata = pdev->dev.platform_data;
+ pdata = mfd_get_data(pdev);
if (!pdata) {
dev_err(dev, "no platform data\n");
ret = -ENXIO;
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 36a166b..58de1e2 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -87,7 +87,6 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
/* Add platform data */
pdata->modno = modno;
cell->platform_data = pdata;
- cell->data_size = sizeof(*pdata);

/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
res->flags = IORESOURCE_MEM;
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 366f5cc..102b16c 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>

#include <linux/netdevice.h>
#include <linux/can.h>
@@ -1643,7 +1644,7 @@ static int __devinit ican3_probe(struct platform_device *pdev)
struct device *dev;
int ret;

- pdata = pdev->dev.platform_data;
+ pdata = mfd_get_data(pdev);
if (!pdata)
return -ENXIO;

--
1.7.2.3

2011-02-18 03:08:10

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 10/29] wl1273: mfd_cell is now implicitly available to drivers

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/media/radio/radio-wl1273.c | 2 +-
drivers/mfd/wl1273-core.c | 2 --
sound/soc/codecs/wl1273.c | 3 ++-
3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 7ecc8e6..4698eb0 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -2138,7 +2138,7 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev)

static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
{
- struct wl1273_core **core = pdev->dev.platform_data;
+ struct wl1273_core **core = mfd_get_data(pdev);
struct wl1273_device *radio;
struct v4l2_ctrl *ctrl;
int r = 0;
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index d2ecc24..703085e 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -80,7 +80,6 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
cell = &core->cells[children];
cell->name = "wl1273_fm_radio";
cell->platform_data = &core;
- cell->data_size = sizeof(core);
children++;

if (pdata->children & WL1273_CODEC_CHILD) {
@@ -89,7 +88,6 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
cell->name = "wl1273-codec";
cell->platform_data = &core;
- cell->data_size = sizeof(core);
children++;
}

diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 861b28f..1ad0d5a 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -436,7 +436,8 @@ EXPORT_SYMBOL_GPL(wl1273_get_format);

static int wl1273_probe(struct snd_soc_codec *codec)
{
- struct wl1273_core **core = codec->dev->platform_data;
+ struct wl1273_core **core =
+ mfd_get_data(to_platform_device(codec->dev));
struct wl1273_priv *wl1273;
int r;

--
1.7.2.3

2011-02-18 03:08:08

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 08/29] timberdale: mfd_cell is now implicitly available to drivers (v2)

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

Note that the mfd's platform_data is marked __devinitdata. This
is still correct in all cases except for the timbgpio driver, whose
remove hook has been changed to no longer reference the pdata.

v2: add some missing mfd/core.h includes.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/dma/timb_dma.c | 3 ++-
drivers/gpio/timbgpio.c | 6 +++---
drivers/i2c/busses/i2c-ocores.c | 3 ++-
drivers/i2c/busses/i2c-xiic.c | 3 ++-
drivers/media/radio/radio-timb.c | 3 ++-
drivers/media/video/timblogiw.c | 3 ++-
drivers/mfd/timberdale.c | 27 ---------------------------
drivers/net/ks8842.c | 3 ++-
drivers/spi/xilinx_spi.c | 3 ++-
9 files changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 3b88a4e..ea8705b 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/slab.h>

#include <linux/timb_dma.h>
@@ -684,7 +685,7 @@ static irqreturn_t td_irq(int irq, void *devid)

static int __devinit td_probe(struct platform_device *pdev)
{
- struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
+ struct timb_dma_platform_data *pdata = mfd_get_data(pdev);
struct timb_dma *td;
struct resource *iomem;
int irq;
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
index 58c8f30..ffcd815 100644
--- a/drivers/gpio/timbgpio.c
+++ b/drivers/gpio/timbgpio.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/timb_gpio.h>
@@ -228,7 +229,7 @@ static int __devinit timbgpio_probe(struct platform_device *pdev)
struct gpio_chip *gc;
struct timbgpio *tgpio;
struct resource *iomem;
- struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timbgpio_platform_data *pdata = mfd_get_data(pdev);
int irq = platform_get_irq(pdev, 0);

if (!pdata || pdata->nr_pins > 32) {
@@ -319,14 +320,13 @@ err_mem:
static int __devexit timbgpio_remove(struct platform_device *pdev)
{
int err;
- struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
struct timbgpio *tgpio = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);

if (irq >= 0 && tgpio->irq_base > 0) {
int i;
- for (i = 0; i < pdata->nr_pins; i++) {
+ for (i = 0; i < tgpio->gpio.ngpio; i++) {
set_irq_chip(tgpio->irq_base + i, NULL);
set_irq_chip_data(tgpio->irq_base + i, NULL);
}
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index ef3bcb1..a3f4799 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -49,6 +49,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
@@ -305,7 +306,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
return -EIO;
}

- pdata = pdev->dev.platform_data;
+ pdata = mfd_get_data(pdev);
if (pdata) {
i2c->regstep = pdata->regstep;
i2c->clock_khz = pdata->clock_khz;
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index a9c419e..9fbd7e6 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -34,6 +34,7 @@
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
@@ -704,7 +705,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
if (irq < 0)
goto resource_missing;

- pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
+ pdata = mfd_get_data(pdev);
if (!pdata)
return -EINVAL;

diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index a185610..1e3a8dd 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -21,6 +21,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/i2c.h>
@@ -148,7 +149,7 @@ static const struct v4l2_file_operations timbradio_fops = {

static int __devinit timbradio_probe(struct platform_device *pdev)
{
- struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
+ struct timb_radio_platform_data *pdata = mfd_get_data(pdev);
struct timbradio *tr;
int err;

diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c
index fc611eb..84d4c7c 100644
--- a/drivers/media/video/timblogiw.c
+++ b/drivers/media/video/timblogiw.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
+#include <linux/mfd/core.h>
#include <linux/scatterlist.h>
#include <linux/interrupt.h>
#include <linux/list.h>
@@ -790,7 +791,7 @@ static int __devinit timblogiw_probe(struct platform_device *pdev)
{
int err;
struct timblogiw *lw = NULL;
- struct timb_video_platform_data *pdata = pdev->dev.platform_data;
+ struct timb_video_platform_data *pdata = mfd_get_data(pdev);

if (!pdata) {
dev_err(&pdev->dev, "No platform data\n");
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 6ad8a7f..6353921 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -385,7 +385,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
- .data_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
@@ -397,42 +396,36 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
- .data_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
- .data_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
- .data_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
- .data_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
- .data_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
- .data_size = sizeof(timberdale_ks8842_platform_data)
},
};

@@ -442,7 +435,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
- .data_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
@@ -459,14 +451,12 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
- .data_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
- .data_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-mlogicore",
@@ -478,28 +468,24 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
- .data_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
- .data_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
- .data_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
- .data_size = sizeof(timberdale_ks8842_platform_data)
},
};

@@ -509,7 +495,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
- .data_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
@@ -521,35 +506,30 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
.resources = timberdale_xiic_resources,
.platform_data = &timberdale_xiic_platform_data,
- .data_size = sizeof(timberdale_xiic_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
- .data_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
- .data_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
- .data_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
- .data_size = sizeof(timberdale_xspi_platform_data),
},
};

@@ -559,7 +539,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
.resources = timberdale_dma_resources,
.platform_data = &timb_dma_platform_data,
- .data_size = sizeof(timb_dma_platform_data),
},
{
.name = "timb-uart",
@@ -571,42 +550,36 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
.resources = timberdale_ocores_resources,
.platform_data = &timberdale_ocores_platform_data,
- .data_size = sizeof(timberdale_ocores_platform_data),
},
{
.name = "timb-gpio",
.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
.resources = timberdale_gpio_resources,
.platform_data = &timberdale_gpio_platform_data,
- .data_size = sizeof(timberdale_gpio_platform_data),
},
{
.name = "timb-video",
.num_resources = ARRAY_SIZE(timberdale_video_resources),
.resources = timberdale_video_resources,
.platform_data = &timberdale_video_platform_data,
- .data_size = sizeof(timberdale_video_platform_data),
},
{
.name = "timb-radio",
.num_resources = ARRAY_SIZE(timberdale_radio_resources),
.resources = timberdale_radio_resources,
.platform_data = &timberdale_radio_platform_data,
- .data_size = sizeof(timberdale_radio_platform_data),
},
{
.name = "xilinx_spi",
.num_resources = ARRAY_SIZE(timberdale_spi_resources),
.resources = timberdale_spi_resources,
.platform_data = &timberdale_xspi_platform_data,
- .data_size = sizeof(timberdale_xspi_platform_data),
},
{
.name = "ks8842",
.num_resources = ARRAY_SIZE(timberdale_eth_resources),
.resources = timberdale_eth_resources,
.platform_data = &timberdale_ks8842_platform_data,
- .data_size = sizeof(timberdale_ks8842_platform_data)
},
};

diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 928b2b8..efd44af 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -1145,7 +1146,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
struct resource *iomem;
struct net_device *netdev;
struct ks8842_adapter *adapter;
- struct ks8842_platform_data *pdata = pdev->dev.platform_data;
+ struct ks8842_platform_data *pdata = mfd_get_data(pdev);
u16 id;
unsigned i;

diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 7adaef6..c9bf074 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/xilinx_spi.h>
@@ -474,7 +475,7 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev)
struct spi_master *master;
u8 i;

- pdata = dev->dev.platform_data;
+ pdata = mfd_get_data(dev);
if (pdata) {
num_cs = pdata->num_chipselect;
little_endian = pdata->little_endian;
--
1.7.2.3

2011-02-18 03:12:41

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 14/29] tc6387xb: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/tc6387xb.c | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 6315f63..6bf1775 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -190,11 +190,6 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)

printk(KERN_INFO "Toshiba tc6387xb initialised\n");

- tc6387xb_cells[TC6387XB_CELL_MMC].platform_data =
- &tc6387xb_cells[TC6387XB_CELL_MMC];
- tc6387xb_cells[TC6387XB_CELL_MMC].data_size =
- sizeof(tc6387xb_cells[TC6387XB_CELL_MMC]);
-
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
ARRAY_SIZE(tc6387xb_cells), iomem, irq);

--
1.7.2.3

2011-02-18 03:12:45

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 13/29] twl4030: mfd_cell is now implicitly available to drivers (v2)

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

v2: add some missing mfd/core.h includes.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/input/misc/twl4030-vibra.c | 3 ++-
drivers/mfd/twl4030-codec.c | 2 --
sound/soc/codecs/twl4030.c | 6 ++++--
3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 014dd4a..6a11694 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -29,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/i2c/twl.h>
#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/core.h>
#include <linux/input.h>
#include <linux/slab.h>

@@ -196,7 +197,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,

static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
{
- struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
+ struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev);
struct vibra_info *info;
int ret;

diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
index 9a4b196..0f57426 100644
--- a/drivers/mfd/twl4030-codec.c
+++ b/drivers/mfd/twl4030-codec.c
@@ -209,14 +209,12 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
cell = &codec->cells[childs];
cell->name = "twl4030-codec";
cell->platform_data = pdata->audio;
- cell->data_size = sizeof(*pdata->audio);
childs++;
}
if (pdata->vibra) {
cell = &codec->cells[childs];
cell->name = "twl4030-vibra";
cell->platform_data = pdata->vibra;
- cell->data_size = sizeof(*pdata->vibra);
childs++;
}

diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index e4d464b..8512800 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -26,6 +26,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include <linux/i2c/twl.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -732,7 +733,8 @@ static int aif_event(struct snd_soc_dapm_widget *w,

static void headset_ramp(struct snd_soc_codec *codec, int ramp)
{
- struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
+ struct twl4030_codec_audio_data *pdata =
+ mfd_get_data(to_platform_device(codec->dev));
unsigned char hs_gain, hs_pop;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
/* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -2297,7 +2299,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {

static int __devinit twl4030_codec_probe(struct platform_device *pdev)
{
- struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
+ struct twl4030_codec_audio_data *pdata = mfd_get_data(pdev);

if (!pdata) {
dev_err(&pdev->dev, "platform_data is missing\n");
--
1.7.2.3

2011-02-18 03:07:59

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 02/29] mfd-core: unconditionally add mfd_cell to every platform_device

Previously, one would set the mfd_cell's platform_data/data_size to point
to the current mfd_cell in order to pass that information along to drivers.

This causes the current mfd_cell to always be available to drivers. It
also adds a wrapper function for fetching the mfd cell from a platform
device, similar to what originally existed for mfd devices.

Drivers who previously used platform_data for other purposes can still
use it; the difference is that mfd_get_data() must be used to
access it (and the pdata structure is no longer allocated in
mfd_add_devices).

Note that mfd_get_data is intentionally vague (in name) about where
the data is stored; variable name changes can come later without having
to touch brazillions of drivers.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/mfd-core.c | 9 +++------
include/linux/mfd/core.h | 23 +++++++++++++++++++++--
2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index d83ad0f..21a39dc 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -39,12 +39,9 @@ static int mfd_add_device(struct device *parent, int id,
pdev->dev.parent = parent;
platform_set_drvdata(pdev, cell->driver_data);

- if (cell->data_size) {
- ret = platform_device_add_data(pdev,
- cell->platform_data, cell->data_size);
- if (ret)
- goto fail_res;
- }
+ ret = platform_device_add_data(pdev, cell, sizeof(*cell));
+ if (ret)
+ goto fail_res;

for (r = 0; r < cell->num_resources; r++) {
res[r].name = cell->resources[r].name;
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 1fd7c44..aefc378 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -33,9 +33,10 @@ struct mfd_cell {
/* driver-specific data for MFD-aware "cell" drivers */
void *driver_data;

- /* platform_data can be used to either pass data to "generic"
- driver or as a hook to mfd_cell for the "cell" drivers */
+ /* platform_data can be used to pass data to "generic" drivers */
void *platform_data;
+
+ /* unused */
size_t data_size;

/*
@@ -55,6 +56,24 @@ struct mfd_cell {
bool pm_runtime_no_callbacks;
};

+/*
+ * Given a platform device that's been created by mfd_add_devices(), fetch
+ * the mfd_cell that created it.
+ */
+static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
+{
+ return pdev->dev.platform_data;
+}
+
+/*
+ * Given a platform device that's been created by mfd_add_devices(), fetch
+ * the .platform_data entry from the mfd_cell that created it.
+ */
+static inline void *mfd_get_data(struct platform_device *pdev)
+{
+ return mfd_get_cell(pdev)->platform_data;
+}
+
extern int mfd_add_devices(struct device *parent, int id,
const struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
--
1.7.2.3

2011-02-18 03:13:24

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 07/29] htc-pasic3: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/htc-pasic3.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 7bc7522..079d396 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -165,8 +165,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
ds1wm_pdata.clock_rate = pdata->clock_rate;
/* the first 5 PASIC3 registers control the DS1WM */
ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
- ds1wm_cell.platform_data = &ds1wm_cell;
- ds1wm_cell.data_size = sizeof(ds1wm_cell);
ret = mfd_add_devices(&pdev->dev, pdev->id,
&ds1wm_cell, 1, r, irq);
if (ret < 0)
@@ -175,8 +173,6 @@ static int __init pasic3_probe(struct platform_device *pdev)

if (pdata && pdata->led_pdata) {
led_cell.driver_data = pdata->led_pdata;
- led_cell.platform_data = &led_cell;
- led_cell.data_size = sizeof(ds1wm_cell);
ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
if (ret < 0)
dev_warn(dev, "failed to register LED device\n");
--
1.7.2.3

2011-02-18 03:07:57

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 01/29] mfd-core: fix up typos/vagueness in comment

This is my interpretation of the comment for mfd_cell's resources.. :)

Signed-off-by: Andres Salomon <[email protected]>
---
include/linux/mfd/core.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 835996e..1fd7c44 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -39,8 +39,8 @@ struct mfd_cell {
size_t data_size;

/*
- * This resources can be specified relatively to the parent device.
- * For accessing device you should use resources from device
+ * These resources can be specified relative to the parent device.
+ * For accessing hardware you should use resources from the platform dev
*/
int num_resources;
const struct resource *resources;
--
1.7.2.3

2011-02-18 03:13:27

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 06/29] asic3: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Modify clients to use mfd_get_cell helper function instead of
accessing platform_data directly.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/asic3.c | 6 ------
drivers/mmc/host/tmio_mmc.c | 24 ++++++++++++------------
drivers/w1/masters/ds1wm.c | 2 +-
3 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 6a1f940..71d2901 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -810,9 +810,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].start >>= asic->bus_shift;
ds1wm_resources[0].end >>= asic->bus_shift;

- asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm;
- asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
-
/* MMC */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start, 0x400 >> asic->bus_shift);
@@ -824,9 +821,6 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift;

- asic3_cell_mmc.platform_data = &asic3_cell_mmc;
- asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
-
ret = mfd_add_devices(&pdev->dev, pdev->id,
&asic3_cell_ds1wm, 1, mem, asic->irq_base);
if (ret < 0)
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index e3c6ef2..816fb74 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -300,7 +300,7 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)

static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
{
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;

/*
@@ -324,7 +324,7 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)

static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
{
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;

sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
@@ -666,7 +666,7 @@ out:
static irqreturn_t tmio_mmc_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;
unsigned int ireg, irq_mask, status;
unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
@@ -796,7 +796,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_rx;
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;
dma_cookie_t cookie;
int ret, i;
@@ -873,7 +873,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_tx;
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;
dma_cookie_t cookie;
int ret, i;
@@ -1071,7 +1071,7 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
static int tmio_mmc_start_data(struct tmio_mmc_host *host,
struct mmc_data *data)
{
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;

pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n",
@@ -1177,7 +1177,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int tmio_mmc_get_ro(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;

return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
@@ -1187,7 +1187,7 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
static int tmio_mmc_get_cd(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- struct mfd_cell *cell = host->pdev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(host->pdev);
struct tmio_mmc_data *pdata = cell->driver_data;

if (!pdata->get_cd)
@@ -1207,7 +1207,7 @@ static const struct mmc_host_ops tmio_mmc_ops = {
#ifdef CONFIG_PM
static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
{
- struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret;

@@ -1222,7 +1222,7 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)

static int tmio_mmc_resume(struct platform_device *dev)
{
- struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;

@@ -1245,7 +1245,7 @@ out:

static int __devinit tmio_mmc_probe(struct platform_device *dev)
{
- struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct tmio_mmc_data *pdata;
struct resource *res_ctl;
struct tmio_mmc_host *host;
@@ -1360,7 +1360,7 @@ out:

static int __devexit tmio_mmc_remove(struct platform_device *dev)
{
- struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct mfd_cell *cell = mfd_get_cell(dev);
struct mmc_host *mmc = platform_get_drvdata(dev);

platform_set_drvdata(dev, NULL);
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 6b85e7f..94f55d8 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -336,7 +336,7 @@ static int ds1wm_probe(struct platform_device *pdev)
if (!pdev)
return -ENODEV;

- cell = pdev->dev.platform_data;
+ cell = mfd_get_cell(pdev);
if (!cell)
return -ENODEV;

--
1.7.2.3

2011-02-18 03:13:49

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 05/29] ab3100: mfd_cell is now implicitly available to drivers (v2)

The cell's platform_data is now accessed with a helper function;
change clients to use that, and remove the now-unused data_size.

v2: add some missing mfd/core.h includes.

Signed-off-by: Andres Salomon <[email protected]>
---
drivers/mfd/ab3100-core.c | 4 +---
drivers/regulator/ab3100.c | 3 ++-
2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 4193af5..b44c3d9 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -949,10 +949,8 @@ static int __devinit ab3100_probe(struct i2c_client *client,
goto exit_no_ops;

/* Set up and register the platform devices. */
- for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) {
+ for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++)
ab3100_devs[i].platform_data = ab3100_plf_data;
- ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data);
- }

err = mfd_add_devices(&client->dev, 0, ab3100_devs,
ARRAY_SIZE(ab3100_devs), NULL, 0);
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index ed6feaf..2dec589 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/core.h>

/* LDO registers and some handy masking definitions for AB3100 */
#define AB3100_LDO_A 0x40
@@ -576,7 +577,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {

static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
{
- struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
+ struct ab3100_platform_data *plfdata = mfd_get_data(pdev);
int err = 0;
u8 data;
int i;
--
1.7.2.3

2011-02-18 03:14:12

by Andres Salomon

[permalink] [raw]
Subject: [PATCH 03/29] jz4740: mfd_cell is now implicitly available to drivers

No need to explicitly set the cell's platform_data/data_size.

Modify clients to use mfd_get_cell helper function instead of
accessing platform_data directly.

Signed-off-by: Andres Salomon <[email protected]>
Acked-by: Jean Delvare <[email protected]>
---
drivers/hwmon/jz4740-hwmon.c | 2 +-
drivers/mfd/jz4740-adc.c | 4 ----
drivers/power/jz4740-battery.c | 2 +-
3 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
index 1c8b3d9..40f106d 100644
--- a/drivers/hwmon/jz4740-hwmon.c
+++ b/drivers/hwmon/jz4740-hwmon.c
@@ -112,7 +112,7 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
return -ENOMEM;
}

- hwmon->cell = pdev->dev.platform_data;
+ hwmon->cell = mfd_get_cell(pdev);

hwmon->irq = platform_get_irq(pdev, 0);
if (hwmon->irq < 0) {
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index 0cc5979..aa518b9 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -232,8 +232,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-hwmon",
.num_resources = ARRAY_SIZE(jz4740_hwmon_resources),
.resources = jz4740_hwmon_resources,
- .platform_data = (void *)&jz4740_adc_cells[0],
- .data_size = sizeof(struct mfd_cell),

.enable = jz4740_adc_cell_enable,
.disable = jz4740_adc_cell_disable,
@@ -243,8 +241,6 @@ const struct mfd_cell jz4740_adc_cells[] = {
.name = "jz4740-battery",
.num_resources = ARRAY_SIZE(jz4740_battery_resources),
.resources = jz4740_battery_resources,
- .platform_data = (void *)&jz4740_adc_cells[1],
- .data_size = sizeof(struct mfd_cell),

.enable = jz4740_adc_cell_enable,
.disable = jz4740_adc_cell_disable,
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 02414db..0938650 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -258,7 +258,7 @@ static int __devinit jz_battery_probe(struct platform_device *pdev)
return -ENOMEM;
}

- jz_battery->cell = pdev->dev.platform_data;
+ jz_battery->cell = mfd_get_cell(pdev);

jz_battery->irq = platform_get_irq(pdev, 0);
if (jz_battery->irq < 0) {
--
1.7.2.3

2011-02-18 03:51:24

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH 20/29] wm8400-codec: use mfd_data instead of driver_data (v2)

On Thu, Feb 17, 2011 at 07:07:27PM -0800, Andres Salomon wrote:
> Use mfd_data for passing information from mfd drivers to soc
> clients. The mfd_cell's driver_data field is being phased out.
>
> Clients that were using driver_data now access .mfd_data
> via mfd_get_data().
>
> v2: add some missing mfd/core.h includes.
>
> Signed-off-by: Andres Salomon <[email protected]>

Acked-by: Mark Brown <[email protected]>

2011-02-18 06:44:41

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH 13/29] twl4030: mfd_cell is now implicitly available to drivers (v2)

On 02/18/11 05:07, ext Andres Salomon wrote:
> The cell's platform_data is now accessed with a helper function;
> change clients to use that, and remove the now-unused data_size.
>
> v2: add some missing mfd/core.h includes.
>
> Signed-off-by: Andres Salomon <[email protected]>
> ---
> drivers/input/misc/twl4030-vibra.c | 3 ++-
> drivers/mfd/twl4030-codec.c | 2 --
> sound/soc/codecs/twl4030.c | 6 ++++--
> 3 files changed, 6 insertions(+), 5 deletions(-)

Acked-by: Peter Ujfalusi <[email protected]>

2011-02-25 09:06:48

by Artem Bityutskiy

[permalink] [raw]
Subject: Re: [PATCH 09/29] t7166xb: mfd_cell is now implicitly available to drivers

On Thu, 2011-02-17 at 19:07 -0800, Andres Salomon wrote:
> No need to explicitly set the cell's platform_data/data_size.
>
> Modify clients to use mfd_get_cell helper function instead of
> accessing platform_data directly.
>
> Signed-off-by: Andres Salomon <[email protected]>

Just to re-confirm, I suggest to merge these MTD changes via Samuel's
tree, thanks.

--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

2011-02-25 10:47:31

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 09/29] t7166xb: mfd_cell is now implicitly available to drivers

Hi Artem,

On Fri, Feb 25, 2011 at 11:05:12AM +0200, Artem Bityutskiy wrote:
> On Thu, 2011-02-17 at 19:07 -0800, Andres Salomon wrote:
> > No need to explicitly set the cell's platform_data/data_size.
> >
> > Modify clients to use mfd_get_cell helper function instead of
> > accessing platform_data directly.
> >
> > Signed-off-by: Andres Salomon <[email protected]>
>
> Just to re-confirm, I suggest to merge these MTD changes via Samuel's
> tree, thanks.
Thanks, I'll take them.

Cheers,
Samuel.

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

2011-02-28 16:39:41

by Samuel Ortiz

[permalink] [raw]
Subject: Re: MFD sharing support (v3, full)

Hi Andres,

On Thu, Feb 17, 2011 at 07:07:07PM -0800, Andres Salomon wrote:
> Here's all of my third attempt at MFD cell sharing. This includes all
> parts; some of the patches from v2 are being resent without changes. I
> apologize for the noise, but since I screwed up the threading in the first
> batch and people were having trouble finding some of the patches, I figured
> I'd resend everything together. There are some changes in there as well;
> they've been marked in commit messages.
>
> This whole set does the following things:
> - make mfd_cell structs always accessible to platform devices
> - adjust the mfd_cell API to (hopefully) be cleaner, replacing platform_data
> and driver_data with mfd_data
> - add wrapper functions to access mfd cell and data fields
> - adjust all mfd clients/drivers to use the new API
> - add a reference counting wrapper for mfd_cell's enable/disable hooks
> - add platform device sharing wrappers to allow mfd clients to create
> new platform devices (at the same time as platform drivers are being
> registered)
> - update the cs5535-mfd driver (and clients) to make use of the new
> sharing code
>
> This effectively provides the ability for mfd clients to share a single
> mfd_cell, and provide the framework for mfd-core be handle shared hardware
> resources.
Thanks a lot for that. I applied all patches now. I have some really minor
comment regarding the naming in patch #28, but we can fix that later.

Cheers,
Samuel.

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

2011-02-28 16:39:59

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 27/29] mfd-core: add refcounting support to mfd_cells (v2)

Hi Andres,

On Thu, Feb 17, 2011 at 07:07:34PM -0800, Andres Salomon wrote:
> This provides convenience functions for sharing of cells across
> multiple mfd clients. Mfd drivers can provide enable/disable hooks
> to actually tweak the hardware, and clients can call
> mfd_shared_cell_{en,dis}able without having to worry about whether
> or not another client happens to have enabled or disabled the
> cell/hardware.
>
> Note that this is purely optional; drivers can continue to use
> the mfd_cell's enable/disable hooks for their own purposes, if
> desired.
>
> v2: modify mfd_shared_cell_enable/disable to only modify refcount
> if the hook call succeeds.
>
> Signed-off-by: Andres Salomon <[email protected]>
> ---
> drivers/mfd/mfd-core.c | 64 +++++++++++++++++++++++++++++++++++++++++++---
> include/linux/mfd/core.h | 14 +++++++++-
> 2 files changed, 73 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 01115f6..ca789f8 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -18,6 +18,43 @@
> #include <linux/pm_runtime.h>
> #include <linux/slab.h>
>
> +int mfd_shared_cell_enable(struct platform_device *pdev)
> +{
> + const struct mfd_cell *cell = mfd_get_cell(pdev);
> + int err = 0;
> +
> + /* only call enable hook if the cell wasn't previously enabled */
> + if (atomic_inc_return(cell->usage_count) == 1)
> + err = cell->enable(pdev);
> +
> + /* if the enable hook failed, decrement counter to allow retries */
> + if (err)
> + atomic_dec(cell->usage_count);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(mfd_shared_cell_enable);
> +
> +int mfd_shared_cell_disable(struct platform_device *pdev)
> +{
> + const struct mfd_cell *cell = mfd_get_cell(pdev);
> + int err = 0;
> +
> + /* only disable if no other clients are using it */
> + if (atomic_dec_return(cell->usage_count) == 0)
> + err = cell->disable(pdev);
> +
> + /* if the disable hook failed, increment to allow retries */
> + if (err)
> + atomic_inc(cell->usage_count);
> +
> + /* sanity check; did someone call disable too many times? */
> + WARN_ON(atomic_read(cell->usage_count) < 0);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(mfd_shared_cell_disable);
It would probably make sense to rename both of these routines by simply
removing the shared part: mfd_cell_enable/disable().

Cheers,
Samuel.

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

2011-02-28 16:40:21

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 28/29] mfd-core: add platform_device sharing support for mfd (v2)

Hi Andres,

On Thu, Feb 17, 2011 at 07:07:35PM -0800, Andres Salomon wrote:
> This adds functions to enable platform_device sharing for mfd clients.
>
> Each platform driver (mfd client) that wants to share an mfd_cell's
> platform_device uses the mfd_shared_platform_driver_{un,}register()
> functions instead of platform_driver_{un,}register(). Along with
> registering the platform driver, these also register a new platform
> device with the same characteristics as the original cell, but a different
> name. Given an mfd_cell with the name "foo", drivers that want to
> share access to its resources can call mfd_shared_platform_driver_register
> with platform drivers named (for example) "bar" and "baz". This
> will register two platform devices and drivers named "bar" and "baz"
> that share the same cell as the platform device "foo". The drivers
> can then call "foo" cell's enable hooks (or mfd_shared_cell_enable)
> to enable resources, and obtain platform resources as they normally
> would.
I'm not fine with the naming, as it really is doing more than
registering a platform driver. But since I can not come up with a better name
right now, I would really appreciate if you could add some comments there
explaining what this routine (mfd_shared_platform_driver_register)
does and in which cases it is needed. The OLPC example could also be
mentioned.

Cheers,
Samuel.

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