@@ -147,6 +147,20 @@ static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
};
+/* Errata handling */
+u32 dma_errata;
+#define IS_DMA_ERRATA(id) (dma_errata & (id))
+#define SET_DMA_ERRATA(id) (dma_errata | (id))
+
+/* Errata: Inter Frame DMA buffering issue */
+#define DMA_ERRATA_IFRAME_BUFFERING (1 << 0)
+/* Errata: DMA may hang when several channels are used in parallel */
+#define DMA_ERRATA_PARALLEL_CHANNELS (1 << 1)
+/* Errata i378: sDMA Channel is not disabled after a transaction error */
+#define DMA_ERRATA_i378 (1 << 2)
+/* Errata i541: sDMA FIFO draining does not finish */
+#define DMA_ERRATA_i541 (1 << 3)
+
static inline void disable_lnk(int lch);
static void omap_disable_channel_irq(int lch);
static inline void omap_enable_channel_irq(int lch);
@@ -985,9 +999,7 @@ void omap_start_dma(int lch)
cur_lch = next_lch;
} while (next_lch != -1);
- } else if (cpu_is_omap242x() ||
- (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) {
-
+ } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) {
/* Errata: Need to write lch even if not using chaining */
dma_write(lch, CLNK_CTRL(lch));
}
@@ -1005,8 +1017,7 @@ void omap_start_dma(int lch)
* guarantee no data will stay in the DMA FIFO in case inter frame
* buffering occurs.
*/
- if (cpu_is_omap2420() ||
- (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
+ if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
l |= OMAP_DMA_CCR_EN;
@@ -1026,7 +1037,8 @@ void omap_stop_dma(int lch)
l = dma_read(CCR(lch));
/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
- if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+ if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
+ (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
int i = 0;
u32 sys_cf;
@@ -1960,7 +1972,7 @@ static int omap2_dma_handle_ch(int ch)
if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
printk(KERN_INFO "DMA transaction error with device %d\n",
dma_chan[ch].dev_id);
- if (cpu_class_is_omap2()) {
+ if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
/*
* Errata: sDMA Channel is not disabled
* after a transaction error. So we explicitely
@@ -2079,6 +2091,22 @@ void omap_dma_global_context_restore(void)
/*----------------------------------------------------------------------------*/
+/* Initialize sDMA errata flags */
+static void dma_errata_configure(void)
+{
+ if (cpu_is_omap242x() ||
+ (cpu_is_omap243x() && (omap_type() == OMAP2430_REV_ES1_0))) {
+ SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+ SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+ }
+
+ if (cpu_class_is_omap2())
+ SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+ if (cpu_is_omap34xx())
+ SET_DMA_ERRATA(DMA_ERRATA_i541);
+}
+
static int __init omap_init_dma(void)
{
unsigned long base;
@@ -2101,6 +2129,8 @@ static int __init omap_init_dma(void)
return -ENODEV;
}
+ dma_errata_configure();
+
omap_dma_base = ioremap(base, SZ_4K);
BUG_ON(!omap_dma_base);