diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-05 15:18:00 -0700 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-05 15:18:00 -0700 | 
| commit | 64dc9e2e7320f079b97c46b106133b58b8e18d40 (patch) | |
| tree | ab010dc1337d44e29c2b32b7f11788620a91fe4f /drivers/usb/musb/ux500.c | |
| parent | 01a60e76b6392547ad3dca3ac05b9c886fa5da45 (diff) | |
| parent | 9b192de60b5a584ee4ed967fb6758773c75e4643 (diff) | |
| download | olio-linux-3.10-64dc9e2e7320f079b97c46b106133b58b8e18d40.tar.xz olio-linux-3.10-64dc9e2e7320f079b97c46b106133b58b8e18d40.zip  | |
Merge tag 'usb-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
usb: patches for v3.10 merge window
Here is the big Gadget & PHY pull request. Many of us have
been really busy lately getting multiple drivers to a better
position.
Since this pull request is so large, I will divide it in sections
so it's easier to grasp what's included.
- cleanups:
	. UDC drivers no longer touch gadget->dev, that's now udc-core
		responsibility
	. Many more UDC drivers converted to usb_gadget_map/unmap_request()
	. UDC drivers no longer initialize DMA-related fields from gadget's
		device structure
	. UDC drivers don't touch gadget.dev.driver directly
	. UDC drivers don't assign gadget.dev.release directly
	. Removal of some unused DMA_ADDR_INVALID
	. Introduction of CONFIG_USB_PHY
	. All phy drivers have been moved to drivers/usb/phy and renamed to
		a common naming scheme
	. Fix PHY layer so it never returns a NULL pointer, also fix all
		callers to avoid using IS_ERR_OR_NULL()
	. Sparse fixes all over the place
	. drivers/usb/otg/ has been deleted
	. Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock
		usage
- new features:
	. UDC core now provides a generic way for tracking and reporting
		UDC's state (not attached, resuming, suspended, addressed,
		default, etc)
	. twl4030-usb learned that it shouldn't be enabled during init
	. Full DT support for DWC3 has been implemented
	. ab8500-usb learned about pinctrl framework
	. nop PHY learned about DeviceTree and regulators
	. DWC3 learned about suspend/resume
	. DWC3 can now be compiled in host-only and gadget-only (as well as
		DRD) configurations
	. UVC now enables streaming endpoint based on negotiated speed
	. isp1301 now implements the PHY API properly
	. configfs-based interface for gadget drivers which will lead to
		the removal of all code which just combines functions together
		to build functional gadget drivers.
	. f_serial and f_obex were converted to new configfs interface while
		maintaining old interface around.
- non-critical fixes:
	. UVC gadget driver got fixes for Endpoint usage and stream calculation
	. ab8500-usb fixed unbalanced clock and regulator API usage
	. twl4030-usb got a fix for when OMAP3 is booted with cable connected
	. fusb300_udc got a fix for DMA usage
	. UVC got fixes for two assertions of the USB Video Class Compliance
		specification revision 1.1
	. build warning issues caused by recent addition of __must_check to
		regulator API
These are all changes which deserve a mention, all other changes are related
to these one or minor spelling fixes and other similar tasks.
Signed-of-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/ux500.c')
| -rw-r--r-- | drivers/usb/musb/ux500.c | 106 | 
1 files changed, 106 insertions, 0 deletions
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 13a39291376..2c80004e0a8 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -26,6 +26,7 @@  #include <linux/err.h>  #include <linux/io.h>  #include <linux/platform_device.h> +#include <linux/usb/musb-ux500.h>  #include "musb_core.h" @@ -36,6 +37,98 @@ struct ux500_glue {  };  #define glue_to_musb(g)	platform_get_drvdata(g->musb) +static void ux500_musb_set_vbus(struct musb *musb, int is_on) +{ +	u8            devctl; +	unsigned long timeout = jiffies + msecs_to_jiffies(1000); +	/* HDRC controls CPEN, but beware current surges during device +	 * connect.  They can trigger transient overcurrent conditions +	 * that must be ignored. +	 */ + +	devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + +	if (is_on) { +		if (musb->xceiv->state == OTG_STATE_A_IDLE) { +			/* start the session */ +			devctl |= MUSB_DEVCTL_SESSION; +			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); +			/* +			 * Wait for the musb to set as A device to enable the +			 * VBUS +			 */ +			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { + +				if (time_after(jiffies, timeout)) { +					dev_err(musb->controller, +					"configured as A device timeout"); +					break; +				} +			} + +		} else { +			musb->is_active = 1; +			musb->xceiv->otg->default_a = 1; +			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; +			devctl |= MUSB_DEVCTL_SESSION; +			MUSB_HST_MODE(musb); +		} +	} else { +		musb->is_active = 0; + +		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping +		 * right to B_IDLE... +		 */ +		musb->xceiv->otg->default_a = 0; +		devctl &= ~MUSB_DEVCTL_SESSION; +		MUSB_DEV_MODE(musb); +	} +	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + +	/* +	 * Devctl values will be updated after vbus goes below +	 * session_valid. The time taken depends on the capacitance +	 * on VBUS line. The max discharge time can be upto 1 sec +	 * as per the spec. Typically on our platform, it is 200ms +	 */ +	if (!is_on) +		mdelay(200); + +	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", +		usb_otg_state_string(musb->xceiv->state), +		musb_readb(musb->mregs, MUSB_DEVCTL)); +} + +static int musb_otg_notifications(struct notifier_block *nb, +		unsigned long event, void *unused) +{ +	struct musb *musb = container_of(nb, struct musb, nb); + +	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n", +			event, usb_otg_state_string(musb->xceiv->state)); + +	switch (event) { +	case UX500_MUSB_ID: +		dev_dbg(musb->controller, "ID GND\n"); +		ux500_musb_set_vbus(musb, 1); +		break; +	case UX500_MUSB_VBUS: +		dev_dbg(musb->controller, "VBUS Connect\n"); +		break; +	case UX500_MUSB_NONE: +		dev_dbg(musb->controller, "VBUS Disconnect\n"); +		if (is_host_active(musb)) +			ux500_musb_set_vbus(musb, 0); +		else +			musb->xceiv->state = OTG_STATE_B_IDLE; +		break; +	default: +		dev_dbg(musb->controller, "ID float\n"); +		return NOTIFY_DONE; +	} +	return NOTIFY_OK; +} +  static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)  {  	unsigned long   flags; @@ -58,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)  static int ux500_musb_init(struct musb *musb)  { +	int status; +  	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);  	if (IS_ERR_OR_NULL(musb->xceiv)) {  		pr_err("HS USB OTG: no transceiver configured\n");  		return -EPROBE_DEFER;  	} +	musb->nb.notifier_call = musb_otg_notifications; +	status = usb_register_notifier(musb->xceiv, &musb->nb); +	if (status < 0) { +		dev_dbg(musb->controller, "notification register failed\n"); +		return status; +	} +  	musb->isr = ux500_musb_interrupt;  	return 0; @@ -71,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)  static int ux500_musb_exit(struct musb *musb)  { +	usb_unregister_notifier(musb->xceiv, &musb->nb); +  	usb_put_phy(musb->xceiv);  	return 0; @@ -79,6 +183,8 @@ static int ux500_musb_exit(struct musb *musb)  static const struct musb_platform_ops ux500_ops = {  	.init		= ux500_musb_init,  	.exit		= ux500_musb_exit, + +	.set_vbus	= ux500_musb_set_vbus,  };  static int ux500_probe(struct platform_device *pdev)  |