omap-otg platform device will be needed also by other transceivers.
It's not possible to have multiple instances of the driver, so it needs
to be moved into a separate file so that other drivers can hook into it.

Start this change with a very simplest implementation, much of the
OMAP OTG code in isp1301 is tightly coupled with isp1301 and cannot be
trivially moved out, but still this provides a way for other drivers to
register to OTG interrupt.

Signed-off-by: Aaro Koskinen <[email protected]>
---
 drivers/usb/otg/Kconfig        |    5 ++
 drivers/usb/otg/Makefile       |    1 +
 drivers/usb/otg/isp1301_omap.c |   78 ++-----------------------------
 drivers/usb/otg/omap-otg.c     |   99 ++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/omap-otg.h   |   30 ++++++++++++
 5 files changed, 138 insertions(+), 75 deletions(-)
 create mode 100644 drivers/usb/otg/omap-otg.c
 create mode 100644 include/linux/usb/omap-otg.h

diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 37962c9..12af870 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -27,9 +27,14 @@ config USB_GPIO_VBUS
          optionally control of a D+ pullup GPIO as well as a VBUS
          current limit regulator.
 
+config OMAP_OTG
+       tristate
+       depends on ARCH_OMAP_OTG
+
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
        depends on I2C && ARCH_OMAP_OTG
+       select OMAP_OTG if USB_OTG
        select USB_OTG_UTILS
        help
          If you say yes here you get support for the Philips ISP1301
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index a844b8d..4e05c6a 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_OTG_UTILS)   += otg.o
 
 # transceiver drivers
 obj-$(CONFIG_USB_GPIO_VBUS)    += gpio_vbus.o
+obj-$(CONFIG_OMAP_OTG)         += omap-otg.o
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)      += twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)      += twl6030-usb.o
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index af9cb11..5217b7e 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -28,6 +28,7 @@
 #include <linux/gpio.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/omap-otg.h>
 #include <linux/usb.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c.h>
@@ -74,22 +75,6 @@ struct isp1301 {
 #              define WORK_STOP        7       /* don't resubmit */
 };
 
-
-/* bits in OTG_CTRL */
-
-#define        OTG_XCEIV_OUTPUTS \
-       (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
-#define        OTG_XCEIV_INPUTS \
-       (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
-#define        OTG_CTRL_BITS \
-       (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
-       /* and OTG_PULLUP is sometimes written */
-
-#define        OTG_CTRL_MASK   (OTG_DRIVER_SEL| \
-       OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
-       OTG_CTRL_BITS)
-
-
 /*-------------------------------------------------------------------------*/
 
 /* board-specific PM hooks */
@@ -822,15 +807,10 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
        return ret;
 }
 
-static struct platform_device *otg_dev;
-
 static int isp1301_otg_init(struct isp1301 *isp)
 {
        u32 l;
 
-       if (!otg_dev)
-               return -ENODEV;
-
        dump_regs(isp, __func__);
        /* some of these values are board-specific... */
        l = omap_readl(OTG_SYSCON_2);
@@ -864,58 +844,6 @@ static int isp1301_otg_init(struct isp1301 *isp)
        return 0;
 }
 
-static int otg_probe(struct platform_device *dev)
-{
-       // struct omap_usb_config *config = dev->platform_data;
-
-       otg_dev = dev;
-       return 0;
-}
-
-static int otg_remove(struct platform_device *dev)
-{
-       otg_dev = NULL;
-       return 0;
-}
-
-static struct platform_driver omap_otg_driver = {
-       .probe          = otg_probe,
-       .remove         = otg_remove,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "omap_otg",
-       },
-};
-
-static int otg_bind(struct isp1301 *isp)
-{
-       int     status;
-
-       if (otg_dev)
-               return -EBUSY;
-
-       status = platform_driver_register(&omap_otg_driver);
-       if (status < 0)
-               return status;
-
-       if (otg_dev)
-               status = request_irq(otg_dev->resource[1].start, omap_otg_irq,
-                               0, DRIVER_NAME, isp);
-       else
-               status = -ENODEV;
-
-       if (status < 0)
-               platform_driver_unregister(&omap_otg_driver);
-       return status;
-}
-
-static void otg_unbind(struct isp1301 *isp)
-{
-       if (!otg_dev)
-               return;
-       free_irq(otg_dev->resource[1].start, isp);
-}
-
 #else
 
 /* OTG controller isn't clocked */
