From 0d79ef71f42089011d7069d8120c04812b3e2969 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 12 Sep 2006 14:46:20 +0300 Subject: [PATCH] MUSB: Miscellaneous updates Lots of miscellaneous updates: - bugfixes * flag hcd-framework "got irq" state earlier * reject urb submission if port is suspended * linkage fix: unbind became optional * initialize vbus error retry count earlier * tusb init removes diagnostic-only settings - procfs updates * always show otg state info in procfs * show some TUSB-specific registers in procfs - cleanups * remove pointless MUSB_ERR stuff (handled better now) * tusb init removes dead code * more informative vbus error debug message * comment fixes * etc Signed-off-by: David Brownell --- drivers/usb/musb/musb_gadget.c | 3 +-- drivers/usb/musb/musb_host.c | 6 +++-- drivers/usb/musb/musb_procfs.c | 31 ++++++++++++++------- drivers/usb/musb/musbdefs.h | 40 +++++++++------------------ drivers/usb/musb/otg.c | 3 +++ drivers/usb/musb/plat_uds.c | 49 +++++++++++++++++++--------------- drivers/usb/musb/tusb6010.c | 17 ------------ drivers/usb/musb/tusb6010.h | 4 +-- drivers/usb/musb/virthub.c | 3 +-- 9 files changed, 72 insertions(+), 84 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index df9d2245f1f..6aac44d3d22 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1708,7 +1708,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || driver->speed != USB_SPEED_HIGH || !driver->bind - || !driver->unbind || !driver->setup) return -EINVAL; @@ -1847,7 +1846,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) int retval = 0; struct musb *musb = the_gadget; - if (!driver || !musb) + if (!driver || !driver->unbind || !musb) return -EINVAL; /* REVISIT always use otg_set_peripheral() here too; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6cf568058d1..e7f22d048e6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1176,7 +1176,6 @@ irqreturn_t musb_h_ep0_irq(struct musb *pThis) if (bComplete) musb_advance_schedule(pThis, pUrb, pEnd, 1); done: - set_bit(HCD_FLAG_SAW_IRQ, &musb_to_hcd(pThis)->flags); return retval; } @@ -1812,7 +1811,7 @@ static int musb_urb_enqueue( unsigned interval; /* host role must be active */ - if (!is_host_active(musb)) + if (!is_host_active(musb) || !musb->is_active) return -ENODEV; /* DMA mapping was already done, if needed, and this urb is on @@ -2154,6 +2153,9 @@ static int musb_h_get_frame_number(struct usb_hcd *hcd) static int musb_h_start(struct usb_hcd *hcd) { + /* NOTE: musb_start() is called when the hub driver turns + * on port power, or when (OTG) peripheral starts. + */ hcd->state = HC_STATE_RUNNING; return 0; } diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c index eae8c5b9b70..7b687e34f7b 100644 --- a/drivers/usb/musb/musb_procfs.c +++ b/drivers/usb/musb/musb_procfs.c @@ -48,8 +48,6 @@ #include "davinci.h" -#ifdef CONFIG_USB_MUSB_OTG - static const char *state_string(enum usb_otg_state state) { switch (state) { @@ -70,8 +68,6 @@ static const char *state_string(enum usb_otg_state state) } } -#endif - #ifdef CONFIG_USB_MUSB_HDRC_HCD static int dump_qh(struct musb_qh *qh, char *buf, unsigned max) @@ -489,15 +485,12 @@ static int dump_header_stats(struct musb *pThis, char *buffer) return count; buffer += count; -#ifdef CONFIG_USB_MUSB_OTG - code = sprintf(buffer, "OTG state: %s (%s)\n", - state_string(pThis->OtgMachine.bState), - state_string(pThis->xceiv.state)); + code = sprintf(buffer, "OTG state: %s\n", + state_string(pThis->xceiv.state)); if (code < 0) return code; buffer += code; count += code; -#endif code = sprintf(buffer, "Options: " @@ -548,6 +541,26 @@ static int dump_header_stats(struct musb *pThis, char *buffer) buffer += code; #endif /* DAVINCI */ +#ifdef CONFIG_USB_TUSB6010 + code = sprintf(buffer, + "TUSB6010: devconf %08x, phy enable %08x drive %08x" + "\n\totg %08x timer %08x" + "\n\tprcm conf %08x mgmt %08x; intmask %08x" + "\n", + musb_readl(pThis->ctrl_base, TUSB_DEV_CONF), + musb_readl(pThis->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE), + musb_readl(pThis->ctrl_base, TUSB_PHY_OTG_CTRL), + musb_readl(pThis->ctrl_base, TUSB_DEV_OTG_STAT), + musb_readl(pThis->ctrl_base, TUSB_DEV_OTG_TIMER), + musb_readl(pThis->ctrl_base, TUSB_PRCM_CONF), + musb_readl(pThis->ctrl_base, TUSB_PRCM_MNGMT), + musb_readl(pThis->ctrl_base, TUSB_INT_MASK)); + if (code < 0) + return count; + count += code; + buffer += code; +#endif /* DAVINCI */ + #ifdef CONFIG_USB_TI_CPPI_DMA if (pThis->pDmaController) { code = sprintf(buffer, diff --git a/drivers/usb/musb/musbdefs.h b/drivers/usb/musb/musbdefs.h index 6ec73166fad..fe1803463a3 100644 --- a/drivers/usb/musb/musbdefs.h +++ b/drivers/usb/musb/musbdefs.h @@ -101,6 +101,7 @@ struct musb_ep; #define is_host_active(musb) is_host_capable() #endif + #ifdef CONFIG_PROC_FS #include #define MUSB_CONFIG_PROC_FS @@ -197,15 +198,10 @@ enum musb_g_ep0_state { MGC_END0_STAGE_ACKWAIT, /* after zlp, before statusin */ } __attribute__ ((packed)); -/* failure codes */ -#define MUSB_ERR_WAITING 1 -#define MUSB_ERR_VBUS -1 -#define MUSB_ERR_BABBLE -2 -#define MUSB_ERR_CORRUPTED -3 -#define MUSB_ERR_IRQ -4 -#define MUSB_ERR_SHUTDOWN -5 -#define MUSB_ERR_RESTART -6 - +/* OTG protocol constants */ +#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) */ /*************************** REGISTER ACCESS ********************************/ @@ -265,25 +261,15 @@ enum musb_g_ep0_state { /****************************** FUNCTIONS ********************************/ #define MUSB_HST_MODE(_pthis)\ - { (_pthis)->bIsHost=TRUE; (_pthis)->bIsDevice=FALSE; \ - (_pthis)->bFailCode=0; } + { (_pthis)->bIsHost=TRUE; (_pthis)->bIsDevice=FALSE; } #define MUSB_DEV_MODE(_pthis) \ - { (_pthis)->bIsHost=FALSE; (_pthis)->bIsDevice=TRUE; \ - (_pthis)->bFailCode=0; } + { (_pthis)->bIsHost=FALSE; (_pthis)->bIsDevice=TRUE; } #define MUSB_OTG_MODE(_pthis) \ - { (_pthis)->bIsHost=FALSE; (_pthis)->bIsDevice=FALSE; \ - (_pthis)->bFailCode=MUSB_ERR_WAITING; } -#define MUSB_ERR_MODE(_pthis, _cause) \ - { (_pthis)->bIsHost=FALSE; (_pthis)->bIsDevice=FALSE; \ - (_pthis)->bFailCode=_cause; } - -#define MUSB_IS_ERR(_x) ( (_x)->bFailCode<0 ) -#define MUSB_IS_HST(_x) (!MUSB_IS_ERR(_x) \ - && (_x)->bIsHost && !(_x)->bIsDevice ) -#define MUSB_IS_DEV(_x) (!MUSB_IS_ERR(_x) \ - && !(_x)->bIsHost && (_x)->bIsDevice ) -#define MUSB_IS_OTG(_x) (!MUSB_IS_ERR(_x) \ - && !(_x)->bIsHost && !(_x)->bIsDevice ) + { (_pthis)->bIsHost=FALSE; (_pthis)->bIsDevice=FALSE; } + +#define MUSB_IS_HST(_x) ((_x)->bIsHost && !(_x)->bIsDevice) +#define MUSB_IS_DEV(_x) (!(_x)->bIsHost && (_x)->bIsDevice) +#define MUSB_IS_OTG(_x) (!(_x)->bIsHost && !(_x)->bIsDevice) #define test_devctl_hst_mode(_x) \ (musb_readb((_x)->pRegs, MGC_O_HDRC_DEVCTL)&MGC_M_DEVCTL_HM) @@ -447,8 +433,6 @@ struct musb { u8 board_mode; /* enum musb_mode */ int (*board_set_power)(int state); - s8 bFailCode; /* one of MUSB_ERR_* failure code */ - u8 min_power; /* vbus for periph, in mA/2 */ /* active means connected and not suspended */ diff --git a/drivers/usb/musb/otg.c b/drivers/usb/musb/otg.c index 1be6259d6ca..576c0eecf23 100644 --- a/drivers/usb/musb/otg.c +++ b/drivers/usb/musb/otg.c @@ -42,6 +42,9 @@ * * - needs updating along the lines of * + * - TUSB has a hardware OTG timer, unclear how much of this would + * ever be needed for it ... + * * - doesn't yet use all the linux 2.6.10 usbcore hooks for OTG, but * some of the conversion (and consequent shrinkage) has begun. * diff --git a/drivers/usb/musb/plat_uds.c b/drivers/usb/musb/plat_uds.c index 2b081c3c4bc..97c6a03b804 100644 --- a/drivers/usb/musb/plat_uds.c +++ b/drivers/usb/musb/plat_uds.c @@ -89,14 +89,6 @@ * (And if it were to understand, there would still be limitations * because of the lack of periodic endpoint scheduling.) * - * - Host-side doesn't use the HCD framework, even the older version in - * the 2.6.10 kernel, which doesn't provide per-endpoint URB queues. - * - * +++ PARTIALLY RESOLVED +++ - * - * RESULT: code bloat, because it provides its own root hub; - * correctness issues. - * * - Provides its own OTG bits. These are untested, and many of them * seem to be superfluous code bloat given what usbcore does. (They * have now been partially removed.) @@ -444,9 +436,23 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB, if (bIntrUSB & MGC_M_INTR_VBUSERROR) { // MGC_OtgMachineInputsChanged(otgm, &Inputs); + // otg_input_changed_X(pThis, TRUE, TRUE); // ... may need to abort otg timer ... - DBG(1, "VBUS_ERROR (%02x)\n", devctl); + DBG(1, "VBUS_ERROR (%02x, %s), retry #%d\n", devctl, + ({ char *s; + switch (devctl & MGC_M_DEVCTL_VBUS) { + case 0 << MGC_S_DEVCTL_VBUS: + s = "vbuserr_retry); /* after hw goes to A_IDLE, try connecting again */ pThis->xceiv.state = OTG_STATE_A_IDLE; @@ -460,6 +466,7 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB, if (bIntrUSB & MGC_M_INTR_CONNECT) { handled = IRQ_HANDLED; pThis->is_active = 1; + set_bit(HCD_FLAG_SAW_IRQ, &musb_to_hcd(pThis)->flags); pThis->bEnd0Stage = MGC_END0_START; @@ -514,9 +521,12 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB, /* REVISIT it's unclear how to handle this. Mentor's * code stopped the whole USB host, which is clearly - * very wrong. For now, just expect the hardware is - * sane, so babbling devices also trigger a normal - * endpoint i/o fault (with automatic recovery). + * very wrong. Docs say (15.1) that babble ends the + * current sesssion, so shutdown _with restart_ would + * be appropriate ... except that seems to be wrong, + * at least some lowspeed enumerations trigger the + * babbles without aborting the session! + * * (A "babble" IRQ seems quite pointless...) */ @@ -658,10 +668,10 @@ void musb_start(struct musb * pThis) musb_writew(pBase, MGC_O_HDRC_INTRRXE, pThis->wEndMask & 0xfffe); musb_writeb(pBase, MGC_O_HDRC_INTRUSBE, 0xf7); - musb_platform_enable(pThis); - musb_writeb(pBase, MGC_O_HDRC_TESTMODE, 0); + musb_platform_enable(pThis); + /* enable high-speed/low-power and start session */ musb_writeb(pBase, MGC_O_HDRC_POWER, MGC_M_POWER_SOFTCONN | MGC_M_POWER_HSENAB); @@ -744,8 +754,9 @@ static void musb_shutdown(struct platform_device *pdev) spin_lock_irqsave(&musb->Lock, flags); musb_platform_disable(musb); musb_generic_disable(musb); - MUSB_ERR_MODE(musb, MUSB_ERR_SHUTDOWN); spin_unlock_irqrestore(&musb->Lock, flags); + + /* FIXME power down */ } @@ -1312,13 +1323,6 @@ irqreturn_t musb_interrupt(struct musb *musb) (devctl & MGC_M_DEVCTL_HM) ? "host" : "peripheral", musb->int_usb, musb->int_tx, musb->int_rx); - /* ignore requests when in error */ - if (MUSB_IS_ERR(musb)) { - WARN("irq in error\n"); - musb_platform_disable(musb); - return IRQ_NONE; - } - /* the core can interrupt us for multiple reasons; docs have * a generic interrupt flowchart to follow */ @@ -1534,6 +1538,7 @@ allocate_instance(struct device *dev, void __iomem *mbase) hcd->uses_new_polling = 1; + musb->vbuserr_retry = VBUSERR_RETRY_COUNT; #else musb = kzalloc(sizeof *musb, GFP_KERNEL); if (!musb) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 182711e09f5..3b087d2e8b8 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -463,7 +463,6 @@ static int dma_off; * Enables TUSB6010. Caller must take care of locking. * REVISIT: * - Check what is unnecessary in MGC_HdrcStart() - * - Interrupt should really be IRQT_FALLING level sensitive */ void musb_platform_enable(struct musb * musb) { @@ -612,25 +611,9 @@ static int tusb_start(struct musb *musb) musb_writel(base, TUSB_PRCM_MNGMT, TUSB_PRCM_MNGMT_VBUS_VALID_TIMER(0xa) | TUSB_PRCM_MNGMT_VBUS_VALID_FLT_EN | - TUSB_PRCM_MNGMT_DFT_CLK_DIS | - TUSB_PRCM_MNGMT_VLYNQ_CLK_DIS | TUSB_PRCM_MNGMT_OTG_SESS_END_EN | TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN | TUSB_PRCM_MNGMT_OTG_ID_PULLUP); -#if 0 - musb_writel(base, TUSB_PHY_OTG_CTRL_ENABLE, - musb_readl(base, TUSB_PHY_OTG_CTRL_ENABLE) | - TUSB_PHY_OTG_CTRL_WRPROTECT | - TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP | - TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN | - TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN); - musb_writel(base, TUSB_PHY_OTG_CTRL, - musb_readl(base, TUSB_PHY_OTG_CTRL) | - TUSB_PHY_OTG_CTRL_WRPROTECT | - TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP | - TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN | - TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN); -#endif tusb_setup_cpu_interface(musb); spin_unlock_irqrestore(&musb->Lock, flags); diff --git a/drivers/usb/musb/tusb6010.h b/drivers/usb/musb/tusb6010.h index cf30f89a00b..cf3b250f51b 100644 --- a/drivers/usb/musb/tusb6010.h +++ b/drivers/usb/musb/tusb6010.h @@ -80,6 +80,8 @@ #define TUSB_DEV_OTG_STAT_DM_ENABLE (1 << 0) #define TUSB_DEV_OTG_TIMER (TUSB_SYS_REG_BASE + 0x010) +# define TUSB_DEV_OTG_TIMER_ENABLE (1 << 31) +# define TUSB_DEV_OTG_TIMER_VAL(v) ((v) & 0x07ffffff) #define TUSB_PRCM_REV (TUSB_SYS_REG_BASE + 0x014) /* PRCM configuration register */ @@ -198,8 +200,6 @@ #define TUSB_PROD_TEST_RESET (TUSB_SYS_REG_BASE + 0x1d8) /* Device System & Control register bitfields */ -#define TUSB_DEV_OTG_TIMER_ENABLE (1 << 31) -#define TUSB_DEV_OTG_TIMER_VAL(v) ((v) & 0x07ffffff) #define TUSB_INT_CTRL_CONF_INT_RELCYC(v) (((v) & 0x7) << 18) #define TUSB_INT_CTRL_CONF_INT_POLARITY (1 << 17) #define TUSB_INT_CTRL_CONF_INT_MODE (1 << 16) diff --git a/drivers/usb/musb/virthub.c b/drivers/usb/musb/virthub.c index 0d0b02cd0f3..04d54e3bdc0 100644 --- a/drivers/usb/musb/virthub.c +++ b/drivers/usb/musb/virthub.c @@ -277,7 +277,6 @@ int musb_hub_control( * logic relating to VBUS power-up. */ musb_start(musb); - musb->port1_status |= USB_PORT_STAT_POWER; break; case USB_PORT_FEAT_RESET: musb_port_reset(musb, TRUE); @@ -316,12 +315,12 @@ int musb_hub_control( goto error; } musb_writeb(musb->pRegs, MGC_O_HDRC_TESTMODE, temp); - musb->port1_status |= USB_PORT_STAT_TEST; break; default: goto error; } DBG(5, "set feature %d\n", wValue); + musb->port1_status |= 1 << wValue; break; default: -- 2.41.1