SAMA5: Add support for sharing ports when both OHCI and EHCI are enabled

This commit is contained in:
Gregory Nutt 2013-08-23 10:58:30 -06:00
parent e59924a9e6
commit 189174e26b
4 changed files with 172 additions and 24 deletions

View File

@ -370,7 +370,7 @@ config SAMA5_OHCI_REGDEBUG
default n
depends on DEBUG
endif # OHCI
endif # SAMA5_OHCI
config SAMA5_EHCI
bool "High speed EHCI support"
@ -408,7 +408,75 @@ config SAMA5_EHCI_REGDEBUG
default n
depends on DEBUG
endif # EHCI
endif # SAMA5_EHCI
if SAMA5_OHCI && SAMA5_EHCI
config SAMA5_OHCI_RHPORT1
bool "Use Port A for OHCI"
default n
depends on !SAMA5_UDPHS
config SAMA5_OHCI_RHPORT2
bool "Use Port B for OHCI"
default n
config SAMA5_OHCI_RHPORT3
bool "Use Port C for OHCI"
default y
config SAMA5_EHCI_RHPORT1
bool
default y if !SAMA5_OHCI_RHPORT1
default n if SAMA5_OHCI_RHPORT1
depends on !SAMA5_UDPHS
config SAMA5_EHCI_RHPORT2
bool
default y if !SAMA5_OHCI_RHPORT2
default n if SAMA5_OHCI_RHPORT2
config SAMA5_EHCI_RHPORT3
bool
default y if !SAMA5_OHCI_RHPORT3
default n if SAMA5_OHCI_RHPORT3
endif # SAMA5_OHCI && SAMA5_EHCI
if SAMA5_OHCI && !SAMA5_EHCI
config SAMA5_OHCI_RHPORT1
bool
default y
depends on !SAMA5_UDPHS
config SAMA5_OHCI_RHPORT2
bool
default y
config SAMA5_OHCI_RHPORT3
bool
default y
endif # SAMA5_OHCI && !SAMA5_EHCI
if !SAMA5_OHCI && SAMA5_EHCI
config SAMA5_EHCI_RHPORT1
bool
default y
depends on !SAMA5_UDPHS
config SAMA5_EHCI_RHPORT2
bool
default y
config SAMA5_EHCI_RHPORT3
bool
default y
endif # !SAMA5_OHCI && SAMA5_EHCI
endmenu # USB High Speed Host driver option
endif # SAMA5_UHPHS

View File

