we use the notifier to kick the charger detection.
Needed on RX-51 board. Later on we will notify
also the bMaxPower field from usb_configuration.

Signed-off-by: Felipe Balbi <felipe.ba...@nokia.com>
---
 drivers/usb/musb/musb_core.c |   72 ++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/musb/musb_core.h |    5 +++
 2 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 55e185a..c7c60df 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -98,6 +98,7 @@
 #include <linux/kobject.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/notifier.h>
 
 #ifdef CONFIG_ARM
 #include <mach/hardware.h>
@@ -144,6 +145,74 @@ MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
 
 /*-------------------------------------------------------------------------*/
 
+#include "isp1704.h"
+
+static int musb_detect_charger(struct musb *musb)
+{
+       unsigned long           timeout;
+       u8                      vdat = 0;
+       u8                      power;
+       u8                      r;
+
+       /* first we disable data pullups */
+       power = musb_readb(musb->mregs, MUSB_POWER);
+       power &= ~MUSB_POWER_SOFTCONN;
+       musb_writeb(musb->mregs, MUSB_POWER, power);
+
+       /* now we set SW control bit in PWR_CTRL register */
+       r = musb_ulpi_readb(musb->mregs, ISP1704_PWR_CTRL);
+       r |= ISP1704_PWR_CTRL_SWCTRL;
+       musb_ulpi_writeb(musb->mregs, ISP1704_PWR_CTRL, r);
+
+       /* and finally enable manual charger detection */
+       r |= ISP1704_PWR_CTRL_DPVSRC_EN;
+       musb_ulpi_writeb(musb->mregs, ISP1704_PWR_CTRL, r);
+       msleep(10);
+
+       timeout = jiffies + msecs_to_jiffies(300);
+       while (!time_after(jiffies, timeout)) {
+               /* Check if there is a charger */
+               vdat = !!(musb_ulpi_readb(musb->mregs, ISP1704_PWR_CTRL)
+                               & ISP1704_PWR_CTRL_VDAT_DET);
+               if (vdat)
+                       break;
+       }
+
+       /* clear DPVSRC_EN, otherwise usb communication doesn't work */
+       r &= ~ISP1704_PWR_CTRL_DPVSRC_EN;
+       musb_ulpi_writeb(musb->mregs, ISP1704_PWR_CTRL, r);
+
+       if (vdat)
+               blocking_notifier_call_chain(&musb->xceiv->notifier,
+                               USB_EVENT_CHARGER, &musb->g);
+
+       /*
+        * re-enable data pullups, we might have been connected
+        * to a host/hub charger
+        */
+       power |= MUSB_POWER_SOFTCONN;
+       musb_writeb(musb->mregs, MUSB_POWER, power);
+
+       return vdat;
+}
+
+static int musb_notifier_call(struct notifier_block *nb, unsigned long event,
+               void *_gadget)
+{
+       struct usb_gadget       *g = _gadget;
+       struct musb             *musb = container_of(g, struct musb, g);
+
+       switch (event) {
+       case USB_EVENT_VBUS:
+               musb->is_charger = musb_detect_charger(musb);
+               break;
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
+}
+
 static inline struct musb *dev_to_musb(struct device *dev)
 {
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
@@ -1961,6 +2030,9 @@ bad_config:
                goto fail2;
        }
 
+       musb->nb.notifier_call = musb_notifier_call;
+       otg_register_notifier(musb->xceiv, &musb->nb);
+
 #ifndef CONFIG_MUSB_PIO_ONLY
        if (use_dma && dev->dma_mask) {
                struct dma_controller   *c;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 644fcd8..3de6eb8 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -322,6 +322,9 @@ struct musb {
        struct clk              *clock;
        irqreturn_t             (*isr)(int, void *);
        struct work_struct      irq_work;
+
+       struct notifier_block   nb;
+
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
 #define MUSB_HWVERS_MINOR(x)   (x & 0x3ff)
 #define MUSB_HWVERS_RC         0x8000
@@ -432,6 +435,8 @@ struct musb {
        unsigned                is_self_powered:1;
        unsigned                is_bus_powered:1;
 
+       unsigned                is_charger:1;
+
        unsigned                set_address:1;
        unsigned                test_mode:1;
        unsigned                softconnect:1;
-- 
1.6.6.rc0

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

Reply via email to