drivers/usbhost/usbhost_max3421e.c: Fix several errors found in early testing.

This commit is contained in:
Gregory Nutt 2018-07-30 16:56:19 -06:00
parent 89459594f6
commit 8b2dc155a0

View File

@ -530,6 +530,10 @@ static inline void max3421e_int_enable(FAR struct max3421e_usbhost_s *priv,
static inline void max3421e_int_disable(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset);
static inline uint8_t max3421e_int_status(FAR struct max3421e_usbhost_s *priv);
static inline void max3421e_int_clear(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset);
static void max3421e_int_wait(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset, unsigned int usec);
/* USB host controller operations **********************************************/
@ -1506,7 +1510,7 @@ static void max3421e_put_sndfifo(FAR struct max3421e_usbhost_s *priv,
for (i = 0;
i < 2 && committed < priv->buflen &&
(max3421e_getreg(priv, MAX3421E_USBHOST_HIRQ) & USBHOST_HIRQ_SNDBAVIRQ) == 1;
(max3421e_int_status(priv) & USBHOST_HIRQ_SNDBAVIRQ) == 1;
i++)
{
/* Get the size of the biggest thing that we can put in the current
@ -3048,8 +3052,7 @@ static void max3421e_irqwork(FAR void *arg)
/* Clear the pending HXFRDN interrupt */
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ,
USBHOST_HIRQ_HXFRDNIRQ);
max3421e_int_clear(priv, USBHOST_HIRQ_HXFRDNIRQ);
/* Check transfer status and terminate the transfer if any error
* occurred.
@ -3072,8 +3075,7 @@ static void max3421e_irqwork(FAR void *arg)
{
/* Clear the pending CONNIRQ interrupt */
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ,
USBHOST_HIRQ_CONNIRQ);
max3421e_int_clear(priv, USBHOST_HIRQ_CONNIRQ);
/* Check if a peripheral device has been connected */
@ -3097,8 +3099,7 @@ static void max3421e_irqwork(FAR void *arg)
/* Clear the pending SNDBAV interrupt */
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ,
USBHOST_HIRQ_SNDBAVIRQ);
max3421e_int_clear(priv, USBHOST_HIRQ_SNDBAVIRQ);
/* Finish long transfer, possibly re-enabling the SNDBAV
* interrupt (see max3421e_send_start)
@ -3122,8 +3123,7 @@ static void max3421e_irqwork(FAR void *arg)
* will catch that the next time through this loop.
*/
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ,
USBHOST_HIRQ_RCVDAVIRQ);
max3421e_int_clear(priv, USBHOST_HIRQ_RCVDAVIRQ);
/* Handle the receipt of data */
@ -3170,7 +3170,8 @@ static int max3421e_interrupt(int irq, FAR void *context, FAR void *arg)
}
/****************************************************************************
* Name: max3421e_int_enable, max3421e_int_disable, and max3421e_int_status
* Name: max3421e_int_enable, max3421e_int_disable, max3421e_int_status, and
* max3421e_int_wait
*
* Description:
* Respectively enable, disable, or get status of the USB host interrupt
@ -3185,6 +3186,8 @@ static int max3421e_interrupt(int irq, FAR void *context, FAR void *arg)
*
****************************************************************************/
/* Enable a set of interrupts */
static inline void max3421e_int_enable(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset)
{
@ -3192,6 +3195,8 @@ static inline void max3421e_int_enable(FAR struct max3421e_usbhost_s *priv,
max3421e_putreg(priv, MAX3421E_USBHOST_HIEN, priv->irqset);
}
/* Disable a set of interrupts */
static inline void max3421e_int_disable(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset)
{
@ -3199,11 +3204,41 @@ static inline void max3421e_int_disable(FAR struct max3421e_usbhost_s *priv,
max3421e_putreg(priv, MAX3421E_USBHOST_HIEN, priv->irqset);
}
/* Get the set of pending interrupts */
static inline uint8_t max3421e_int_status(FAR struct max3421e_usbhost_s *priv)
{
return max3421e_getreg(priv, MAX3421E_USBHOST_HIRQ) & priv->irqset;
}
/* Clear a set of pending interrupts */
static inline void max3421e_int_clear(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset)
{
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ, irqset);
}
/* Wait until any interrupt from a set of interrupts occurs */
static void max3421e_int_wait(FAR struct max3421e_usbhost_s *priv,
uint8_t irqset, unsigned int usec)
{
uint8_t regval;
do
{
regval = max3421e_getreg(priv, MAX3421E_USBHOST_HIRQ);
regval &= irqset;
if (regval == 0 && usec > 0)
{
usleep(usec);
}
}
while (regval == 0);
}
/****************************************************************************
* Name: max3421e_wait
*
@ -3235,7 +3270,6 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
FAR struct max3421e_connection_s *maxconn;
FAR struct max3421e_usbhost_s *priv;
struct usbhost_hubport_s *connport;
irqstate_t flags;
maxconn = (FAR struct max3421e_connection_s *)conn;
DEBUGASSERT(maxconn != NULL && maxconn->priv != NULL);
@ -3243,9 +3277,12 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
/* Loop until a change in connection state is detected */
flags = enter_critical_section();
for (; ; )
{
/* We must have exclusive access to the USB host hardware and state structures */
max3421e_takesem(&priv->exclsem);
/* Is there a change in the connection state of the single root hub
* port?
*/
@ -3262,9 +3299,10 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
/* And return the root hub port */
*hport = connport;
leave_critical_section(flags);
usbhost_vtrace1(MAX3421E_VTRACE1_CONNECTED2, connport->connected);
max3421e_givesem(&priv->exclsem);
return OK;
}
@ -3279,10 +3317,11 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
priv->hport = NULL;
*hport = connport;
leave_critical_section(flags);
usbhost_vtrace1(MAX3421E_VTRACE1_HUB_CONNECTED,
connport->connected);
max3421e_givesem(&priv->exclsem);
return OK;
}
#endif
@ -3290,6 +3329,7 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
/* Wait for the next connection event */
priv->pscwait = true;
max3421e_givesem(&priv->exclsem);
max3421e_takesem(&priv->pscsem);
}
}
@ -3312,7 +3352,7 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
* returned indicating the nature of the failure
*
* Assumptions:
* This function will *not* be called from an interrupt handler.
* The caller has the SPI bus locked.
*
****************************************************************************/
@ -3328,7 +3368,7 @@ static int max3421e_getspeed(FAR struct max3421e_usbhost_s *priv,
* method first to be assured that a device is connected.
*/
while (!priv->connected)
if (!priv->connected)
{
/* No, return an error */
@ -3344,6 +3384,17 @@ static int max3421e_getspeed(FAR struct max3421e_usbhost_s *priv,
nxsig_usleep(100*1000);
/* Make sure we are still connected */
if (!priv->connected)
{
/* No, return an error */
usbhost_trace1(MAX3421E_TRACE1_DEVDISCONN6, 0);
max3421e_givesem(&priv->exclsem);
return -ENODEV;
}
/* Stop SOF generation and reset the host port */
max3421e_busreset(priv);
@ -3399,10 +3450,17 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
DEBUGASSERT(maxconn != NULL && maxconn->priv != NULL);
priv = maxconn->priv;
/* We must have exclusive access to the USB host hardware and state structures */
max3421e_takesem(&priv->exclsem);
/* If this is a connection on the root hub, then we need to go to
* little more effort to get the device speed. If it is a connection
* on an external hub, then we already have that information.
*/
max3421e_lock(priv);
#warning REVISIT: Isnt this already done?
#ifdef CONFIG_USBHOST_HUB
@ -3412,6 +3470,7 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
ret = max3421e_getspeed(priv, conn, hport);
if (ret < 0)
{
max3421e_givesem(&priv->exclsem);
return ret;
}
}
@ -3426,7 +3485,9 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
usbhost_vtrace1(MAX3421E_VTRACE1_ENUMERATE, 0);
priv->smstate = SMSTATE_ENUM;
ret = usbhost_enumerate(hport, &hport->devclass);
max3421e_unlock(priv);
/* The enumeration may fail either because of some HCD interfaces failure
* or because the device class is not supported. In either case, we just
@ -3444,9 +3505,13 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
/* Set post-enumeration data toggles (assuming success) */
max3421e_lock(priv);
max3421e_modifyreg(priv, MAX3421E_USBHOST_HCTL,
USBHOST_HCTL_TOGGLES_MASK,
USBHOST_HCTL_RCVTOG0| USBHOST_HCTL_SNDTOG0);
max3421e_unlock(priv);
max3421e_givesem(&priv->exclsem);
return ret;
}
@ -4339,13 +4404,14 @@ static void max3421e_busreset(FAR struct max3421e_usbhost_s *priv)
max3421e_modifyreg(priv, MAX3421E_USBHOST_MODE, USBHOST_MODE_SOFKAENAB, 0);
/* Clear any pending bus event */
max3421e_int_clear(priv, USBHOST_HIRQ_BUSEVENTIRQ);
/* Perform the reset */
max3421e_modifyreg(priv, MAX3421E_USBHOST_HCTL, 0, USBHOST_HCTL_BUSRST);
while ((max3421e_getreg(priv, MAX3421E_USBHOST_HCTL) & MAX3421E_USBHOST_HCTL) == 0)
{
usleep(250);
}
max3421e_int_wait(priv, USBHOST_HIRQ_BUSEVENTIRQ, 250);
}
/****************************************************************************
@ -4450,11 +4516,7 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
/* Wait for the first SOF received and 20ms has passed */
while ((max3421e_getreg(priv, MAX3421E_USBHOST_HIRQ) &
USBHOST_HIRQ_FRAMEIRQ) == 0)
{
}
max3421e_int_wait(priv, USBHOST_HIRQ_FRAMEIRQ, 0);
usleep(20*1000);
return OK;
}
@ -4638,8 +4700,7 @@ static inline int max3421e_hw_initialize(FAR struct max3421e_usbhost_s *priv)
max3421e_modifyreg(priv, MAX3421E_USBHOST_CPUCTL, USBHOST_CPUCTL_IE, 0);
max3421e_putreg(priv, MAX3421E_USBHOST_HIEN, 0);
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ, 0xff);
max3421e_int_clear(priv, 0xff);
priv->irqset = 0;
/* Configure as full-speed USB host */
@ -4649,10 +4710,10 @@ static inline int max3421e_hw_initialize(FAR struct max3421e_usbhost_s *priv)
USBHOST_MODE_HOST | USBHOST_MODE_DMPULLD |
USBHOST_MODE_DPPULLDN);
/* Enable and clear the connection detected (CONDIRQ) interrupt */
/* Clear and enable the connection detected (CONDIRQ) interrupt */
max3421e_int_clear(priv, USBHOST_HIRQ_CONNIRQ);
max3421e_int_enable(priv, USBHOST_HIRQ_CONNIRQ);
max3421e_putreg(priv, MAX3421E_USBHOST_HIRQ, USBHOST_HIRQ_CONNIRQ);
/* Enable MAX3412E interrupts */