summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-05-20 01:23:17 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-05-20 01:35:25 +0200
commit1b6e8cba62d0ea12bc39b0e3f60f66c3892ca1ff (patch)
tree9d034e05f485b42f837a509ff91844c0f7432be5
parent1adc47477144e701dcb1184f907887eadec05fda (diff)
downloadrockbox-1b6e8cba62d0ea12bc39b0e3f60f66c3892ca1ff.tar.gz
rockbox-1b6e8cba62d0ea12bc39b0e3f60f66c3892ca1ff.zip
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
-rw-r--r--firmware/export/imx233.h6
-rw-r--r--firmware/target/arm/imx233/dma-imx233.h4
-rw-r--r--firmware/target/arm/imx233/i2c-imx233.c6
-rw-r--r--firmware/target/arm/imx233/pcm-imx233.c19
-rw-r--r--firmware/target/arm/imx233/ssp-imx233.c6
5 files changed, 34 insertions, 7 deletions
diff --git a/firmware/export/imx233.h b/firmware/export/imx233.h
index ba5ca7a284..70be3788ff 100644
--- a/firmware/export/imx233.h
+++ b/firmware/export/imx233.h
@@ -86,6 +86,12 @@
86/* 32 bytes per cache line */ 86/* 32 bytes per cache line */
87#define CACHEALIGN_BITS 5 87#define CACHEALIGN_BITS 5
88 88
89#define ___ENSURE_ZERO(line, x) static uint8_t __ensure_zero_##line[-(x)] __attribute__((unused));
90#define __ENSURE_ZERO(x) ___ENSURE_ZERO(__LINE__, x)
91#define __ENSURE_MULTIPLE(x, y) __ENSURE_ZERO((x) % (y))
92#define __ENSURE_CACHELINE_MULTIPLE(x) __ENSURE_MULTIPLE(x, 1 << CACHEALIGN_BITS)
93#define __ENSURE_STRUCT_CACHE_FRIENDLY(name) __ENSURE_CACHELINE_MULTIPLE(sizeof(name))
94
89#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP) 95#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
90#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP) 96#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
91#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP) 97#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
diff --git a/firmware/target/arm/imx233/dma-imx233.h b/firmware/target/arm/imx233/dma-imx233.h
index fe220dc5f7..ee836c2186 100644
--- a/firmware/target/arm/imx233/dma-imx233.h
+++ b/firmware/target/arm/imx233/dma-imx233.h
@@ -118,6 +118,10 @@
118 * COMMON * 118 * COMMON *
119 **********/ 119 **********/
120 120
121/* DMA structures should be cache aligned and be padded so that their size
122 * is a multiple of a cache line size. Otherwise some nasty side effects
123 * could occur with adjacents data fields.
124 * The same apply to DMA buffers for the same reasons */
121struct apb_dma_command_t 125struct apb_dma_command_t
122{ 126{
123 struct apb_dma_command_t *next; 127 struct apb_dma_command_t *next;
diff --git a/firmware/target/arm/imx233/i2c-imx233.c b/firmware/target/arm/imx233/i2c-imx233.c
index fd9801ec1d..0bf5213854 100644
--- a/firmware/target/arm/imx233/i2c-imx233.c
+++ b/firmware/target/arm/imx233/i2c-imx233.c
@@ -34,7 +34,11 @@ struct i2c_dma_command_t
34 struct apb_dma_command_t dma; 34 struct apb_dma_command_t dma;
35 /* PIO words */ 35 /* PIO words */
36 uint32_t ctrl0; 36 uint32_t ctrl0;
37}; 37 /* padded to next multiple of cache line size (32 bytes) */
38 uint32_t pad[4];
39} __attribute__((packed)) CACHEALIGN_ATTR;
40
41__ENSURE_STRUCT_CACHE_FRIENDLY(struct i2c_dma_command_t)
38 42
39#define I2C_NR_STAGES 4 43#define I2C_NR_STAGES 4
40/* Current transfer */ 44/* Current transfer */
diff --git a/firmware/target/arm/imx233/pcm-imx233.c b/firmware/target/arm/imx233/pcm-imx233.c
index e94260e457..5cce1591fa 100644
--- a/firmware/target/arm/imx233/pcm-imx233.c
+++ b/firmware/target/arm/imx233/pcm-imx233.c
@@ -26,8 +26,17 @@
26#include "pcm-internal.h" 26#include "pcm-internal.h"
27#include "audioout-imx233.h" 27#include "audioout-imx233.h"
28 28
29struct pcm_dma_command_t
30{
31 struct apb_dma_command_t dma;
32 /* padded to next multiple of cache line size (32 bytes) */
33 uint32_t pad[5];
34} __attribute__((packed)) CACHEALIGN_ATTR;
35
36__ENSURE_STRUCT_CACHE_FRIENDLY(struct pcm_dma_command_t)
37
29static int locked = 0; 38static int locked = 0;
30static struct apb_dma_command_t dac_dma; 39static struct pcm_dma_command_t dac_dma;
31static bool pcm_freezed = false; 40static bool pcm_freezed = false;
32 41
33/** 42/**
@@ -37,14 +46,14 @@ static bool pcm_freezed = false;
37 46
38static void play(const void *addr, size_t size) 47static void play(const void *addr, size_t size)
39{ 48{
40 dac_dma.next = NULL; 49 dac_dma.dma.next = NULL;
41 dac_dma.buffer = (void *)addr; 50 dac_dma.dma.buffer = (void *)addr;
42 dac_dma.cmd = HW_APB_CHx_CMD__COMMAND__READ | 51 dac_dma.dma.cmd = HW_APB_CHx_CMD__COMMAND__READ |
43 HW_APB_CHx_CMD__IRQONCMPLT | 52 HW_APB_CHx_CMD__IRQONCMPLT |
44 HW_APB_CHx_CMD__SEMAPHORE | 53 HW_APB_CHx_CMD__SEMAPHORE |
45 size << HW_APB_CHx_CMD__XFER_COUNT_BP; 54 size << HW_APB_CHx_CMD__XFER_COUNT_BP;
46 /* dma subsystem will make sure cached stuff is written to memory */ 55 /* dma subsystem will make sure cached stuff is written to memory */
47 imx233_dma_start_command(APB_AUDIO_DAC, &dac_dma); 56 imx233_dma_start_command(APB_AUDIO_DAC, &dac_dma.dma);
48} 57}
49 58
50void INT_DAC_DMA(void) 59void INT_DAC_DMA(void)
diff --git a/firmware/target/arm/imx233/ssp-imx233.c b/firmware/target/arm/imx233/ssp-imx233.c
index 21dcba67aa..1b773a4dd0 100644
--- a/firmware/target/arm/imx233/ssp-imx233.c
+++ b/firmware/target/arm/imx233/ssp-imx233.c
@@ -43,7 +43,11 @@ struct ssp_dma_command_t
43 uint32_t ctrl0; 43 uint32_t ctrl0;
44 uint32_t cmd0; 44 uint32_t cmd0;
45 uint32_t cmd1; 45 uint32_t cmd1;
46}; 46 /* padded to next multiple of cache line size (32 bytes) */
47 uint32_t pad[2];
48} __attribute__((packed)) CACHEALIGN_ATTR;
49
50__ENSURE_STRUCT_CACHE_FRIENDLY(struct ssp_dma_command_t)
47 51
48static bool ssp_in_use[2]; 52static bool ssp_in_use[2];
49static int ssp_nr_in_use = 0; 53static int ssp_nr_in_use = 0;