int in_cnt = 0x00;
static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
struct mmc_data *data)
{
struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
//sg_cpu dma描述符表的虚拟地址 cpu可以使用
//sg_dma dma描述符表的物理地址 dma总线控制器硬件来使用 2者都是指向同一个内存地址
//cpu要访问 由于开启了mmu 必须使用虚拟地址
//dma硬件要绕开cpu来直接dma访问 就不能用虚拟地址访问 只能用实际的物理地址访问
//这个理解应该有问题???
//总的来说 dma硬件寄存器 使用的是sg_dma地址
//具体dma是怎么操作的 还没有搞明白
int i = 0;
int debug_en;
in_cnt++;
if( in_cnt > 0x1700 ){
debug_en = 0;
}else{
debug_en = 0;
}
//printk( "in_cnt = %x\n", in_cnt );
if( debug_en ){
printk( "data->sg_len = %x\n", data->sg_len );
printk( "in_cnt = %x\n", in_cnt );
printk( "pdes = %p\n", pdes );
printk( "pdes_pa = %p\n", pdes_pa );
}
for( i = 0; i < data->sg_len; i++) {
pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_DIC;
pdes[i].buf_size = data->sg[i].length;
if( debug_en ){
//printk( "pdes[%d].buf_size = %x\n", i, pdes[i].buf_size );
}
pdes[i].buf_addr_ptr1 = sunxi_mmc_host_des_addr(host, sg_dma_address(&data->sg[i]));
//存储数据访问的地址 从此处读数据 或者数据存入此地址 物理内存地址
/*We use size_t only to avoid compile waring */
/*pdes[i].buf_addr_ptr2 = (u32) (size_t) &pdes_pa[i + 1];*/
pdes[i].buf_addr_ptr2 = (u32)sunxi_mmc_host_des_addr(host, (size_t)&pdes_pa[i + 1]);
//存储下一描述符条目的入口地址 物理地址
//[738]mmcxxxx 2 frag 0, remain 4096, des[0](42000000): [0] = 8000001a, [1] = 1000, [2] = 42e00000, [3] = 42000010
//[748]mmcxxxx 2 frag 1, remain 4096, des[1](42000010): [0] = 80000012, [1] = 1000, [2] = 42e01000, [3] = 42000020
//uboot阶段的描述符情况
if( debug_en ){
//printk( "pdes[i].buf_addr_ptr1 = %x\n", pdes[i].buf_addr_ptr1 );
//printk( "pdes[i].buf_addr_ptr2 = %x\n", pdes[i].buf_addr_ptr2 );
//printk( "sg_dma_address(&data->sg[i]) = %x\n", sg_dma_address(&data->sg[i]) );
//printk( "host->des_addr_shift = %x\n", host->des_addr_shift );
}
}
pdes[0].config |= SDXC_IDMAC_DES0_FD;
pdes[i - 1].config |= SDXC_IDMAC_DES0_LD;
pdes[i - 1].config &= ~SDXC_IDMAC_DES0_DIC;
/*
* **Avoid the io-store starting the idmac hitting io-mem before the
* descriptors hit the main-mem.
*/
wmb();
if( debug_en ){
printk( "pdes[i].buf_addr_ptr1 = %x\n", pdes[0].buf_addr_ptr1 );
printk( "pdes[i].buf_addr_ptr2 = %x\n", pdes[0].buf_addr_ptr2 );
if( (pdes[0].buf_addr_ptr1+0x80000000) > 0xc0000000 ){
//print_hex_dump_bytes("wsm_buf.data1: ", DUMP_PREFIX_ADDRESS, (u8 *)(pdes[0].buf_addr_ptr1+0x80000000), 64 );
print_hex_dump_bytes("wsm_buf.data1x: ", DUMP_PREFIX_ADDRESS, (u8 *)(pdes), 64 );
}
}
}
host->sg_cpu = dma_alloc_coherent(&pdev->dev, SUNXI_REQ_PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
mmc_writel(host, REG_DLBA, sunxi_mmc_host_des_addr(host, host->sg_dma));
本文详细解释了在Sunxi平台的MMC初始化过程中,如何使用IDMA进行数据传输,涉及sg_cpu与sg_dma的映射关系,以及DMA硬件对物理地址的使用。通过代码片段展示了des配置和地址计算的流程,对dma操作原理进行了剖析。
297

被折叠的 条评论
为什么被折叠?



