Make sti a bus driver so sti-netlink and sti-console can
register to it.

Signed-off-by: Felipe Balbi <[email protected]>
---
 arch/arm/plat-omap/include/mach/sti.h |   57 +++++++++++
 drivers/misc/sti/sdti.c               |  178 ++++++++++++++++++++++++++++++++-
 2 files changed, 234 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/include/mach/sti.h 
b/arch/arm/plat-omap/include/mach/sti.h
index f4cbd8f..da7ca49 100644
--- a/arch/arm/plat-omap/include/mach/sti.h
+++ b/arch/arm/plat-omap/include/mach/sti.h
@@ -1,8 +1,65 @@
 #ifndef __ASM_ARCH_OMAP_STI_H
 #define __ASM_ARCH_OMAP_STI_H
 
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pm.h>
 #include <asm/io.h>
 
+/* -------------------------------------------------------------------------- 
*/
+
+extern struct bus_type sti_bus_type;
+
+#define STI_NAME_SIZE  20
+
+struct sti_client;
+
+struct sti_driver {
+       int id;
+       unsigned int class;
+       char name[STI_NAME_SIZE];
+
+       int (*probe)(struct sti_client *);
+       int (*remove)(struct sti_client *);
+       void (*shutdown)(struct sti_client *);
+       int (*suspend)(struct sti_client *, pm_message_t mesg);
+       int (*resume)(struct sti_client *);
+
+       struct device_driver driver;
+       struct list_head clients;
+};
+#define to_sti_driver(d) container_of(d, struct sti_driver, driver)
+
+struct sti_client {
+       unsigned short flags;           /* div., see below              */
+       char name[STI_NAME_SIZE];
+       struct sti_driver *driver;      /* and our access routines      */
+       struct device dev;              /* the device structure         */
+       int irq;                        /* irq issued by device         */
+};
+#define to_sti_client(d) container_of(d, struct sti_client, dev)
+
+#define STI_CLIENT_WAKE                BIT(0)
+
+static inline void sti_set_clientdata(struct sti_client *client, void *data)
+{
+       dev_set_drvdata(&client->dev, data);
+}
+
+static inline void *sti_get_clientdata(const struct sti_client *client)
+{
+       return dev_get_drvdata(&client->dev);
+}
+
+extern int sti_register_driver(struct module *, struct sti_driver *);
+
+static inline int sti_add_driver(struct sti_driver *driver)
+{
+       return sti_register_driver(THIS_MODULE, driver);
+}
+
+/* -------------------------------------------------------------------------- 
*/
+
 /*
  * STI/SDTI
  */
diff --git a/drivers/misc/sti/sdti.c b/drivers/misc/sti/sdti.c
index 4f4fcef..7563a67 100644
--- a/drivers/misc/sti/sdti.c
+++ b/drivers/misc/sti/sdti.c
@@ -270,6 +270,173 @@ fail1:
        return ret;
 }
 
