mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
Correct logic that turns on USB host power
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3224 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -3219,12 +3219,6 @@ build
|
|||||||
<li>
|
<li>
|
||||||
<code>CONFIG_USBHOST</code>: Enables USB host support
|
<code>CONFIG_USBHOST</code>: Enables USB host support
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<code>CONFIG_USBHOST_HAVERHSC</code>:
|
|
||||||
Define if the hardware is able to detect a root hub status change when a device is inserted.
|
|
||||||
If <code>CONFIG_USBHOST_HAVERHSC</code> is not set, then it is assumed that the hardware cannot detect the presence of a USB device
|
|
||||||
and that the application must periodically attempt to enumerate the device.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<code>CONFIG_USBHOST_NPREALLOC</code>: Number of pre-allocated class instances
|
<code>CONFIG_USBHOST_NPREALLOC</code>: Number of pre-allocated class instances
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -82,10 +82,12 @@
|
|||||||
# error "No IO buffers allocated"
|
# error "No IO buffers allocated"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Frame Interval */
|
/* Frame Interval / Periodic Start */
|
||||||
|
|
||||||
#define FI (12000-1) /* 12000 bits per frame (-1) */
|
#define FI (12000-1) /* 12000 bits per frame (-1) */
|
||||||
#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
|
#define FSMPS ((6 * (FI - 210)) / 7)
|
||||||
|
#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
|
||||||
|
#define DEFAULT_PERSTART ((9 * FI) / 10)
|
||||||
|
|
||||||
/* CLKCTRL enable bits */
|
/* CLKCTRL enable bits */
|
||||||
|
|
||||||
@@ -279,7 +281,7 @@ static struct lpc17_usbhost_s g_usbhost =
|
|||||||
{
|
{
|
||||||
.drvr =
|
.drvr =
|
||||||
{
|
{
|
||||||
.wait = lpc17_wait,
|
.wait = lpc17_wait,
|
||||||
.enumerate = lpc17_enumerate,
|
.enumerate = lpc17_enumerate,
|
||||||
.ep0configure = lpc17_ep0configure,
|
.ep0configure = lpc17_ep0configure,
|
||||||
.alloc = lpc17_alloc,
|
.alloc = lpc17_alloc,
|
||||||
@@ -676,6 +678,7 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
uvdbg("Bad TD completion status: %d\n", priv->tdstatus);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,13 +738,15 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
if (!priv->connected)
|
if (!priv->connected)
|
||||||
{
|
{
|
||||||
|
/* Yes.. connected. */
|
||||||
|
|
||||||
ullvdbg("Connected\n");
|
ullvdbg("Connected\n");
|
||||||
priv->tdstatus = 0;
|
priv->tdstatus = 0;
|
||||||
|
|
||||||
|
/* Notify any waiters */
|
||||||
|
|
||||||
priv->connected = true;
|
priv->connected = true;
|
||||||
#ifdef CONFIG_USBHOST_HAVERHSC
|
|
||||||
DEBUGASSERT(priv->rhssem.semcount <= 0);
|
|
||||||
lpc17_givesem(&priv->rhssem);
|
lpc17_givesem(&priv->rhssem);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -756,7 +761,6 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
|
|||||||
/* Yes.. disable interrupts and disconnect the device */
|
/* Yes.. disable interrupts and disconnect the device */
|
||||||
|
|
||||||
ullvdbg("Disconnected\n");
|
ullvdbg("Disconnected\n");
|
||||||
lpc17_putreg(0, LPC17_USBHOST_INTEN);
|
|
||||||
priv->connected = false;
|
priv->connected = false;
|
||||||
|
|
||||||
/* Are we bound to a class instance? */
|
/* Are we bound to a class instance? */
|
||||||
@@ -768,7 +772,8 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
|
|||||||
CLASS_DISCONNECTED(priv->class);
|
CLASS_DISCONNECTED(priv->class);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGASSERT(priv->rhssem.semcount <= 0);
|
/* Notify any waiters */
|
||||||
|
|
||||||
lpc17_givesem(&priv->rhssem);
|
lpc17_givesem(&priv->rhssem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -846,7 +851,6 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
|
|||||||
{
|
{
|
||||||
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
|
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_HAVERHSC
|
|
||||||
/* Are we already connected? */
|
/* Are we already connected? */
|
||||||
|
|
||||||
while (priv->connected == connected)
|
while (priv->connected == connected)
|
||||||
@@ -855,19 +859,7 @@ static int lpc17_wait(FAR struct usbhost_driver_s *drvr, bool connected)
|
|||||||
|
|
||||||
lpc17_takesem(&priv->rhssem);
|
lpc17_takesem(&priv->rhssem);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (!connected)
|
|
||||||
{
|
|
||||||
/* Are we already connected? */
|
|
||||||
|
|
||||||
while (priv->connected)
|
|
||||||
{
|
|
||||||
/* Yes... wait for the disconnection */
|
|
||||||
|
|
||||||
lpc17_takesem(&priv->rhssem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,21 +899,19 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
|
|||||||
* method first to be assured that a device is connected.
|
* method first to be assured that a device is connected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_USBHOST_HAVERHSC
|
|
||||||
while (!priv->connected)
|
while (!priv->connected)
|
||||||
{
|
{
|
||||||
/* No, return an error */
|
/* No, return an error */
|
||||||
|
|
||||||
udbg("Not connected\n");
|
udbg("Not connected\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB 2.0 spec says at least 50ms delay before port reset */
|
/* USB 2.0 spec says at least 50ms delay before port reset */
|
||||||
|
|
||||||
up_mdelay(100);
|
up_mdelay(100);
|
||||||
|
|
||||||
/* Put the RH port in reset */
|
/* Put RH port 1 in reset (the LPC176x supports only a single downstream port) */
|
||||||
|
|
||||||
lpc17_putreg(OHCI_RHPORTST_PRS, LPC17_USBHOST_RHPORTST1);
|
lpc17_putreg(OHCI_RHPORTST_PRS, LPC17_USBHOST_RHPORTST1);
|
||||||
|
|
||||||
@@ -929,7 +919,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
|
|||||||
|
|
||||||
while ((lpc17_getreg(LPC17_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0);
|
while ((lpc17_getreg(LPC17_USBHOST_RHPORTST1) & OHCI_RHPORTST_PRS) != 0);
|
||||||
|
|
||||||
/* Release the RH port from reset and wait a bit */
|
/* Release RH port 1 from reset and wait a bit */
|
||||||
|
|
||||||
lpc17_putreg(OHCI_RHPORTST_PRSC, LPC17_USBHOST_RHPORTST1);
|
lpc17_putreg(OHCI_RHPORTST_PRSC, LPC17_USBHOST_RHPORTST1);
|
||||||
up_mdelay(200);
|
up_mdelay(200);
|
||||||
@@ -1091,6 +1081,11 @@ static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr,
|
|||||||
uint16_t len;
|
uint16_t len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(drvr && req);
|
||||||
|
uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
|
||||||
|
req->type, req->req, req->value[1], req->value[0],
|
||||||
|
req->index[1], req->index[0], req->len[1], req->len[0]);
|
||||||
|
|
||||||
len = lpc17_getle16(req->len);
|
len = lpc17_getle16(req->len);
|
||||||
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
|
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
@@ -1116,6 +1111,11 @@ static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
|
|||||||
uint16_t len;
|
uint16_t len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(drvr && req);
|
||||||
|
uvdbg("type:%02x req:%02x value:%02x%02x index:%02x%02x len:%02x%02x\n",
|
||||||
|
req->type, req->req, req->value[1], req->value[0],
|
||||||
|
req->index[1], req->index[0], req->len[1], req->len[0]);
|
||||||
|
|
||||||
len = lpc17_getle16(req->len);
|
len = lpc17_getle16(req->len);
|
||||||
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
|
ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
@@ -1429,7 +1429,7 @@ FAR struct usbhost_driver_s *usbhost_initialize(int controller)
|
|||||||
* 10: reserved
|
* 10: reserved
|
||||||
* 11: U1=host, U2=device
|
* 11: U1=host, U2=device
|
||||||
*
|
*
|
||||||
* We need only select U1=host (Bit 0=1);
|
* We need only select U1=host (Bit 0=1, Bit 1 is not used on LPC176x);
|
||||||
* NOTE: The PORTSEL clock needs to be enabled when accessing OTGSTCTRL
|
* NOTE: The PORTSEL clock needs to be enabled when accessing OTGSTCTRL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1504,9 +1504,12 @@ FAR struct usbhost_driver_s *usbhost_initialize(int controller)
|
|||||||
|
|
||||||
lpc17_putreg(OHCI_CMDST_HCR, LPC17_USBHOST_CMDST);
|
lpc17_putreg(OHCI_CMDST_HCR, LPC17_USBHOST_CMDST);
|
||||||
|
|
||||||
/* Write Fm interval and largest data packet counter */
|
/* Write Fm interval (FI), largest data packet counter (FSMPS), and
|
||||||
|
* periodic start.
|
||||||
|
*/
|
||||||
|
|
||||||
lpc17_putreg(DEFAULT_FMINTERVAL, LPC17_USBHOST_FMINT);
|
lpc17_putreg(DEFAULT_FMINTERVAL, LPC17_USBHOST_FMINT);
|
||||||
|
lpc17_putreg(DEFAULT_PERSTART, LPC17_USBHOST_PERSTART);
|
||||||
|
|
||||||
/* Put HC in operational state */
|
/* Put HC in operational state */
|
||||||
|
|
||||||
@@ -1515,9 +1518,9 @@ FAR struct usbhost_driver_s *usbhost_initialize(int controller)
|
|||||||
regval |= OHCI_CTRL_HCFS_OPER;
|
regval |= OHCI_CTRL_HCFS_OPER;
|
||||||
lpc17_putreg(regval, LPC17_USBHOST_CTRL);
|
lpc17_putreg(regval, LPC17_USBHOST_CTRL);
|
||||||
|
|
||||||
/* Set global power */
|
/* Set global power in HcRhStatus */
|
||||||
|
|
||||||
lpc17_putreg(OHCI_RHSTATUS_LPS, LPC17_USBHOST_RHSTATUS);
|
lpc17_putreg(OHCI_RHSTATUS_SGP, LPC17_USBHOST_RHSTATUS);
|
||||||
|
|
||||||
/* Set HCCA base address */
|
/* Set HCCA base address */
|
||||||
|
|
||||||
|
|||||||
@@ -706,12 +706,6 @@ defconfig -- This is a configuration file similar to the Linux
|
|||||||
USB host controller driver
|
USB host controller driver
|
||||||
CONFIG_USBHOST
|
CONFIG_USBHOST
|
||||||
Enables USB host support
|
Enables USB host support
|
||||||
CONFIG_USBHOST_HAVERHSC
|
|
||||||
Define if the hardware is able to detect a root hub status change
|
|
||||||
when a device is inserted. If CONFIG_USBHOST_HAVERHSC is not set,
|
|
||||||
then it is assumed that the hardware cannot detect the presence
|
|
||||||
of a USB device and that the application must periodically attempt
|
|
||||||
to enumerate the device.
|
|
||||||
CONFIG_USBHOST_NPREALLOC
|
CONFIG_USBHOST_NPREALLOC
|
||||||
Number of pre-allocated class instances
|
Number of pre-allocated class instances
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
message("nsh_waiter: Running\n");
|
message("nsh_waiter: Running\n");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBHOST_HAVERHSC
|
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, connected);
|
||||||
@@ -189,39 +188,6 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Is the device connected? */
|
|
||||||
|
|
||||||
if (connected)
|
|
||||||
{
|
|
||||||
/* Yes.. wait for the disconnect event */
|
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, false);
|
|
||||||
DEBUGASSERT(ret == OK);
|
|
||||||
|
|
||||||
connected = false;
|
|
||||||
message("nsh_waiter: Not connected\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Wait a bit */
|
|
||||||
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
/* Try to enumerate the device */
|
|
||||||
|
|
||||||
uvdbg("nsh_usbhostinitialize: Enumerate device\n");
|
|
||||||
ret = DRVR_ENUMERATE(g_drvr);
|
|
||||||
if (ret != OK)
|
|
||||||
{
|
|
||||||
uvdbg("nsh_usbhostinitialize: Enumeration failed: %d\n", ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message("nsh_usbhostinitialize: Connected\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep the compiler from complaining */
|
/* Keep the compiler from complaining */
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
message("nsh_waiter: Running\n");
|
message("nsh_waiter: Running\n");
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USBHOST_HAVERHSC
|
|
||||||
/* Wait for the device to change state */
|
/* Wait for the device to change state */
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, connected);
|
ret = DRVR_WAIT(g_drvr, connected);
|
||||||
@@ -182,39 +181,6 @@ static int nsh_waiter(int argc, char *argv[])
|
|||||||
|
|
||||||
(void)DRVR_ENUMERATE(g_drvr);
|
(void)DRVR_ENUMERATE(g_drvr);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Is the device connected? */
|
|
||||||
|
|
||||||
if (connected)
|
|
||||||
{
|
|
||||||
/* Yes.. wait for the disconnect event */
|
|
||||||
|
|
||||||
ret = DRVR_WAIT(g_drvr, false);
|
|
||||||
DEBUGASSERT(ret == OK);
|
|
||||||
|
|
||||||
connected = false;
|
|
||||||
message("nsh_waiter: Not connected\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Wait a bit */
|
|
||||||
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
/* Try to enumerate the device */
|
|
||||||
|
|
||||||
uvdbg("nsh_usbhostinitialize: Enumerate device\n");
|
|
||||||
ret = DRVR_ENUMERATE(g_drvr);
|
|
||||||
if (ret != OK)
|
|
||||||
{
|
|
||||||
uvdbg("nsh_usbhostinitialize: Enumeration failed: %d\n", ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message("nsh_usbhostinitialize: Connected\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep the compiler from complaining */
|
/* Keep the compiler from complaining */
|
||||||
|
|||||||
@@ -226,26 +226,19 @@
|
|||||||
|
|
||||||
/* HcRhStatus: Root hub status (7.4.3) */
|
/* HcRhStatus: Root hub status (7.4.3) */
|
||||||
|
|
||||||
#define OHCI_RHSTATUS_LPS (1 << 0) /* Bit 0: Local power status */
|
#define OHCI_RHSTATUS_LPS (1 << 0) /* Bit 0: Local power status (read)*/
|
||||||
|
#define OHCI_RHSTATUS_CGP (1 << 0) /* Bit 0: Clear global power (write)*/
|
||||||
#define OHCI_RHSTATUS_OCI (1 << 1) /* Bit 1: Over current indicator */
|
#define OHCI_RHSTATUS_OCI (1 << 1) /* Bit 1: Over current indicator */
|
||||||
/* Bits 2-14: Reserved */
|
/* Bits 2-14: Reserved */
|
||||||
#define OHCI_RHSTATUS_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */
|
#define OHCI_RHSTATUS_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */
|
||||||
#define OHCI_RHSTATUS_LPSC (1 << 16) /* Bit 16: Local power status change */
|
#define OHCI_RHSTATUS_LPSC (1 << 16) /* Bit 16: Local power status change (read) */
|
||||||
|
#define OHCI_RHSTATUS_SGP (1 << 16) /* Bit 16: Set global power (write) */
|
||||||
#define OHCI_RHSTATUS_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */
|
#define OHCI_RHSTATUS_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */
|
||||||
/* Bits 18-30: Reserved */
|
/* Bits 18-30: Reserved */
|
||||||
#define OHCI_RHSTATUS_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */
|
#define OHCI_RHSTATUS_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */
|
||||||
|
|
||||||
/* HcRhPortStatus: Root hub port status (7.4.4) */
|
/* HcRhPortStatus: Root hub port status (7.4.4) */
|
||||||
|
|
||||||
#define OHCI_RHPORTST_LPS (1 << 0) /* Bit 0: Local power status */
|
|
||||||
#define OHCI_RHPORTST_OCI (1 << 1) /* Bit 1: Over current indicator */
|
|
||||||
/* Bits 2-14: Reserved */
|
|
||||||
#define OHCI_RHPORTST_DRWE (1 << 15) /* Bit 15: Device remote wakeup enable */
|
|
||||||
#define OHCI_RHPORTST_LPSC (1 << 16) /* Bit 16: Local power status change */
|
|
||||||
#define OHCI_RHPORTST_OCIC (1 << 17) /* Bit 17: Overcurrent indicator change */
|
|
||||||
/* Bits 18-30: Reserved */
|
|
||||||
#define OHCI_RHPORTST_CRWE (1 << 31) /* Bit 31: Clear remote wakeup enable */
|
|
||||||
|
|
||||||
#define OHCI_RHPORTST_CCS (1 << 0) /* Bit 0: Current connect status */
|
#define OHCI_RHPORTST_CCS (1 << 0) /* Bit 0: Current connect status */
|
||||||
#define OHCI_RHPORTST_PES (1 << 1) /* Bit 1: Port enable status*/
|
#define OHCI_RHPORTST_PES (1 << 1) /* Bit 1: Port enable status*/
|
||||||
#define OHCI_RHPORTST_PSS (1 << 2) /* Bit 2: Port suspend status */
|
#define OHCI_RHPORTST_PSS (1 << 2) /* Bit 2: Port suspend status */
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ struct usbhost_class_s
|
|||||||
struct usbhost_epdesc_s;
|
struct usbhost_epdesc_s;
|
||||||
struct usbhost_driver_s
|
struct usbhost_driver_s
|
||||||
{
|
{
|
||||||
/* Wait for a device to connect or disconnect (see CONFIG_USBHOST_HAVERHSC). */
|
/* Wait for a device to connect or disconnect. */
|
||||||
|
|
||||||
int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected);
|
int (*wait)(FAR struct usbhost_driver_s *drvr, bool connected);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user