EFM32: Completes very basic DMA support. Needs review. Untested

This commit is contained in:
Gregory Nutt 2014-10-25 11:31:13 -06:00
parent 1502ba31b3
commit 116129adf8
3 changed files with 255 additions and 183 deletions

View File

@ -72,107 +72,107 @@
*******************************************************************************************************************************/ *******************************************************************************************************************************/
#if defined(CONFIG_EFM32_EFM32GG) #if defined(CONFIG_EFM32_EFM32GG)
# define EFM_DMA_NCHANNELS 12 # define EFM32_DMA_NCHANNELS 12
#elif defined(CONFIG_EFM32_EFM32G) #elif defined(CONFIG_EFM32_EFM32G)
# define EFM_DMA_NCHANNELS 8 # define EFM32_DMA_NCHANNELS 8
#endif #endif
/* DMA Register Offsets ********************************************************************************************************/ /* DMA Register Offsets ********************************************************************************************************/
#define EFM_DMA_STATUS_OFFSET 0x0000 /* DMA Status Registers */ #define EFM32_DMA_STATUS_OFFSET 0x0000 /* DMA Status Registers */
#define EFM_DMA_CONFIG_OFFSET 0x0004 /* DMA Configuration Register */ #define EFM32_DMA_CONFIG_OFFSET 0x0004 /* DMA Configuration Register */
#define EFM_DMA_CTRLBASE_OFFSET 0x0008 /* Channel Control Data Base Pointer Register */ #define EFM32_DMA_CTRLBASE_OFFSET 0x0008 /* Channel Control Data Base Pointer Register */
#define EFM_DMA_ALTCTRLBASE_OFFSET 0x000c /* Channel Alternate Control Data Base Pointer Register */ #define EFM32_DMA_ALTCTRLBASE_OFFSET 0x000c /* Channel Alternate Control Data Base Pointer Register */
#define EFM_DMA_CHWAITSTATUS_OFFSET 0x0010 /* Channel Wait on Request Status Register */ #define EFM32_DMA_CHWAITSTATUS_OFFSET 0x0010 /* Channel Wait on Request Status Register */
#define EFM_DMA_CHSWREQ_OFFSET 0x0014 /* Channel Software Request Register */ #define EFM32_DMA_CHSWREQ_OFFSET 0x0014 /* Channel Software Request Register */
#define EFM_DMA_CHUSEBURSTS_OFFSET 0x0018 /* Channel Useburst Set Register */ #define EFM32_DMA_CHUSEBURSTS_OFFSET 0x0018 /* Channel Useburst Set Register */
#define EFM_DMA_CHUSEBURSTC_OFFSET 0x001c /* Channel Useburst Clear Register */ #define EFM32_DMA_CHUSEBURSTC_OFFSET 0x001c /* Channel Useburst Clear Register */
#define EFM_DMA_CHREQMASKS_OFFSET 0x0020 /* Channel Request Mask Set Register */ #define EFM32_DMA_CHREQMASKS_OFFSET 0x0020 /* Channel Request Mask Set Register */
#define EFM_DMA_CHREQMASKC_OFFSET 0x0024 /* Channel Request Mask Clear Register */ #define EFM32_DMA_CHREQMASKC_OFFSET 0x0024 /* Channel Request Mask Clear Register */
#define EFM_DMA_CHENS_OFFSET 0x0028 /* Channel Enable Set Register */ #define EFM32_DMA_CHENS_OFFSET 0x0028 /* Channel Enable Set Register */
#define EFM_DMA_CHENC_OFFSET 0x002c /* Channel Enable Clear Register */ #define EFM32_DMA_CHENC_OFFSET 0x002c /* Channel Enable Clear Register */
#define EFM_DMA_CHALTS_OFFSET 0x0030 /* Channel Alternate Set Register */ #define EFM32_DMA_CHALTS_OFFSET 0x0030 /* Channel Alternate Set Register */
#define EFM_DMA_CHALTC_OFFSET 0x0034 /* Channel Alternate Clear Register */ #define EFM32_DMA_CHALTC_OFFSET 0x0034 /* Channel Alternate Clear Register */
#define EFM_DMA_CHPRIS_OFFSET 0x0038 /* Channel Priority Set Register */ #define EFM32_DMA_CHPRIS_OFFSET 0x0038 /* Channel Priority Set Register */
#define EFM_DMA_CHPRIC_OFFSET 0x003c /* Channel Priority Clear Register */ #define EFM32_DMA_CHPRIC_OFFSET 0x003c /* Channel Priority Clear Register */
#define EFM_DMA_ERRORC_OFFSET 0x004c /* Bus Error Clear Register */ #define EFM32_DMA_ERRORC_OFFSET 0x004c /* Bus Error Clear Register */
#define EFM_DMA_CHREQSTATUS_OFFSET 0x0e10 /* Channel Request Status */ #define EFM32_DMA_CHREQSTATUS_OFFSET 0x0e10 /* Channel Request Status */
#define EFM_DMA_CHSREQSTATUS_OFFSET 0x0e18 /* Channel Single Request Status */ #define EFM32_DMA_CHSREQSTATUS_OFFSET 0x0e18 /* Channel Single Request Status */
#define EFM_DMA_IF_OFFSET 0x1000 /* Interrupt Flag Register */ #define EFM32_DMA_IF_OFFSET 0x1000 /* Interrupt Flag Register */
#define EFM_DMA_IFS_OFFSET 0x1004 /* Interrupt Flag Set Register */ #define EFM32_DMA_IFS_OFFSET 0x1004 /* Interrupt Flag Set Register */
#define EFM_DMA_IFC_OFFSET 0x1008 /* Interrupt Flag Clear Register */ #define EFM32_DMA_IFC_OFFSET 0x1008 /* Interrupt Flag Clear Register */
#define EFM_DMA_IEN_OFFSET 0x100c /* Interrupt Enable register */ #define EFM32_DMA_IEN_OFFSET 0x100c /* Interrupt Enable register */
#if defined(CONFIG_EFM32_EFM32GG) #if defined(CONFIG_EFM32_EFM32GG)
# define EFM_DMA_CTRL_OFFSET 0x1010 /* DMA Control Register */ # define EFM32_DMA_CTRL_OFFSET 0x1010 /* DMA Control Register */
# define EFM_DMA_RDS_OFFSET 0x1014 /* DMA Retain Descriptor State */ # define EFM32_DMA_RDS_OFFSET 0x1014 /* DMA Retain Descriptor State */
# define EFM_DMA_LOOP0_OFFSET 0x1020 /* Channel 0 Loop Register */ # define EFM32_DMA_LOOP0_OFFSET 0x1020 /* Channel 0 Loop Register */
# define EFM_DMA_LOOP1_OFFSET 0x1024 /* Channel 1 Loop Register */ # define EFM32_DMA_LOOP1_OFFSET 0x1024 /* Channel 1 Loop Register */
# define EFM_DMA_RECT0_OFFSET 0x1060 /* Channel 0 Rectangle Register */ # define EFM32_DMA_RECT0_OFFSET 0x1060 /* Channel 0 Rectangle Register */
#endif #endif
#define EFM_DMA_CHn_CTRL_OFFSET(n) (0x1100+((n)<<2)) /* Channel n Control Register */ #define EFM32_DMA_CHn_CTRL_OFFSET(n) (0x1100+((n)<<2)) /* Channel n Control Register */
#define EFM_DMA_CH0_CTRL_OFFSET 0x1100 /* Channel 0 Control Register */ #define EFM32_DMA_CH0_CTRL_OFFSET 0x1100 /* Channel 0 Control Register */
#define EFM_DMA_CH1_CTRL_OFFSET 0x1104 /* Channel 1 Control Register */ #define EFM32_DMA_CH1_CTRL_OFFSET 0x1104 /* Channel 1 Control Register */
#define EFM_DMA_CH2_CTRL_OFFSET 0x1108 /* Channel 2 Control Register */ #define EFM32_DMA_CH2_CTRL_OFFSET 0x1108 /* Channel 2 Control Register */
#define EFM_DMA_CH3_CTRL_OFFSET 0x110c /* Channel 3 Control Register */ #define EFM32_DMA_CH3_CTRL_OFFSET 0x110c /* Channel 3 Control Register */
#define EFM_DMA_CH4_CTRL_OFFSET 0x1110 /* Channel 4 Control Register */ #define EFM32_DMA_CH4_CTRL_OFFSET 0x1110 /* Channel 4 Control Register */
#define EFM_DMA_CH5_CTRL_OFFSET 0x1114 /* Channel 5 Control Register */ #define EFM32_DMA_CH5_CTRL_OFFSET 0x1114 /* Channel 5 Control Register */
#define EFM_DMA_CH6_CTRL_OFFSET 0x1118 /* Channel 6 Control Register */ #define EFM32_DMA_CH6_CTRL_OFFSET 0x1118 /* Channel 6 Control Register */
#define EFM_DMA_CH7_CTRL_OFFSET 0x111c /* Channel 7 Control Register */ #define EFM32_DMA_CH7_CTRL_OFFSET 0x111c /* Channel 7 Control Register */
#if defined(CONFIG_EFM32_EFM32GG) #if defined(CONFIG_EFM32_EFM32GG)
# define EFM_DMA_CH8_CTRL_OFFSET 0x1120 /* Channel 8 Control Register */ # define EFM32_DMA_CH8_CTRL_OFFSET 0x1120 /* Channel 8 Control Register */
# define EFM_DMA_CH9_CTRL_OFFSET 0x1124 /* Channel 9 Control Register */ # define EFM32_DMA_CH9_CTRL_OFFSET 0x1124 /* Channel 9 Control Register */
# define EFM_DMA_CH10_CTRL_OFFSET 0x1128 /* Channel 10 Control Register */ # define EFM32_DMA_CH10_CTRL_OFFSET 0x1128 /* Channel 10 Control Register */
# define EFM_DMA_CH11_CTRL_OFFSET 0x112c /* Channel 11 Control Register */ # define EFM32_DMA_CH11_CTRL_OFFSET 0x112c /* Channel 11 Control Register */
#endif #endif
/* DMA Register Addresses ******************************************************************************************************/ /* DMA Register Addresses ******************************************************************************************************/
#define EFM_DMA_STATUS (EFM32_DMA_BASE+EFM_DMA_STATUS_OFFSET) #define EFM32_DMA_STATUS (EFM32_DMA_BASE+EFM32_DMA_STATUS_OFFSET)
#define EFM_DMA_CONFIG (EFM32_DMA_BASE+EFM_DMA_CONFIG_OFFSET) #define EFM32_DMA_CONFIG (EFM32_DMA_BASE+EFM32_DMA_CONFIG_OFFSET)
#define EFM_DMA_CTRLBASE (EFM32_DMA_BASE+EFM_DMA_CTRLBASE_OFFSET) #define EFM32_DMA_CTRLBASE (EFM32_DMA_BASE+EFM32_DMA_CTRLBASE_OFFSET)
#define EFM_DMA_ALTCTRLBASE (EFM32_DMA_BASE+EFM_DMA_ALTCTRLBASE_OFFSET) #define EFM32_DMA_ALTCTRLBASE (EFM32_DMA_BASE+EFM32_DMA_ALTCTRLBASE_OFFSET)
#define EFM_DMA_CHWAITSTATUS (EFM32_DMA_BASE+EFM_DMA_CHWAITSTATUS_OFFSET) #define EFM32_DMA_CHWAITSTATUS (EFM32_DMA_BASE+EFM32_DMA_CHWAITSTATUS_OFFSET)
#define EFM_DMA_CHSWREQ (EFM32_DMA_BASE+EFM_DMA_CHSWREQ_OFFSET) #define EFM32_DMA_CHSWREQ (EFM32_DMA_BASE+EFM32_DMA_CHSWREQ_OFFSET)
#define EFM_DMA_CHUSEBURSTS (EFM32_DMA_BASE+EFM_DMA_CHUSEBURSTS_OFFSET) #define EFM32_DMA_CHUSEBURSTS (EFM32_DMA_BASE+EFM32_DMA_CHUSEBURSTS_OFFSET)
#define EFM_DMA_CHUSEBURSTC (EFM32_DMA_BASE+EFM_DMA_CHUSEBURSTC_OFFSET) #define EFM32_DMA_CHUSEBURSTC (EFM32_DMA_BASE+EFM32_DMA_CHUSEBURSTC_OFFSET)
#define EFM_DMA_CHREQMASKS (EFM32_DMA_BASE+EFM_DMA_CHREQMASKS_OFFSET) #define EFM32_DMA_CHREQMASKS (EFM32_DMA_BASE+EFM32_DMA_CHREQMASKS_OFFSET)
#define EFM_DMA_CHREQMASKC (EFM32_DMA_BASE+EFM_DMA_CHREQMASKC_OFFSET) #define EFM32_DMA_CHREQMASKC (EFM32_DMA_BASE+EFM32_DMA_CHREQMASKC_OFFSET)
#define EFM_DMA_CHENS (EFM32_DMA_BASE+EFM_DMA_CHENS_OFFSET) #define EFM32_DMA_CHENS (EFM32_DMA_BASE+EFM32_DMA_CHENS_OFFSET)
#define EFM_DMA_CHENC (EFM32_DMA_BASE+EFM_DMA_CHENC_OFFSET) #define EFM32_DMA_CHENC (EFM32_DMA_BASE+EFM32_DMA_CHENC_OFFSET)
#define EFM_DMA_CHALTS (EFM32_DMA_BASE+EFM_DMA_CHALTS_OFFSET) #define EFM32_DMA_CHALTS (EFM32_DMA_BASE+EFM32_DMA_CHALTS_OFFSET)
#define EFM_DMA_CHALTC (EFM32_DMA_BASE+EFM_DMA_CHALTC_OFFSET) #define EFM32_DMA_CHALTC (EFM32_DMA_BASE+EFM32_DMA_CHALTC_OFFSET)
#define EFM_DMA_CHPRIS (EFM32_DMA_BASE+EFM_DMA_CHPRIS_OFFSET) #define EFM32_DMA_CHPRIS (EFM32_DMA_BASE+EFM32_DMA_CHPRIS_OFFSET)
#define EFM_DMA_CHPRIC (EFM32_DMA_BASE+EFM_DMA_CHPRIC_OFFSET) #define EFM32_DMA_CHPRIC (EFM32_DMA_BASE+EFM32_DMA_CHPRIC_OFFSET)
#define EFM_DMA_ERRORC (EFM32_DMA_BASE+EFM_DMA_ERRORC_OFFSET) #define EFM32_DMA_ERRORC (EFM32_DMA_BASE+EFM32_DMA_ERRORC_OFFSET)
#define EFM_DMA_CHREQSTATUS (EFM32_DMA_BASE+EFM_DMA_CHREQSTATUS_OFFSET) #define EFM32_DMA_CHREQSTATUS (EFM32_DMA_BASE+EFM32_DMA_CHREQSTATUS_OFFSET)
#define EFM_DMA_CHSREQSTATUS (EFM32_DMA_BASE+EFM_DMA_CHSREQSTATUS_OFFSET) #define EFM32_DMA_CHSREQSTATUS (EFM32_DMA_BASE+EFM32_DMA_CHSREQSTATUS_OFFSET)
#define EFM_DMA_IF (EFM32_DMA_BASE+EFM_DMA_IF_OFFSET) #define EFM32_DMA_IF (EFM32_DMA_BASE+EFM32_DMA_IF_OFFSET)
#define EFM_DMA_IFS (EFM32_DMA_BASE+EFM_DMA_IFS_OFFSET) #define EFM32_DMA_IFS (EFM32_DMA_BASE+EFM32_DMA_IFS_OFFSET)
#define EFM_DMA_IFC (EFM32_DMA_BASE+EFM_DMA_IFC_OFFSET) #define EFM32_DMA_IFC (EFM32_DMA_BASE+EFM32_DMA_IFC_OFFSET)
#define EFM_DMA_IEN (EFM32_DMA_BASE+EFM_DMA_IEN_OFFSET) #define EFM32_DMA_IEN (EFM32_DMA_BASE+EFM32_DMA_IEN_OFFSET)
#if defined(CONFIG_EFM32_EFM32GG) #if defined(CONFIG_EFM32_EFM32GG)
# define EFM_DMA_CTRL (EFM32_DMA_BASE+EFM_DMA_CTRL_OFFSET) # define EFM32_DMA_CTRL (EFM32_DMA_BASE+EFM32_DMA_CTRL_OFFSET)
# define EFM_DMA_RDS (EFM32_DMA_BASE+EFM_DMA_RDS_OFFSET) # define EFM32_DMA_RDS (EFM32_DMA_BASE+EFM32_DMA_RDS_OFFSET)
# define EFM_DMA_LOOP0 (EFM32_DMA_BASE+EFM_DMA_LOOP0_OFFSET) # define EFM32_DMA_LOOP0 (EFM32_DMA_BASE+EFM32_DMA_LOOP0_OFFSET)
# define EFM_DMA_LOOP1 (EFM32_DMA_BASE+EFM_DMA_LOOP1_OFFSET) # define EFM32_DMA_LOOP1 (EFM32_DMA_BASE+EFM32_DMA_LOOP1_OFFSET)
# define EFM_DMA_RECT0 (EFM32_DMA_BASE+EFM_DMA_RECT0_OFFSET) # define EFM32_DMA_RECT0 (EFM32_DMA_BASE+EFM32_DMA_RECT0_OFFSET)
#endif #endif
#define EFM_DMA_CHn_CTRL(n) (EFM32_DMA_BASE+EFM_DMA_CHn_CTRL_OFFSET(n)) #define EFM32_DMA_CHn_CTRL(n) (EFM32_DMA_BASE+EFM32_DMA_CHn_CTRL_OFFSET(n))
#define EFM_DMA_CH0_CTRL (EFM32_DMA_BASE+EFM_DMA_CH0_CTRL_OFFSET) #define EFM32_DMA_CH0_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH0_CTRL_OFFSET)
#define EFM_DMA_CH1_CTRL (EFM32_DMA_BASE+EFM_DMA_CH1_CTRL_OFFSET) #define EFM32_DMA_CH1_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH1_CTRL_OFFSET)
#define EFM_DMA_CH2_CTRL (EFM32_DMA_BASE+EFM_DMA_CH2_CTRL_OFFSET) #define EFM32_DMA_CH2_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH2_CTRL_OFFSET)
#define EFM_DMA_CH3_CTRL (EFM32_DMA_BASE+EFM_DMA_CH3_CTRL_OFFSET) #define EFM32_DMA_CH3_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH3_CTRL_OFFSET)
#define EFM_DMA_CH4_CTRL (EFM32_DMA_BASE+EFM_DMA_CH4_CTRL_OFFSET) #define EFM32_DMA_CH4_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH4_CTRL_OFFSET)
#define EFM_DMA_CH5_CTRL (EFM32_DMA_BASE+EFM_DMA_CH5_CTRL_OFFSET) #define EFM32_DMA_CH5_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH5_CTRL_OFFSET)
#define EFM_DMA_CH6_CTRL (EFM32_DMA_BASE+EFM_DMA_CH6_CTRL_OFFSET) #define EFM32_DMA_CH6_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH6_CTRL_OFFSET)
#define EFM_DMA_CH7_CTRL (EFM32_DMA_BASE+EFM_DMA_CH7_CTRL_OFFSET) #define EFM32_DMA_CH7_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH7_CTRL_OFFSET)
#if defined(CONFIG_EFM32_EFM32GG) #if defined(CONFIG_EFM32_EFM32GG)
# define EFM_DMA_CH8_CTRL (EFM32_DMA_BASE+EFM_DMA_CH8_CTRL_OFFSET) # define EFM32_DMA_CH8_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH8_CTRL_OFFSET)
# define EFM_DMA_CH9_CTRL (EFM32_DMA_BASE+EFM_DMA_CH9_CTRL_OFFSET) # define EFM32_DMA_CH9_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH9_CTRL_OFFSET)
# define EFM_DMA_CH10_CTRL (EFM32_DMA_BASE+EFM_DMA_CH10_CTRL_OFFSET) # define EFM32_DMA_CH10_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH10_CTRL_OFFSET)
# define EFM_DMA_CH11_CTRL (EFM32_DMA_BASE+EFM_DMA_CH11_CTRL_OFFSET) # define EFM32_DMA_CH11_CTRL (EFM32_DMA_BASE+EFM32_DMA_CH11_CTRL_OFFSET)
#endif #endif
/* DMA Register Bit Field Definitions ******************************************************************************************/ /* DMA Register Bit Field Definitions ******************************************************************************************/

View File

@ -50,6 +50,7 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include "up_arch.h" #include "up_arch.h"
#include "chip/efm32_cmu.h"
#include "chip/efm32_dma.h" #include "chip/efm32_dma.h"
#include "efm32_dma.h" #include "efm32_dma.h"
@ -76,7 +77,7 @@ union dma_descriptor_u
struct dma_channel_s struct dma_channel_s
{ {
uint8_t chan; /* DMA channel number (0-EFM_DMA_NCHANNELS) */ uint8_t chan; /* DMA channel number (0-EFM32_DMA_NCHANNELS) */
bool inuse; /* TRUE: The DMA channel is in use */ bool inuse; /* TRUE: The DMA channel is in use */
struct dma_descriptor_s *desc; /* DMA descriptor assigned to the channel */ struct dma_descriptor_s *desc; /* DMA descriptor assigned to the channel */
dma_config_t config; /* Current configuration */ dma_config_t config; /* Current configuration */
@ -104,7 +105,7 @@ static struct dma_controller_s g_dmac;
/* This is the array of all DMA channels */ /* This is the array of all DMA channels */
static struct dma_channel_s g_dmach[EFM_DMA_NCHANNELS]; static struct dma_channel_s g_dmach[EFM32_DMA_NCHANNELS];
/* This array describes the available channel control data structures. /* This array describes the available channel control data structures.
* Each structure must be aligned to the size of the DMA descriptor. * Each structure must be aligned to the size of the DMA descriptor.
@ -216,7 +217,7 @@ static void efm32_set_chctrl(struct dma_channel_s *dmach, dma_config_t config)
decoded = (uint32_t)(config & EFM32_DMA_SOURCSEL_MASK) >> EFM32_DMA_SOURCSEL_SHIFT; decoded = (uint32_t)(config & EFM32_DMA_SOURCSEL_MASK) >> EFM32_DMA_SOURCSEL_SHIFT;
regval |= (decoded << _DMA_CH_CTRL_SOURCESEL_SHIFT); regval |= (decoded << _DMA_CH_CTRL_SOURCESEL_SHIFT);
regaddr = EFM_DMA_CHn_CTRL(dmach->chan); regaddr = EFM32_DMA_CHn_CTRL(dmach->chan);
putreg32(regval, regaddr); putreg32(regval, regaddr);
} }
@ -247,7 +248,47 @@ static inline unsigned int efm32_align_shift(dma_config_t config)
static int efm32_dmac_interrupt(int irq, void *context) static int efm32_dmac_interrupt(int irq, void *context)
{ {
#warning Missing logic struct dma_channel_s *dmach;
unsigned int chndx;
uint32_t pending;
uint32_t bit;
/* Get the set of pending, unmasked global XDMAC interrupts */
pending = getreg32(EFM32_DMA_IF) & getreg32(EFM32_DMA_IEN);
putreg32(pending, EFM32_DMA_IFC);
/* Check each bit to see which channel(s) have interrupted */
for (chndx = 0; chndx < EFM32_DMA_NCHANNELS && pending != 0; chndx++)
{
/* Are any interrupts pending for this channel? */
bit = 1 << chndx;
if ((pending & bit) != 0)
{
dmach = &g_dmach[chndx];
/* Put the DMA channel in the stopped state */
efm32_dmastop((DMA_HANDLE)dmach);
/* Call the DMA completion callback */
if (dmach->callback)
{
dmach->callback((DMA_HANDLE)dmach, OK, dmach->arg);
dmach->callback = NULL;
}
dmach->arg = NULL;
/* Clear the bit in the sampled set of pending interrupts */
pending &= !bit;
}
}
return OK; return OK;
} }
@ -268,6 +309,7 @@ static int efm32_dmac_interrupt(int irq, void *context)
void weak_function up_dmainitialize(void) void weak_function up_dmainitialize(void)
{ {
uint32_t regval;
int i; int i;
dmallvdbg("Initialize XDMAC0\n"); dmallvdbg("Initialize XDMAC0\n");
@ -285,23 +327,26 @@ void weak_function up_dmainitialize(void)
/* Initialize the channel list */ /* Initialize the channel list */
sem_init(&g_dmac.exclsem, 0, 1); sem_init(&g_dmac.exclsem, 0, 1);
sem_init(&g_dmac.chansem, 0, EFM_DMA_NCHANNELS); sem_init(&g_dmac.chansem, 0, EFM32_DMA_NCHANNELS);
for (i = 0; i < EFM_DMA_NCHANNELS; i++) for (i = 0; i < EFM32_DMA_NCHANNELS; i++)
{ {
g_dmach[i].chan = i; g_dmach[i].chan = i;
} }
/* Enable clock to the DMA module */ /* Enable clock to the DMA module. DMA is clocked by HFCORECLK. */
#warning Missing logic
regval = getreg32(EFM32_CMU_HFCORECLKEN0);
regval |= CMU_HFCORECLKEN0_DMA;
putreg32(regval, EFM32_CMU_HFCORECLKEN0);
/* Attach DMA interrupt vector */ /* Attach DMA interrupt vector */
(void)irq_attach(EFM32_IRQ_DMA, efm32_dmac_interrupt); (void)irq_attach(EFM32_IRQ_DMA, efm32_dmac_interrupt);
/* Enale the DMA controller */ /* Enable the DMA controller */
putreg32(DMA_CONFIG_EN, EFM_DMA_CONFIG); putreg32(DMA_CONFIG_EN, EFM32_DMA_CONFIG);
/* Enable the IRQ at the AIC (still disabled at the DMA controller) */ /* Enable the IRQ at the AIC (still disabled at the DMA controller) */
@ -335,6 +380,7 @@ DMA_HANDLE efm32_dmachannel(void)
{ {
struct dma_channel_s *dmach; struct dma_channel_s *dmach;
unsigned int chndx; unsigned int chndx;
uint32_t bit;
/* Take a count from from the channel counting semaphore. We may block /* Take a count from from the channel counting semaphore. We may block
* if there are no free channels. When we get the count, then we can * if there are no free channels. When we get the count, then we can
@ -360,7 +406,7 @@ DMA_HANDLE efm32_dmachannel(void)
/* Search for an available DMA channel */ /* Search for an available DMA channel */
for (chndx = 0, dmach = NULL; chndx < EFM_DMA_NCHANNELS; chndx++) for (chndx = 0, dmach = NULL; chndx < EFM32_DMA_NCHANNELS; chndx++)
{ {
struct dma_channel_s *candidate = &g_dmach[chndx]; struct dma_channel_s *candidate = &g_dmach[chndx];
if (!candidate->inuse) if (!candidate->inuse)
@ -369,11 +415,13 @@ DMA_HANDLE efm32_dmachannel(void)
dmach->inuse = true; dmach->inuse = true;
/* Clear any pending channel interrupts */ /* Clear any pending channel interrupts */
#warning Missing logic
bit = 1 << chndx;
putreg32(bit, EFM32_DMA_IFC);
/* Disable the channel */ /* Disable the channel */
putreg32(1 << dmach->chan, EFM_DMA_CHENC); putreg32(bit, EFM32_DMA_CHENC);
break; break;
} }
} }
@ -422,7 +470,7 @@ void efm32_dmafree(DMA_HANDLE handle)
/* Disable the channel */ /* Disable the channel */
putreg32(1 << dmach->chan, EFM_DMA_CHENC); putreg32(1 << dmach->chan, EFM32_DMA_CHENC);
/* Mark the channel no longer in use. Clearing the in-use flag is an atomic /* Mark the channel no longer in use. Clearing the in-use flag is an atomic
* operation and so should be safe. * operation and so should be safe.
@ -624,6 +672,8 @@ void efm32_txdmasetup(DMA_HANDLE handle, uintptr_t paddr, uintptr_t maddr,
void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg) void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
{ {
struct dma_channel_s *dmach = (struct dma_channel_s *)handle; struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
irqstate_t flags;
uint32_t regval;
uint32_t bit; uint32_t bit;
DEBUGASSERT(dmach && dmach->inuse && dmach->desc); DEBUGASSERT(dmach && dmach->inuse && dmach->desc);
@ -642,30 +692,38 @@ void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
* available, wait for buffer full) * available, wait for buffer full)
*/ */
putreg32(bit, EFM_DMA_CHUSEBURSTS); putreg32(bit, EFM32_DMA_CHUSEBURSTS);
/* Enable buffer-full requests for the channel */ /* Enable buffer-full requests for the channel */
putreg32(bit, EFM_DMA_CHREQMASKC); putreg32(bit, EFM32_DMA_CHREQMASKC);
} }
else else
{ {
/* Enable the single requests for the channel */ /* Enable the single requests for the channel */
putreg32(bit, EFM_DMA_CHUSEBURSTC); putreg32(bit, EFM32_DMA_CHUSEBURSTC);
/* Disable buffer-full requests for the channel */ /* Disable buffer-full requests for the channel */
putreg32(bit, EFM_DMA_CHREQMASKS); putreg32(bit, EFM32_DMA_CHREQMASKS);
} }
/* Use the primary data structure for channel 0 */ /* Use the primary data structure for channel 0 */
putreg32(bit, EFM_DMA_CHALTC); putreg32(bit, EFM32_DMA_CHALTC);
/* Enable DMA completion interrupts */
flags = irqsave();
regval = getreg32(EFM32_DMA_IEN);
regval |= bit;
putreg32(bit, EFM32_DMA_IEN);
/* Enable the channel */ /* Enable the channel */
putreg32(bit, EFM_DMA_CHENS); putreg32(bit, EFM32_DMA_CHENS);
irqrestore(flags);
} }
/**************************************************************************** /****************************************************************************
@ -683,49 +741,36 @@ void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
void efm32_dmastop(DMA_HANDLE handle) void efm32_dmastop(DMA_HANDLE handle)
{ {
#warning Missing logic struct dma_channel_s *dmach = (struct dma_channel_s *)handle;
irqstate_t flags;
uint32_t regval;
uint32_t bit;
DEBUGASSERT(dmach && dmach->inuse && dmach->desc);
bit = 1 << dmach->chan;
/* Disable the channel */
flags = irqsave();
putreg32(bit, EFM32_DMA_CHENC);
/* Disable Channel interrupts */
regval = getreg32(EFM32_DMA_IEN);
regval |= bit;
putreg32(bit, EFM32_DMA_IEN);
/* Free any attached DMA descriptor */
if (dmach->desc)
{
efm32_free_descriptor(dmach->desc);
dmach->desc = NULL;
}
irqrestore(flags);
} }
/****************************************************************************
* Name: efm32_dmaresidual
*
* Description:
* Returns the number of bytes remaining to be transferred
*
* Assumptions:
* - DMA handle allocated by efm32_dmachannel()
*
****************************************************************************/
size_t efm32_dmaresidual(DMA_HANDLE handle)
{
#warning Missing logic
return 0;
}
/****************************************************************************
* Name: efm32_dmacapable
*
* Description:
* Check if the DMA controller can transfer data to/from given memory
* address with the given configuration. This depends on the internal
* connections in the ARM bus matrix of the processor. Note that this
* only applies to memory addresses, it will return false for any peripheral
* address.
*
* Returned value:
* True, if transfer is possible.
*
****************************************************************************/
#ifdef CONFIG_EFM32_DMACAPABLE
bool efm32_dmacapable(uintptr_t maddr, uint32_t count, uint32_t ccr)
{
#warning Missing logic
return false;
}
#endif
/**************************************************************************** /****************************************************************************
* Name: efm32_dmasample * Name: efm32_dmasample
* *
@ -740,7 +785,42 @@ return false;
#ifdef CONFIG_DEBUG_DMA #ifdef CONFIG_DEBUG_DMA
void efm32_dmasample(DMA_HANDLE handle, struct efm32_dmaregs_s *regs) void efm32_dmasample(DMA_HANDLE handle, struct efm32_dmaregs_s *regs)
{ {
#warning Missing logic struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
uintptr_t regaddr;
irqstate_t flags;
/* Sample DMA registers. */
flags = irqsave();
regs->status = getreg32(EFM32_DMA_STATUS);
regs->ctrlbase = getreg32(EFM32_DMA_CTRLBASE);
regs->altctrlbase = getreg32(EFM32_DMA_ALTCTRLBASE);
regs->chwaitstatus = getreg32(EFM32_DMA_CHWAITSTATUS);
regs->chusebursts = getreg32(EFM32_DMA_CHUSEBURSTS);
regs->chreqmasks = getreg32(EFM32_DMA_CHREQMASKS);
regs->chens = getreg32(EFM32_DMA_CHENS);
regs->chalts = getreg32(EFM32_DMA_CHALTS);
regs->chpris = getreg32(EFM32_DMA_CHPRIS);
regs->errorc = getreg32(EFM32_DMA_ERRORC);
regs->chreqstatus = getreg32(EFM32_DMA_CHREQSTATUS);
regs->chsreqstatus = getreg32(EFM32_DMA_CHSREQSTATUS);
regs->ifr = getreg32(EFM32_DMA_IF);
regs->ien = getreg32(EFM32_DMA_IEN);
#if defined(CONFIG_EFM32_EFM32GG)
regs->ctrl = getreg32(EFM32_DMA_CTRL);
regs->rds = getreg32(EFM32_DMA_RDS);
regs->loop0 = getreg32(EFM32_DMA_LOOP0);
regs->loop1 = getreg32(EFM32_DMA_LOOP1);
regs->rect0 = getreg32(EFM32_DMA_RECT0);
#endif
/* Sample channel control register */
regaddr = EFM32_DMA_CHn_CTRL(dmach->chan)
regs->chnctrl = getreg32(regaddr);
irqrestore(flags);
} }
#endif #endif
@ -759,6 +839,32 @@ void efm32_dmasample(DMA_HANDLE handle, struct efm32_dmaregs_s *regs)
void efm32_dmadump(DMA_HANDLE handle, const struct efm32_dmaregs_s *regs, void efm32_dmadump(DMA_HANDLE handle, const struct efm32_dmaregs_s *regs,
const char *msg) const char *msg)
{ {
#warning Missing logic struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
struct sam_xdmac_s *xdmac = sam_controller(xdmach);
dmadbg("%s\n", msg);
dmadbg(" DMA Registers:\n");
dmadbg(" STATUS: %08x\n", regs->status);
dmadbg(" CTRLBASE: %08x\n", regs->ctrlbase);
dmadbg(" ALTCTRLBASE: %08x\n", regs->altctrlbase);
dmadbg(" CHWAITSTATUS: %08x\n", regs->chwaitstatus);
dmadbg(" CHUSEBURSTS: %08x\n", regs->chusebursts);
dmadbg(" CHREQMASKS: %08x\n", regs->chreqmasks);
dmadbg(" CHENS: %08x\n", regs->chens);
dmadbg(" CHALTS: %08x\n", regs->chalts);
dmadbg(" CHPRIS: %08x\n", regs->chpris);
dmadbg(" ERRORC: %08x\n", regs->errorc);
dmadbg(" CHREQSTATUS: %08x\n", regs->chreqstatus);
dmadbg(" CHSREQSTATUS: %08x\n", regs->chsreqstatus);
dmadbg(" IEN: %08x\n", regs->ien);
#if defined(CONFIG_EFM32_EFM32GG)
dmadbg(" CTRL: %08x\n", regs->ctrl);
dmadbg(" RDS: %08x\n", regs->rds);
dmadbg(" LOOP0: %08x\n", regs->loop0);
dmadbg(" LOOP1: %08x\n", regs->loop1);
dmadbg(" RECT0: %08x\n", regs->rect0);
#endif
dmadbg(" DMA Channel %d Registers:\n", dmach->chan);
dmadbg(" CHCTRL: %08x\n", regs->chnctrl);
} }
#endif #endif

View File

@ -107,7 +107,7 @@ typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg);
#ifdef CONFIG_DEBUG_DMA #ifdef CONFIG_DEBUG_DMA
struct efm32_dmaregs_s struct efm32_dmaregs_s
{ {
uint32_t status; /* DMA Status Registers */ uint32_t status; /* DMA Status Register */
uint32_t ctrlbase; /* Channel Control Data Base Pointer Register */ uint32_t ctrlbase; /* Channel Control Data Base Pointer Register */
uint32_t altctrlbase; /* Channel Alternate Control Data Base Pointer Register */ uint32_t altctrlbase; /* Channel Alternate Control Data Base Pointer Register */
uint32_t chwaitstatus; /* Channel Wait on Request Status Register */ uint32_t chwaitstatus; /* Channel Wait on Request Status Register */
@ -128,7 +128,7 @@ struct efm32_dmaregs_s
uint32_t loop1; /* Channel 1 Loop Register */ uint32_t loop1; /* Channel 1 Loop Register */
uint32_t rect0; /* Channel 0 Rectangle Register */ uint32_t rect0; /* Channel 0 Rectangle Register */
#endif #endif
uint32_t chcgrl /* Channel n Control Register */ uint32_t chnctrl; /* Channel n Control Register */
}; };
#endif #endif
@ -266,40 +266,6 @@ void efm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg);
void efm32_dmastop(DMA_HANDLE handle); void efm32_dmastop(DMA_HANDLE handle);
/****************************************************************************
* Name: efm32_dmaresidual
*
* Description:
* Returns the number of bytes remaining to be transferred
*
* Assumptions:
* - DMA handle allocated by efm32_dmachannel()
*
****************************************************************************/
size_t efm32_dmaresidual(DMA_HANDLE handle);
/****************************************************************************
* Name: efm32_dmacapable
*
* Description:
* Check if the DMA controller can transfer data to/from given memory
* address with the given configuration. This depends on the internal
* connections in the ARM bus matrix of the processor. Note that this
* only applies to memory addresses, it will return false for any peripheral
* address.
*
* Returned value:
* True, if transfer is possible.
*
****************************************************************************/
#ifdef CONFIG_EFM32_DMACAPABLE
bool efm32_dmacapable(uintptr_t maddr, uint32_t count, uint32_t ccr);
#else
# define efm32_dmacapable(maddr, count, ccr) (true)
#endif
/**************************************************************************** /****************************************************************************
* Name: efm32_dmasample * Name: efm32_dmasample
* *