SAMA5 OHCI: Use physical address and flush and/or invalidate data caches as necessary

This commit is contained in:
Gregory Nutt 2013-08-14 12:23:06 -06:00
parent bdbe4a4f25
commit e32b60a78c
4 changed files with 617 additions and 169 deletions

View File

@ -348,15 +348,15 @@ config SAMA5_OHCI
if SAMA5_OHCI if SAMA5_OHCI
config SAMA5_OHCI_NEDS config SAMA5_OHCI_NEDS
int "Number of endpoint descriptors" int "Number of endpoint descriptors"
default 2 default 6
config SAMA5_OHCI_NTDS config SAMA5_OHCI_NTDS
int "Number of transfer descriptors" int "Number of transfer descriptors"
default 3 default 9
config SAMA5_OHCI_TDBUFFERS config SAMA5_OHCI_TDBUFFERS
int "Number of transfer descriptor buffers" int "Number of transfer descriptor buffers"
default 2 default 6
config SAMA5_OHCI_TDBUFSIZE config SAMA5_OHCI_TDBUFSIZE
int "Size of one transfer descriptor buffer" int "Size of one transfer descriptor buffer"

View File

@ -58,19 +58,19 @@
* Name: peripha_physregaddr * Name: peripha_physregaddr
* *
* Description: * Description:
* Give the virtual address of a peripheral A register, return the * Given the virtual address of a peripheral A register, return the
* physical address of the register * physical address of the register
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t peripha_physregaddr(uintptr_t vregaddr) static inline uintptr_t peripha_physregaddr(uintptr_t virtregaddr)
{ {
#if SAM_PERIPHA_PSECTION != SAM_PERIPHA_VSECTION #if SAM_PERIPHA_PSECTION != SAM_PERIPHA_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* register * register
*/ */
uintptr_t sectoffset = vregaddr - SAM_PERIPHA_VSECTION; uintptr_t sectoffset = virtregaddr - SAM_PERIPHA_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -79,7 +79,7 @@ static inline uintptr_t peripha_physregaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtregaddr;
#endif #endif
} }
@ -88,19 +88,19 @@ static inline uintptr_t peripha_physregaddr(uintptr_t vregaddr)
* Name: periphb_physregaddr * Name: periphb_physregaddr
* *
* Description: * Description:
* Give the virtual address of a peripheral B register, return the * Given the virtual address of a peripheral B register, return the
* physical address of the register * physical address of the register
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t periphb_physregaddr(uintptr_t vregaddr) static inline uintptr_t periphb_physregaddr(uintptr_t virtregaddr)
{ {
#if SAM_PERIPHB_PSECTION != SAM_PERIPHB_VSECTION #if SAM_PERIPHB_PSECTION != SAM_PERIPHB_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* register * register
*/ */
uintptr_t sectoffset = vregaddr - SAM_PERIPHB_VSECTION; uintptr_t sectoffset = virtregaddr - SAM_PERIPHB_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -109,7 +109,7 @@ static inline uintptr_t periphb_physregaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtregaddr;
#endif #endif
} }
@ -118,19 +118,19 @@ static inline uintptr_t periphb_physregaddr(uintptr_t vregaddr)
* Name: sysc_physregaddr * Name: sysc_physregaddr
* *
* Description: * Description:
* Give the virtual address of a system controller register, return the * Given the virtual address of a system controller register, return the
* physical address of the register * physical address of the register
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t sysc_physregaddr(uintptr_t vregaddr) static inline uintptr_t sysc_physregaddr(uintptr_t virtregaddr)
{ {
#if SAM_SYSC_PSECTION != SAM_SYSC_VSECTION #if SAM_SYSC_PSECTION != SAM_SYSC_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* register * register
*/ */
uintptr_t sectoffset = vregaddr - SAM_SYSC_VSECTION; uintptr_t sectoffset = virtregaddr - SAM_SYSC_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -139,7 +139,7 @@ static inline uintptr_t sysc_physregaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtregaddr;
#endif #endif
} }
@ -148,19 +148,19 @@ static inline uintptr_t sysc_physregaddr(uintptr_t vregaddr)
* Name: isram_physramaddr * Name: isram_physramaddr
* *
* Description: * Description:
* Give the virtual address of an internal SRAM memory location, return the * Given the virtual address of an internal SRAM memory location, return the
* physical address of that location * physical address of that location
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t isram_physramaddr(uintptr_t vregaddr) static inline uintptr_t isram_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_ISRAM_PSECTION != SAM_ISRAM_VSECTION #if SAM_ISRAM_PSECTION != SAM_ISRAM_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_ISRAM_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_ISRAM_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -169,7 +169,7 @@ static inline uintptr_t isram_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -178,20 +178,20 @@ static inline uintptr_t isram_physramaddr(uintptr_t vregaddr)
* Name: sdram_physramaddr * Name: sdram_physramaddr
* *
* Description: * Description:
* Give the virtual address of an external SDRAM memory location, return * Given the virtual address of an external SDRAM memory location, return
* the physical address of that location * the physical address of that location
* *
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SAMA5_DDRCS #ifdef CONFIG_SAMA5_DDRCS
static inline uintptr_t sdram_physramaddr(uintptr_t vregaddr) static inline uintptr_t sdram_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_DDRCS_PSECTION != SAM_DDRCS_VSECTION #if SAM_DDRCS_PSECTION != SAM_DDRCS_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_DDRCS_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_DDRCS_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -200,7 +200,7 @@ static inline uintptr_t sdram_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -210,19 +210,19 @@ static inline uintptr_t sdram_physramaddr(uintptr_t vregaddr)
* Name: nfcsram_physramaddr * Name: nfcsram_physramaddr
* *
* Description: * Description:
* Give the virtual address of an NFC SRAM memory location, return the * Given the virtual address of an NFC SRAM memory location, return the
* physical address of that location * physical address of that location
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t nfcsram_physramaddr(uintptr_t vregaddr) static inline uintptr_t nfcsram_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_NFCSRAM_PSECTION != SAM_NFCSRAM_VSECTION #if SAM_NFCSRAM_PSECTION != SAM_NFCSRAM_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_NFCSRAM_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_NFCSRAM_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -231,7 +231,7 @@ static inline uintptr_t nfcsram_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -240,19 +240,19 @@ static inline uintptr_t nfcsram_physramaddr(uintptr_t vregaddr)
* Name: udphsram_physramaddr * Name: udphsram_physramaddr
* *
* Description: * Description:
* Give the virtual address of an UDPH SRAM memory location, return the * Given the virtual address of an UDPH SRAM memory location, return the
* physical address of that location * physical address of that location
* *
****************************************************************************/ ****************************************************************************/
static inline uintptr_t udphsram_physramaddr(uintptr_t vregaddr) static inline uintptr_t udphsram_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_UDPHSRAM_PSECTION != SAM_UDPHSRAM_VSECTION #if SAM_UDPHSRAM_PSECTION != SAM_UDPHSRAM_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_UDPHSRAM_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_UDPHSRAM_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -261,7 +261,7 @@ static inline uintptr_t udphsram_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -270,21 +270,21 @@ static inline uintptr_t udphsram_physramaddr(uintptr_t vregaddr)
* Name: ebics0_physramaddr * Name: ebics0_physramaddr
* *
* Description: * Description:
* Give the virtual address of an external CS0 SRAM memory location, * Given the virtual address of an external CS0 SRAM memory location,
* return the physical address of that location * return the physical address of that location
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \ #if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \
defined(CONFIG_SAMA5_EBICS0_PSRAM)) defined(CONFIG_SAMA5_EBICS0_PSRAM))
static inline uintptr_t ebics0_physramaddr(uintptr_t vregaddr) static inline uintptr_t ebics0_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_EBICS0_PSECTION != SAM_EBICS0_VSECTION #if SAM_EBICS0_PSECTION != SAM_EBICS0_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_EBICS0_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_EBICS0_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -293,7 +293,7 @@ static inline uintptr_t ebics0_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -303,21 +303,21 @@ static inline uintptr_t ebics0_physramaddr(uintptr_t vregaddr)
* Name: ebics1_physramaddr * Name: ebics1_physramaddr
* *
* Description: * Description:
* Give the virtual address of an external CS1 SRAM memory location, * Given the virtual address of an external CS1 SRAM memory location,
* return the physical address of that location * return the physical address of that location
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS1) && (defined(CONFIG_SAMA5_EBICS1_SRAM) || \ #if defined(CONFIG_SAMA5_EBICS1) && (defined(CONFIG_SAMA5_EBICS1_SRAM) || \
defined(CONFIG_SAMA5_EBICS1_PSRAM)) defined(CONFIG_SAMA5_EBICS1_PSRAM))
static inline uintptr_t ebics1_physramaddr(uintptr_t vregaddr) static inline uintptr_t ebics1_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_EBICS1_PSECTION != SAM_EBICS1_VSECTION #if SAM_EBICS1_PSECTION != SAM_EBICS1_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_EBICS1_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_EBICS1_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -326,7 +326,7 @@ static inline uintptr_t ebics1_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -336,21 +336,21 @@ static inline uintptr_t ebics1_physramaddr(uintptr_t vregaddr)
* Name: ebics2_physramaddr * Name: ebics2_physramaddr
* *
* Description: * Description:
* Give the virtual address of an external CS2 SRAM memory location, * Given the virtual address of an external CS2 SRAM memory location,
* return the physical address of that location * return the physical address of that location
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS2) && (defined(CONFIG_SAMA5_EBICS2_SRAM) || \ #if defined(CONFIG_SAMA5_EBICS2) && (defined(CONFIG_SAMA5_EBICS2_SRAM) || \
defined(CONFIG_SAMA5_EBICS2_PSRAM)) defined(CONFIG_SAMA5_EBICS2_PSRAM))
static inline uintptr_t ebics2_physramaddr(uintptr_t vregaddr) static inline uintptr_t ebics2_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_EBICS2_PSECTION != SAM_EBICS2_VSECTION #if SAM_EBICS2_PSECTION != SAM_EBICS2_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_EBICS2_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_EBICS2_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -359,7 +359,7 @@ static inline uintptr_t ebics2_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif #endif
} }
@ -369,21 +369,21 @@ static inline uintptr_t ebics2_physramaddr(uintptr_t vregaddr)
* Name: ebics3_physramaddr * Name: ebics3_physramaddr
* *
* Description: * Description:
* Give the virtual address of an external CS3 SRAM memory location, * Given the virtual address of an external CS3 SRAM memory location,
* return the physical address of that location * return the physical address of that location
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS3) && (defined(CONFIG_SAMA5_EBICS3_SRAM) || \ #if defined(CONFIG_SAMA5_EBICS3) && (defined(CONFIG_SAMA5_EBICS3_SRAM) || \
defined(CONFIG_SAMA5_EBICS3_PSRAM)) defined(CONFIG_SAMA5_EBICS3_PSRAM))
static inline uintptr_t ebics3_physramaddr(uintptr_t vregaddr) static inline uintptr_t ebics3_physramaddr(uintptr_t virtramaddr)
{ {
#if SAM_EBICS3_PSECTION != SAM_EBICS3_VSECTION #if SAM_EBICS3_PSECTION != SAM_EBICS3_VSECTION
/* Get the offset into the virtual memory region section containing the /* Get the offset into the virtual memory region section containing the
* RAM memory location. * RAM memory location.
*/ */
uintptr_t sectoffset = vregaddr - SAM_EBICS3_VSECTION; uintptr_t sectoffset = virtramaddr - SAM_EBICS3_VSECTION;
/* Add that offset to the physical base address of the memory region */ /* Add that offset to the physical base address of the memory region */
@ -392,7 +392,261 @@ static inline uintptr_t ebics3_physramaddr(uintptr_t vregaddr)
#else #else
/* 1-to-1 mapping */ /* 1-to-1 mapping */
return vregaddr; return virtramaddr;
#endif
}
#endif
/****************************************************************************
* Name: isram_virtramaddr
*
* Description:
* Given the physical address of an internal SRAM memory location, return
* the virtual address of that location
*
****************************************************************************/
static inline uintptr_t isram_virtramaddr(uintptr_t physramaddr)
{
#if SAM_ISRAM_PSECTION != SAM_ISRAM_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_ISRAM_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_ISRAM_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
/****************************************************************************
* Name: sdram_virtramaddr
*
* Description:
* Given the physical address of an external SDRAM memory location, return
* the virtual address of that location
*
****************************************************************************/
#ifdef CONFIG_SAMA5_DDRCS
static inline uintptr_t sdram_virtramaddr(uintptr_t physramaddr)
{
#if SAM_DDRCS_PSECTION != SAM_DDRCS_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_DDRCS_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_DDRCS_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
#endif
/****************************************************************************
* Name: nfcsram_virtramaddr
*
* Description:
* Given the physical address of an NFC SRAM memory location, return the
* virtual address of that location
*
****************************************************************************/
static inline uintptr_t nfcsram_virtramaddr(uintptr_t physramaddr)
{
#if SAM_NFCSRAM_PSECTION != SAM_NFCSRAM_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_NFCSRAM_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_NFCSRAM_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
/****************************************************************************
* Name: udphsram_virtramaddr
*
* Description:
* Given the physical address of an UDPH SRAM memory location, return the
* virtual address of that location
*
****************************************************************************/
static inline uintptr_t udphsram_virtramaddr(uintptr_t physramaddr)
{
#if SAM_UDPHSRAM_PSECTION != SAM_UDPHSRAM_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_UDPHSRAM_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_UDPHSRAM_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
/****************************************************************************
* Name: ebics0_virtramaddr
*
* Description:
* Given the physical address of an external CS0 SRAM memory location,
* return the virtual address of that location
*
****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \
defined(CONFIG_SAMA5_EBICS0_PSRAM))
static inline uintptr_t ebics0_virtramaddr(uintptr_t physramaddr)
{
#if SAM_EBICS0_PSECTION != SAM_EBICS0_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_EBICS0_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_EBICS0_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
#endif
/****************************************************************************
* Name: ebics1_virtramaddr
*
* Description:
* Given the physical address of an external CS1 SRAM memory location,
* return the virtual address of that location
*
****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS1) && (defined(CONFIG_SAMA5_EBICS1_SRAM) || \
defined(CONFIG_SAMA5_EBICS1_PSRAM))
static inline uintptr_t ebics1_virtramaddr(uintptr_t physramaddr)
{
#if SAM_EBICS1_PSECTION != SAM_EBICS1_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_EBICS1_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_EBICS1_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
#endif
/****************************************************************************
* Name: ebics2_virtramaddr
*
* Description:
* Given the physical address of an external CS2 SRAM memory location,
* return the virtual address of that location
*
****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS2) && (defined(CONFIG_SAMA5_EBICS2_SRAM) || \
defined(CONFIG_SAMA5_EBICS2_PSRAM))
static inline uintptr_t ebics2_virtramaddr(uintptr_t physramaddr)
{
#if SAM_EBICS2_PSECTION != SAM_EBICS2_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_EBICS2_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_EBICS2_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif
}
#endif
/****************************************************************************
* Name: ebics3_virtramaddr
*
* Description:
* Given the physical address of an external CS3 SRAM memory location,
* return the virtual address of that location
*
****************************************************************************/
#if defined(CONFIG_SAMA5_EBICS3) && (defined(CONFIG_SAMA5_EBICS3_SRAM) || \
defined(CONFIG_SAMA5_EBICS3_PSRAM))
static inline uintptr_t ebics3_virtramaddr(uintptr_t physramaddr)
{
#if SAM_EBICS3_PSECTION != SAM_EBICS3_VSECTION
/* Get the offset into the virtual memory region section containing the
* RAM memory location.
*/
uintptr_t sectoffset = physramaddr - SAM_EBICS3_PSECTION;
/* Add that offset to the physical base address of the memory region */
return SAM_EBICS3_VSECTION + sectoffset;
#else
/* 1-to-1 mapping */
return physramaddr;
#endif #endif
} }
@ -406,35 +660,35 @@ static inline uintptr_t ebics3_physramaddr(uintptr_t vregaddr)
* Name: sam_physregaddr * Name: sam_physregaddr
* *
* Description: * Description:
* Give the virtual address of a register, return the physical address of * Given the virtual address of a register, return the physical address of
* the register * the register
* *
****************************************************************************/ ****************************************************************************/
uintptr_t sam_physregaddr(uintptr_t vregaddr) uintptr_t sam_physregaddr(uintptr_t virtregaddr)
{ {
/* Check for a peripheral A register */ /* Check for a peripheral A register */
if (vregaddr >= SAM_PERIPHA_VSECTION && if (virtregaddr >= SAM_PERIPHA_VSECTION &&
vregaddr < (SAM_PERIPHA_VSECTION + SAM_PERIPHA_SIZE)) virtregaddr < (SAM_PERIPHA_VSECTION + SAM_PERIPHA_SIZE))
{ {
return peripha_physregaddr(vregaddr); return peripha_physregaddr(virtregaddr);
} }
/* Check for a peripheral A register */ /* Check for a peripheral A register */
else if (vregaddr >= SAM_PERIPHB_VSECTION && else if (virtregaddr >= SAM_PERIPHB_VSECTION &&
vregaddr < (SAM_PERIPHB_VSECTION + SAM_PERIPHB_SIZE)) virtregaddr < (SAM_PERIPHB_VSECTION + SAM_PERIPHB_SIZE))
{ {
return periphb_physregaddr(vregaddr); return periphb_physregaddr(virtregaddr);
} }
/* Check for a system controller register */ /* Check for a system controller register */
else if (vregaddr >= SAM_SYSC_VSECTION && else if (virtregaddr >= SAM_SYSC_VSECTION &&
vregaddr < (SAM_SYSC_VSECTION + SAM_SYSC_SIZE)) virtregaddr < (SAM_SYSC_VSECTION + SAM_SYSC_SIZE))
{ {
return sysc_physregaddr(vregaddr); return sysc_physregaddr(virtregaddr);
} }
/* We will not get here unless we are called with an invalid register /* We will not get here unless we are called with an invalid register
@ -442,64 +696,64 @@ uintptr_t sam_physregaddr(uintptr_t vregaddr)
*/ */
DEBUGPANIC(); DEBUGPANIC();
return vregaddr; return virtregaddr;
} }
/**************************************************************************** /****************************************************************************
* Name: sam_physramaddr * Name: sam_physramaddr
* *
* Description: * Description:
* Give the virtual address of a RAM memory location, return the physical * Given the virtual address of a RAM memory location, return the physical
* address of that location. * address of that location.
* *
****************************************************************************/ ****************************************************************************/
uintptr_t sam_physramaddr(uintptr_t vregaddr) uintptr_t sam_physramaddr(uintptr_t virtramaddr)
{ {
/* Check for internal SRAM. We we assume that ISRAM0 and ISRAM1 are /* Check for internal SRAM. We we assume that ISRAM0 and ISRAM1 are
* contiguous. * contiguous.
*/ */
if (vregaddr >= SAM_ISRAM_VSECTION && if (virtramaddr >= SAM_ISRAM_VSECTION &&
vregaddr < (SAM_ISRAM_VSECTION + SAM_ISRAM_SIZE)) virtramaddr < (SAM_ISRAM_VSECTION + SAM_ISRAM_SIZE))
{ {
return isram_physramaddr(vregaddr); return isram_physramaddr(virtramaddr);
} }
#ifdef CONFIG_SAMA5_DDRCS #ifdef CONFIG_SAMA5_DDRCS
/* Check for external SDRAM */ /* Check for external SDRAM */
else if (vregaddr >= SAM_DDRCS_VSECTION && else if (virtramaddr >= SAM_DDRCS_VSECTION &&
vregaddr < (SAM_DDRCS_VSECTION + SAMA5_DDRCS_SIZE)) virtramaddr < (SAM_DDRCS_VSECTION + SAMA5_DDRCS_SIZE))
{ {
return sdram_physramaddr(vregaddr); return sdram_physramaddr(virtramaddr);
} }
#endif #endif
/* Check for NFCS SRAM. */ /* Check for NFCS SRAM. */
if (vregaddr >= SAM_NFCSRAM_VSECTION && if (virtramaddr >= SAM_NFCSRAM_VSECTION &&
vregaddr < (SAM_NFCSRAM_VSECTION + SAM_NFCSRAM_SIZE)) virtramaddr < (SAM_NFCSRAM_VSECTION + SAM_NFCSRAM_SIZE))
{ {
return nfcsram_physramaddr(vregaddr); return nfcsram_physramaddr(virtramaddr);
} }
/* Check for UDPH SRAM. */ /* Check for UDPH SRAM. */
if (vregaddr >= SAM_UDPHSRAM_VSECTION && if (virtramaddr >= SAM_UDPHSRAM_VSECTION &&
vregaddr < (SAM_UDPHSRAM_VSECTION + SAM_UDPHSRAM_SIZE)) virtramaddr < (SAM_UDPHSRAM_VSECTION + SAM_UDPHSRAM_SIZE))
{ {
return udphsram_physramaddr(vregaddr); return udphsram_physramaddr(virtramaddr);
} }
#if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \ #if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \
defined(CONFIG_SAMA5_EBICS0_PSRAM)) defined(CONFIG_SAMA5_EBICS0_PSRAM))
/* Check for external SRAM or PSRAM on CS0 */ /* Check for external SRAM or PSRAM on CS0 */
else if (vregaddr >= SAM_EBICS0_VSECTION && else if (virtramaddr >= SAM_EBICS0_VSECTION &&
vregaddr < (SAM_EBICS0_VSECTION + SAMA5_EBICS0_SIZE)) virtramaddr < (SAM_EBICS0_VSECTION + SAMA5_EBICS0_SIZE))
{ {
return ebics0_physramaddr(vregaddr); return ebics0_physramaddr(virtramaddr);
} }
#endif #endif
@ -507,10 +761,10 @@ uintptr_t sam_physramaddr(uintptr_t vregaddr)
defined(CONFIG_SAMA5_EBICS1_PSRAM)) defined(CONFIG_SAMA5_EBICS1_PSRAM))
/* Check for external SRAM or PSRAM on CS1 */ /* Check for external SRAM or PSRAM on CS1 */
else if (vregaddr >= SAM_EBICS1_VSECTION && else if (virtramaddr >= SAM_EBICS1_VSECTION &&
vregaddr < (SAM_EBICS1_VSECTION + SAMA5_EBICS1_SIZE)) virtramaddr < (SAM_EBICS1_VSECTION + SAMA5_EBICS1_SIZE))
{ {
return ebics1_physramaddr(vregaddr); return ebics1_physramaddr(virtramaddr);
} }
#endif #endif
@ -518,10 +772,10 @@ uintptr_t sam_physramaddr(uintptr_t vregaddr)
defined(CONFIG_SAMA5_EBICS2_PSRAM)) defined(CONFIG_SAMA5_EBICS2_PSRAM))
/* Check for external SRAM or PSRAM on CS2 */ /* Check for external SRAM or PSRAM on CS2 */
else if (vregaddr >= SAM_EBICS2_VSECTION && else if (virtramaddr >= SAM_EBICS2_VSECTION &&
vregaddr < (SAM_EBICS2_VSECTION + SAMA5_EBICS2_SIZE)) virtramaddr < (SAM_EBICS2_VSECTION + SAMA5_EBICS2_SIZE))
{ {
return ebics2_physramaddr(vregaddr); return ebics2_physramaddr(virtramaddr);
} }
#endif #endif
@ -529,10 +783,10 @@ uintptr_t sam_physramaddr(uintptr_t vregaddr)
defined(CONFIG_SAMA5_EBICS3_PSRAM)) defined(CONFIG_SAMA5_EBICS3_PSRAM))
/* Check for external SRAM or PSRAM on CS3 */ /* Check for external SRAM or PSRAM on CS3 */
else if (vregaddr >= SAM_EBICS3_VSECTION && else if (virtramaddr >= SAM_EBICS3_VSECTION &&
vregaddr < (SAM_EBICS3_VSECTION + SAMA5_EBICS3_SIZE)) virtramaddr < (SAM_EBICS3_VSECTION + SAMA5_EBICS3_SIZE))
{ {
return ebics3_physramaddr(vregaddr); return ebics3_physramaddr(virtramaddr);
} }
#endif #endif
@ -541,5 +795,104 @@ uintptr_t sam_physramaddr(uintptr_t vregaddr)
*/ */
DEBUGPANIC(); DEBUGPANIC();
return vregaddr; return virtramaddr;
}
/****************************************************************************
* Name: sam_virtramaddr
*
* Description:
* Give the phsical address of a RAM memory location, return the virtual
* address of that location.
*
****************************************************************************/
uintptr_t sam_virtramaddr(uintptr_t physramaddr)
{
/* Check for internal SRAM. We we assume that ISRAM0 and ISRAM1 are
* contiguous.
*/
if (physramaddr >= SAM_ISRAM_PSECTION &&
physramaddr < (SAM_ISRAM_PSECTION + SAM_ISRAM_SIZE))
{
return isram_virtramaddr(physramaddr);
}
#ifdef CONFIG_SAMA5_DDRCS
/* Check for external SDRAM */
else if (physramaddr >= SAM_DDRCS_PSECTION &&
physramaddr < (SAM_DDRCS_PSECTION + SAMA5_DDRCS_SIZE))
{
return sdram_virtramaddr(physramaddr);
}
#endif
/* Check for NFCS SRAM. */
if (physramaddr >= SAM_NFCSRAM_PSECTION &&
physramaddr < (SAM_NFCSRAM_PSECTION + SAM_NFCSRAM_SIZE))
{
return nfcsram_virtramaddr(physramaddr);
}
/* Check for UDPH SRAM. */
if (physramaddr >= SAM_UDPHSRAM_PSECTION &&
physramaddr < (SAM_UDPHSRAM_PSECTION + SAM_UDPHSRAM_SIZE))
{
return udphsram_virtramaddr(physramaddr);
}
#if defined(CONFIG_SAMA5_EBICS0) && (defined(CONFIG_SAMA5_EBICS0_SRAM) || \
defined(CONFIG_SAMA5_EBICS0_PSRAM))
/* Check for external SRAM or PSRAM on CS0 */
else if (physramaddr >= SAM_EBICS0_PSECTION &&
physramaddr < (SAM_EBICS0_PSECTION + SAMA5_EBICS0_SIZE))
{
return ebics0_virtramaddr(physramaddr);
}
#endif
#if defined(CONFIG_SAMA5_EBICS1) && (defined(CONFIG_SAMA5_EBICS1_SRAM) || \
defined(CONFIG_SAMA5_EBICS1_PSRAM))
/* Check for external SRAM or PSRAM on CS1 */
else if (physramaddr >= SAM_EBICS1_PSECTION &&
physramaddr < (SAM_EBICS1_PSECTION + SAMA5_EBICS1_SIZE))
{
return ebics1_virtramaddr(physramaddr);
}
#endif
#if defined(CONFIG_SAMA5_EBICS2) && (defined(CONFIG_SAMA5_EBICS2_SRAM) || \
defined(CONFIG_SAMA5_EBICS2_PSRAM))
/* Check for external SRAM or PSRAM on CS2 */
else if (physramaddr >= SAM_EBICS2_PSECTION &&
physramaddr < (SAM_EBICS2_PSECTION + SAMA5_EBICS2_SIZE))
{
return ebics2_virtramaddr(physramaddr);
}
#endif
#if defined(CONFIG_SAMA5_EBICS3) && (defined(CONFIG_SAMA5_EBICS3_SRAM) || \
defined(CONFIG_SAMA5_EBICS3_PSRAM))
/* Check for external SRAM or PSRAM on CS3 */
else if (physramaddr >= SAM_EBICS3_PSECTION &&
physramaddr < (SAM_EBICS3_PSECTION + SAMA5_EBICS3_SIZE))
{
return ebics3_virtramaddr(physramaddr);
}
#endif
/* We will not get here unless we are called with an invalid or
* unsupported RAM address
*/
DEBUGPANIC();
return physramaddr;
} }

View File

@ -82,7 +82,7 @@ extern "C"
* *
****************************************************************************/ ****************************************************************************/
uintptr_t sam_physregaddr(uintptr_t vregaddr); uintptr_t sam_physregaddr(uintptr_t virtregaddr);
/**************************************************************************** /****************************************************************************
* Name: sam_physramaddr * Name: sam_physramaddr
@ -93,7 +93,18 @@ uintptr_t sam_physregaddr(uintptr_t vregaddr);
* *
****************************************************************************/ ****************************************************************************/
uintptr_t sam_physramaddr(uintptr_t vregaddr); uintptr_t sam_physramaddr(uintptr_t vramaddr);
/****************************************************************************
* Name: sam_virtramaddr
*
* Description:
* Give the phsical address of a RAM memory location, return the virtual
* address of that location.
*
****************************************************************************/
uintptr_t sam_virtramaddr(uintptr_t physramaddr);
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)

View File

@ -61,8 +61,10 @@
#include "up_arch.h" #include "up_arch.h"
#include "up_internal.h" #include "up_internal.h"
#include "cache.h"
#include "chip.h" #include "chip.h"
#include "sam_periphclks.h" #include "sam_periphclks.h"
#include "sam_memories.h"
#include "sam_usbhost.h" #include "sam_usbhost.h"
#include "chip/sam_pmc.h" #include "chip/sam_pmc.h"
#include "chip/sam_sfr.h" #include "chip/sam_sfr.h"
@ -73,14 +75,6 @@
*******************************************************************************/ *******************************************************************************/
/* Configuration ***************************************************************/ /* Configuration ***************************************************************/
/* Fixed endpoint descriptor size. The actual size required by the hardware is only
* 16 bytes, however, we set aside an additional 16 bytes for for internal use by
* the OHCI host driver. 16-bytes is set aside because the EDs must still be
* aligned to 16-byte boundaries.
*/
#define SAM_ED_SIZE 32
/* Configurable number of user endpoint descriptors (EDs). This number excludes /* Configurable number of user endpoint descriptors (EDs). This number excludes
* the control endpoint that is always allocated. * the control endpoint that is always allocated.
*/ */
@ -89,14 +83,6 @@
# define CONFIG_SAMA5_OHCI_NEDS 2 # define CONFIG_SAMA5_OHCI_NEDS 2
#endif #endif
/* Fixed transfer descriptor size. The actual size required by the hardware is
* only 16 bytes, however, we set aside an additional 16 bytes for for internal
* use by the OHCI host driver. 16-bytes is set aside because the TDs must still
* be aligned to 16-byte boundaries.
*/
#define SAM_TD_SIZE 32
/* Configurable number of user transfer descriptors (TDs). */ /* Configurable number of user transfer descriptors (TDs). */
#ifndef CONFIG_SAMA5_OHCI_NTDS #ifndef CONFIG_SAMA5_OHCI_NTDS
@ -198,7 +184,7 @@ struct sam_rhport_s
struct usbhost_class_s *class; struct usbhost_class_s *class;
}; };
/* This structure retains the state of the USB host controller */ /* This structure retains the overall state of the USB host controller */
struct sam_ohci_s struct sam_ohci_s
{ {
@ -219,27 +205,34 @@ struct sam_ohci_s
}; };
/* The OCHI expects the size of an endpoint descriptor to be 16 bytes. /* The OCHI expects the size of an endpoint descriptor to be 16 bytes.
* However, the size allocated for an endpoint descriptor is 32 bytes in * However, the size allocated for an endpoint descriptor is 32 bytes. This
* sam_ohciram.h. This extra 16-bytes is used by the OHCI host driver in * extra 16-bytes is used by the OHCI host driver in order to maintain
* order to maintain additional endpoint-specific data. * additional endpoint-specific data.
*/ */
#define SAMD_ED_PADSIZE (12 - sizeof(sem_t))
struct sam_ed_s struct sam_ed_s
{ {
/* Hardware specific fields */ /* Hardware specific fields */
struct ohci_ed_s hw; struct ohci_ed_s hw; /* 0-15 */
/* Software specific fields */ /* Software specific fields */
uint8_t xfrtype; /* Transfer type. See SB_EP_ATTR_XFER_* in usb.h */ uint8_t xfrtype; /* 16: Transfer type. See SB_EP_ATTR_XFER_* in usb.h */
uint8_t interval; /* Periodic EP polling interval: 2, 4, 6, 16, or 32 */ uint8_t interval; /* 17: Periodic EP polling interval: 2, 4, 6, 16, or 32 */
volatile uint8_t tdstatus; /* TD control status bits from last Writeback Done Head event */ volatile uint8_t tdstatus; /* 18: TD control status bits from last Writeback Done Head event */
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */ volatile bool wdhwait; /* 19: TRUE: Thread is waiting for WDH interrupt */
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */ sem_t wdhsem; /* 20-23: Semaphore used to wait for Writeback Done Head event */
/* Unused bytes follow, depending on the size of sem_t */
/* Padding to 32-bytes follow. The amount of padding depends on the size of sem_t */
uint8_t pad[SAMD_ED_PADSIZE];
}; };
#define SIZEOF_SAM_ED_S 32
/* The OCHI expects the size of an transfer descriptor to be 16 bytes. /* The OCHI expects the size of an transfer descriptor to be 16 bytes.
* However, the size allocated for an endpoint descriptor is 32 bytes in * However, the size allocated for an endpoint descriptor is 32 bytes in
* RAM. This extra 16-bytes is used by the OHCI host driver in order to * RAM. This extra 16-bytes is used by the OHCI host driver in order to
@ -250,15 +243,17 @@ struct sam_gtd_s
{ {
/* Hardware specific fields */ /* Hardware specific fields */
struct ohci_gtd_s hw; struct ohci_gtd_s hw; /* 0-15 */
/* Software specific fields */ /* Software specific fields */
struct sam_ed_s *ed; /* Pointer to parent ED */ struct sam_ed_s *ed; /* 16-19: Pointer to parent ED */
bool prealloc; /* Indicates a pre-allocated ED */ bool prealloc; /* 20: Indicates a pre-allocated ED */
uint8_t pad[11]; uint8_t pad[11]; /* 21-31: Pad to 32 bytes */
}; };
#define SIZEOF_SAM_TD_S 32
/* The following is used to manage lists of free EDs, TDs, and TD buffers */ /* The following is used to manage lists of free EDs, TDs, and TD buffers */
struct sam_list_s struct sam_list_s
@ -730,11 +725,14 @@ static inline int sam_addbulked(struct sam_ed_s *ed)
{ {
#ifndef CONFIG_USBHOST_BULK_DISABLE #ifndef CONFIG_USBHOST_BULK_DISABLE
uint32_t regval; uint32_t regval;
uintptr_t physed;
/* Add the new bulk ED to the head of the bulk list */ /* Add the new bulk ED to the head of the bulk list */
ed->hw.nexted = sam_getreg(SAM_USBHOST_BULKHEADED); ed->hw.nexted = sam_getreg(SAM_USBHOST_BULKHEADED);
sam_putreg((uint32_t)ed, SAM_USBHOST_BULKHEADED);
physed = sam_physramaddr((uintptr_t)ed);
sam_putreg((uint32_t)physed, SAM_USBHOST_BULKHEADED);
/* BulkListEnable. This bit is set to enable the processing of the /* BulkListEnable. This bit is set to enable the processing of the
* Bulk list. Note: once enabled, it remains. We really should * Bulk list. Note: once enabled, it remains. We really should
@ -763,14 +761,15 @@ static inline int sam_rembulked(struct sam_ed_s *ed)
#ifndef CONFIG_USBHOST_BULK_DISABLE #ifndef CONFIG_USBHOST_BULK_DISABLE
struct sam_ed_s *curr; struct sam_ed_s *curr;
struct sam_ed_s *prev; struct sam_ed_s *prev;
uint32_t regval; uintptr_t physed;
uint32_t regval;
/* Find the ED in the bulk list. NOTE: We really should never be mucking /* Find the ED in the bulk list. NOTE: We really should never be mucking
* with the bulk list while BLE is set. * with the bulk list while BLE is set.
*/ */
for (curr = (struct sam_ed_s *)sam_getreg(SAM_USBHOST_BULKHEADED), physed = sam_getreg(SAM_USBHOST_BULKHEADED);
prev = NULL; for (curr = (struct sam_ed_s *)sam_virtramaddr(physed), prev = NULL;
curr && curr != ed; curr && curr != ed;
prev = curr, curr = (struct sam_ed_s *)curr->hw.nexted); prev = curr, curr = (struct sam_ed_s *)curr->hw.nexted);
@ -897,7 +896,8 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
#ifndef CONFIG_USBHOST_INT_DISABLE #ifndef CONFIG_USBHOST_INT_DISABLE
unsigned int interval; unsigned int interval;
unsigned int offset; unsigned int offset;
uint32_t head; uintptr_t physed;
uintptr_t physhead;
uint32_t regval; uint32_t regval;
/* Disable periodic list processing. Does this take effect immediately? Or /* Disable periodic list processing. Does this take effect immediately? Or
@ -949,11 +949,12 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
} }
uvdbg("min interval: %d offset: %d\n", interval, offset); uvdbg("min interval: %d offset: %d\n", interval, offset);
/* Get the head of the first of the duplicated entries. The first offset /* Get the (physical) head of the first of the duplicated entries. The
* entry is always guaranteed to contain the common ED list head. * first offset entry is always guaranteed to contain the common ED list
* head.
*/ */
head = g_hcca.inttbl[offset]; physhead = g_hcca.inttbl[offset];
/* Clear all current entries in the interrupt table for this direction */ /* Clear all current entries in the interrupt table for this direction */
@ -964,9 +965,10 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
* interrupt table. * interrupt table.
*/ */
ed->hw.nexted = head; ed->hw.nexted = physhead;
sam_setinttab((uint32_t)ed, interval, offset); physed = sam_virtramaddr((uintptr_t)ed);
uvdbg("head: %08x next: %08x\n", ed, head); sam_setinttab((uint32_t)physed, interval, offset);
uvdbg("head: %08x next: %08x\n", physed, physhead);
/* Re-enabled periodic list processing */ /* Re-enabled periodic list processing */
@ -1005,9 +1007,10 @@ static inline int sam_reminted(struct sam_ed_s *ed)
struct sam_ed_s *head; struct sam_ed_s *head;
struct sam_ed_s *curr; struct sam_ed_s *curr;
struct sam_ed_s *prev; struct sam_ed_s *prev;
unsigned int interval; uintptr_t physhead;
unsigned int offset; unsigned int interval;
uint32_t regval; unsigned int offset;
uint32_t regval;
/* Disable periodic list processing. Does this take effect immediately? Or /* Disable periodic list processing. Does this take effect immediately? Or
* at the next SOF... need to check. * at the next SOF... need to check.
@ -1034,9 +1037,11 @@ static inline int sam_reminted(struct sam_ed_s *ed)
* entry is always guaranteed to contain the common ED list head. * entry is always guaranteed to contain the common ED list head.
*/ */
head = (struct sam_ed_s *)g_hcca.inttbl[offset]; physhead = g_hcca.inttbl[offset];
head = (struct sam_ed_s *)sam_virtramaddr((uintptr_t)physhead);
uvdbg("ed: %08x head: %08x next: %08x offset: %d\n", uvdbg("ed: %08x head: %08x next: %08x offset: %d\n",
ed, head, head ? head->hw.nexted : 0, offset); ed, physhead, head ? head->hw.nexted : 0, offset);
/* Find the ED to be removed in the ED list */ /* Find the ED to be removed in the ED list */
@ -1059,7 +1064,8 @@ static inline int sam_reminted(struct sam_ed_s *ed)
{ {
/* Yes... set the head of the bulk list to skip over this ED */ /* Yes... set the head of the bulk list to skip over this ED */
head = (struct sam_ed_s *)ed->hw.nexted; physhead = ed->hw.nexted;
head = (struct sam_ed_s *)sam_virtramaddr((uintptr_t)physhead);
} }
else else
{ {
@ -1069,8 +1075,9 @@ static inline int sam_reminted(struct sam_ed_s *ed)
prev->hw.nexted = ed->hw.nexted; prev->hw.nexted = ed->hw.nexted;
} }
uvdbg("ed: %08x head: %08x next: %08x\n",
ed, head, head ? head->hw.nexted : 0); uvdbg("ed: %08x head: %08x next: %08x\n",
ed, physhead, head ? head->hw.nexted : 0);
/* Calculate the new minimum interval for this list */ /* Calculate the new minimum interval for this list */
@ -1082,6 +1089,7 @@ static inline int sam_reminted(struct sam_ed_s *ed)
interval = curr->interval; interval = curr->interval;
} }
} }
uvdbg("min interval: %d offset: %d\n", interval, offset); uvdbg("min interval: %d offset: %d\n", interval, offset);
/* Save the new minimum interval */ /* Save the new minimum interval */
@ -1099,7 +1107,7 @@ static inline int sam_reminted(struct sam_ed_s *ed)
* table (head might be NULL). * table (head might be NULL).
*/ */
sam_setinttab((uint32_t)head, interval, offset); sam_setinttab((uint32_t)physhead, interval, offset);
} }
/* Re-enabled periodic list processing */ /* Re-enabled periodic list processing */
@ -1166,6 +1174,9 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
{ {
struct sam_gtd_s *td; struct sam_gtd_s *td;
struct sam_gtd_s *tdtail; struct sam_gtd_s *tdtail;
uintptr_t phytd;
uintptr_t phytail;
uintptr_t phybuf;
int ret = -ENOMEM; int ret = -ENOMEM;
/* Allocate a TD from the free list */ /* Allocate a TD from the free list */
@ -1173,29 +1184,52 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
td = sam_tdalloc(); td = sam_tdalloc();
if (td != NULL) if (td != NULL)
{ {
/* Skip processing of this ED */
ed->hw.ctrl |= ED_CONTROL_K;
/* Select the common tail ED for this root hub port */
tdtail = &g_tdtail[rhport->rhpndx]; tdtail = &g_tdtail[rhport->rhpndx];
/* Get physical addresses to support the DMA */
phytd = sam_physramaddr((uintptr_t)td);
phytail = sam_physramaddr((uintptr_t)tdtail);
phybuf = sam_physramaddr((uintptr_t)buffer);
/* Initialize the allocated TD and link it before the common tail TD. */ /* Initialize the allocated TD and link it before the common tail TD. */
td->hw.ctrl = (GTD_STATUS_R | dirpid | TD_DELAY(0) | toggle | GTD_STATUS_CC_MASK); td->hw.ctrl = (GTD_STATUS_R | dirpid | TD_DELAY(0) |
toggle | GTD_STATUS_CC_MASK);
tdtail->hw.ctrl = 0; tdtail->hw.ctrl = 0;
td->hw.cbp = (uint32_t)buffer; td->hw.cbp = (uint32_t)phybuf;
tdtail->hw.cbp = 0; tdtail->hw.cbp = 0;
td->hw.nexttd = (uint32_t)tdtail; td->hw.nexttd = (uint32_t)phytail;
tdtail->hw.nexttd = 0; tdtail->hw.nexttd = 0;
td->hw.be = (uint32_t)(buffer + (buflen - 1)); td->hw.be = (uint32_t)(phybuf + (buflen - 1));
tdtail->hw.be = 0; tdtail->hw.be = 0;
/* Configure driver-only fields in the extended TD structure */ /* Configure driver-only fields in the extended TD structure */
td->ed = ed; td->ed = ed;
/* Link the td to the head of the ED's TD list */ /* Link the td to the head of the ED's TD list */
ed->hw.headp = (uint32_t)td | ((ed->hw.headp) & ED_HEADP_C); ed->hw.headp = (uint32_t)phytd | ((ed->hw.headp) & ED_HEADP_C);
ed->hw.tailp = (uint32_t)tdtail; ed->hw.tailp = (uint32_t)phytail;
ret = OK; /* Flush the buffer, the new TD, and the modified ED to RAM */
cp15_coherent_dcache((uintptr_t)buffer, buflen);
cp15_coherent_dcache((uintptr_t)tdtail, sizeof(struct sam_gtd_s));
cp15_coherent_dcache((uintptr_t)td, sizeof(struct sam_gtd_s));
/* Resume processing of this ED */
ed->hw.ctrl &= ~ED_CONTROL_K;
cp15_coherent_dcache((uintptr_t)ed, sizeof(struct sam_ed_s));
ret = OK;
} }
return ret; return ret;
@ -1296,6 +1330,13 @@ static int sam_ctrltd(struct sam_rhport_s *rhport, uint32_t dirpid,
sam_takesem(&edctrl->wdhsem); sam_takesem(&edctrl->wdhsem);
/* Invalidate the D cache to force the control ED to be reloaded from
* RAM.
*/
cp15_invalidate_dcache((uintptr_t)edctrl,
(uintptr_t)edctrl + sizeof(struct sam_ed_s));
/* Check the TD completion status bits */ /* Check the TD completion status bits */
if (edctrl->tdstatus == TD_CC_NOERROR) if (edctrl->tdstatus == TD_CC_NOERROR)
@ -1470,7 +1511,7 @@ static void sam_wdh_interrupt(void)
* cleared in the interrupt status register. * cleared in the interrupt status register.
*/ */
td = (struct sam_gtd_s *)g_hcca.donehead; td = (struct sam_gtd_s *)sam_virtramaddr(g_hcca.donehead);
g_hcca.donehead = 0; g_hcca.donehead = 0;
/* Process each TD in the write done list */ /* Process each TD in the write done list */
@ -1795,6 +1836,10 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
/* Set the transfer type to control */ /* Set the transfer type to control */
edctrl->xfrtype = USB_EP_ATTR_XFER_CONTROL; edctrl->xfrtype = USB_EP_ATTR_XFER_CONTROL;
/* Flush the modified control ED to RAM */
cp15_coherent_dcache((uintptr_t)edctrl, sizeof(struct sam_ed_s));
sam_givesem(&g_ohci.exclsem); sam_givesem(&g_ohci.exclsem);
uvdbg("RHPort%d EP0 CTRL: %08x\n", rhport->rhpndx + 1, edctrl->hw.ctrl); uvdbg("RHPort%d EP0 CTRL: %08x\n", rhport->rhpndx + 1, edctrl->hw.ctrl);
@ -2195,7 +2240,8 @@ static int sam_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
* created by DRVR_ALLOC. * created by DRVR_ALLOC.
* buffer - A buffer used for sending the request and for returning any * buffer - A buffer used for sending the request and for returning any
* responses. This buffer must be large enough to hold the length value * responses. This buffer must be large enough to hold the length value
* in the request description. buffer must have been allocated using DRVR_ALLOC * in the request description. buffer must have been allocated using
* DRVR_ALLOC
* *
* NOTE: On an IN transaction, req and buffer may refer to the same allocated * NOTE: On an IN transaction, req and buffer may refer to the same allocated
* memory. * memory.
@ -2243,7 +2289,13 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr,
} }
} }
/* On an IN transaction, we need to invalidate the buffer contents to force
* it to be reloaded from RAM after the DMA.
*/
sam_givesem(&g_ohci.exclsem); sam_givesem(&g_ohci.exclsem);
cp15_invalidate_dcache((uintptr_t)buffer, (uintptr_t)buffer + len);
return ret; return ret;
} }
@ -2337,6 +2389,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
DEBUGASSERT(rhport && ed && buffer && buflen > 0); DEBUGASSERT(rhport && ed && buffer && buflen > 0);
in = (ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN; in = (ed->hw.ctrl & ED_CONTROL_D_MASK) == ED_CONTROL_D_IN;
uvdbg("EP%d %s toggle: %d maxpacket: %d buflen: %d\n", uvdbg("EP%d %s toggle: %d maxpacket: %d buflen: %d\n",
(ed->hw.ctrl & ED_CONTROL_EN_MASK) >> ED_CONTROL_EN_SHIFT, (ed->hw.ctrl & ED_CONTROL_EN_MASK) >> ED_CONTROL_EN_SHIFT,
in ? "IN" : "OUT", in ? "IN" : "OUT",
@ -2391,10 +2444,25 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
sam_takesem(&ed->wdhsem); sam_takesem(&ed->wdhsem);
/* Invalidate the D cache to force the ED to be reloaded from RAM */
cp15_invalidate_dcache((uintptr_t)ed,
(uintptr_t)ed + sizeof(struct sam_ed_s));
/* Check the TD completion status bits */ /* Check the TD completion status bits */
if (ed->tdstatus == TD_CC_NOERROR) if (ed->tdstatus == TD_CC_NOERROR)
{ {
/* On an IN transaction, we also need to invalidate the buffer
* contents to force it to be reloaded from RAM.
*/
if (in)
{
cp15_invalidate_dcache((uintptr_t)buffer,
(uintptr_t)buffer + buflen);
}
ret = OK; ret = OK;
} }
else else
@ -2467,6 +2535,8 @@ static inline void sam_ep0init(void)
struct sam_ed_s *edctrl; struct sam_ed_s *edctrl;
struct sam_ed_s *preved; struct sam_ed_s *preved;
struct sam_gtd_s *tdtail; struct sam_gtd_s *tdtail;
uintptr_t phyctrl;
uintptr_t phytail;
int rhpndx; int rhpndx;
/* Initialize the EP0 control EDs */ /* Initialize the EP0 control EDs */
@ -2475,14 +2545,16 @@ static inline void sam_ep0init(void)
rhpndx < SAM_USBHOST_NRHPORT; rhpndx < SAM_USBHOST_NRHPORT;
rhpndx++, preved = edctrl) rhpndx++, preved = edctrl)
{ {
/* Set up some default values */ /* Get some pointers to the EP0 control ED and to the common tail TD
* for this root hub port.
*/
(void)sam_ep0configure(&g_ohci.rhport[rhpndx].drvr, 1, 8); tdtail = &g_tdtail[rhpndx];
edctrl = &g_edctrl[rhpndx];
/* Get some convenience pointers */ /* We will also need the physical addresses for the DMA */
tdtail = &g_tdtail[rhpndx]; phytail = sam_physramaddr((uintptr_t)tdtail);
edctrl = &g_edctrl[rhpndx];
/* Initialize the common tail TD for this port */ /* Initialize the common tail TD for this port */
@ -2495,10 +2567,14 @@ static inline void sam_ep0init(void)
memset(edctrl, 0, sizeof(struct sam_ed_s)); memset(edctrl, 0, sizeof(struct sam_ed_s));
sem_init(&edctrl->wdhsem, 0, 0); sem_init(&edctrl->wdhsem, 0, 0);
/* Set up some default values (like max packetsize = 8). */
(void)sam_ep0configure(&g_ohci.rhport[rhpndx].drvr, 0, 8);
/* Link the common tail TD to the ED's TD list */ /* Link the common tail TD to the ED's TD list */
edctrl->hw.headp = (uint32_t)tdtail; edctrl->hw.headp = (uint32_t)phytail;
edctrl->hw.tailp = (uint32_t)tdtail; edctrl->hw.tailp = (uint32_t)phytail;
/* If this is not the first ED in the list, then link the previous ED /* If this is not the first ED in the list, then link the previous ED
* to this one. Because of the memset, the last ED in the list will * to this one. Because of the memset, the last ED in the list will
@ -2507,13 +2583,22 @@ static inline void sam_ep0init(void)
if (preved) if (preved)
{ {
preved->hw.nexted = (uint32_t)edctrl; phyctrl = sam_physramaddr((uintptr_t)edctrl);
preved->hw.nexted = (uint32_t)phyctrl;
} }
} }
/* Flush all of the control EDs and tail TDs to RAM */
cp15_coherent_dcache((uintptr_t)g_edctrl,
SAM_USBHOST_NRHPORT * sizeof(struct sam_ed_s));
cp15_coherent_dcache((uintptr_t)g_tdtail,
SAM_USBHOST_NRHPORT * sizeof(struct sam_gtd_s));
/* Set the head of the control list to the EP0 ED for RHport0. */ /* Set the head of the control list to the EP0 ED for RHport0. */
sam_putreg((uint32_t)&g_edctrl[0], SAM_USBHOST_CTRLHEADED); sam_putreg((uint32_t)sam_physramaddr((uintptr_t)&g_edctrl[0]),
SAM_USBHOST_CTRLHEADED);
/* ControlListEnable. This bit is set to enable the processing of the /* ControlListEnable. This bit is set to enable the processing of the
* Control list. Note: once enabled, it remains enabled and we may even * Control list. Note: once enabled, it remains enabled and we may even
@ -2562,13 +2647,11 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
irqstate_t flags; irqstate_t flags;
int i; int i;
/* Sanity checks. NOTE: If certain OS features are enabled, it may be /* One time sanity checks */
* necessary to increase the size of SAM_ED/TD_SIZE in sam_ohciram.h
*/
DEBUGASSERT(controller == 0); DEBUGASSERT(controller == 0);
DEBUGASSERT(sizeof(struct sam_ed_s) <= SAM_ED_SIZE); DEBUGASSERT(sizeof(struct sam_ed_s) == SIZEOF_SAM_ED_S);
DEBUGASSERT(sizeof(struct sam_gtd_s) <= SAM_TD_SIZE); DEBUGASSERT(sizeof(struct sam_gtd_s) == SIZEOF_SAM_TD_S);
/* Initialize the state data structure */ /* Initialize the state data structure */
@ -2722,6 +2805,13 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
return NULL; return NULL;
} }
/* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG
* mode.
*/
sam_usbhost_vbusdrive(SAM_OHCI_IFACE, true);
up_mdelay(50);
/* If there is a USB device in the slot at power up, then we will not /* If there is a USB device in the slot at power up, then we will not
* get the status change interrupt to signal us that the device is * get the status change interrupt to signal us that the device is
* connected. We need to set the initial connected state accordingly. * connected. We need to set the initial connected state accordingly.
@ -2736,12 +2826,6 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
i+1, g_ohci.rhport[i].connected ? "YES" : "NO"); i+1, g_ohci.rhport[i].connected ? "YES" : "NO");
} }
/* Drive Vbus +5V (the smoke test). Should be done elsewhere in OTG
* mode.
*/
sam_usbhost_vbusdrive(SAM_OHCI_IFACE, true);
/* 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 */