+#define STI_MODULE_PREFIX      "sti:"
+
+static ssize_t sti_name_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct sti_client       *client = to_sti_client(dev);
+       return sprintf(buf, "%s\n", client->name);
+}
+
+static ssize_t sti_modalias_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct sti_client       *client = to_sti_client(dev);
+       return sprintf(buf, "%s%s\n", STI_MODULE_PREFIX, client->name);
+}
+
+static struct device_attribute sti_dev_attrs[] = {
+       __ATTR(name, S_IRUGO, sti_name_show, NULL),
+       __ATTR(modalias, S_IRUGO, sti_modalias_show, NULL),
+       __ATTR_NULL,
+};
+
+static int sti_dev_match(struct device *dev, struct device_driver *drv)
+{
+       struct sti_client               *client = to_sti_client(dev);
+       struct sti_driver               *driver = to_sti_driver(drv);
+
+       return !strcmp(client->name, driver->driver.name);
+}
+
+static int sti_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct sti_client               *client = to_sti_client(dev);
+
+       dev_dbg(dev, "uevent\n");
+
+       if (add_uevent_var(env, "MODALIAS=%s%s", STI_MODULE_PREFIX,
+                               client->name))
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int sti_dev_probe(struct device *dev)
+{
+       struct sti_driver               *driver = to_sti_driver(dev->driver);
+       struct sti_client               *client = to_sti_client(dev);
+       int                             status;
+
+       dev_dbg(dev, "probe\n");
+
+       if (!driver->probe)
+               return -ENODEV;
+
+       client->driver = driver;
+       if (!device_can_wakeup(&client->dev))
+               device_init_wakeup(&client->dev,
+                               client->flags & STI_CLIENT_WAKE);
+
+       status = driver->probe(client);
+       if (status)
+               client->driver = NULL;
+
+       return status;
+}
+
+static int sti_dev_remove(struct device *dev)
+{
+       struct sti_client               *client = to_sti_client(dev);
+       struct sti_driver               *driver;
+       int                             status;
+
+       dev_dbg(dev, "remove\n");
+
+       if (!dev->driver)
+               return 0;
+
+       driver = to_sti_driver(dev->driver);
+       if (driver->remove) {
+               status = driver->remove(client);
+       } else {
+               dev->driver = NULL;
+               status = 0;
+       }
+
+       if (status == 0)
+               client->driver = NULL;
+
+       return status;
+}
+
+static void sti_dev_shutdown(struct device *dev)
+{
+       struct sti_driver               *driver;
+
+       dev_dbg(dev, "shutdown\n");
+
+       if (dev->driver)
+               return;
+
+       driver = to_sti_driver(dev->driver);
+       if (driver->shutdown)
+               driver->shutdown(to_sti_client(dev));
+}
+
+static int sti_dev_suspend(struct device *dev, pm_message_t msg)
+{
+       struct sti_driver               *driver;
+
+       if (!dev->driver)
+               return 0;
+
+       driver = to_sti_driver(dev->driver);
+
+       if (!driver->suspend)
+               return 0;
+
+       return driver->suspend(to_sti_client(dev), msg);
+}
+
+static int sti_dev_resume(struct device *dev)
+{
+       struct sti_driver               *driver;
+
+       if (!dev->driver)
+               return 0;
+
+       driver = to_sti_driver(dev->driver);
+
+       if (!driver->resume)
+               return 0;
+
+       return driver->resume(to_sti_client(dev));
+}
+
+struct bus_type sti_bus_type = {
+       .name           = "sti",
+       .dev_attrs      = sti_dev_attrs,
+       .match          = sti_dev_match,
+       .uevent         = sti_dev_uevent,
+       .probe          = sti_dev_probe,
+       .remove         = sti_dev_remove,
+       .shutdown       = sti_dev_shutdown,
+       .suspend        = sti_dev_suspend,
+       .resume         = sti_dev_resume,
+};
+EXPORT_SYMBOL_GPL(sti_bus_type);
+
+int sti_register_driver(struct module *owner, struct sti_driver *driver)
+{
+       int                     status;
+
+       driver->driver.owner = owner;
+       driver->driver.bus = &sti_bus_type;
+
+       status = driver_register(&driver->driver);
+       if (status)
+               return status;
+
+       pr_debug("sti: driver [%s] registered\n", driver->driver.name);
+
+       INIT_LIST_HEAD(&driver->clients);
+
+       return 0;
+}
+EXPORT_SYMBOL(sti_register_driver);
+
 static int __devexit omap_sdti_remove(struct platform_device *pdev)
 {
        struct sti *sti = platform_get_drvdata(pdev);
@@ -294,15 +461,24 @@ static struct platform_driver omap_sdti_driver = {
 
 static int __init omap_sdti_module_init(void)
 {
+       int                     status;
+
+       status = bus_register(&sti_bus_type);
+       if (status)
+               return status;
+
        return platform_driver_register(&omap_sdti_driver);
 }
+subsys_initcall(omap_sdti_module_init);
 
 static void __exit omap_sdti_module_exit(void)
 {
        platform_driver_unregister(&omap_sdti_driver);
+       bus_unregister(&sti_bus_type);
 }
-subsys_initcall(omap_sdti_module_init);
 module_exit(omap_sdti_module_exit);
 
 MODULE_AUTHOR("Roman Tereshonkov");
+MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
+
-- 
1.6.3.1.244.gf9275

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to