aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/omap_hsi/hsi_driver_bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/omap_hsi/hsi_driver_bus.c')
-rw-r--r--drivers/omap_hsi/hsi_driver_bus.c203
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);