diff options
Diffstat (limited to 'drivers/sdio/stack/platform/sdioplatformdriver.c')
-rw-r--r-- | drivers/sdio/stack/platform/sdioplatformdriver.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/drivers/sdio/stack/platform/sdioplatformdriver.c b/drivers/sdio/stack/platform/sdioplatformdriver.c new file mode 100644 index 00000000000..d5520fc2908 --- /dev/null +++ b/drivers/sdio/stack/platform/sdioplatformdriver.c @@ -0,0 +1,300 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +@file: sdioplatformdriver.c + +@abstract: Linux implementation module for SDIO pltaform driver + +#notes: + +@notice: Copyright (c), 2006 Atheros Communications, Inc. + +@license: This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Portions of this code were developed with information supplied from the + * SD Card Association Simplified Specifications. The following conditions and disclaimers may apply: + * + * The following conditions apply to the release of the SD simplified specification (�Simplified + * Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete + * SD Specification which is owned by the SD Card Association. This Simplified Specification is provided + * on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified + * Specification may require a license from the SD Card Association or other third parties. + * Disclaimers: + * The information contained in the Simplified Specification is presented only as a standard + * specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any + * representations or warranties of any kind. No responsibility is assumed by the SD Card Association for + * any damages, any infringements of patents or other right of the SD Card Association or any third + * parties, which may result from its use. No license is granted by implication, estoppel or otherwise + * under any patent or other rights of the SD Card Association or any third party. Nothing herein shall + * be construed as an obligation by the SD Card Association to disclose or distribute any technical + * information, know-how or other confidential information to any third party. + * + * + * The initial developers of the original code are Seung Yi and Paul Lever + * + * sdio@atheros.com + * + * + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#define DESCRIPTION "SDIO Platform Driver" +#define AUTHOR "Atheros Communications, Inc." + +//??for .h + +struct sdioplatform_peripheral { + struct list_head node; + struct sdioplatform_controller *controller; + struct device dev; +}; +struct sdioplatform_driver { + struct device_driver drv; + int (*probe)(struct sdioplatform_peripheral *); + void (*remove)(struct sdioplatform_peripheral *); + int (*suspend)(struct sdioplatform_peripheral *, pm_message_t); + int (*resume)(struct sdioplatform_peripheral *); +}; + + +struct sdioplatform_controller { + struct device *dev; +}; +struct sdioplatform_controller_driver { + struct device_driver drv; + int (*probe)(struct sdioplatform_controller *); + void (*remove)(struct sdioplatform_controller *); + int (*suspend)(struct sdioplatform_controller *, pm_message_t); + int (*resume)(struct sdioplatform_controller *); +}; + + + +#define device_to_sdioplatform_peripheral(d) container_of(d, struct sdioplatform_peripheral, dev) +#define driver_to_sdioplatform_driver(d) container_of(d, struct sdioplatform_driver, drv) + +#define device_to_sdioplatform_controller(d) container_of(d, struct sdioplatform_controller, dev) +#define driver_to_sdioplatform_controller_driver(d) container_of(d, struct sdioplatform_controller_driver, drv) + +#define SDIOPLATFORM_ATTR(name, fmt, args...) \ +static ssize_t sdio_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); \ + return sprintf(buf, fmt, args); \ +} + +SDIOPLATFORM_ATTR(bus_id, "%s\n", bus_id); +#define SDIOPLATFORM_ATTR_RO(name) __ATTR(name, S_IRUGO, sdioplatform_##name##_show, NULL) + +static struct device_attribute sdioplatform_dev_attrs[] = { + SDIOPLATFORM_ATTR_RO(bus_id), + __ATTR_NULL +}; + +static struct bus_type sdioplatform_bus_type = { + .name = "sdioplatform", + .dev_attrs = sdioplatform_dev_attrs, + .match = sdioplatform_bus_match, + .hotplug = NULL, + .suspend = sdioplatform_bus_suspend, + .resume = sdioplatform_bus_resume, +}; + + +/* controller functions */ +static int sdioplatform_controllerdrv_probe(struct device *dev) +{ + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); + + return drv->probe(controller); +} + +static int sdioplatform_controllerdrv_remove(struct device *dev) +{ + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); + + return drv->remove(controller); +} + +/* + * sdioplatform_register_controller_driver - register a controller driver + */ +int sdioplatform_register_controller_driver(struct sdioplatform_controller_driver *drv) +{ + drv->drv.bus = &sdioplatform_bus_type; + drv->drv.probe = sdioplatform_controllerdrv_probe; + drv->drv.remove = sdioplatform_controllerdrv_remove; + return driver_register(&drv->drv); +} + +/* + * sdioplatform_unregister_controller_driver - unregister a controller driver + */ +void sdioplatform_unregister_controller_driver(struct sdioplatform_driver *drv) +{ + driver_unregister(&drv->drv); +} + +/* + * sdioplatform_add_controller - register a controller device + */ +int sdioplatform_add_controller(char *name, struct sdioplatform_controller *dev) +{ + if (!dev) { + return -EINVAL; + } + strncpy(dev->dev.bus_id, BUS_ID_SIZE, name); + return device_register(&dev->dev); +} + +/* + * sdioplatform_remove_controller - unregister a controller device + */ +int sdioplatform_remove_controller(char *name, struct sdioplatform_controller *dev) +{ + if (!dev) { + return -EINVAL; + } + return device_unregister(&dev->dev); +} + +/* peripheral functions */ +static int sdioplatform_drv_probe(struct device *dev) +{ + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); + + return drv->probe(peripheral); +} + +static int sdioplatform_controllerdrv_remove(struct device *dev) +{ + struct sdioplatform_controller_driver *drv = driver_to_sdioplatform_controller_driver(dev->driver); + struct sdioplatform_controller *controller = device_to_sdioplatform_controller(dev); + + return drv->remove(controller); +} + +/* + * sdioplatform_register_driver - register a driver + */ +int sdioplatform_register_driver(struct sdioplatform_driver *drv) +{ + drv->drv.bus = &sdioplatform_bus_type; + drv->drv.probe = sdioplatform_drv_probe; + drv->drv.remove = sdioplatform_drv_remove; + return driver_register(&drv->drv); +} + +/* + * sdioplatform_unregister_driver - unregister a driver + */ +void sdioplatform_unregister_driver(struct sdioplatform_driver *drv) +{ + driver_unregister(&drv->drv); +} + +/* + * sdioplatform_add_peripheral - register a peripheral device + */ +int sdioplatform_add_peripheral(char *name, struct sdioplatform_peripheral *dev) +{ + if (!dev) { + return -EINVAL; + } + strncpy(dev->dev.bus_id, BUS_ID_SIZE, name); + return device_register(&dev->dev); +} + +/* + * sdioplatform_remove_peripheral - unregister a peripheral device + */ +int sdioplatform_remove_peripheral(char *name, struct sdioplatform_peripheral *dev) +{ + if (!dev) { + return -EINVAL; + } + return device_unregister(&dev->dev); +} + + + + + +static int sdioplatform_bus_match(struct device *dev, struct device_driver *drv) +{ + /* probes handle the matching */ + return 1; +} + +static int sdioplatform_bus_suspend(struct device *dev, pm_message_t state) +{ + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); + int ret = 0; + + if (peripheral->driver && drv->suspend) { + ret = drv->suspend(peripheral, state); + } + return ret; +} + +static int sdioplatform_bus_resume(struct device *dev) +{ + struct sdioplatform_driver *drv = driver_to_sdioplatform_driver(dev->driver); + struct sdioplatform_peripheral *peripheral = device_to_sdioplatform_peripheral(dev); + int ret = 0; + + if (peripheral->driver && drv->resume) { + ret = drv->resume(card); + } + return ret; +} + +/* + * module init +*/ +static int __init sdio_platformdriver_init(void) { + int ret = bus_register(&sdioplatform_bus_type); + return ret; +} + +/* + * module cleanup +*/ +static void __exit sdio_platformdriver_cleanup(void) { + REL_PRINT(SDDBG_TRACE, ("SDIO unloaded\n")); + _SDIO_BusDriverCleanup(); +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DESCRIPTION); +MODULE_AUTHOR(AUTHOR); + +module_init(sdio_platformdriver_init); +module_exit(sdio_platformdriver_cleanup); +EXPORT_SYMBOL(sdioplatform_register_controller_driver); +EXPORT_SYMBOL(sdioplatform_unregister_controller_driver); +EXPORT_SYMBOL(sdioplatform_add_controller); +EXPORT_SYMBOL(sdioplatform_remove_controller); +EXPORT_SYMBOL(sdioplatform_register_driver); +EXPORT_SYMBOL(sdioplatform_unregister_driver); +EXPORT_SYMBOL(sdioplatform_add_peripheral); +EXPORT_SYMBOL(sdioplatform_remove_peripheral); + + + |