mfd-core: add mfd_clone_cell(), convert cs5535-mfd/olpc-xo1 to it
Subsystems (2)
PATCH 1/1 mfd-core: 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.
--- arch/x86/platform/olpc/olpc-xo1.c | 11 +++---- drivers/mfd/cs5535-mfd.c | 18 ++++++++++++ drivers/mfd/mfd-core.c | 53 +++++++----------------------------- include/linux/mfd/core.h | 27 ++++++++++++------ 4 files changed, 52 insertions(+), 57 deletions(-)
arch/x86/platform/olpc/olpc-xo1.c +5 -6
@@ -121,22 +121,21 @@ static int __init olpc_xo1_init(void) {int r; - r =mfd_shared_platform_driver_register (&cs5535_pms_drv,"cs5535-pms" ); + r =platform_driver_register (&cs5535_pms_drv);if (r)return r; - r =mfd_shared_platform_driver_register (&cs5535_acpi_drv, -"cs5535-acpi" ); + r =platform_driver_register (&cs5535_acpi_drv);if (r) -mfd_shared_platform_driver_unregister (&cs5535_pms_drv); +platform_driver_unregister (&cs5535_pms_drv);return r; } static void __exit olpc_xo1_exit(void) { -mfd_shared_platform_driver_unregister (&cs5535_acpi_drv); -mfd_shared_platform_driver_unregister (&cs5535_pms_drv); +platform_driver_unregister (&cs5535_acpi_drv); +platform_driver_unregister (&cs5535_pms_drv); }MODULE_AUTHOR ("Daniel Drake <[email protected]>" );
drivers/mfd/cs5535-mfd.c +18 -0
@@ -27,6 +27,7 @@#include <linux/mfd/core.h> #include <linux/module.h> #include <linux/pci.h> +#include <asm/olpc.h> #define DRV_NAME "cs5535-mfd"
@@ -111,6 +112,22 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = { }, }; +#ifdef CONFIG_OLPC +static void __devinit cs5535_clone_olpc_cells (void ) +{ +const char *acpi_clones[] = {"olpc-xo1-acpi" }; +const char *pms_clones[] = {"olpc-xo1-pms" }; + +if (!machine_is_olpc ()) +return ; + +mfd_clone_cell ("cs5535-acpi" , acpi_clones,ARRAY_SIZE (acpi_clones)); +mfd_clone_cell ("cs5535-pms" , pms_clones,ARRAY_SIZE (pms_clones)); +} +#else +static void cs5535_clone_olpc_cells (void ) { } +#endif +static int __devinit cs5535_mfd_probe (struct pci_dev *pdev,const struct pci_device_id *id) {
@@ -139,6 +156,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,dev_err (&pdev->dev,"MFD add devices failed: %d\n" , err); goto err_disable; } +cs5535_clone_olpc_cells ();dev_info (&pdev->dev,"%zu devices registered.\n" ,ARRAY_SIZE (cs5535_mfd_cells));
drivers/mfd/mfd-core.c +11 -42
71 lines not on this page · raw message
include/linux/mfd/core.h +18 -9
@@ -63,6 +63,24 @@ extern int mfd_cell_enable(struct platform_device *pdev);extern int mfd_cell_disable (struct platform_device *pdev);/* +* "Clone" multiple platform devices for a single cell. This is to be used +* for devices that have multiple users of a cell. For example, if an mfd +* driver wants the cell "foo" to be used by a GPIO driver, an MTD driver, +* and a platform driver, the following bit of code would be use after first +* calling mfd_add_devices(): +* +* const char *fclones[] = { "foo-gpio", "foo-mtd" }; +* err = mfd_clone_cells("foo", fclones, ARRAY_SIZE(fclones)); +* +* Each driver (MTD, GPIO, and platform driver) would then register +* platform_drivers for "foo-mtd", "foo-gpio", and "foo", respectively. +* The cell's .enable/.disable hooks should be used to deal with hardware +* resource contention. +*/ +extern int mfd_clone_cell (const char *cell,const char **clones, +size_t n_clones); + +/* * Given a platform device that's been created by mfd_add_devices(), fetch * the mfd_cell that created it. */
@@ -87,13 +105,4 @@ 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
Signature · 1 line
1.7.2.5
PATCH 1/1 mfd: OLPC: clean up names to match what OLPC actually uses
From: Daniel Drake <[email protected]>
The cs5535-pms cell doesn't actually need to be cloned, so we can drop that and simply have the olpc-xo1.c driver use "cs5535-pms" directly.
Also, rename the cs5535-acpi clones to what we actually use for the (currently out-of-tree) SCI driver. In the process, that fixes a subtle bug in olpc-xo1.c which broke powerdown on XO-1s.. olpc-xo1-ac-acpi was a typo, not something that actually existed.
---
This is on top of my prior mfd_clone_cell patch. I'll leave it up to Samuel to determine if it should be merged with it, or separate.
arch/x86/platform/olpc/olpc-xo1.c | 12 ++++++------ drivers/mfd/cs5535-mfd.c | 4 +--- 2 files changed, 7 insertions(+), 9 deletions(-)
arch/x86/platform/olpc/olpc-xo1.c +6 -6
@@ -72,9 +72,9 @@ static int __devinit olpc_xo1_probe(struct platform_device *pdev)dev_err (&pdev->dev,"can't fetch device resource info\n" );return -EIO ; } -if (strcmp (pdev->name,"olpc-xo1-pms" ) ==0 ) +if (strcmp (pdev->name,"cs5535-pms" ) ==0 ) pms_base = res->start; -else if (strcmp (pdev->name,"olpc-xo1-ac-acpi" ) ==0 ) +else if (strcmp (pdev->name,"olpc-xo1-pm-acpi" ) ==0 ) acpi_base = res->start;/* If we have both addresses, we can override the poweroff hook */
@@ -90,9 +90,9 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev) {mfd_cell_disable (pdev); -if (strcmp (pdev->name,"olpc-xo1-pms" ) ==0 ) +if (strcmp (pdev->name,"cs5535-pms" ) ==0 ) pms_base =0 ; -else if (strcmp (pdev->name,"olpc-xo1-acpi" ) ==0 ) +else if (strcmp (pdev->name,"olpc-xo1-pm-acpi" ) ==0 ) acpi_base =0 ; pm_power_off =NULL ;
@@ -101,7 +101,7 @@ static int __devexit olpc_xo1_remove(struct platform_device *pdev)static struct platform_driver cs5535_pms_drv = { .driver = { - .name ="olpc-xo1-pms" , + .name ="cs5535-pms" , .owner =THIS_MODULE , }, .probe = olpc_xo1_probe,
@@ -110,7 +110,7 @@ static struct platform_driver cs5535_pms_drv = {static struct platform_driver cs5535_acpi_drv = { .driver = { - .name ="olpc-xo1-acpi" , + .name ="olpc-xo1-pm-acpi" , .owner =THIS_MODULE , }, .probe = olpc_xo1_probe,
drivers/mfd/cs5535-mfd.c +1 -3
@@ -115,14 +115,12 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {#ifdef CONFIG_OLPC static void __devinit cs5535_clone_olpc_cells (void ) { -const char *acpi_clones[] = {"olpc-xo1-acpi" }; -const char *pms_clones[] = {"olpc-xo1-pms" }; +const char *acpi_clones[] = {"olpc-xo1-pm-acpi" ,"olpc-xo1-sci-acpi" };if (!machine_is_olpc ())return ;mfd_clone_cell ("cs5535-acpi" , acpi_clones,ARRAY_SIZE (acpi_clones)); -mfd_clone_cell ("cs5535-pms" , pms_clones,ARRAY_SIZE (pms_clones)); }#else static void cs5535_clone_olpc_cells (void ) { }