2 ahb_dma.c programmed by Ivan Wang
3 AHB dma program for audio 2004/8/13 06:00pm
5 #include <linux/module.h>
7 #include <linux/slab.h>
10 #include <asm/arch/ahb_dma.h>
13 ahb_dma_data_t
*ahb_dma_alloc(void)
16 priv
=(ahb_dma_data_t
*)kmalloc(sizeof(ahb_dma_data_t
), GFP_KERNEL
);
20 void ahb_dma_free(ahb_dma_data_t
*priv
)
23 size
=sizeof(ahb_lld_t
)*(priv
->llp_count
);
26 consistent_free((void *)priv
->ahb_dma_lld
,size
,(dma_addr_t
)priv
->ahb_dma_lld_phys
);
27 //printk("free 0x%x whit 0x%x size 0x%x\n",priv->ahb_dma_lld,priv->ahb_dma_lld_phys,size);
35 base: base address of ahb dma
36 llp_master: LLP master channel number
37 src_data_master: source data channel number
38 dest_data_master: dest data channel number
40 channel: ahb dma channel
41 hw is it hardware handshake?
43 int ahb_dma_init(ahb_dma_data_t
*priv
)
47 ahb_lld_t
*lld_phys
=0;
51 printk("NULL priv data!\n");
57 size
=sizeof(ahb_lld_t
)*(priv
->llp_count
);
58 priv
->ahb_dma_lld
=(ahb_lld_t
*)consistent_alloc(GFP_DMA
|GFP_KERNEL
,
59 size
,(dma_addr_t
*)&priv
->ahb_dma_lld_phys
);
60 //printk("priv->ahb_dma_lld=0x%x phys=0x%x size=0x%x\n",(int)priv->ahb_dma_lld,(int)priv->ahb_dma_lld_phys,size);
61 if(priv
->ahb_dma_lld
==0)
63 printk("ahb_dma_lld allocate memory fail!\n");
68 priv
->channel_base
=(priv
->base
)+0x100+((priv
->channel
)*0x20);
73 lld
=priv
->ahb_dma_lld
;
74 lld_phys
=priv
->ahb_dma_lld_phys
;
75 /* initialize value */
76 for(i
=0;i
<priv
->llp_count
;i
++)
78 lld
[i
].source
=0; //source
79 lld
[i
].dest
=0; //dest,16bit
82 if(i
==priv
->llp_count
-1)
85 lld
[i
].llp
=(unsigned int)(&lld_phys
[i
+1])|(priv
->llp_master
); //use second channel
86 //printk("ahb_dma_lld[%d].llp\n",i,ahb_dma_lld[i].llp);
89 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_LLP_0x10
)=0;
90 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CFG_0x4
)=0x0; //enabled all interrupt
91 *(unsigned int *)(priv
->base
+AHBDMA_ENABLE_0x24
)=0x1; //enable DMA controller
92 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CSR_0x0
)=0;
97 LLP count =3 (example)
104 sw: source width (0/1/2=>8/16/32)
105 dw: dest width (0/1/2=>8/16/32)
106 sctl: source control (0/1/2/3=>inc/dec/fix/x)
107 dctl: dest coontrol (0/1/2/3=>inc/dec/fix/x)
109 irq: (0/1)==>(disable/enable)
111 void ahb_dma_add(ahb_dma_data_t
*priv
,ahb_dma_parm_t
*parm
)
116 //printk("add priv=0x%x\n",priv);
117 lld
=priv
->ahb_dma_lld
;
118 lld_phys
=priv
->ahb_dma_lld_phys
;
120 if(priv
->llp_free_idx
==0) //first to call ahb_dma_add
122 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_TXSZ_0x14
)=parm
->size
;
123 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_SRC_0x8
)=parm
->src
;
124 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_DST_0xC
)=parm
->dest
;
126 if (priv
->llp_count
== 0)
127 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_LLP_0x10
)= 0; //john modified, for no LLP
129 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_LLP_0x10
)=
130 (unsigned int)(&lld_phys
[0])|priv
->llp_master
;
132 val
=(((1-(parm
->irq
))<<31)&0x80000000)|
133 ((parm
->sw
<<11)&0x00003800)|((parm
->dw
<<8)&0x00000700)|
134 ((priv
->hw_handshake
<<7)&0x00000080)|
135 ((parm
->sctl
<<5)&0x00000060)|((parm
->dctl
<<3)&0x00000018)|
136 ((priv
->src_data_master
<<2)&0x4)|
137 ((priv
->dest_data_master
<<1)&0x2);
138 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CSR_0x0
)=val
;
142 val
=((parm
->irq
<<28)&0x10000000)|
143 ((parm
->sw
<<25)&0x0e000000)|((parm
->dw
<<22)&0x01c00000)|
144 ((parm
->sctl
<<20)&0x00300000)|((parm
->dctl
<<18)&0x000c0000)|
145 ((priv
->src_data_master
<<17)&0x00020000)|
146 ((priv
->dest_data_master
<<16)&0x00010000)|(parm
->size
);
147 lld
[priv
->llp_free_idx
-1].source
=parm
->src
;
148 lld
[priv
->llp_free_idx
-1].dest
=parm
->dest
;
149 lld
[priv
->llp_free_idx
-1].control
=val
;
150 lld
[priv
->llp_free_idx
-1].llp
=0;
152 if(priv
->ahb_last_lld
)
153 priv
->ahb_last_lld
->llp
=(unsigned int)(&lld_phys
[priv
->llp_free_idx
-1])|priv
->llp_master
;
154 priv
->ahb_last_lld
=&lld
[priv
->llp_free_idx
-1];
157 if (priv
->llp_count
) //john add check
159 if(priv
->llp_free_idx
==priv
->llp_count
)
160 priv
->llp_free_idx
=1;
162 priv
->llp_free_idx
++;
166 inline void ahb_dma_start(ahb_dma_data_t
*priv
)
168 *(volatile unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CSR_0x0
)|=0x1;
171 void ahb_dma_reset(ahb_dma_data_t
*priv
)
173 priv
->llp_last_idx
=0;
174 priv
->llp_free_idx
=0;
175 priv
->ahb_last_lld
=0;
177 //printk("ahb_dma_stop\n");
178 *(unsigned int *)(priv
->base
+AHBDMA_ENABLE_0x24
)=0; //disable DMA controller
179 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CSR_0x0
)=0; //disable DMA channel 0
180 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_LLP_0x10
)=0;
181 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_TXSZ_0x14
)=0; //no transfer size (use LLP)
182 *(unsigned int *)(priv
->channel_base
+AHBDMA_CHANNEL_CFG_0x4
)=0; //disable all interrupt
185 inline void ahbdma_clear_int(ahb_dma_data_t
*priv
)
187 *(volatile unsigned int *)(priv
->base
+AHBDMA_ISR_0x8
)=1<<(priv
->channel
);
190 //john add, get ext DMA address
191 // so we can get DMA lenth
192 inline u32
ahbdma_get_dest_addr(ahb_dma_data_t
*priv
)
194 return *(volatile u32
*)(priv
->channel_base
+AHBDMA_CHANNEL_DST_0xC
);
197 // John add, to get interrupt status
198 // Bit 0 indicate interrupt created,
199 // bit 1 indicate interrupt error
200 u32
ahbdma_get_status(ahb_dma_data_t
*priv
)
205 temp
= *(volatile u32
*)(priv
->base
+AHBDMA_INT_ERR_0x0C
);
206 if ( temp
& (1<<(priv
->channel
)) )
207 status
|= INT_ERROR
; //error
209 temp
= *(volatile u32
*)(priv
->base
+AHBDMA_INT_TC_0x04
);
210 if ( temp
& (1<<(priv
->channel
)) )
211 status
|= INT_TRIGGER
; //complete