aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorAndres Salomon <dilinger@queued.net>2011-03-21 22:19:35 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-03-26 19:09:30 -0400
commitfa1df691688f34cbcd5bf77bd084bbe47e9d6bfe (patch)
tree83df18f1d427115c0016a059535b04f2d600a2d0 /drivers/mfd
parent16c29dafcc86024048f1dbb8349d31cb22c7c55a (diff)
mfd: Add mfd_clone_cell(), convert cs5535-mfd/olpc-xo1 to it
Replace mfd_shared_platform_driver_register with mfd_clone_cell. The former was called by an mfd client, and registered both a platform driver and device. The latter is called by an mfd driver, and registers only a platform device. The downside of this is that mfd drivers need to be modified whenever new clients are added that share a cell; the upside is that it fits Linux's driver model better. It's also simpler. This also converts cs5535-mfd/olpc-xo1 from the old API. cs5535-mfd now creates the olpc-xo1-{acpi,pms} devices, while olpc-xo1 binds to them via platform drivers. Signed-off-by: Andres Salomon <dilinger@queued.net> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/cs5535-mfd.c18
-rw-r--r--drivers/mfd/mfd-core.c53
2 files changed, 29 insertions, 42 deletions
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 886a06871065..24959ddd9324 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -27,6 +27,7 @@
27#include <linux/mfd/core.h> 27#include <linux/mfd/core.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <asm/olpc.h>
30 31
31#define DRV_NAME "cs5535-mfd" 32#define DRV_NAME "cs5535-mfd"
32 33
@@ -111,6 +112,22 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
111 }, 112 },
112}; 113};
113 114
115#ifdef CONFIG_OLPC
116static void __devinit cs5535_clone_olpc_cells(void)
117{
118 const char *acpi_clones[] = { "olpc-xo1-acpi" };
119 const char *pms_clones[] = { "olpc-xo1-pms" };
120
121 if (!machine_is_olpc())
122 return;
123
124 mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones));
125 mfd_clone_cell("cs5535-pms", pms_clones, ARRAY_SIZE(pms_clones));
126}
127#else
128static void cs5535_clone_olpc_cells(void) { }
129#endif
130
114static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, 131static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
115 const struct pci_device_id *id) 132 const struct pci_device_id *id)
116{ 133{
@@ -139,6 +156,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
139 dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); 156 dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
140 goto err_disable; 157 goto err_disable;
141 } 158 }
159 cs5535_clone_olpc_cells();
142 160
143 dev_info(&pdev->dev, "%zu devices registered.\n", 161 dev_info(&pdev->dev, "%zu devices registered.\n",
144 ARRAY_SIZE(cs5535_mfd_cells)); 162 ARRAY_SIZE(cs5535_mfd_cells));
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 79eda0264fb2..d01574d98870 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -184,16 +184,12 @@ void mfd_remove_devices(struct device *parent)
184} 184}
185EXPORT_SYMBOL(mfd_remove_devices); 185EXPORT_SYMBOL(mfd_remove_devices);
186 186
187static int add_shared_platform_device(const char *cell, const char *name) 187int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
188{ 188{
189 struct mfd_cell cell_entry; 189 struct mfd_cell cell_entry;
190 struct device *dev; 190 struct device *dev;
191 struct platform_device *pdev; 191 struct platform_device *pdev;
192 int err; 192 int i;
193
194 /* check if we've already registered a device (don't fail if we have) */
195 if (bus_find_device_by_name(&platform_bus_type, NULL, name))
196 return 0;
197 193
198 /* fetch the parent cell's device (should already be registered!) */ 194 /* fetch the parent cell's device (should already be registered!) */
199 dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); 195 dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
@@ -206,44 +202,17 @@ static int add_shared_platform_device(const char *cell, const char *name)
206 202
207 WARN_ON(!cell_entry.enable); 203 WARN_ON(!cell_entry.enable);
208 204
209 cell_entry.name = name; 205 for (i = 0; i < n_clones; i++) {
210 err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0); 206 cell_entry.name = clones[i];
211 if (err) 207 /* don't give up if a single call fails; just report error */
212 dev_err(dev, "MFD add devices failed: %d\n", err); 208 if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
213 return err; 209 dev_err(dev, "failed to create platform device '%s'\n",
214} 210 clones[i]);
215 211 }
216int mfd_shared_platform_driver_register(struct platform_driver *drv,
217 const char *cellname)
218{
219 int err;
220
221 err = add_shared_platform_device(cellname, drv->driver.name);
222 if (err)
223 printk(KERN_ERR "failed to add platform device %s\n",
224 drv->driver.name);
225
226 err = platform_driver_register(drv);
227 if (err)
228 printk(KERN_ERR "failed to add platform driver %s\n",
229 drv->driver.name);
230
231 return err;
232}
233EXPORT_SYMBOL(mfd_shared_platform_driver_register);
234
235void mfd_shared_platform_driver_unregister(struct platform_driver *drv)
236{
237 struct device *dev;
238
239 dev = bus_find_device_by_name(&platform_bus_type, NULL,
240 drv->driver.name);
241 if (dev)
242 platform_device_unregister(to_platform_device(dev));
243 212
244 platform_driver_unregister(drv); 213 return 0;
245} 214}
246EXPORT_SYMBOL(mfd_shared_platform_driver_unregister); 215EXPORT_SYMBOL(mfd_clone_cell);
247 216
248MODULE_LICENSE("GPL"); 217MODULE_LICENSE("GPL");
249MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); 218MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");