EFM32: Integrate SPI DMA capability

This commit is contained in:
Gregory Nutt
2014-10-26 11:22:16 -06:00
parent 741f98fe0a
commit c392115fbd
5 changed files with 553 additions and 104 deletions
+34
View File
@@ -340,4 +340,38 @@ config LEUART1_2STOP
endmenu # LEUART1 Configuration
if EFM32_USART_ISSPI
menu "SPI Configuration"
config EFM32_SPI_DMA
bool "SPI DMA support"
default n
depends on EFM32_DMA
---help---
Select to enable DMA SPI transfers
if EFM32_SPI_DMA
config EFM32_SPI_DMA_TIMEO_NSEC
int "Per word timer (nsec)"
default 500
---help---
A timeout will be be used to detect hung DMA transfers. The timeout
will vary as a function of the number of words transferred. This
value provides the per-word timeout value in nanoseconds.
config EFM32_SPI_DMA_MINSIZE
int "Minimum DMA size"
default 16
---help---
DMA is particularly helpful for the case of large SPI transfers.
Smaller SPI transfer may be more efficiently performed without DMA.
This option determines a threshold: For transfers of this size and
below, DMA will not be used. A value of zero will force all DMA-
based transfers.
endif # EFM32_SPI_DMA
endmenu # SPI Configuration
endif # EFM32_USART_ISSPI
endif # ARCH_CHIP_EFM32
+1 -1
View File
@@ -1,6 +1,6 @@
/********************************************************************************************************************************
* arch/arm/src/efm32/EFM32GG/efm32_usart.h
*
*
* (C) Copyright 2014 Silicon Labs, http://www.silabs.com
*
* Permission is granted to anyone to use this software for any purpose,
+30 -8
View File
@@ -457,6 +457,7 @@ void efm32_rxdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
unsigned int xfersize;
unsigned int shift;
uint32_t regval;
uint32_t incr;
uint32_t mask;
DEBUGASSERT(dmach != NULL && dmach->inuse);
@@ -500,18 +501,28 @@ void efm32_rxdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
{
default:
case 0: /* Byte transfer */
regval = DMA_CTRL_DST_INC_BYTE | DMA_CTRL_DST_SIZE_BYTE | DMA_CTRL_SRC_SIZE_BYTE;
regval |= DMA_CTRL_DST_SIZE_BYTE | DMA_CTRL_SRC_SIZE_BYTE;
incr = DMA_CTRL_DST_INC_BYTE;
break;
case 1: /* Half word transfer */
regval = DMA_CTRL_DST_INC_HALFWORD | DMA_CTRL_DST_SIZE_HALFWORD | DMA_CTRL_SRC_SIZE_HALFWORD;
regval |= DMA_CTRL_DST_SIZE_HALFWORD | DMA_CTRL_SRC_SIZE_HALFWORD;
incr = DMA_CTRL_DST_INC_HALFWORD;
break;
case 2: /* Word transfer */
regval = DMA_CTRL_DST_INC_WORD | DMA_CTRL_DST_SIZE_WORD | DMA_CTRL_SRC_SIZE_WORD;
regval |= DMA_CTRL_DST_SIZE_WORD | DMA_CTRL_SRC_SIZE_WORD;
incr = DMA_CTRL_DST_INC_WORD;
break;
}
/* Do we need to increment the memory address? */
if ((config & EFM32_DMA_MEMINCR_MASK) == EFM32_DMA_MEMINCR)
{
regval |= incr;
}
/* Set the number of transfers (minus 1) */
DEBUGASSERT((nbytes >> shift) < 1024);
@@ -543,6 +554,7 @@ void efm32_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
unsigned int xfersize;
unsigned int shift;
uint32_t regval;
uint32_t incr;
uint32_t mask;
DEBUGASSERT(dmach != NULL && dmach->inuse);
@@ -579,25 +591,35 @@ void efm32_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
*/
regval = DMA_CTRL_DST_INC_NONE | DMA_CTRL_DST_PROT_NON_PRIVILEGED |
DMA_CTRL_SRC_PROT_NON_PRIVILEGED | DMA_CTRL_R_POWER_1 |
(0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) | _DMA_CTRL_CYCLE_CTRL_BASIC;
DMA_CTRL_SRC_PROT_NON_PRIVILEGED | DMA_CTRL_R_POWER_1 |
(0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) | _DMA_CTRL_CYCLE_CTRL_BASIC;
switch (shift)
{
default:
case 0: /* Byte transfer */
regval = DMA_CTRL_DST_SIZE_BYTE | DMA_CTRL_SRC_INC_BYTE | DMA_CTRL_SRC_SIZE_BYTE;
regval |= DMA_CTRL_DST_SIZE_BYTE | DMA_CTRL_SRC_SIZE_BYTE;
incr = DMA_CTRL_SRC_INC_BYTE;
break;
case 1: /* Half word transfer */
regval = DMA_CTRL_DST_SIZE_HALFWORD | DMA_CTRL_SRC_INC_HALFWORD | DMA_CTRL_SRC_SIZE_HALFWORD;
regval |= DMA_CTRL_DST_SIZE_HALFWORD | DMA_CTRL_SRC_SIZE_HALFWORD;
incr = DMA_CTRL_SRC_INC_HALFWORD;
break;
case 2: /* Word transfer */
regval = DMA_CTRL_DST_SIZE_WORD | DMA_CTRL_SRC_INC_WORD | DMA_CTRL_SRC_SIZE_WORD;
regval |= DMA_CTRL_DST_SIZE_WORD | DMA_CTRL_SRC_SIZE_WORD;
incr = DMA_CTRL_SRC_INC_WORD;
break;
}
/* Do we need to increment the memory address? */
if ((config & EFM32_DMA_MEMINCR_MASK) == EFM32_DMA_MEMINCR)
{
regval |= incr;
}
/* Set the number of transfers (minus 1) */
DEBUGASSERT((nbytes >> shift) < 1024);
+18 -14
View File
@@ -63,23 +63,27 @@
* - Memory address is always incremented.
*/
#define EFM32_DMA_SIGSEL_SHIFT (0) /* Bits 0-3: _DMA_CH_CTRL_ * value */
#define EFM32_DMA_SIGSEL_MASK (15 << EFM32_DMA_SIGSEL_SHIFT)
# define EFM32_DMA_SIGSEL(n) ((dma_config_t)(n) << EFM32_DMA_SIGSEL_SHIFT)
#define EFM32_DMA_SIGSEL_SHIFT (0) /* Bits 0-3: _DMA_CH_CTRL_ * value */
#define EFM32_DMA_SIGSEL_MASK (15 << EFM32_DMA_SIGSEL_SHIFT)
# define EFM32_DMA_SIGSEL(n) ((dma_config_t)(n) << EFM32_DMA_SIGSEL_SHIFT)
#define EFM32_DMA_SOURCSEL_SHIFT (4) /* Bits 4-9: _DMA_CH_SOURCESEL_* value */
#define EFM32_DMA_SOURCSEL_MASK (63 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_SOURCSEL(n) (dma_config_t)(n) << EFM32_DMA_SOURCSEL_SHIFT)
#define EFM32_DMA_SOURCSEL_SHIFT (4) /* Bits 4-9: _DMA_CH_SOURCESEL_* value */
#define EFM32_DMA_SOURCSEL_MASK (63 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_SOURCSEL(n) ((dma_config_t)(n) << EFM32_DMA_SOURCSEL_SHIFT)
#define EFM32_DMA_XFERSIZE_SHIFT (10) /* Bits 10-11: Transfer size */
#define EFM32_DMA_XFERSIZE_MASK (3 << EFM32_DMA_XFERSIZE_SHIFT)
# define EFM32_DMA_XFERSIZE_SHIFT_BYTE (0 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_XFERSIZE_SHIFT_HWORD (1 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_XFERSIZE_SHIFT_WORD (2 << EFM32_DMA_SOURCSEL_SHIFT)
#define EFM32_DMA_XFERSIZE_SHIFT (10) /* Bits 10-11: Transfer size */
#define EFM32_DMA_XFERSIZE_MASK (3 << EFM32_DMA_XFERSIZE_SHIFT)
# define EFM32_DMA_XFERSIZE_BYTE (0 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_XFERSIZE_HWORD (1 << EFM32_DMA_SOURCSEL_SHIFT)
# define EFM32_DMA_XFERSIZE_WORD (2 << EFM32_DMA_SOURCSEL_SHIFT)
#define EFM32_DMA_SINGLE_MASK (1 << 12) /* Bit 12: Single or Buffer full request */
# define EFM32_DMA_SINGLE (1 << 12) /* 1=Buffer full request */
# define EFM32_DMA_BUFFER_FULL (0) /* 0=Buffer full request */
#define EFM32_DMA_SINGLE_MASK (1 << 12) /* Bit 12: Single or Buffer full request */
# define EFM32_DMA_SINGLE (1 << 12) /* 1=Buffer full request */
# define EFM32_DMA_BUFFER_FULL (0) /* 0=Buffer full request */
#define EFM32_DMA_MEMINCR_MASK (1 << 13) /* Bit 13: Increment memory address */
# define EFM32_DMA_MEMINCR (1 << 13) /* 1=Increment memory address */
# define EFM32_DMA_NOINCR (0) /* 0=No memory address increment */
/************************************************************************************
* Public Types
File diff suppressed because it is too large Load Diff