diff options
Diffstat (limited to 'drivers/omap_hsi/hsi_driver_bus.c')
-rw-r--r-- | drivers/omap_hsi/hsi_driver_bus.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/drivers/omap_hsi/hsi_driver_bus.c b/drivers/omap_hsi/hsi_driver_bus.c new file mode 100644 index 0000000..4bce43d --- /dev/null +++ b/drivers/omap_hsi/hsi_driver_bus.c @@ -0,0 +1,203 @@ +/* + * hsi_driver_bus.c + * + * Implements an HSI bus, device and driver interface. + * + * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved. + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Author: Carlos Chinea <carlos.chinea@nokia.com> + * Author: Sebastien JAN <s-jan@ti.com> + * + * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <linux/device.h> +#include "hsi_driver.h" + +#define HSI_PREFIX "hsi:" + +struct bus_type hsi_bus_type; + +static ssize_t modalias_show(struct device *dev, struct device_attribute *a, + char *buf) +{ + return snprintf(buf, PAGE_SIZE + 1, "%s%s\n", HSI_PREFIX, + dev_name(dev)); +} + +static struct device_attribute hsi_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + add_uevent_var(env, "MODALIAS=%s%s", HSI_PREFIX, dev_name(dev)); + return 0; +} + +static int hsi_bus_match(struct device *device, struct device_driver *driver) +{ + struct hsi_device *dev = to_hsi_device(device); + struct hsi_device_driver *drv = to_hsi_device_driver(driver); + + pr_debug("HSI DRIVER BUS : hsi_bus_match for ctrl:%d, port:%d, ch%d\n", + dev->n_ctrl, dev->n_p, dev->n_ch); + + if (!test_bit(dev->n_ctrl, &drv->ctrl_mask)) + return 0; + + if (!test_bit(dev->n_ch, &drv->ch_mask[dev->n_p])) + return 0; + + pr_info + ("HSI DRIVER BUS : hsi_bus_match SUCCESS : ctrl:%d (mask:%x)," + " port:%d, ch:%d (mask:%x)\n", + dev->n_ctrl, (u32) drv->ctrl_mask, dev->n_p, dev->n_ch, + (u32) drv->ch_mask[dev->n_p]); + + return 1; +} + +int hsi_bus_unreg_dev(struct device *device, void *p) +{ + device->release(device); + device_unregister(device); + + return 0; +} + +int __init hsi_bus_init(void) +{ + return bus_register(&hsi_bus_type); +} + +void hsi_bus_exit(void) +{ + bus_for_each_dev(&hsi_bus_type, NULL, NULL, hsi_bus_unreg_dev); + bus_unregister(&hsi_bus_type); +} + +static int hsi_bus_probe(struct device *dev) +{ + struct hsi_device_driver *drv; + int rc; + + pr_debug("HSI DRIVER BUS : hsi_bus_probe\n"); + + if (!dev->driver) + return 0; + + drv = to_hsi_device_driver(dev->driver); + + if (!drv->probe) + return -ENODEV; + + rc = drv->probe(to_hsi_device(dev)); + + return rc; +} + +static int hsi_bus_remove(struct device *dev) +{ + struct hsi_device_driver *drv; + int ret; + + pr_debug("HSI DRIVER BUS : hsi_bus_remove\n"); + + if (!dev->driver) + return 0; + + drv = to_hsi_device_driver(dev->driver); + if (drv->remove) { + ret = drv->remove(to_hsi_device(dev)); + } else { + dev->driver = NULL; + ret = 0; + } + + return ret; +} + +static int hsi_bus_suspend(struct device *dev, pm_message_t mesg) +{ + struct hsi_device_driver *drv; + + if (!dev->driver) + return 0; + + drv = to_hsi_device_driver(dev->driver); + if (!drv->suspend) + return 0; + + return drv->suspend(to_hsi_device(dev), mesg); +} + +static int hsi_bus_resume(struct device *dev) +{ + struct hsi_device_driver *drv; + + if (!dev->driver) + return 0; + + drv = to_hsi_device_driver(dev->driver); + if (!drv->resume) + return 0; + + return drv->resume(to_hsi_device(dev)); +} + +struct bus_type hsi_bus_type = { + .name = "hsi", + .dev_attrs = hsi_dev_attrs, + .match = hsi_bus_match, + .uevent = hsi_bus_uevent, + .probe = hsi_bus_probe, + .remove = hsi_bus_remove, + .suspend = hsi_bus_suspend, + .resume = hsi_bus_resume, +}; + +/** + * hsi_register_driver - Register HSI device driver + * @driver - reference to the HSI device driver. + */ +int hsi_register_driver(struct hsi_device_driver *driver) +{ + int ret = 0; + + if (driver == NULL) + return -EINVAL; + + driver->driver.bus = &hsi_bus_type; + + ret = driver_register(&driver->driver); + + if (ret == 0) + pr_debug("hsi: driver %s registered\n", driver->driver.name); + + return ret; +} +EXPORT_SYMBOL(hsi_register_driver); + +/** + * hsi_unregister_driver - Unregister HSI device driver + * @driver - reference to the HSI device driver. + */ +void hsi_unregister_driver(struct hsi_device_driver *driver) +{ + if (driver == NULL) + return; + + driver_unregister(&driver->driver); + + pr_debug("hsi: driver %s unregistered\n", driver->driver.name); +} +EXPORT_SYMBOL(hsi_unregister_driver); |