diff --git a/arch/arm/src/lpc31xx/chip.h b/arch/arm/src/lpc31xx/chip.h index 4ffcf2fbf36..7fcc5f0f260 100644 --- a/arch/arm/src/lpc31xx/chip.h +++ b/arch/arm/src/lpc31xx/chip.h @@ -70,6 +70,11 @@ # undef HAVE_AESENGINE /* No AES engine */ #endif +/* Cache line sizes (in bytes)for the SAVA5Dx */ + +#define ARM_DCACHE_LINESIZE 32 /* 32 bytes (8 words) */ +#define ARM_ICACHE_LINESIZE 32 /* 32 bytes (8 words) */ + /************************************************************************************ * Public Types ************************************************************************************/ diff --git a/arch/arm/src/lpc31xx/lpc31_ehci.c b/arch/arm/src/lpc31xx/lpc31_ehci.c index e74cc1c2f6a..c08b8712cfe 100644 --- a/arch/arm/src/lpc31xx/lpc31_ehci.c +++ b/arch/arm/src/lpc31xx/lpc31_ehci.c @@ -60,6 +60,7 @@ #include "up_arch.h" #include "cache.h" +#include "chip.h" #include "lpc31_internal.h" #include "lpc31_cgudrvr.h" #include "lpc31_syscreg.h" @@ -96,12 +97,19 @@ # define CONFIG_LPC31_EHCI_NQTDS (LPC31_EHCI_NRHPORT + 3) #endif +/* Buffers must be aligned to the cache line size */ + +#define DCACHE_LINEMASK (ARM_DCACHE_LINESIZE -1) + /* Configurable size of a request/descriptor buffers */ #ifndef CONFIG_LPC31_EHCI_BUFSIZE # define CONFIG_LPC31_EHCI_BUFSIZE 128 #endif +#define LPC31_EHCI_BUFSIZE \ + ((CONFIG_LPC31_EHCI_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK) + /* Debug options */ #ifndef CONFIG_DEBUG @@ -4005,12 +4013,15 @@ static int lpc31_alloc(FAR struct usbhost_driver_s *drvr, int ret = -ENOMEM; DEBUGASSERT(drvr && buffer && maxlen); - /* There is no special requirements for transfer/descriptor buffers. */ + /* The only special requirements for transfer/descriptor buffers are that (1) + * they be aligned to a cache line boundary and (2) they are a multiple of the + * cache line size in length. + */ - *buffer = (FAR uint8_t *)kmm_malloc(CONFIG_LPC31_EHCI_BUFSIZE); + *buffer = (FAR uint8_t *)kmm_memalign(LPC31_EHCI_BUFSIZE, ARM_DCACHE_LINESIZE); if (*buffer) { - *maxlen = CONFIG_LPC31_EHCI_BUFSIZE; + *maxlen = LPC31_EHCI_BUFSIZE; ret = OK; } @@ -4082,11 +4093,14 @@ static int lpc31_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer { DEBUGASSERT(drvr && buffer && buflen > 0); - /* The only special requirements for I/O buffers are they might need to be user - * accessible (depending on how the class driver implements its buffering). + /* The only special requirements for I/O buffers are that (1) they be aligned to a + * cache line boundary, (2) they are a multiple of the cache line size in length, + * and (3) they might need to be user accessible (depending on how the class driver + * implements its buffering). */ - *buffer = (FAR uint8_t *)kumm_malloc(buflen); + buflen = (buflen + DCACHE_LINEMASK) & ~DCACHE_LINEMASK; + *buffer = (FAR uint8_t *)kumm_memalign(buflen, ARM_DCACHE_LINESIZE); return *buffer ? OK : -ENOMEM; } diff --git a/arch/arm/src/sama5/chip.h b/arch/arm/src/sama5/chip.h index 924e05558a0..8928a48c33e 100644 --- a/arch/arm/src/sama5/chip.h +++ b/arch/arm/src/sama5/chip.h @@ -55,5 +55,9 @@ #define L2CC_VBASE SAM_L2CC_VSECTION -#endif /* __ARCH_ARM_SRC_SAMA5_CHIP_H */ +/* Cache line sizes (in bytes)for the SAVA5Dx */ +#define ARMV7A_DCACHE_LINESIZE 32 /* 32 bytes (8 words) */ +#define ARMV7A_ICACHE_LINESIZE 32 /* 32 bytes (8 words) */ + +#endif /* __ARCH_ARM_SRC_SAMA5_CHIP_H */ diff --git a/arch/arm/src/sama5/sam_ehci.c b/arch/arm/src/sama5/sam_ehci.c index c992d8bb406..b5383c3b5fe 100644 --- a/arch/arm/src/sama5/sam_ehci.c +++ b/arch/arm/src/sama5/sam_ehci.c @@ -59,6 +59,7 @@ #include "up_arch.h" #include "cache.h" +#include "chip.h" #include "sam_periphclks.h" #include "sam_memories.h" #include "sam_usbhost.h" @@ -95,12 +96,19 @@ # define CONFIG_SAMA5_EHCI_NQTDS (SAM_EHCI_NRHPORT + 3) #endif +/* Buffers must be aligned to the cache line size */ + +#define DCACHE_LINEMASK (ARMV7A_DCACHE_LINESIZE -1) + /* Configurable size of a request/descriptor buffers */ #ifndef CONFIG_SAMA5_EHCI_BUFSIZE # define CONFIG_SAMA5_EHCI_BUFSIZE 128 #endif +#define SAMA5_EHCI_BUFSIZE \ + ((CONFIG_SAMA5_EHCI_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK) + /* Debug options */ #ifndef CONFIG_DEBUG @@ -3832,12 +3840,15 @@ static int sam_alloc(FAR struct usbhost_driver_s *drvr, int ret = -ENOMEM; DEBUGASSERT(drvr && buffer && maxlen); - /* There is no special requirements for transfer/descriptor buffers. */ + /* The only special requirements for transfer/descriptor buffers are that (1) + * they be aligned to a cache line boundary and (2) they are a multiple of the + * cache line size in length. + */ - *buffer = (FAR uint8_t *)kmm_malloc(CONFIG_SAMA5_EHCI_BUFSIZE); + *buffer = (FAR uint8_t *)kmm_memalign(SAMA5_EHCI_BUFSIZE, ARMV7A_DCACHE_LINESIZE); if (*buffer) { - *maxlen = CONFIG_SAMA5_EHCI_BUFSIZE; + *maxlen = SAMA5_EHCI_BUFSIZE; ret = OK; } @@ -3909,11 +3920,14 @@ static int sam_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer, { DEBUGASSERT(drvr && buffer && buflen > 0); - /* The only special requirements for I/O buffers are they might need to be user - * accessible (depending on how the class driver implements its buffering). + /* The only special requirements for I/O buffers are that (1) they be aligned to a + * cache line boundary, (2) they are a multiple of the cache line size in length, + * and (3) they might need to be user accessible (depending on how the class driver + * implements its buffering). */ - *buffer = (FAR uint8_t *)kumm_malloc(buflen); + buflen = (buflen + DCACHE_LINEMASK) & ~DCACHE_LINEMASK; + *buffer = (FAR uint8_t *)kumm_memalign(buflen, ARMV7A_DCACHE_LINESIZE); return *buffer ? OK : -ENOMEM; }