]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/musb/omap2430.c
usb: musb: omap: write directly to mailbox instead of using phy
[~andy/linux] / drivers / usb / musb / omap2430.c
index 02c39a72b27e3bae66fac6bf12dd1ce71f6b8122..f4d95037db5d352a1c6381a55cc0c9f07ddccff4 100644 (file)
@@ -45,6 +45,7 @@ struct omap2430_glue {
        struct platform_device  *musb;
        enum omap_musb_vbus_id_status status;
        struct work_struct      omap_musb_mailbox_work;
+       u32 __iomem             *control_otghs;
 };
 #define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
@@ -52,6 +53,26 @@ struct omap2430_glue         *_glue;
 
 static struct timer_list musb_idle_timer;
 
+/**
+ * omap4_usb_phy_mailbox - write to usb otg mailbox
+ * @glue: struct omap2430_glue *
+ * @val: the value to be written to the mailbox
+ *
+ * On detection of a device (ID pin is grounded), this API should be called
+ * to set AVALID, VBUSVALID and ID pin is grounded.
+ *
+ * When OMAP is connected to a host (OMAP in device mode), this API
+ * is called to set AVALID, VBUSVALID and ID pin in high impedance.
+ *
+ * XXX: This function will be removed once we have a seperate driver for
+ * control module
+ */
+static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
+{
+       if (glue->control_otghs)
+               writel(val, glue->control_otghs);
+}
+
 static void musb_do_idle(unsigned long _musb)
 {
        struct musb     *musb = (void *)_musb;
@@ -247,6 +268,7 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox);
 
 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
+       u32 val;
        struct musb *musb = glue_to_musb(glue);
        struct device *dev = musb->controller;
        struct musb_hdrc_platform_data *pdata = dev->platform_data;
@@ -262,7 +284,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                musb->xceiv->last_event = USB_EVENT_ID;
                if (musb->gadget_driver) {
                        pm_runtime_get_sync(dev);
-                       usb_phy_init(musb->xceiv);
+                       val = AVALID | VBUSVALID;
+                       omap4_usb_phy_mailbox(glue, val);
                        omap2430_musb_set_vbus(musb, 1);
                }
                break;
@@ -275,7 +298,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                musb->xceiv->last_event = USB_EVENT_VBUS;
                if (musb->gadget_driver)
                        pm_runtime_get_sync(dev);
-               usb_phy_init(musb->xceiv);
+               val = IDDIG | AVALID | VBUSVALID;
+               omap4_usb_phy_mailbox(glue, val);
                break;
 
        case OMAP_MUSB_ID_FLOAT:
@@ -292,7 +316,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                        if (musb->xceiv->otg->set_vbus)
                                otg_set_vbus(musb->xceiv->otg, 0);
                }
-               usb_phy_shutdown(musb->xceiv);
+               val = SESSEND | IDDIG;
+               omap4_usb_phy_mailbox(glue, val);
                break;
        default:
                dev_dbg(dev, "ID float\n");
@@ -367,6 +392,7 @@ err1:
 static void omap2430_musb_enable(struct musb *musb)
 {
        u8              devctl;
+       u32             val;
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
@@ -376,7 +402,8 @@ static void omap2430_musb_enable(struct musb *musb)
        switch (glue->status) {
 
        case OMAP_MUSB_ID_GROUND:
-               usb_phy_init(musb->xceiv);
+               val = AVALID | VBUSVALID;
+               omap4_usb_phy_mailbox(glue, val);
                if (data->interface_type != MUSB_INTERFACE_UTMI)
                        break;
                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -395,7 +422,8 @@ static void omap2430_musb_enable(struct musb *musb)
                break;
 
        case OMAP_MUSB_VBUS_VALID:
-               usb_phy_init(musb->xceiv);
+               val = IDDIG | AVALID | VBUSVALID;
+               omap4_usb_phy_mailbox(glue, val);
                break;
 
        default:
@@ -405,11 +433,14 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
+       u32 val;
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
-       if (glue->status != OMAP_MUSB_UNKNOWN)
-               usb_phy_shutdown(musb->xceiv);
+       if (glue->status != OMAP_MUSB_UNKNOWN) {
+               val = SESSEND | IDDIG;
+               omap4_usb_phy_mailbox(glue, val);
+       }
 }
 
 static int omap2430_musb_exit(struct musb *musb)
@@ -441,6 +472,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
        struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;
        struct platform_device          *musb;
        struct omap2430_glue            *glue;
+       struct resource                 *res;
        int                             ret = -ENOMEM;
 
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
@@ -463,6 +495,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
        glue->musb                      = musb;
        glue->status                    = OMAP_MUSB_UNKNOWN;
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+       glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
+       if (glue->control_otghs == NULL)
+               dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
+
        pdata->platform_ops             = &omap2430_ops;
 
        platform_set_drvdata(pdev, glue);