Explorar o código

ARM: OMAP: Sync DMA with linux-omap tree

This patch syncs OMAP DMA code with linux-omap tree.
Mostly allow changing DMA callback function and set
OMAP2 specific transfer mode.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Tony Lindgren %!s(int64=19) %!d(string=hai) anos
pai
achega
709eb3e5cc
Modificáronse 2 ficheiros con 75 adicións e 22 borrados
  1. 64 21
      arch/arm/plat-omap/dma.c
  2. 11 1
      include/asm-arm/arch-omap/dma.h

+ 64 - 21
arch/arm/plat-omap/dma.c

@@ -119,32 +119,41 @@ static void clear_lch_regs(int lch)
 		omap_writew(0, lch_base + i);
 }
 
-void omap_set_dma_priority(int dst_port, int priority)
+void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
 	u32 l;
 
-	switch (dst_port) {
-	case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
-		reg = OMAP_TC_OCPT1_PRIOR;
-		break;
-	case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
-		reg = OMAP_TC_OCPT2_PRIOR;
-		break;
-	case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
-		reg = OMAP_TC_EMIFF_PRIOR;
-		break;
-	case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
-		reg = OMAP_TC_EMIFS_PRIOR;
-		break;
-	default:
-		BUG();
-		return;
+	if (cpu_class_is_omap1()) {
+		switch (dst_port) {
+		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
+			reg = OMAP_TC_OCPT1_PRIOR;
+			break;
+		case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
+			reg = OMAP_TC_OCPT2_PRIOR;
+			break;
+		case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
+			reg = OMAP_TC_EMIFF_PRIOR;
+			break;
+		case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
+			reg = OMAP_TC_EMIFS_PRIOR;
+			break;
+		default:
+			BUG();
+			return;
+		}
+		l = omap_readl(reg);
+		l &= ~(0xf << 8);
+		l |= (priority & 0xf) << 8;
+		omap_writel(l, reg);
+	}
+
+	if (cpu_is_omap24xx()) {
+		if (priority)
+			OMAP_DMA_CCR_REG(lch) |= (1 << 6);
+		else
+			OMAP_DMA_CCR_REG(lch) &= ~(1 << 6);
 	}
-	l = omap_readl(reg);
-	l &= ~(0xf << 8);
-	l |= (priority & 0xf) << 8;
-	omap_writel(l, reg);
 }
 
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
@@ -234,6 +243,14 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 	OMAP1_DMA_LCH_CTRL_REG(lch) = w;
 }
 
+void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
+{
+	if (cpu_is_omap24xx()) {
+		OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
+		OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
+	}
+}
+
 /* Note that src_port is only for omap1 */
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 			     unsigned long src_start,
@@ -697,6 +714,32 @@ void omap_stop_dma(int lch)
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
+/*
+ * Allows changing the DMA callback function or data. This may be needed if
+ * the driver shares a single DMA channel for multiple dma triggers.
+ */
+int omap_set_dma_callback(int lch,
+			  void (* callback)(int lch, u16 ch_status, void *data),
+			  void *data)
+{
+	unsigned long flags;
+
+	if (lch < 0)
+		return -ENODEV;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	if (dma_chan[lch].dev_id == -1) {
+		printk(KERN_ERR "DMA callback for not set for free channel\n");
+		spin_unlock_irqrestore(&dma_chan_lock, flags);
+		return -EINVAL;
+	}
+	dma_chan[lch].callback = callback;
+	dma_chan[lch].data = data;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+
+	return 0;
+}
+
 /*
  * Returns current physical source address for the given DMA channel.
  * If the channel is running the caller must disable interrupts prior calling

+ 11 - 1
include/asm-arm/arch-omap/dma.h

@@ -331,6 +331,12 @@ enum omap_dma_color_mode {
 	OMAP_DMA_TRANSPARENT_COPY
 };
 
+enum omap_dma_write_mode {
+	OMAP_DMA_WRITE_NON_POSTED = 0,
+	OMAP_DMA_WRITE_POSTED,
+	OMAP_DMA_WRITE_LAST_NON_POSTED
+};
+
 struct omap_dma_channel_params {
 	int data_type;		/* data type 8,16,32 */
 	int elem_count;		/* number of elements in a frame */
@@ -356,7 +362,7 @@ struct omap_dma_channel_params {
 };
 
 
-extern void omap_set_dma_priority(int dst_port, int priority);
+extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
 			    void (* callback)(int lch, u16 ch_status, void *data),
 			    void *data, int *dma_ch);
@@ -371,6 +377,7 @@ extern void omap_set_dma_transfer_params(int lch, int data_type,
 					 int dma_trigger, int src_or_dst_synch);
 extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
 				    u32 color);
+extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
 
 extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 				    unsigned long src_start,
@@ -394,6 +401,9 @@ extern void omap_set_dma_params(int lch,
 extern void omap_dma_link_lch (int lch_head, int lch_queue);
 extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
 
+extern int omap_set_dma_callback(int lch,
+			void (* callback)(int lch, u16 ch_status, void *data),
+			void *data);
 extern dma_addr_t omap_get_dma_src_pos(int lch);
 extern dma_addr_t omap_get_dma_dst_pos(int lch);
 extern int omap_get_dma_src_addr_counter(int lch);