First of several changes needed to support multiple USB host root hubs

This commit is contained in:
Gregory Nutt 2013-08-12 14:44:06 -06:00
parent f5a0ce709c
commit 39696cbf96
4 changed files with 235 additions and 152 deletions

View File

@ -294,8 +294,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context);
/* USB host controller operations **********************************************/ /* USB host controller operations **********************************************/
static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected); static int lpc17_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected);
static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr); static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, static int lpc17_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize); uint16_t maxpacketsize);
static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr, static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
@ -1518,8 +1518,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method. * the class create() method.
* connected - TRUE: Wait for device to be connected; FALSE: wait for device * connected - A pointer to a boolean value: TRUE: Wait for device to be
* to be disconnected * connected; FALSE: wait for device to be disconnected
* *
* Returned Values: * Returned Values:
* Zero (OK) is returned when a device in connected. This function will not * Zero (OK) is returned when a device in connected. This function will not
@ -1533,7 +1533,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected) static int lpc17_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
irqstate_t flags; irqstate_t flags;
@ -1541,13 +1541,14 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
/* Are we already connected? */ /* Are we already connected? */
flags = irqsave(); flags = irqsave();
while (priv->connected == connected) while (priv->connected == *connected)
{ {
/* No... wait for the connection/disconnection */ /* No... wait for the connection/disconnection */
priv->rhswait = true; priv->rhswait = true;
lpc17_takesem(&priv->rhssem); lpc17_takesem(&priv->rhssem);
} }
irqrestore(flags); irqrestore(flags);
udbg("Connected:%s\n", priv->connected ? "YES" : "NO"); udbg("Connected:%s\n", priv->connected ? "YES" : "NO");
@ -1570,6 +1571,7 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method. * the class create() method.
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, zero (OK) is returned. On a failure, a negated errno value is
@ -1582,9 +1584,10 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* *
*******************************************************************************/ *******************************************************************************/
static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr) static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr, int rphndx)
{ {
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
DEBUGASSERT(priv && rhpndx == 0);
/* Are we connected to a device? The caller should have called the wait() /* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected. * method first to be assured that a device is connected.

View File

@ -49,6 +49,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* The SAMA5 supports 3 root hub ports */
#define SAM_USBHOST_NRHPORT 3
/* Register offsets *********************************************************/ /* Register offsets *********************************************************/
/* See nuttx/usb/ohci.h */ /* See nuttx/usb/ohci.h */
@ -85,9 +88,11 @@
#define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET) #define SAM_USBHOST_RHDESCA (SAM_UHPOHCI_VSECTION+OHCI_RHDESCA_OFFSET)
#define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET) #define SAM_USBHOST_RHDESCB (SAM_UHPOHCI_VSECTION+OHCI_RHDESCB_OFFSET)
#define SAM_USBHOST_RHSTATUS (SAM_UHPOHCI_VSECTION+OHCI_RHSTATUS_OFFSET) #define SAM_USBHOST_RHSTATUS (SAM_UHPOHCI_VSECTION+OHCI_RHSTATUS_OFFSET)
#define SAM_USBHOST_RHPORTST(n) (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST_OFFSET(n))
#define SAM_USBHOST_RHPORTST1 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST1_OFFSET) #define SAM_USBHOST_RHPORTST1 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST1_OFFSET)
#define SAM_USBHOST_RHPORTST2 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST2_OFFSET) #define SAM_USBHOST_RHPORTST2 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST2_OFFSET)
#define SAM_USBHOST_MODID (SAM_UHPOHCI_VSECTION+SAM_USBHOST_MODID_OFFSET) #define SAM_USBHOST_RHPORTST3 (SAM_UHPOHCI_VSECTION+OHCI_RHPORTST3_OFFSET)
/* Register bit definitions *************************************************/ /* Register bit definitions *************************************************/
/* See include/nuttx/usb/ohci.h */ /* See include/nuttx/usb/ohci.h */

View File

@ -176,6 +176,13 @@
/******************************************************************************* /*******************************************************************************
* Private Types * Private Types
*******************************************************************************/ *******************************************************************************/
/* This structure retins the state of one root hub port */
struct sam_rhport_s
{
volatile bool connected; /* Connected to device */
volatile bool lowspeed; /* Low speed device attached. */
};
/* This structure retains the state of the USB host controller */ /* This structure retains the state of the USB host controller */
@ -194,9 +201,8 @@ struct sam_ohci_s
/* Driver status */ /* Driver status */
volatile bool connected; /* Connected to device */
volatile bool lowspeed; /* Low speed device attached. */
volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */ volatile bool rhswait; /* TRUE: Thread is waiting for Root Hub Status change */
#ifndef CONFIG_USBHOST_INT_DISABLE #ifndef CONFIG_USBHOST_INT_DISABLE
uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */ uint8_t ininterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
uint8_t outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */ uint8_t outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
@ -204,6 +210,10 @@ struct sam_ohci_s
sem_t exclsem; /* Support mutually exclusive access */ sem_t exclsem; /* Support mutually exclusive access */
sem_t rhssem; /* Semaphore to wait Writeback Done Head event */ sem_t rhssem; /* Semaphore to wait Writeback Done Head event */
/* Root hub ports */
struct sam_rhport_s rhport[SAM_USBHOST_NRHPORT];
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAMA5_SPI_REGDEBUG #ifdef CONFIG_SAMA5_SPI_REGDEBUG
@ -337,8 +347,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context);
/* USB host controller operations **********************************************/ /* USB host controller operations **********************************************/
static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected); static int sam_wait(FAR struct usbhost_driver_s *drvr, FAR const bool *connected);
static int sam_enumerate(FAR struct usbhost_driver_s *drvr); static int sam_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize); uint16_t maxpacketsize);
static int sam_epalloc(FAR struct usbhost_driver_s *drvr, static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
@ -1231,7 +1241,9 @@ static int sam_wdhwait(struct sam_ohci_s *priv, struct sam_ed_s *ed)
/* Is the device still connected? */ /* Is the device still connected? */
#if 0 /* REVISIT */
if (priv->connected) if (priv->connected)
#endif
{ {
/* Yes.. then set wdhwait to indicate that we expect to be informed when /* Yes.. then set wdhwait to indicate that we expect to be informed when
* either (1) the device is disconnected, or (2) the transfer completed. * either (1) the device is disconnected, or (2) the transfer completed.
@ -1339,6 +1351,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
uint32_t intst; uint32_t intst;
uint32_t pending; uint32_t pending;
uint32_t regval; uint32_t regval;
uint32_t regaddr;
int rhpndx;
/* Read Interrupt Status and mask out interrupts that are not enabled. */ /* Read Interrupt Status and mask out interrupts that are not enabled. */
@ -1353,15 +1367,27 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
if ((pending & OHCI_INT_RHSC) != 0) if ((pending & OHCI_INT_RHSC) != 0)
{ {
uint32_t rhportst1 = sam_getreg(SAM_USBHOST_RHPORTST1); /* Hand root hub status change on each root port */
ullvdbg("Root Hub Status Change, RHPORTST1: %08x\n", rhportst1);
if ((rhportst1 & OHCI_RHPORTST_CSC) != 0) ullvdbg("Root Hub Status Change\n");
for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
{
uint32_t rhportst;
regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
rhportst = sam_getreg(regaddr);
ullvdbg("RHPORTST%d: %08x\n",
rhpndx + 1, rhportst);
if ((rhportst & OHCI_RHPORTST_CSC) != 0)
{ {
uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS); uint32_t rhstatus = sam_getreg(SAM_USBHOST_RHSTATUS);
ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus); ullvdbg("Connect Status Change, RHSTATUS: %08x\n", rhstatus);
/* If DRWE is set, Connect Status Change indicates a remote wake-up event */ /* If DRWE is set, Connect Status Change indicates a remote
* wake-up event
*/
if (rhstatus & OHCI_RHSTATUS_DRWE) if (rhstatus & OHCI_RHSTATUS_DRWE)
{ {
@ -1374,16 +1400,18 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
{ {
/* Check current connect status */ /* Check current connect status */
if ((rhportst1 & OHCI_RHPORTST_CCS) != 0) if ((rhportst & OHCI_RHPORTST_CCS) != 0)
{ {
/* Connected ... Did we just become connected? */ /* Connected ... Did we just become connected? */
if (!priv->connected) if (!priv->rhport[rhpndx].connected)
{ {
/* Yes.. connected. */ /* Yes.. connected. */
ullvdbg("Connected\n"); priv->rhport[rhpndx].connected = true;
priv->connected = true;
ullvdbg("RHPort%d connected, rhswait: %d\n",
rhpndx + 1, priv->rhswait);
/* Notify any waiters */ /* Notify any waiters */
@ -1402,19 +1430,22 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
* when CCS == 1. * when CCS == 1.
*/ */
priv->lowspeed = (rhportst1 & OHCI_RHPORTST_LSDA) != 0; priv->rhport[rhpndx].lowspeed =
ullvdbg("Speed:%s\n", priv->lowspeed ? "LOW" : "FULL"); (rhportst & OHCI_RHPORTST_LSDA) != 0;
ullvdbg("Speed: %s\n",
priv->rhport[rhpndx].lowspeed ? "LOW" : "FULL");
} }
/* Check if we are now disconnected */ /* Check if we are now disconnected */
else if (priv->connected) else if (priv->rhport[rhpndx].connected)
{ {
/* Yes.. disconnect the device */ /* Yes.. disconnect the device */
ullvdbg("Disconnected\n"); ullvdbg("RHport%d disconnected\n", rhpndx+1);
priv->connected = false; priv->rhport[rhpndx].connected = false;
priv->lowspeed = false; priv->rhport[rhpndx].lowspeed = false;
/* Are we bound to a class instance? */ /* Are we bound to a class instance? */
@ -1426,7 +1457,9 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
priv->class = NULL; priv->class = NULL;
} }
/* Notify any waiters for the Root Hub Status change event */ /* Notify any waiters for the Root Hub Status change
* event.
*/
if (priv->rhswait) if (priv->rhswait)
{ {
@ -1442,16 +1475,17 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
/* Clear the status change interrupt */ /* Clear the status change interrupt */
sam_putreg(OHCI_RHPORTST_CSC, SAM_USBHOST_RHPORTST1); sam_putreg(OHCI_RHPORTST_CSC, regaddr);
} }
/* Check for port reset status change */ /* Check for port reset status change */
if ((rhportst1 & OHCI_RHPORTST_PRSC) != 0) if ((rhportst & OHCI_RHPORTST_PRSC) != 0)
{ {
/* Release the RH port from reset */ /* Release the RH port from reset */
sam_putreg(OHCI_RHPORTST_PRSC, SAM_USBHOST_RHPORTST1); sam_putreg(OHCI_RHPORTST_PRSC, regaddr);
}
} }
} }
@ -1495,9 +1529,8 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
{ {
/* The transfer failed for some reason... dump some diagnostic info. */ /* The transfer failed for some reason... dump some diagnostic info. */
ulldbg("ERROR: ED xfrtype:%d TD CTRL:%08x/CC:%d RHPORTST1:%08x\n", ulldbg("ERROR: ED xfrtype: %d TD CTRL: %08x/CC: %d\n",
ed->xfrtype, td->hw.ctrl, ed->tdstatus, ed->xfrtype, td->hw.ctrl, ed->tdstatus);
sam_getreg(SAM_USBHOST_RHPORTST1));
} }
#endif #endif
@ -1539,17 +1572,21 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
* Name: sam_wait * Name: sam_wait
* *
* Description: * Description:
* Wait for a device to be connected or disconneced. * Wait for a device to be connected or disconnected to/from a root hub port.
* *
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call * drvr - The USB host driver instance obtained as a parameter from the call
* to the class create() method. * to the class create() method.
* connected - TRUE: Wait for device to be connected; FALSE: wait for device * connected - A pointer to an array of 3 boolean values corresponding to
* to be disconnected * root hubs 1, 2, and 3. For each boolean value: TRUE: Wait for a device
* to be connected on the root hub; FALSE: wait for device to be
* disconnected from the root hub.
* *
* Returned Values: * Returned Values:
* Zero (OK) is returned when a device in connected. This function will not * And index [0, 1, or 2} corresponding to the root hub port number {1, 2,
* return until either (1) a device is connected or (2) some failure occurs. * or 3} is returned when a device is connected or disconnected. This
* function will not return until either (1) a device is connected or
* disconnected to/from any root hub port or until (2) some failure occurs.
* On a failure, a negated errno value is returned indicating the nature of * On a failure, a negated errno value is returned indicating the nature of
* the failure * the failure
* *
@ -1559,25 +1596,47 @@ static int sam_ohci_interrupt(int irq, FAR void *context)
* *
*******************************************************************************/ *******************************************************************************/
static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected) static int sam_wait(FAR struct usbhost_driver_s *drvr, FAR const bool *connected)
{ {
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr; struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
irqstate_t flags; irqstate_t flags;
int rhpndx;
/* Are we already connected? */ /* Loop until a change in the connection state changes on one of the root hub
* ports or until an error occurs.
*/
flags = irqsave(); flags = irqsave();
while (priv->connected == connected) for (;;)
{ {
/* No... wait for the connection/disconnection */ /* Check for a change in the connection state on any root hub port */
for (rhpndx = 0; rhpndx < SAM_USBHOST_NRHPORT; rhpndx++)
{
/* Has the connection state changed on the RH port? */
while (priv->rhport[rhpndx].connected != connected[rhpndx])
{
/* Yes.. break out and return the RH port number */
break;
}
}
/* No changes on any port. Wait for a connection/disconnection event
* and check again
*/
priv->rhswait = true; priv->rhswait = true;
sam_takesem(&priv->rhssem); sam_takesem(&priv->rhssem);
} }
irqrestore(flags); irqrestore(flags);
udbg("Connected:%s\n", priv->connected ? "YES" : "NO"); udbg("RHPort%d connected: %s\n",
return OK; rhpndx + 1, priv->rhport[rhpndx].connected ? "YES" : "NO");
return rhpndx;
} }
/******************************************************************************* /*******************************************************************************
@ -1596,6 +1655,7 @@ static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method. * the class create() method.
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, zero (OK) is returned. On a failure, a negated errno value is
@ -1608,15 +1668,16 @@ static int sam_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* *
*******************************************************************************/ *******************************************************************************/
static int sam_enumerate(FAR struct usbhost_driver_s *drvr) static int sam_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx)
{ {
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr; struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
uint32_t regaddr;
/* Are we connected to a device? The caller should have called the wait() /* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected. * method first to be assured that a device is connected.
*/ */
while (!priv->connected) while (!priv->rhport[rhpndx].connected)
{ {
/* No, return an error */ /* No, return an error */
@ -1628,25 +1689,26 @@ static int sam_enumerate(FAR struct usbhost_driver_s *drvr)
up_mdelay(100); up_mdelay(100);
/* Put RH port 1 in reset (the LPC176x supports only a single downstream port) */ /* Put the root hub port in reset (the SAMA5 supports three downstream ports) */
sam_putreg(OHCI_RHPORTST_PRS, SAM_USBHOST_RHPORTST1); regaddr = SAM_USBHOST_RHPORTST(rhpndx+1);
sam_putreg(OHCI_RHPORTST_PRS, regaddr);
/* Wait for the port reset to complete */ /* Wait for the port reset to complete */
while ((sam_getreg(SAM_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0); while ((sam_getreg(regaddr) & OHCI_RHPORTST_PRS) != 0);
/* Release RH port 1 from reset and wait a bit */ /* Release RH port 1 from reset and wait a bit */
sam_putreg(OHCI_RHPORTST_PRSC, SAM_USBHOST_RHPORTST1); sam_putreg(OHCI_RHPORTST_PRSC, regaddr);
up_mdelay(200); up_mdelay(200);
/* Let the common usbhost_enumerate do all of the real work. Note that the /* Let the common usbhost_enumerate do all of the real work. Note that the
* FunctionAddress (USB address) is hardcoded to one. * FunctionAddress (USB address) is set to the root hub port number for now.
*/ */
uvdbg("Enumerate the device\n"); uvdbg("Enumerate the device\n");
return usbhost_enumerate(drvr, 1, &priv->class); return usbhost_enumerate(drvr, rhpndx+1, &priv->class);
} }
/************************************************************************************ /************************************************************************************
@ -1678,8 +1740,10 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize) uint16_t maxpacketsize)
{ {
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr; struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
int rhpndx = (int)funcaddr - 1;
DEBUGASSERT(drvr && funcaddr < 128 && maxpacketsize < 2048); DEBUGASSERT(drvr && funcaddr > 0 && funcaddr <= SAM_USBHOST_NRHPORT &&
maxpacketsize < 2048);
/* We must have exclusive access to EP0 and the control list */ /* We must have exclusive access to EP0 and the control list */
@ -1690,7 +1754,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
g_edctrl.hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | g_edctrl.hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT |
(uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT;
if (priv->lowspeed) if (priv->rhport[rhpndx].lowspeed)
{ {
g_edctrl.hw.ctrl |= ED_CONTROL_S; g_edctrl.hw.ctrl |= ED_CONTROL_S;
} }
@ -1731,13 +1795,16 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
{ {
struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr; struct sam_ohci_s *priv = (struct sam_ohci_s *)drvr;
struct sam_ed_s *ed; struct sam_ed_s *ed;
int rhpndx = (int)epdesc->funcaddr - 1;
int ret = -ENOMEM; int ret = -ENOMEM;
/* Sanity check. NOTE that this method should only be called if a device is /* Sanity check. NOTE that this method should only be called if a device is
* connected (because we need a valid low speed indication). * connected (because we need a valid low speed indication).
*/ */
DEBUGASSERT(priv && epdesc && ep && priv->connected); DEBUGASSERT(priv && epdesc && ep &&
rhpndx >= 0 && rhpndx < SAM_USBHOST_NRHPORT &&
priv->rhport[rhpndx].connected);
/* We must have exclusive access to the ED pool, the bulk list, the periodic list /* We must have exclusive access to the ED pool, the bulk list, the periodic list
* and the interrupt table. * and the interrupt table.
@ -1776,7 +1843,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
/* Check for a low-speed device */ /* Check for a low-speed device */
if (priv->lowspeed) if (priv->rhport[rhpndx].lowspeed)
{ {
ed->hw.ctrl |= ED_CONTROL_S; ed->hw.ctrl |= ED_CONTROL_S;
} }
@ -2583,8 +2650,14 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
* connected. We need to set the initial connected state accordingly. * connected. We need to set the initial connected state accordingly.
*/ */
regval = sam_getreg(SAM_USBHOST_RHPORTST1); for (i = 0; i < SAM_USBHOST_NRHPORT; i++)
priv->connected = ((regval & OHCI_RHPORTST_CCS) != 0); {
regval = sam_getreg(SAM_USBHOST_RHPORTST(i));
priv->rhport[i].connected = ((regval & OHCI_RHPORTST_CCS) != 0);
uvdbg("RHPort%d Device connected: %s\n",
i+1, priv->rhport[i].connected ? "YES" : "NO");
}
/* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG /* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG
* mode. * mode.
@ -2595,8 +2668,7 @@ FAR struct usbhost_driver_s *sam_ohci_initialize(int controller)
/* Enable interrupts at the interrupt controller */ /* Enable interrupts at the interrupt controller */
up_enable_irq(SAM_IRQ_UHPHS); /* enable USB interrupt */ up_enable_irq(SAM_IRQ_UHPHS); /* enable USB interrupt */
udbg("USB host Initialized, Device connected:%s\n", uvdbg("USB OHCI Initialized\n");
priv->connected ? "YES" : "NO");
return &priv->drvr; return &priv->drvr;
} }

View File

@ -358,8 +358,8 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx);
/* USB host controller operations **********************************************/ /* USB host controller operations **********************************************/
static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected); static int stm32_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected);
static int stm32_enumerate(FAR struct usbhost_driver_s *drvr); static int stm32_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx);
static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr, static int stm32_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
uint16_t maxpacketsize); uint16_t maxpacketsize);
static int stm32_epalloc(FAR struct usbhost_driver_s *drvr, static int stm32_epalloc(FAR struct usbhost_driver_s *drvr,
@ -3013,8 +3013,8 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx)
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method. * the class create() method.
* connected - TRUE: Wait for device to be connected; FALSE: wait for device * connected - A pointer to a boolean value. TRUE: Wait for device to be
* to be disconnected * connected; FALSE: wait for device to be disconnected
* *
* Returned Values: * Returned Values:
* Zero (OK) is returned when a device in connected. This function will not * Zero (OK) is returned when a device in connected. This function will not
@ -3028,7 +3028,7 @@ static void stm32_txfe_enable(FAR struct stm32_usbhost_s *priv, int chidx)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected) static int stm32_wait(FAR struct usbhost_driver_s *drvr, FAR bool *connected)
{ {
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
irqstate_t flags; irqstate_t flags;
@ -3036,7 +3036,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
/* Are we already connected? */ /* Are we already connected? */
flags = irqsave(); flags = irqsave();
while (priv->connected == connected) while (priv->connected == *connected)
{ {
/* No... wait for the connection/disconnection */ /* No... wait for the connection/disconnection */
@ -3066,6 +3066,7 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* Input Parameters: * Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to * drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method. * the class create() method.
* rphndx - Root hub port index. 0-(n-1) corresponds to root hub port 1-n.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, zero (OK) is returned. On a failure, a negated errno value is
@ -3078,13 +3079,15 @@ static int stm32_wait(FAR struct usbhost_driver_s *drvr, bool connected)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_enumerate(FAR struct usbhost_driver_s *drvr) static int stm32_enumerate(FAR struct usbhost_driver_s *drvr, int rhpndx)
{ {
struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr; struct stm32_usbhost_s *priv = (struct stm32_usbhost_s *)drvr;
uint32_t regval; uint32_t regval;
int chidx; int chidx;
int ret; int ret;
DEBUGASSERT(priv && rhpndx == 0);
/* Are we connected to a device? The caller should have called the wait() /* Are we connected to a device? The caller should have called the wait()
* method first to be assured that a device is connected. * method first to be assured that a device is connected.
*/ */