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

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
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
#include "davinci.h" #include "davinci.h"
#endif #endif
#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
unsigned musb_debug; unsigned musb_debug;
...@@ -287,12 +288,6 @@ const char *otg_state_string(struct musb *musb) ...@@ -287,12 +288,6 @@ const char *otg_state_string(struct musb *musb)
#ifdef CONFIG_USB_MUSB_OTG #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 * Handles OTG hnp timeouts, such as b_ase0_brst
*/ */
...@@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data) ...@@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data)
spin_unlock_irqrestore(&musb->lock, flags); 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) void musb_hnp_stop(struct musb *musb)
{ {
...@@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb_g_reset(musb); musb_g_reset(musb);
/* FALLTHROUGH */ /* FALLTHROUGH */
case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
DBG(1, "HNP: Setting timer as %s\n", /* never use invalid T(a_wait_bcon) */
otg_state_string(musb)); DBG(1, "HNP: in %s, %d msec timeout\n",
musb_otg_timer.data = (unsigned long)musb; otg_state_string(musb),
mod_timer(&musb_otg_timer, jiffies TA_WAIT_BCON(musb));
+ msecs_to_jiffies(100)); mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
break; break;
case OTG_STATE_A_PERIPHERAL: case OTG_STATE_A_PERIPHERAL:
musb_hnp_stop(musb); musb_hnp_stop(musb);
...@@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, ...@@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
#ifdef CONFIG_USB_MUSB_OTG #ifdef CONFIG_USB_MUSB_OTG
musb->xceiv->state = OTG_STATE_B_WAIT_ACON; musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
DBG(1, "HNP: Setting timer for b_ase0_brst\n"); DBG(1, "HNP: Setting timer for b_ase0_brst\n");
musb_otg_timer.data = (unsigned long)musb; mod_timer(&musb->otg_timer, jiffies
mod_timer(&musb_otg_timer, jiffies + msecs_to_jiffies(
+ msecs_to_jiffies(TB_ASE0_BRST)); OTG_TIME_B_ASE0_BRST));
#endif #endif
} }
break; break;
...@@ -1681,7 +1675,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, ...@@ -1681,7 +1675,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
} }
spin_lock_irqsave(&musb->lock, flags); 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) if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
musb->is_active = 0; musb->is_active = 0;
musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); 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) ...@@ -1700,10 +1695,13 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
val = musb->a_wait_bcon; 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); vbus = musb_platform_get_vbus_status(musb);
spin_unlock_irqrestore(&musb->lock, flags); 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); vbus ? "on" : "off", val);
} }
static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
...@@ -1776,6 +1774,7 @@ allocate_instance(struct device *dev, ...@@ -1776,6 +1774,7 @@ allocate_instance(struct device *dev,
hcd->uses_new_polling = 1; hcd->uses_new_polling = 1;
musb->vbuserr_retry = VBUSERR_RETRY_COUNT; musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
#else #else
musb = kzalloc(sizeof *musb, GFP_KERNEL); musb = kzalloc(sizeof *musb, GFP_KERNEL);
if (!musb) if (!musb)
...@@ -1970,6 +1969,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -1970,6 +1969,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
if (status < 0) if (status < 0)
goto fail2; 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 IRQ workqueue before request_irq */
INIT_WORK(&musb->irq_work, musb_irq_work); INIT_WORK(&musb->irq_work, musb_irq_work);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/timer.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
...@@ -180,10 +181,15 @@ enum musb_g_ep0_state { ...@@ -180,10 +181,15 @@ enum musb_g_ep0_state {
MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */
} __attribute__ ((packed)); } __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_VRISE 100 /* msec (max) */
#define OTG_TIME_A_WAIT_BCON 0 /* 0=infinite; min 1000 msec */ #define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */
#define OTG_TIME_A_IDLE_BDIS 200 /* msec (min) */ #define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */
#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */
/*************************** REGISTER ACCESS ********************************/ /*************************** REGISTER ACCESS ********************************/
...@@ -332,6 +338,8 @@ struct musb { ...@@ -332,6 +338,8 @@ struct musb {
struct list_head control; /* of musb_qh */ struct list_head control; /* of musb_qh */
struct list_head in_bulk; /* of musb_qh */ struct list_head in_bulk; /* of musb_qh */
struct list_head out_bulk; /* of musb_qh */ struct list_head out_bulk; /* of musb_qh */
struct timer_list otg_timer;
#endif #endif
/* called with IRQs blocked; ON/nonzero implies starting a session, /* called with IRQs blocked; ON/nonzero implies starting a session,
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#define get_cpu_rev() 2 #define get_cpu_rev() 2
#endif #endif
#define MUSB_TIMEOUT_A_WAIT_BCON 1100
static struct timer_list musb_idle_timer; static struct timer_list musb_idle_timer;
...@@ -245,7 +244,6 @@ int __init musb_platform_init(struct musb *musb) ...@@ -245,7 +244,6 @@ int __init musb_platform_init(struct musb *musb)
if (is_host_enabled(musb)) if (is_host_enabled(musb))
musb->board_set_vbus = omap_set_vbus; 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); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment