EHCI HUB: Fix some issues related to speed and device addresses
This commit is contained in:
parent
08b35f042b
commit
5c76c53909
@ -465,6 +465,7 @@ static int lpc31_qh_dump(struct lpc31_qh_s *qh, uint32_t **bp, void *arg);
|
||||
# define lpc31_qh_dump(qh, bp, arg) OK
|
||||
#endif
|
||||
|
||||
static inline uint8_t lpc31_ehci_speed(uint8_t usbspeed);
|
||||
static int lpc31_ioc_setup(struct lpc31_rhport_s *rhport,
|
||||
struct lpc31_epinfo_s *epinfo);
|
||||
static int lpc31_ioc_wait(struct lpc31_epinfo_s *epinfo);
|
||||
@ -565,6 +566,13 @@ static struct lpc31_ehci_s g_ehci;
|
||||
|
||||
static struct usbhost_connection_s g_ehciconn;
|
||||
|
||||
/* Maps USB chapter 9 speed to EHCI speed */
|
||||
|
||||
static const uint8_t g_ehci_speed[4] =
|
||||
{
|
||||
0, EHCI_LOW_SPEED, EHCI_FULL_SPEED, EHCI_HIGH_SPEED
|
||||
};
|
||||
|
||||
/* The head of the asynchronous queue */
|
||||
|
||||
static struct lpc31_qh_s g_asynchead __attribute__ ((aligned(32)));
|
||||
@ -1528,6 +1536,21 @@ static int lpc31_qh_dump(struct lpc31_qh_s *qh, uint32_t **bp, void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: lpc31_ehci_speed
|
||||
*
|
||||
* Description:
|
||||
* Map a speed enumeration value per Chapter 9 of the USB specification to the
|
||||
* speed enumeration required in the EHCI queue head.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static inline uint8_t lpc31_ehci_speed(uint8_t usbspeed)
|
||||
{
|
||||
DEBUGASSERT(usbspeed >= USB_SPEED_LOW && usbspeed <= USB_SPEED_HIGH);
|
||||
return g_ehci_speed[usbspeed];
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: lpc31_ioc_setup
|
||||
*
|
||||
@ -1654,6 +1677,8 @@ static struct lpc31_qh_s *lpc31_qh_create(struct lpc31_rhport_s *rhport,
|
||||
struct lpc31_qh_s *qh;
|
||||
uint32_t rhpndx;
|
||||
uint32_t regval;
|
||||
uint8_t hubaddr;
|
||||
uint8_t hubport;
|
||||
|
||||
/* Allocate a new queue head structure */
|
||||
|
||||
@ -1684,7 +1709,7 @@ static struct lpc31_qh_s *lpc31_qh_create(struct lpc31_rhport_s *rhport,
|
||||
|
||||
regval = ((uint32_t)epinfo->devaddr << QH_EPCHAR_DEVADDR_SHIFT) |
|
||||
((uint32_t)epinfo->epno << QH_EPCHAR_ENDPT_SHIFT) |
|
||||
((uint32_t)EHCI_SPEED(epinfo->speed) << QH_EPCHAR_EPS_SHIFT) |
|
||||
((uint32_t)lpc31_ehci_speed(epinfo->speed) << QH_EPCHAR_EPS_SHIFT) |
|
||||
QH_EPCHAR_DTC |
|
||||
((uint32_t)epinfo->maxpacket << QH_EPCHAR_MAXPKT_SHIFT) |
|
||||
((uint32_t)8 << QH_EPCHAR_RL_SHIFT);
|
||||
@ -1714,14 +1739,33 @@ static struct lpc31_qh_s *lpc31_qh_create(struct lpc31_rhport_s *rhport,
|
||||
* HUBADDR Hub Address Always 0 for now
|
||||
* PORT Port number RH port index + 1
|
||||
* MULT High band width multiplier 1
|
||||
*
|
||||
* REVISIT: Future HUB support will require the HUB port number
|
||||
* and HUB device address to be included here.
|
||||
*/
|
||||
|
||||
rhpndx = RHPNDX(rhport);
|
||||
regval = ((uint32_t)0 << QH_EPCAPS_HUBADDR_SHIFT) |
|
||||
((uint32_t)(rhpndx + 1) << QH_EPCAPS_PORT_SHIFT) |
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/* REVISIT: Future HUB support will require the HUB port number
|
||||
* and HUB device address to be included here:
|
||||
*
|
||||
* - The HUB device address is the USB device address of the USB 2.0 Hub
|
||||
* below which a full- or low-speed device is attached.
|
||||
* - The HUB port number is the port number on the above USB 2.0 Hub
|
||||
*
|
||||
* These fields are used in the split-transaction protocol. The kludge
|
||||
* below should work for hubs connected directly to a root hub port,
|
||||
* but would not work for devices connected to downstream hubs.
|
||||
*/
|
||||
|
||||
#warning Missing logic
|
||||
hubaddr = rhport->ep0.devaddr;
|
||||
hubport = rhpndx + 1;
|
||||
#else
|
||||
hubaddr = rhport->ep0.devaddr;
|
||||
hubport = rhpndx + 1;
|
||||
#endif
|
||||
|
||||
regval = ((uint32_t)hubaddr << QH_EPCAPS_HUBADDR_SHIFT) |
|
||||
((uint32_t)hubport << QH_EPCAPS_PORT_SHIFT) |
|
||||
((uint32_t)1 << QH_EPCAPS_MULT_SHIFT);
|
||||
|
||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||
@ -3562,7 +3606,7 @@ static int lpc31_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
* repeat."
|
||||
*/
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_LOW;
|
||||
hport->speed = USB_SPEED_LOW;
|
||||
|
||||
#if 0 /* The LPC31xx does not support a companion host controller */
|
||||
regval |= EHCI_PORTSC_OWNER;
|
||||
@ -3578,7 +3622,7 @@ static int lpc31_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
{
|
||||
/* Assume full-speed for now */
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_FULL;
|
||||
hport->speed = USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
/* Put the root hub port in reset.
|
||||
@ -3675,7 +3719,7 @@ static int lpc31_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
{
|
||||
/* High speed device */
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_HIGH;
|
||||
hport->speed = USB_SPEED_HIGH;
|
||||
}
|
||||
else if ((regval & USBDEV_PRTSC1_PSPD_MASK) == USBDEV_PRTSC1_PSPD_FS)
|
||||
{
|
||||
@ -3695,7 +3739,7 @@ static int lpc31_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
* repeat."
|
||||
*/
|
||||
|
||||
DEBUGASSERT(rhport->ep0.speed == USB_SPEED_FULL);
|
||||
DEBUGASSERT(hport->speed == USB_SPEED_FULL);
|
||||
|
||||
#if 0 /* The LPC31xx does not support a companion host controller */
|
||||
regval |= EHCI_PORTSC_OWNER;
|
||||
@ -3712,7 +3756,7 @@ static int lpc31_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
|
||||
else
|
||||
{
|
||||
DEBUGASSERT(rhport->ep0.speed == USB_SPEED_LOW);
|
||||
DEBUGASSERT(hport->speed == USB_SPEED_LOW);
|
||||
DEBUGASSERT((regval & USBDEV_PRTSC1_PSPD_MASK) == USBDEV_PRTSC1_PSPD_LS);
|
||||
}
|
||||
|
||||
@ -3794,6 +3838,7 @@ static int lpc31_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep
|
||||
/* Remember the new device address and max packet size */
|
||||
|
||||
epinfo->devaddr = funcaddr;
|
||||
epinfo->speed = speed;
|
||||
epinfo->maxpacket = maxpacketsize;
|
||||
|
||||
lpc31_givesem(&g_ehci.exclsem);
|
||||
|
@ -345,6 +345,7 @@ static int sam_qh_dump(struct sam_qh_s *qh, uint32_t **bp, void *arg);
|
||||
# define sam_qh_dump(qh, bp, arg) OK
|
||||
#endif
|
||||
|
||||
static inline uint8_t sam_ehci_speed(uint8_t usbspeed);
|
||||
static int sam_ioc_setup(struct sam_rhport_s *rhport, struct sam_epinfo_s *epinfo);
|
||||
static int sam_ioc_wait(struct sam_epinfo_s *epinfo);
|
||||
static void sam_qh_enqueue(struct sam_qh_s *qhead, struct sam_qh_s *qh);
|
||||
@ -442,6 +443,13 @@ static struct sam_ehci_s g_ehci;
|
||||
|
||||
static struct usbhost_connection_s g_ehciconn;
|
||||
|
||||
/* Maps USB chapter 9 speed to EHCI speed */
|
||||
|
||||
static const uint8_t g_ehci_speed[4] =
|
||||
{
|
||||
0, EHCI_LOW_SPEED, EHCI_FULL_SPEED, EHCI_HIGH_SPEED
|
||||
};
|
||||
|
||||
/* The head of the asynchronous queue */
|
||||
|
||||
static struct sam_qh_s g_asynchead __attribute__ ((aligned(32)));
|
||||
@ -1343,6 +1351,21 @@ static int sam_qh_dump(struct sam_qh_s *qh, uint32_t **bp, void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: sam_ehci_speed
|
||||
*
|
||||
* Description:
|
||||
* Map a speed enumeration value per Chapter 9 of the USB specification to the
|
||||
* speed enumeration required in the EHCI queue head.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static inline uint8_t sam_ehci_speed(uint8_t usbspeed)
|
||||
{
|
||||
DEBUGASSERT(usbspeed >= USB_SPEED_LOW && usbspeed <= USB_SPEED_HIGH);
|
||||
return g_ehci_speed[usbspeed];
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: sam_ioc_setup
|
||||
*
|
||||
@ -1469,6 +1492,8 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
||||
struct sam_qh_s *qh;
|
||||
uint32_t rhpndx;
|
||||
uint32_t regval;
|
||||
uint8_t hubaddr;
|
||||
uint8_t hubport;
|
||||
|
||||
/* Allocate a new queue head structure */
|
||||
|
||||
@ -1499,7 +1524,7 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
||||
|
||||
regval = ((uint32_t)epinfo->devaddr << QH_EPCHAR_DEVADDR_SHIFT) |
|
||||
((uint32_t)epinfo->epno << QH_EPCHAR_ENDPT_SHIFT) |
|
||||
((uint32_t)EHCI_SPEED(epinfo->speed) << QH_EPCHAR_EPS_SHIFT) |
|
||||
((uint32_t)sam_ehci_speed(epinfo->speed) << QH_EPCHAR_EPS_SHIFT) |
|
||||
QH_EPCHAR_DTC |
|
||||
((uint32_t)epinfo->maxpacket << QH_EPCHAR_MAXPKT_SHIFT) |
|
||||
((uint32_t)8 << QH_EPCHAR_RL_SHIFT);
|
||||
@ -1529,14 +1554,33 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
||||
* HUBADDR Hub Address Always 0 for now
|
||||
* PORT Port number RH port index + 1
|
||||
* MULT High band width multiplier 1
|
||||
*
|
||||
* REVISIT: Future HUB support will require the HUB port number
|
||||
* and HUB device address to be included here.
|
||||
*/
|
||||
|
||||
rhpndx = RHPNDX(rhport);
|
||||
regval = ((uint32_t)0 << QH_EPCAPS_HUBADDR_SHIFT) |
|
||||
((uint32_t)(rhpndx + 1) << QH_EPCAPS_PORT_SHIFT) |
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB
|
||||
/* REVISIT: Future HUB support will require the HUB port number
|
||||
* and HUB device address to be included here:
|
||||
*
|
||||
* - The HUB device address is the USB device address of the USB 2.0 Hub
|
||||
* below which a full- or low-speed device is attached.
|
||||
* - The HUB port number is the port number on the above USB 2.0 Hub
|
||||
*
|
||||
* These fields are used in the split-transaction protocol. The kludge
|
||||
* below should work for hubs connected directly to a root hub port,
|
||||
* but would not work for devices connected to downstream hubs.
|
||||
*/
|
||||
|
||||
#warning Missing logic
|
||||
hubaddr = rhport->ep0.devaddr;
|
||||
hubport = rhpndx + 1;
|
||||
#else
|
||||
hubaddr = rhport->ep0.devaddr;
|
||||
hubport = rhpndx + 1;
|
||||
#endif
|
||||
|
||||
regval = ((uint32_t)hubaddr << QH_EPCAPS_HUBADDR_SHIFT) |
|
||||
((uint32_t)hubport << QH_EPCAPS_PORT_SHIFT) |
|
||||
((uint32_t)1 << QH_EPCAPS_MULT_SHIFT);
|
||||
|
||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||
@ -3402,7 +3446,7 @@ static int sam_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
* repeat."
|
||||
*/
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_LOW;
|
||||
hport->speed = USB_SPEED_LOW;
|
||||
regval |= EHCI_PORTSC_OWNER;
|
||||
sam_putreg(regval, &HCOR->portsc[rhpndx]);
|
||||
|
||||
@ -3425,7 +3469,7 @@ static int sam_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
{
|
||||
/* Assume full-speed for now */
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_FULL;
|
||||
hport->speed = USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
/* Put the root hub port in reset.
|
||||
@ -3504,7 +3548,7 @@ static int sam_rh_enumerate(FAR struct usbhost_connection_s *conn,
|
||||
{
|
||||
/* High speed device */
|
||||
|
||||
rhport->ep0.speed = USB_SPEED_HIGH;
|
||||
hport->speed = USB_SPEED_HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3621,6 +3665,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
||||
/* Remember the new device address and max packet size */
|
||||
|
||||
epinfo->devaddr = funcaddr;
|
||||
epinfo->speed = speed;
|
||||
epinfo->maxpacket = maxpacketsize;
|
||||
|
||||
sam_givesem(&g_ehci.exclsem);
|
||||
|
@ -51,13 +51,12 @@
|
||||
********************************************************************************************/
|
||||
/* General definitions **********************************************************************/
|
||||
/* Endpoint speed values as used in endpoint characteristics field. NOTE: These values
|
||||
* are assumed to equal to the SPEED definitions in usb.h (minus 1).
|
||||
* are *NOT* the same as the SPEED definitions in usb.h.
|
||||
*/
|
||||
|
||||
#define EHCI_FULL_SPEED (0) /* Full-Speed (12Mbs) */
|
||||
#define EHCI_LOW_SPEED (1) /* Low-Speed (1.5Mbs) */
|
||||
#define EHCI_HIGH_SPEED (2) /* High-Speed (480 Mb/s) */
|
||||
#define EHCI_SPEED(s) ((s)-1)
|
||||
|
||||
#define EHCI_DIR_IN (1) /* Direction IN: Peripheral to host */
|
||||
#define EHCI_DIR_OUT (0) /* Direction OUT: Host to peripheral */
|
||||
|
Loading…
Reference in New Issue
Block a user