sg_cpu sg_dma理解

本文详细解释了在Sunxi平台的MMC初始化过程中,如何使用IDMA进行数据传输,涉及sg_cpu与sg_dma的映射关系,以及DMA硬件对物理地址的使用。通过代码片段展示了des配置和地址计算的流程,对dma操作原理进行了剖析。

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));
 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值