[RFC/PATCH 5/5] usb: musb: musb supports otg notifier

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.balbi@xxxxxxxxx>
---
 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux