Skip to content

Commit fa1df69

Browse files
dilingerSamuel Ortiz
authored andcommitted
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 <[email protected]> Signed-off-by: Samuel Ortiz <[email protected]>
1 parent 16c29da commit fa1df69

File tree

4 files changed

+52
-57
lines changed

4 files changed

+52
-57
lines changed

arch/x86/platform/olpc/olpc-xo1.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,21 @@ static int __init olpc_xo1_init(void)
121121
{
122122
int r;
123123

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

128-
r = mfd_shared_platform_driver_register(&cs5535_acpi_drv,
129-
"cs5535-acpi");
128+
r = platform_driver_register(&cs5535_acpi_drv);
130129
if (r)
131-
mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
130+
platform_driver_unregister(&cs5535_pms_drv);
132131

133132
return r;
134133
}
135134

136135
static void __exit olpc_xo1_exit(void)
137136
{
138-
mfd_shared_platform_driver_unregister(&cs5535_acpi_drv);
139-
mfd_shared_platform_driver_unregister(&cs5535_pms_drv);
137+
platform_driver_unregister(&cs5535_acpi_drv);
138+
platform_driver_unregister(&cs5535_pms_drv);
140139
}
141140

142141
MODULE_AUTHOR("Daniel Drake <[email protected]>");

drivers/mfd/cs5535-mfd.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/mfd/core.h>
2828
#include <linux/module.h>
2929
#include <linux/pci.h>
30+
#include <asm/olpc.h>
3031

3132
#define DRV_NAME "cs5535-mfd"
3233

@@ -111,6 +112,22 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
111112
},
112113
};
113114

115+
#ifdef CONFIG_OLPC
116+
static 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
128+
static void cs5535_clone_olpc_cells(void) { }
129+
#endif
130+
114131
static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
115132
const struct pci_device_id *id)
116133
{
@@ -139,6 +156,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
139156
dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
140157
goto err_disable;
141158
}
159+
cs5535_clone_olpc_cells();
142160

143161
dev_info(&pdev->dev, "%zu devices registered.\n",
144162
ARRAY_SIZE(cs5535_mfd_cells));

drivers/mfd/mfd-core.c

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,12 @@ void mfd_remove_devices(struct device *parent)
184184
}
185185
EXPORT_SYMBOL(mfd_remove_devices);
186186

187-
static int add_shared_platform_device(const char *cell, const char *name)
187+
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
188188
{
189189
struct mfd_cell cell_entry;
190190
struct device *dev;
191191
struct platform_device *pdev;
192-
int err;
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;
192+
int i;
197193

198194
/* fetch the parent cell's device (should already be registered!) */
199195
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)
206202

207203
WARN_ON(!cell_entry.enable);
208204

209-
cell_entry.name = name;
210-
err = mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0);
211-
if (err)
212-
dev_err(dev, "MFD add devices failed: %d\n", err);
213-
return err;
214-
}
215-
216-
int 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-
}
233-
EXPORT_SYMBOL(mfd_shared_platform_driver_register);
234-
235-
void 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));
205+
for (i = 0; i < n_clones; i++) {
206+
cell_entry.name = clones[i];
207+
/* don't give up if a single call fails; just report error */
208+
if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
209+
dev_err(dev, "failed to create platform device '%s'\n",
210+
clones[i]);
211+
}
243212

244-
platform_driver_unregister(drv);
213+
return 0;
245214
}
246-
EXPORT_SYMBOL(mfd_shared_platform_driver_unregister);
215+
EXPORT_SYMBOL(mfd_clone_cell);
247216

248217
MODULE_LICENSE("GPL");
249218
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");

include/linux/mfd/core.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@ struct mfd_cell {
6262
extern int mfd_cell_enable(struct platform_device *pdev);
6363
extern int mfd_cell_disable(struct platform_device *pdev);
6464

65+
/*
66+
* "Clone" multiple platform devices for a single cell. This is to be used
67+
* for devices that have multiple users of a cell. For example, if an mfd
68+
* driver wants the cell "foo" to be used by a GPIO driver, an MTD driver,
69+
* and a platform driver, the following bit of code would be use after first
70+
* calling mfd_add_devices():
71+
*
72+
* const char *fclones[] = { "foo-gpio", "foo-mtd" };
73+
* err = mfd_clone_cells("foo", fclones, ARRAY_SIZE(fclones));
74+
*
75+
* Each driver (MTD, GPIO, and platform driver) would then register
76+
* platform_drivers for "foo-mtd", "foo-gpio", and "foo", respectively.
77+
* The cell's .enable/.disable hooks should be used to deal with hardware
78+
* resource contention.
79+
*/
80+
extern int mfd_clone_cell(const char *cell, const char **clones,
81+
size_t n_clones);
82+
6583
/*
6684
* Given a platform device that's been created by mfd_add_devices(), fetch
6785
* the mfd_cell that created it.
@@ -87,13 +105,4 @@ extern int mfd_add_devices(struct device *parent, int id,
87105

88106
extern void mfd_remove_devices(struct device *parent);
89107

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

0 commit comments

Comments
 (0)