@@ -1222,7 +1150,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c)
        isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
        free_irq(i2c->irq, isp);
 #ifdef CONFIG_USB_OTG
-       otg_unbind(isp);
+       omap_otg_unbind(isp);
 #endif
        if (machine_is_omap_h2())
                gpio_free(2);
@@ -1555,7 +1483,7 @@ isp1301_probe(struct i2c_client *i2c, const struct 
i2c_device_id *id)
        isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
 
 #ifdef CONFIG_USB_OTG
-       status = otg_bind(isp);
+       status = omap_otg_bind(isp, omap_otg_irq);
        if (status < 0) {
                dev_dbg(&i2c->dev, "can't bind OTG\n");
                goto fail;
diff --git a/drivers/usb/otg/omap-otg.c b/drivers/usb/otg/omap-otg.c
new file mode 100644
index 0000000..12e8f13
--- /dev/null
+++ b/drivers/usb/otg/omap-otg.c
@@ -0,0 +1,99 @@
+/*
+ * OMAP OTG driver
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/usb/omap-otg.h>
+#include <linux/platform_device.h>
+
+static void *omap_otg_user;
+static DEFINE_MUTEX(omap_otg_lock);
+static struct platform_device *omap_otg_dev;
+
+static int omap_otg_probe(struct platform_device *dev)
+{
+       int ret;
+
+       mutex_lock(&omap_otg_lock);
+       if (omap_otg_dev) {
+               ret = -EBUSY;
+       } else {
+               omap_otg_dev = dev;
+               ret = 0;
+       }
+       mutex_unlock(&omap_otg_lock);
+
+       return ret;
+}
+
+static int omap_otg_remove(struct platform_device *dev)
+{
+       int ret;
+
+       mutex_lock(&omap_otg_lock);
+       if (omap_otg_user) {
+               ret = -EBUSY;
+       } else {
+               omap_otg_dev = NULL;
+               ret = 0;
+       }
+       mutex_unlock(&omap_otg_lock);
+
+       return ret;
+}
+
+int omap_otg_bind(void *transceiver, irq_handler_t irq_handler)
+{
+       int ret;
+
+       mutex_lock(&omap_otg_lock);
+       if (!omap_otg_dev) {
+               ret = -EPROBE_DEFER;
+       } else if (omap_otg_user) {
+               ret = -EBUSY;
+       } else {
+               ret = request_irq(omap_otg_dev->resource[1].start, irq_handler,
+                                 0, "OMAP OTG", transceiver);
+               if (!ret)
+                       omap_otg_user = transceiver;
+       }
+       mutex_unlock(&omap_otg_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(omap_otg_bind);
+
+void omap_otg_unbind(void *transceiver)
+{
+       mutex_lock(&omap_otg_lock);
+       BUG_ON(!omap_otg_dev || !omap_otg_user || omap_otg_user != transceiver);
+       free_irq(omap_otg_dev->resource[1].start, transceiver);
+       omap_otg_user = NULL;
+       mutex_unlock(&omap_otg_lock);
+}
+EXPORT_SYMBOL_GPL(omap_otg_unbind);
+
+static struct platform_driver omap_otg_driver = {
+       .probe          = omap_otg_probe,
+       .remove         = omap_otg_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "omap_otg",
+       },
+};
+module_platform_driver(omap_otg_driver);
diff --git a/include/linux/usb/omap-otg.h b/include/linux/usb/omap-otg.h
new file mode 100644
index 0000000..efc1cb3
--- /dev/null
+++ b/include/linux/usb/omap-otg.h
@@ -0,0 +1,30 @@
+/*
+ * OMAP OTG driver
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* bits in OTG_CTRL */
+#define OTG_XCEIV_OUTPUTS \
+       (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
+#define OTG_XCEIV_INPUTS \
+       (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
+#define OTG_CTRL_BITS \
+       (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
+       /* and OTG_PULLUP is sometimes written */
+#define OTG_CTRL_MASK \
+       (OTG_DRIVER_SEL|OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS|OTG_CTRL_BITS)
+
+int omap_otg_bind(void *, irq_handler_t);
+void omap_otg_unbind(void *);
-- 
1.7.10.4

--
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