@ -60,6 +60,7 @@
#include "sam_periphclks.h"
#include "sam_memories.h"
#include "sam_usbhost.h"
#include "chip/sam_sfr.h"
#include "chip/sam_ehci.h"
#ifdef CONFIG_SAMA5_EHCI
@ -110,6 +111,18 @@
#undef CONFIG_USBHOST_ISOC_DISABLE
#define CONFIG_USBHOST_ISOC_DISABLE 1
/* If UDPHS is enabled, then don't use port A */
#ifdef CONFIG_SAMA5_UDPHS
# undef CONFIG_SAMA5_EHCI_RHPORT1
#endif
/* For now, suppress use of PORTA in any event. I use that for SAM-BA and
* would prefer that the board not try to drive VBUS on that port!
*/
#undef CONFIG_SAMA5_EHCI_RHPORT1
/* Driver-private Definitions **************************************************/
/* This is the set of interrupts handled by this driver */
@ -874,7 +887,7 @@ static int sam_qh_foreach(struct sam_qh_s *qh, uint32_t **bp, foreach_qh_t handl
* the end of the asynchronous queue?
*/
else if (sam_virtramaddr(physaddr & QH_HLP_MASK) == &g_asynchead)
else if (sam_virtramaddr(physaddr & QH_HLP_MASK) == (uintptr_t)&g_asynchead)
{
/* That will also terminate the loop */
@ -1973,16 +1986,16 @@ static int sam_qtd_ioccheck(struct sam_qtd_s *qtd, uint32_t **bp, void *arg)
(uintptr_t)&qtd->hw + sizeof(struct ehci_qtd_s));
sam_qtd_print(qtd);
/* Remove the qTD from the list */
/* Remove the qTD from the list
*
* NOTE that we don't check if the qTD is active nor do we check if there
* are any errors reported in the qTD. If the transfer halted due to
* an error, then qTDs in the list after the error qTD will still appear
* to be active.
*/
**bp = qtd->hw.nqp;
/* NOTE that we don't check if the qTD is active nor do we check if there
* are any errors reported in the qTD. If the transfer halted due to
* an error, then I am not sure if we can believe this information anyway.
* The only sure place to check for errors in in the QH overlay.
*/
/* Release this QH by returning it to the free list */
sam_qtd_free(qtd);
@ -2064,6 +2077,7 @@ static int sam_qh_ioccheck(struct sam_qh_s *qh, uint32_t **bp, void *arg)
*/
**bp = qh->hw.hlp;
cp15_coherent_dcache((uintptr_t)*bp, (uintptr_t)*bp + sizeof(uint32_t));
/* Check for errors, update the data toggle */
@ -3377,9 +3391,30 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
regval = sam_getreg((volatile uint32_t *)SAM_PMC_SCER);
regval |= PMC_UHP;
sam_putreg(regval, (volatile uint32_t *)SAM_PMC_SCER);
/* "One transceiver is shared with the USB High Speed Device (port A). The
* selection between Host Port A and USB Device is controlled by the UDPHS
* enable bit (EN_UDPHS) located in the UDPHS_CTRL control register."
*
* Make all three ports usable for EHCI unless the high speed device is
* enabled; then let the device manage port zero. Zero is the reset
* value for all ports; one makes the corresponding port available to OHCI.
*/
regval = getreg32(SAM_SFR_OHCIICR);
#ifdef CONFIG_SAMA5_EHCI_RHPORT1
regval &= ~SFR_OHCIICR_RES1;
#endif
#ifdef CONFIG_SAMA5_EHCI_RHPORT2
regval &= ~SFR_OHCIICR_RES1;
#endif
#ifdef CONFIG_SAMA5_EHCI_RHPORT3
regval &= ~SFR_OHCIICR_RES2;
#endif
putreg32(regval, SAM_SFR_OHCIICR);
irqrestore(flags);
/* Note that no pin pinconfiguration is required. All USB HS pins have
/* Note that no pin configuration is required. All USB HS pins have
* dedicated function
*/
@ -3631,7 +3666,15 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
* mode.
*/
sam_usbhost_vbusdrive(SAM_EHCI_IFACE, true);
#ifndef CONFIG_SAMA5_EHCI_RHPORT1
sam_usbhost_vbusdrive(SAM_RHPORT1, true);
#endif
#ifndef CONFIG_SAMA5_EHCI_RHPORT2
sam_usbhost_vbusdrive(SAM_RHPORT2, true);
#endif
#ifndef CONFIG_SAMA5_EHCI_RHPORT3
sam_usbhost_vbusdrive(SAM_RHPORT3, true);
#endif
up_mdelay(50);
/* If there is a USB device in the slot at power up, then we will not

View File

@ -117,6 +117,18 @@
#define SAM_BUFALLOC (CONFIG_SAMA5_OHCI_TDBUFFERS * CONFIG_SAMA5_OHCI_TDBUFSIZE)
/* If UDPHS is enabled, then don't use port A */
#ifdef CONFIG_SAMA5_UDPHS
# undef CONFIG_SAMA5_OHCI_RHPORT1
#endif
/* For now, suppress use of PORTA in any event. I use that for SAM-BA and
* would prefer that the board not try to drive VBUS on that port!
*/
#undef CONFIG_SAMA5_OHCI_RHPORT1
/* Debug */
#ifndef CONFIG_DEBUG
@ -3013,20 +3025,30 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
regval = getreg32(SAM_PMC_SCER);
regval |= PMC_UHP;
putreg32(regval, SAM_PMC_SCER);
irqrestore(flags);
/* Make all three ports usable. Zero is the reset value and holds the
* ports in reset.
* REVISIT: This will have to change in future. Should be a configuration
* setting
/* "One transceiver is shared with the USB High Speed Device (port A). The
* selection between Host Port A and USB Device is controlled by the UDPHS
* enable bit (EN_UDPHS) located in the UDPHS_CTRL control register."
*
* Make all three ports usable for OHCI unless the high speed device is
* enabled; then let the device manage port zero. Zero is the reset
* value for all ports; one makes the corresponding port available to OHCI.
*/
regval = getreg32(SAM_SFR_OHCIICR);
regval |= (SFR_OHCIICR_RES0 | SFR_OHCIICR_RES1 | SFR_OHCIICR_RES2);
#ifdef CONFIG_SAMA5_OHCI_RHPORT1
regval |= SFR_OHCIICR_RES1;
#endif
#ifdef CONFIG_SAMA5_OHCI_RHPORT2
regval |= SFR_OHCIICR_RES1;
#endif
#ifdef CONFIG_SAMA5_OHCI_RHPORT3
regval |= SFR_OHCIICR_RES2;
#endif
putreg32(regval, SAM_SFR_OHCIICR);
irqrestore(flags);
/* Note that no pin pinconfiguration is required. All USB HS pins have
/* Note that no pin configuration is required. All USB HS pins have
* dedicated function
*/
@ -3140,7 +3162,15 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
* mode.
*/
sam_usbhost_vbusdrive(SAM_OHCI_IFACE, true);
#ifndef CONFIG_SAMA5_OHCI_RHPORT1
sam_usbhost_vbusdrive(SAM_RHPORT1, true);
#endif
#ifndef CONFIG_SAMA5_OHCI_RHPORT2
sam_usbhost_vbusdrive(SAM_RHPORT2, true);
#endif
#ifndef CONFIG_SAMA5_OHCI_RHPORT3
sam_usbhost_vbusdrive(SAM_RHPORT3, true);
#endif
up_mdelay(50);
/* If there is a USB device in the slot at power up, then we will not

View File

@ -54,6 +54,14 @@
#define SAM_EHCI_IFACE 0
#define SAM_OHCI_IFACE 1
/* This is the interface argument for call outs to board-specific functions which
* need to know which root hub port is being used.
*/
#define SAM_RHPORT1 0
#define SAM_RHPORT2 1
#define SAM_RHPORT3 2
/************************************************************************************
* Public Types
************************************************************************************/
@ -149,9 +157,8 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller);
* each platform that implements the OHCI or EHCI host interface
*
* Input Parameters:
* iface - Selects USB host interface:
* 0 = EHCI
* 1 = OHCI
* rhport - Selects root hub port to be powered host interface. See SAM_RHPORT_*
* definitions above.
* enable - true: enable VBUS power; false: disable VBUS power
*
* Returned Value:
@ -159,7 +166,7 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller);
*
***********************************************************************************/
void sam_usbhost_vbusdrive(int iface, bool enable);
void sam_usbhost_vbusdrive(int rhport, bool enable);
#undef EXTERN
#if defined(__cplusplus)