Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7f9d63e authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman
Browse files

musb: otg timer cleanup



Minor cleanup of OTG timer handling:
    * unify decls for OTG time constants, in the core header
    * set up and use that timer in a more normal way
    * move to the driver struct, so it's usable outside core

And tighten use and setup of T(a_wait_bcon) so that if it's used,
it's always valid.  (If that timer expires, the A-device will
stop powering VBUS.  For non-OTG systems, that will be a surprise.)
No behavioral changes, other than more consistency when applying
that core HNP timeout.

Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 84e250ff
Loading
Loading
Loading
Loading
+22 −19
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@
#include "davinci.h"
#endif

#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)


unsigned musb_debug;
@@ -287,12 +288,6 @@ const char *otg_state_string(struct musb *musb)

#ifdef	CONFIG_USB_MUSB_OTG

/*
 * See also USB_OTG_1-3.pdf 6.6.5 Timers
 * REVISIT: Are the other timers done in the hardware?
 */
#define TB_ASE0_BRST		100	/* Min 3.125 ms */

/*
 * Handles OTG hnp timeouts, such as b_ase0_brst
 */
@@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data)
	spin_unlock_irqrestore(&musb->lock, flags);
}

static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0);

/*
 * Stops the B-device HNP state. Caller must take care of locking.
 * Stops the HNP transition. Caller must take care of locking.
 */
void musb_hnp_stop(struct musb *musb)
{
@@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
				musb_g_reset(musb);
				/* FALLTHROUGH */
			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
				DBG(1, "HNP: Setting timer as %s\n",
						otg_state_string(musb));
				musb_otg_timer.data = (unsigned long)musb;
				mod_timer(&musb_otg_timer, jiffies
					+ msecs_to_jiffies(100));
				/* never use invalid T(a_wait_bcon) */
				DBG(1, "HNP: in %s, %d msec timeout\n",
						otg_state_string(musb),
						TA_WAIT_BCON(musb));
				mod_timer(&musb->otg_timer, jiffies
					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
				break;
			case OTG_STATE_A_PERIPHERAL:
				musb_hnp_stop(musb);
@@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
#ifdef	CONFIG_USB_MUSB_OTG
				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
				DBG(1, "HNP: Setting timer for b_ase0_brst\n");
				musb_otg_timer.data = (unsigned long)musb;
				mod_timer(&musb_otg_timer, jiffies
					+ msecs_to_jiffies(TB_ASE0_BRST));
				mod_timer(&musb->otg_timer, jiffies
					+ msecs_to_jiffies(
							OTG_TIME_B_ASE0_BRST));
#endif
			}
			break;
@@ -1681,7 +1675,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
	}

	spin_lock_irqsave(&musb->lock, flags);
	musb->a_wait_bcon = val;
	/* force T(a_wait_bcon) to be zero/unlimited *OR* valid */
	musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ;
	if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
		musb->is_active = 0;
	musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
@@ -1700,10 +1695,13 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)

	spin_lock_irqsave(&musb->lock, flags);
	val = musb->a_wait_bcon;
	/* FIXME get_vbus_status() is normally #defined as false...
	 * and is effectively TUSB-specific.
	 */
	vbus = musb_platform_get_vbus_status(musb);
	spin_unlock_irqrestore(&musb->lock, flags);

	return sprintf(buf, "Vbus %s, timeout %lu\n",
	return sprintf(buf, "Vbus %s, timeout %lu msec\n",
			vbus ? "on" : "off", val);
}
static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
@@ -1776,6 +1774,7 @@ allocate_instance(struct device *dev,
	hcd->uses_new_polling = 1;

	musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
	musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
#else
	musb = kzalloc(sizeof *musb, GFP_KERNEL);
	if (!musb)
@@ -1970,6 +1969,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
	if (status < 0)
		goto fail2;

#ifdef CONFIG_USB_OTG
	setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
#endif

	/* Init IRQ workqueue before request_irq */
	INIT_WORK(&musb->irq_work, musb_irq_work);

+11 −3
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/usb/ch9.h>
@@ -180,10 +181,15 @@ enum musb_g_ep0_state {
	MUSB_EP0_STAGE_ACKWAIT,		/* after zlp, before statusin */
} __attribute__ ((packed));

/* OTG protocol constants */
/*
 * OTG protocol constants.  See USB OTG 1.3 spec,
 * sections 5.5 "Device Timings" and 6.6.5 "Timers".
 */
#define OTG_TIME_A_WAIT_VRISE	100		/* msec (max) */
#define OTG_TIME_A_WAIT_BCON	0		/* 0=infinite; min 1000 msec */
#define OTG_TIME_A_IDLE_BDIS	200		/* msec (min) */
#define OTG_TIME_A_WAIT_BCON	1100		/* min 1 second */
#define OTG_TIME_A_AIDL_BDIS	200		/* min 200 msec */
#define OTG_TIME_B_ASE0_BRST	100		/* min 3.125 ms */


/*************************** REGISTER ACCESS ********************************/

@@ -332,6 +338,8 @@ struct musb {
	struct list_head	control;	/* of musb_qh */
	struct list_head	in_bulk;	/* of musb_qh */
	struct list_head	out_bulk;	/* of musb_qh */

	struct timer_list	otg_timer;
#endif

	/* called with IRQs blocked; ON/nonzero implies starting a session,
+0 −2
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@
#define	get_cpu_rev()	2
#endif

#define MUSB_TIMEOUT_A_WAIT_BCON	1100

static struct timer_list musb_idle_timer;

@@ -245,7 +244,6 @@ int __init musb_platform_init(struct musb *musb)

	if (is_host_enabled(musb))
		musb->board_set_vbus = omap_set_vbus;
	musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);