if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
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;
if (bComplete)
musb_advance_schedule(pThis, pUrb, pEnd, 1);
done:
- set_bit(HCD_FLAG_SAW_IRQ, &musb_to_hcd(pThis)->flags);
return retval;
}
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
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;
}
#include "davinci.h"
-#ifdef CONFIG_USB_MUSB_OTG
-
static const char *state_string(enum usb_otg_state state)
{
switch (state) {
}
}
-#endif
-
#ifdef CONFIG_USB_MUSB_HDRC_HCD
static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
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: "
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,
#define is_host_active(musb) is_host_capable()
#endif
+
#ifdef CONFIG_PROC_FS
#include <linux/fs.h>
#define MUSB_CONFIG_PROC_FS
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 ********************************/
/****************************** 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)
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 */
*
* - needs updating along the lines of <linux/usb_otg.h>
*
+ * - 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.
*
* (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.)
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 = "<SessEnd"; break;
+ case 1 << MGC_S_DEVCTL_VBUS:
+ s = "<AValid"; break;
+ case 2 << MGC_S_DEVCTL_VBUS:
+ s = "<VBusValid"; break;
+ //case 3 << MGC_S_DEVCTL_VBUS:
+ default:
+ s = "VALID"; break;
+ }; s; }),
+ pThis->vbuserr_retry);
/* after hw goes to A_IDLE, try connecting again */
pThis->xceiv.state = OTG_STATE_A_IDLE;
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;
/* 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...)
*/
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);
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 */
}
(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
*/
hcd->uses_new_polling = 1;
+ musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
#else
musb = kzalloc(sizeof *musb, GFP_KERNEL);
if (!musb)
* 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)
{
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);
#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 */
#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)
* 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);
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: