diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c index 97001210d2..8dac284a38 100644 --- a/firmware/target/arm/imx233/dma-imx233.c +++ b/firmware/target/arm/imx233/dma-imx233.c @@ -24,6 +24,8 @@ #include "config.h" #include "system.h" #include "dma-imx233.h" +#include "lcd.h" +#include "string.h" void imx233_dma_init(void) { @@ -34,12 +36,22 @@ void imx233_dma_init(void) void imx233_dma_reset_channel(unsigned chan) { + volatile uint32_t *ptr; + uint32_t bm; if(APB_IS_APBX_CHANNEL(chan)) - __REG_SET(HW_APBX_CHANNEL_CTRL) = - HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + { + ptr = &HW_APBX_CHANNEL_CTRL; + bm = HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + } else - __REG_SET(HW_APBH_CTRL0) = - HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + { + ptr = &HW_APBH_CTRL0; + bm = HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + } + __REG_SET(*ptr) = bm; + /* wait for end of reset */ + while(*ptr & bm) + ; } void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock) @@ -54,6 +66,27 @@ void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock) HW_APBH_CTRL0__CLKGATE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); } +void imx233_dma_freeze_channel(unsigned chan, bool freeze) +{ + volatile uint32_t *ptr; + uint32_t bm; + if(APB_IS_APBX_CHANNEL(chan)) + { + ptr = &HW_APBX_CHANNEL_CTRL; + bm = HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + } + else + { + ptr = &HW_APBH_CTRL0; + bm = HW_APBH_CTRL0__FREEZE_CHANNEL(APB_GET_DMA_CHANNEL(chan)); + } + + if(freeze) + __REG_SET(*ptr) = bm; + else + __REG_CLR(*ptr) = bm; +} + void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable) { volatile uint32_t *ptr; @@ -65,7 +98,7 @@ void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable) } else { - ptr = &HW_APBH_CTRL1;; + ptr = &HW_APBH_CTRL1; bm = HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(APB_GET_DMA_CHANNEL(chan)); } @@ -186,3 +219,41 @@ void imx233_dma_wait_completion(unsigned chan) while(*sema & HW_APB_CHx_SEMA__PHORE_BM) yield(); } + +struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags) +{ + struct imx233_dma_info_t s; + memset(&s, 0, sizeof(s)); + bool apbx = APB_IS_APBX_CHANNEL(chan); + int dmac = APB_GET_DMA_CHANNEL(chan); + if(flags & DMA_INFO_CURCMDADDR) + s.cur_cmd_addr = apbx ? HW_APBX_CHx_CURCMDAR(dmac) : HW_APBH_CHx_CURCMDAR(dmac); + if(flags & DMA_INFO_NXTCMDADDR) + s.nxt_cmd_addr = apbx ? HW_APBX_CHx_NXTCMDAR(dmac) : HW_APBH_CHx_NXTCMDAR(dmac); + if(flags & DMA_INFO_CMD) + s.cmd = apbx ? HW_APBX_CHx_CMD(dmac) : HW_APBH_CHx_CMD(dmac); + if(flags & DMA_INFO_BAR) + s.bar = apbx ? HW_APBX_CHx_BAR(dmac) : HW_APBH_CHx_BAR(dmac); + if(flags & DMA_INFO_AHB_BYTES) + s.ahb_bytes = apbx ? __XTRACT_EX(HW_APBX_CHx_DEBUG2(dmac), HW_APBX_CHx_DEBUG2__AHB_BYTES) : + __XTRACT_EX(HW_APBH_CHx_DEBUG2(dmac), HW_APBH_CHx_DEBUG2__AHB_BYTES); + if(flags & DMA_INFO_APB_BYTES) + s.apb_bytes = apbx ? __XTRACT_EX(HW_APBX_CHx_DEBUG2(dmac), HW_APBX_CHx_DEBUG2__APB_BYTES) : + __XTRACT_EX(HW_APBH_CHx_DEBUG2(dmac), HW_APBH_CHx_DEBUG2__APB_BYTES); + if(flags & DMA_INFO_FREEZED) + s.freezed = apbx ? HW_APBX_CHANNEL_CTRL & HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(dmac) : + HW_APBH_CTRL0 & HW_APBH_CTRL0__FREEZE_CHANNEL(dmac); + if(flags & DMA_INFO_GATED) + s.gated = apbx ? false : HW_APBH_CTRL0 & HW_APBH_CTRL0__CLKGATE_CHANNEL(dmac); + if(flags & DMA_INFO_INTERRUPT) + { + s.int_enabled = apbx ? HW_APBX_CTRL1 & HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(dmac) : + HW_APBH_CTRL1 & HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(dmac); + s.int_cmdcomplt = apbx ? HW_APBX_CTRL1 & HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(dmac) : + HW_APBH_CTRL1 & HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(dmac); + s.int_error = apbx ? HW_APBX_CTRL2 & HW_APBX_CTRL2__CHx_ERROR_IRQ(dmac) : + HW_APBH_CTRL2 & HW_APBH_CTRL2__CHx_ERROR_IRQ(dmac); + } + return s; +} + diff --git a/firmware/target/arm/imx233/dma-imx233.h b/firmware/target/arm/imx233/dma-imx233.h index c0727a51e1..05baea989c 100644 --- a/firmware/target/arm/imx233/dma-imx233.h +++ b/firmware/target/arm/imx233/dma-imx233.h @@ -65,6 +65,10 @@ #define HW_APBH_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x90 + 0x70 * (i))) #define HW_APBH_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0xa0 + 0x70 * (i))) +#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BP 0 +#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BM 0xffff +#define HW_APBH_CHx_DEBUG2__APB_BYTES_BP 16 +#define HW_APBH_CHx_DEBUG2__APB_BYTES_BM 0xffff0000 /******** * APHX * @@ -104,6 +108,10 @@ #define HW_APBX_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x150 + (i) * 0x70)) #define HW_APBX_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x160 + (i) * 0x70)) +#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BP 0 +#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BM 0xffff +#define HW_APBX_CHx_DEBUG2__APB_BYTES_BP 16 +#define HW_APBX_CHx_DEBUG2__APB_BYTES_BM 0xffff0000 /********** * COMMON * @@ -117,6 +125,32 @@ struct apb_dma_command_t /* PIO words follow */ }; +#define DMA_INFO_CURCMDADDR (1 << 0) +#define DMA_INFO_NXTCMDADDR (1 << 1) +#define DMA_INFO_CMD (1 << 2) +#define DMA_INFO_BAR (1 << 3) +#define DMA_INFO_APB_BYTES (1 << 4) +#define DMA_INFO_AHB_BYTES (1 << 5) +#define DMA_INFO_FREEZED (1 << 6) +#define DMA_INFO_GATED (1 << 7) +#define DMA_INFO_INTERRUPT (1 << 8) +#define DMA_INFO_ALL 0x1ff + +struct imx233_dma_info_t +{ + unsigned long cur_cmd_addr; + unsigned long nxt_cmd_addr; + unsigned long cmd; + unsigned long bar; + unsigned apb_bytes; + unsigned ahb_bytes; + bool freezed; + bool gated; + bool int_enabled; + bool int_cmdcomplt; + bool int_error; +}; + #define APBH_DMA_CHANNEL(i) i #define APBX_DMA_CHANNEL(i) ((i) | 0x10) #define APB_IS_APBX_CHANNEL(x) ((x) & 0x10) @@ -124,6 +158,7 @@ struct apb_dma_command_t #define APB_SSP(ssp) APBH_DMA_CHANNEL(HW_APBH_SSP(ssp)) #define APB_AUDIO_ADC APBX_DMA_CHANNEL(HW_APBX_AUDIO_ADC) +#define APB_AUDIO_DAC APBX_DMA_CHANNEL(HW_APBX_AUDIO_DAC) #define APB_I2C APBX_DMA_CHANNEL(HW_APBX_I2C) #define HW_APB_CHx_CMD__COMMAND_BM 0x3 @@ -160,6 +195,7 @@ void imx233_dma_reset_channel(unsigned chan); /* only apbh channel have clkgate control */ void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock); +void imx233_dma_freeze_channel(unsigned chan, bool freeze); void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable); /* clear both channel complete and error bits */ void imx233_dma_clear_channel_interrupt(unsigned chan); @@ -167,5 +203,8 @@ bool imx233_dma_is_channel_error_irq(unsigned chan); /* assume no command is in progress */ void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd); void imx233_dma_wait_completion(unsigned chan); +/* get some info + * WARNING: if channel is not freezed, data might not be coherent ! */ +struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags); #endif // __DMA_IMX233_H__