summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/dma-imx233.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/firmware/target/arm/imx233/dma-imx233.c b/firmware/target/arm/imx233/dma-imx233.c
index 390add4..fa8ee07 100644
--- a/firmware/target/arm/imx233/dma-imx233.c
+++ b/firmware/target/arm/imx233/dma-imx233.c
@@ -32,8 +32,42 @@
// statistics about unaligned transfers
static int apb_nr_unaligned[32];
+static void safe_reset_channel(int chan)
+{
+ bool apbx_running = !BF_RD(APBX_CTRL0, SFTRST) && !BF_RD(APBX_CTRL0, CLKGATE);
+ bool apbh_running = !BF_RD(APBH_CTRL0, SFTRST) && !BF_RD(APBH_CTRL0, CLKGATE);
+ if(APB_IS_APBX_CHANNEL(chan))
+ {
+ if(!apbx_running)
+ return; /* don't reset if block is not running */
+ }
+ else
+ {
+ if(!apbh_running)
+ return; /* don't reset if block is not running */
+ if(BF_RD(APBH_CTRL0, CLKGATE_CHANNEL) & (1 << chan))
+ return; /* don't reset a gated channel */
+ }
+ imx233_dma_reset_channel(chan);
+}
+
void imx233_dma_init(void)
{
+ /* BUG The stmp3700 (and probably stmp3780) have a hardware bug related to
+ * resetting the block when channel is running. It appears that at least
+ * for the LCDIF channel, resetting the block while the channel is running
+ * will make the channel hang. Once the channel hang, it cannot be recovered
+ * except by a chip reset. On most devices this situation will never arise
+ * but on the Creative ZEN (X-Fi), the OF bootloader leaves the channel
+ * running (to display the logo) when booting. It is unclear if this bug only
+ * affects the APBH or also the APBX. I believe it is related to the errata about
+ * channels not clearing the fifo on abrupt termination which affects both
+ * dma engines. Also note that we can't safely reset 'all' the channels by
+ * setting the reset mask to 0xffff since non-implemented channels don't clear
+ * their reset bit... Also reset won't work on gated channels and won't work if
+ * block is in reset or gated, in which case this situation is assumed not
+ * to exists */
+ safe_reset_channel(APB_LCDIF);
/* Enable APHB and APBX */
imx233_reset_block(&HW_APBH_CTRL0);
imx233_reset_block(&HW_APBX_CTRL0);