mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
imx233: make sure dma descriptors are cache friendly
Because DMA descriptors needs to be committed and discarded from the cache, if they are not cache aligned and/or if their size is not a multiple of cache ligne, nasty side effects could occur with adjacents data. The same applies to DMA buffers which are still potentially broken. Add a macro to ensure that these constraints will not break by error in the future. Change-Id: I1dd69a5a9c29796c156d953eaa57c0d281e79846
This commit is contained in:
parent
1adc474771
commit
1b6e8cba62
5 changed files with 34 additions and 7 deletions
|
@ -86,6 +86,12 @@
|
||||||
/* 32 bytes per cache line */
|
/* 32 bytes per cache line */
|
||||||
#define CACHEALIGN_BITS 5
|
#define CACHEALIGN_BITS 5
|
||||||
|
|
||||||
|
#define ___ENSURE_ZERO(line, x) static uint8_t __ensure_zero_##line[-(x)] __attribute__((unused));
|
||||||
|
#define __ENSURE_ZERO(x) ___ENSURE_ZERO(__LINE__, x)
|
||||||
|
#define __ENSURE_MULTIPLE(x, y) __ENSURE_ZERO((x) % (y))
|
||||||
|
#define __ENSURE_CACHELINE_MULTIPLE(x) __ENSURE_MULTIPLE(x, 1 << CACHEALIGN_BITS)
|
||||||
|
#define __ENSURE_STRUCT_CACHE_FRIENDLY(name) __ENSURE_CACHELINE_MULTIPLE(sizeof(name))
|
||||||
|
|
||||||
#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
|
#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
|
||||||
#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
|
#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
|
||||||
#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
|
#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
|
||||||
|
|
|
@ -118,6 +118,10 @@
|
||||||
* COMMON *
|
* COMMON *
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
|
/* DMA structures should be cache aligned and be padded so that their size
|
||||||
|
* is a multiple of a cache line size. Otherwise some nasty side effects
|
||||||
|
* could occur with adjacents data fields.
|
||||||
|
* The same apply to DMA buffers for the same reasons */
|
||||||
struct apb_dma_command_t
|
struct apb_dma_command_t
|
||||||
{
|
{
|
||||||
struct apb_dma_command_t *next;
|
struct apb_dma_command_t *next;
|
||||||
|
|
|
@ -34,7 +34,11 @@ struct i2c_dma_command_t
|
||||||
struct apb_dma_command_t dma;
|
struct apb_dma_command_t dma;
|
||||||
/* PIO words */
|
/* PIO words */
|
||||||
uint32_t ctrl0;
|
uint32_t ctrl0;
|
||||||
};
|
/* padded to next multiple of cache line size (32 bytes) */
|
||||||
|
uint32_t pad[4];
|
||||||
|
} __attribute__((packed)) CACHEALIGN_ATTR;
|
||||||
|
|
||||||
|
__ENSURE_STRUCT_CACHE_FRIENDLY(struct i2c_dma_command_t)
|
||||||
|
|
||||||
#define I2C_NR_STAGES 4
|
#define I2C_NR_STAGES 4
|
||||||
/* Current transfer */
|
/* Current transfer */
|
||||||
|
|
|
@ -26,8 +26,17 @@
|
||||||
#include "pcm-internal.h"
|
#include "pcm-internal.h"
|
||||||
#include "audioout-imx233.h"
|
#include "audioout-imx233.h"
|
||||||
|
|
||||||
|
struct pcm_dma_command_t
|
||||||
|
{
|
||||||
|
struct apb_dma_command_t dma;
|
||||||
|
/* padded to next multiple of cache line size (32 bytes) */
|
||||||
|
uint32_t pad[5];
|
||||||
|
} __attribute__((packed)) CACHEALIGN_ATTR;
|
||||||
|
|
||||||
|
__ENSURE_STRUCT_CACHE_FRIENDLY(struct pcm_dma_command_t)
|
||||||
|
|
||||||
static int locked = 0;
|
static int locked = 0;
|
||||||
static struct apb_dma_command_t dac_dma;
|
static struct pcm_dma_command_t dac_dma;
|
||||||
static bool pcm_freezed = false;
|
static bool pcm_freezed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,14 +46,14 @@ static bool pcm_freezed = false;
|
||||||
|
|
||||||
static void play(const void *addr, size_t size)
|
static void play(const void *addr, size_t size)
|
||||||
{
|
{
|
||||||
dac_dma.next = NULL;
|
dac_dma.dma.next = NULL;
|
||||||
dac_dma.buffer = (void *)addr;
|
dac_dma.dma.buffer = (void *)addr;
|
||||||
dac_dma.cmd = HW_APB_CHx_CMD__COMMAND__READ |
|
dac_dma.dma.cmd = HW_APB_CHx_CMD__COMMAND__READ |
|
||||||
HW_APB_CHx_CMD__IRQONCMPLT |
|
HW_APB_CHx_CMD__IRQONCMPLT |
|
||||||
HW_APB_CHx_CMD__SEMAPHORE |
|
HW_APB_CHx_CMD__SEMAPHORE |
|
||||||
size << HW_APB_CHx_CMD__XFER_COUNT_BP;
|
size << HW_APB_CHx_CMD__XFER_COUNT_BP;
|
||||||
/* dma subsystem will make sure cached stuff is written to memory */
|
/* dma subsystem will make sure cached stuff is written to memory */
|
||||||
imx233_dma_start_command(APB_AUDIO_DAC, &dac_dma);
|
imx233_dma_start_command(APB_AUDIO_DAC, &dac_dma.dma);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT_DAC_DMA(void)
|
void INT_DAC_DMA(void)
|
||||||
|
|
|
@ -43,7 +43,11 @@ struct ssp_dma_command_t
|
||||||
uint32_t ctrl0;
|
uint32_t ctrl0;
|
||||||
uint32_t cmd0;
|
uint32_t cmd0;
|
||||||
uint32_t cmd1;
|
uint32_t cmd1;
|
||||||
};
|
/* padded to next multiple of cache line size (32 bytes) */
|
||||||
|
uint32_t pad[2];
|
||||||
|
} __attribute__((packed)) CACHEALIGN_ATTR;
|
||||||
|
|
||||||
|
__ENSURE_STRUCT_CACHE_FRIENDLY(struct ssp_dma_command_t)
|
||||||
|
|
||||||
static bool ssp_in_use[2];
|
static bool ssp_in_use[2];
|
||||||
static int ssp_nr_in_use = 0;
|
static int ssp_nr_in_use = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue