pl330 dmac驱动分析1--数据结构

       pl330 dmac是基于arm amba的dma控制器,最多有8个操作通道,32个事件处理,并且有多个外设接口,有自己的命令集,详细信息看pl330 datesheet。


pl330驱动程序:

      pl330驱动程序位于看kernel/driver/dma/pl330.c文件,该驱动程序由三星coder写的。


      驱动的关键数据结构:


pl330 dmac驱动分析1--数据结构_第1张图片






 17 struct dma_pl330_platdata {
 18         /*
 19          * Number of valid peripherals connected to DMAC.
 20          * This may be different from the value read from
 21          * CR0, as the PL330 implementation might have 'holes'
 22          * in the peri list or the peri could also be reached
 23          * from another DMAC which the platform prefers.
 24          */
 25         u8 nr_valid_peri;                         
 26         /* Array of valid peripherals */
 27         u8 *peri_id;                                     
 28         /* Operational capabilities */
 29         dma_cap_mask_t cap_mask;           
 30         /* Bytes to allocate for MC buffer */
 31         unsigned mcbuf_sz;                         //dmac指令存储空间大小
 32 };

该结构体是pl330的平台数据,用于声明具体soc上的pl330 dmac的配置,一般通过amba device的设备平台数据传入。


 577 struct dma_pl330_dmac {
   578         struct pl330_info pif;
   579
   580         /* DMA-Engine Device */
   581         struct dma_device ddma;
   582                 
   583         /* Pool of descriptors available for the DMAC's channels */
   584         struct list_head desc_pool;
   585         /* To protect desc_pool manipulation */
   586         spinlock_t pool_lock;
   587
   588         /* Peripheral channels connected to this DMAC */
   589         struct dma_pl330_chan *peripherals; /* keep at end */
   590 };

该结构体是pl330 dmac的抽象,封装了dma引擎结构体,是更高层的抽象,内部包含了 struct dma_device ddma (dma引擎对象),struct pl330_info pif(pl330的信息),struct list_head desc_pool(dmac通道的执行描述池链表)


 /* Handle to the DMAC provided to the PL330 core */
   308 struct pl330_info {
   309         /* Owning device */
   310         struct device *dev;
   311         /* Size of MicroCode buffers for each channel. */
   312         unsigned mcbufsz;
   313         /* ioremap'ed address of PL330 registers. */
   314         void __iomem    *base;
   315         /* Client can freely use it. */
   316         void    *client_data;
   317         /* PL330 core data, Client must not touch it. */
   318         void    *pl330_data;
   319         /* Populated by the PL330 core driver during pl330_add */
   320         struct pl330_config     pcfg;
   321         /*
   322          * If the DMAC has some reset mechanism, then the
   323          * client may want to provide pointer to the method.
   324          */
   325         void (*dmac_reset)(struct pl330_info *pi);
   326 };
该结构体是pl330中十分重要的数据,包含了pl330 dmac的硬件信息,包括unsigned mcbufsz(每个通道的指令集缓存大小), void __iomem    *base(pl330 dmac寄存器基址),void    *pl330_data(pl330 驱动使用数据),struct pl330_config     pcfg(pl330 dmac配置信息,一般通过读dmac寄存器获取), void (*dmac_reset)(struct pl330_info *pi)(dmac复位操作函数,用来指定特定的复位操作)


 292 /* Populated by the PL330 core driver for DMA API driver's info */
   293 struct pl330_config {
   294         u32     periph_id;   
   295         u32     pcell_id;
   296 #define DMAC_MODE_NS    (1 << 0)
   297         unsigned int    mode;          //apb接口模式
   298         unsigned int    data_bus_width:10; /* In number of bits */   //axi总线宽度
   299         unsigned int    data_buf_dep:10;          //dmac数据缓存深度
   300         unsigned int    num_chan:4;               //dmac通道数量
   301         unsigned int    num_peri:6;                    //dmac支持外设数量
   302         u32             peri_ns;                           
   303          ;                  //事件数量
   304         u32             irq_ns;                                 
   305 };

该结构体包含了pl330 dmac的硬件配置信息,通过读取dmac寄存器来填充。


538 struct dma_device {
 539
 540         unsigned int chancnt;                //dmac 通道数量
 541         unsigned int privatecnt;              // 已经使用的通道数
 542         struct list_head channels;          //dma通道链表
 543         struct list_head global_node;      //dma设备链表
 544         dma_cap_mask_t  cap_mask;     //dma设备能力掩码
 545         unsigned short max_xor;               //最大异或
 546         unsigned short max_pq;
 547         u8 copy_align;
 548         u8 xor_align;
 549         u8 pq_align;
 550         u8 fill_align;
 551         #define DMA_HAS_PQ_CONTINUE (1 << 15)
 552
 553         int dev_id;                                //设备id号
 554         struct device *dev;         
 555
 556         int (*device_alloc_chan_resources)(struct dma_chan *chan);                       //分配一个通道资源,是核心操作函数
 557         void (*device_free_chan_resources)(struct dma_chan *chan);
 558
 559         struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(               
 560                 struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 561                 size_t len, unsigned long flags); //准备一次内存拷贝操作函数,返回一个操作描述结构体struct dma_async_tx_descriptor,核心操作函数。
 562         struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
 563                 struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
 564                 unsigned int src_cnt, size_t len, unsigned long flags);
 565         struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)(
 566                 struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt,
 567                 size_t len, enum sum_check_flags *result, unsigned long flags);
 568         struct dma_async_tx_descriptor *(*device_prep_dma_pq)(
 569                 struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
 570                 unsigned int src_cnt, const unsigned char *scf,
 571                 size_t len, unsigned long flags);
 572         struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)(
 573                 struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
 574                 unsigned int src_cnt, const unsigned char *scf, size_t len,
 575                 enum sum_check_flags *pqres, unsigned long flags);
 576         struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
 577                 struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
 578                 unsigned long flags);
 579         struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
 580                 struct dma_chan *chan, unsigned long flags);
 581         struct dma_async_tx_descriptor *(*device_prep_dma_sg)(
 582                 struct dma_chan *chan,
 583                 struct scatterlist *dst_sg, unsigned int dst_nents,
 584                 struct scatterlist *src_sg, unsigned int src_nents,
 585                 unsigned long flags);
 586
 587         struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
 588                 struct dma_chan *chan, struct scatterlist *sgl,
 589                 unsigned int sg_len, enum dma_transfer_direction direction,
 590                 unsigned long flags, void *context);
 591         struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
 592                 struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 593                 size_t period_len, enum dma_transfer_direction direction,
 594                 unsigned long flags, void *context);
 595         struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
 596                 struct dma_chan *chan, struct dma_interleaved_template *xt,
 597                 unsigned long flags);
 598         int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 599                 unsigned long arg);              //dma设备控制函数
 600
 601         enum dma_status (*device_tx_status)(struct dma_chan *chan,
 602                                             dma_cookie_t cookie,
 603                                             struct dma_tx_state *txstate);                  //dma操作状态查询函数
 604         void (*device_issue_pending)(struct dma_chan *chan);              //让dma通道执行传输操作,核心操作函数。
 605 };

该结构体是dma引擎层的dma设备抽象,该结构体抽象了一个通用的dma设备,和具体的dmac无关,平时在kernel中调用dma设备时就只针对该结构体的操作。注意有的damc除了执行内存拷贝外还可以执行异或等其他操作。



 412 struct dma_async_tx_descriptor {
 413         dma_cookie_t cookie;                           //dma传输踪迹
 414         enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */    
 415         dma_addr_t phys;                  //该描述符的物理地址
 416         struct dma_chan *chan;        //该传输使用的dma通道
 417         dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);     //在相应的dma通道开始执行该描述符
 418         dma_async_tx_callback callback;     //执行完该描述符后的回调。
 419         void *callback_param;                   //回调参数
 420 #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
 421         struct dma_async_tx_descriptor *next;
 422         struct dma_async_tx_descriptor *parent;
 423         spinlock_t lock;
 424 #endif
 425 };

该结构体属于dma引擎层,为传输描述符结构体,每一次传输都有一个该描述符。


   543 struct dma_pl330_chan {
   544         /* Schedule desc completion */
   545         struct tasklet_struct task;               //传输描述符完成后调度
   546
   547         /* DMA-Engine Channel */
   548         struct dma_chan chan;                    
   549
   550         /* List of to be xfered descriptors */
   551         struct list_head work_list;                 //传输描述链表
   552
   553         /* Pointer to the DMAC that manages this channel,
   554          * NULL if the channel is available to be acquired.
   555          * As the parent, this DMAC also provides descriptors
   556          * to the channel.
   557          */
   558         struct dma_pl330_dmac *dmac;             
   559
   560         /* To protect channel manipulation */
   561         spinlock_t lock;
   562
   563         /* Token of a hardware channel thread of PL330 DMAC
   564          * NULL if the channel is available to be acquired.
   565          */
   566         void *pl330_chid;                      
   567
   568         /* For D-to-M and M-to-D channels */
   569         int burst_sz; /* the peripheral fifo width */
   570         int burst_len; /* the number of burst */
   571         dma_addr_t fifo_addr;              //fifo物理地址
   572
   573         /* for cyclic capability */
   574         bool cyclic;                           //是否具有循环能力
   575 };

该结构体是pl330 dma通道的抽象,封装了dma引擎结构,是更高层的抽象,struct tasklet_struct task (传输描述符完成后调度),struct dma_chan chan(dma引擎层数据,是通用dma通道抽象,一般kernel中调用的dma通道指的是该数据结构),


 271 struct dma_chan {
 272         struct dma_device *device;
 273         dma_cookie_t cookie;                                 
 274         dma_cookie_t completed_cookie;
 275
 276         /* sysfs */
 277         int chan_id;
 278         struct dma_chan_dev *dev;
 279
 280         struct list_head device_node;                       //链接到dma device中
 281         struct dma_chan_percpu __percpu *local;
 282         int client_count;                                           //多少用户在使用该dma通道
 283         int table_count;
 284         void *private;
 285 };

dma引擎层数据结构,是通用dma通道抽象,struct dma_chan_dev *dev(在sysfs使用)

 

294 struct dma_chan_dev {
 295         struct dma_chan *chan;
 296         struct device device;
 297         int dev_id;                //所属dma device的id
 298         atomic_t *idr_ref;      //引用计数
 299 };

dma通道在sysfs中的对象



   592 struct dma_pl330_desc {
   593         /* To attach to a queue as child */
   594         struct list_head node;               //描述符链表
   595
   596         /* Descriptor for the DMA Engine API */
   597         struct dma_async_tx_descriptor txd;
   598
   599         /* Xfer for PL330 core */      
   600         struct pl330_xfer px;             //pl330传输结构
   601
   602         struct pl330_reqcfg rqcfg;     //pl330请求配置结构
   603         struct pl330_req req;             //pl330请求数据结构
   604
   605         enum desc_status status;       //描述符状态
   606
   607         /* The channel which currently holds this desc */
   608         struct dma_pl330_chan *pchan;           //描述符所属pl330 dmac通道 
   609 };

该结构为pl330 dma的传输描述符, 封装了dma引擎结构,是更高层的抽象,struct dma_async_tx_descriptor txd(是dma引擎层的数据结构,是通用的dma传输描述符)


   361 struct pl330_xfer {
   362         u32 src_addr;   //源物理地址
   363         u32 dst_addr;   //目的物理地址
   364         /* Size to xfer */ 
   365         u32 bytes;   //传输字节数目
   366         /*
   367          * Pointer to next xfer in the list.
   368          * The last xfer in the req must point to NULL.
   369          */
   370         struct pl330_xfer *next;   //下一次传输信息
   371 };
该结构是pl330的传输数据结构,包含者此次传输的信息。



   336 struct pl330_reqcfg {
   337         /* Address Incrementing */
   338         unsigned dst_inc:1;             //目的地址是否增加
   339         unsigned src_inc:1;              //源地址是否增加
   340         
   341         /*
   342          * For now, the SRC & DST protection levels
   343          * and burst size/length are assumed same.
   344          */
   345         bool nonsecure;              //是否安全模式
   346         bool privileged;              //权限
   347         bool insnaccess;          
   348         unsigned brst_len:5;             //传输突发
   349         unsigned brst_size:3; /* in power of 2 */
   350         
   351         enum pl330_dstcachectrl dcctl;        //源缓存控制
   352         enum pl330_srccachectrl scctl;       
   353         enum pl330_byteswap swap;
   354         struct pl330_config *pcfg;                  //pl330 dmac的配置数据结构
   355 };

该结构体是pl330 请求配置数据结构,pl330 dmac根据该配置执行请求操作、


   383 /* A request defining Scatter-Gather List ending with NULL xfer. */
   384 struct pl330_req {
   385         enum pl330_reqtype rqtype;                 //pl330请求类型
   386         /* Index of peripheral for the xfer. */
   387         unsigned peri:5;                                    //传输外设索引
   388         /* Unique token for this xfer, set by the client. */
   389         void *token;                                         //传输令脾
   390         /* Callback to be called after xfer. */
   391         void (*xfer_cb)(void *token, enum pl330_op_err err);   //传输完成回调
   392         /* If NULL, req will be done at last set parameters. */
   393         struct pl330_reqcfg *cfg;                     //请求配置
   394         /* Pointer to first xfer in the request. */
   395         struct pl330_xfer *x;                               //请求传输信息,是单项链表
   396         /* Hook to attach to DMAC's list of reqs with due callback */
   397         struct list_head rqd;                               //请求链表
   398 };

该结构体是pl330传输请求数据结构



   476 /* A DMAC Thread */
   477 struct pl330_thread {
   478         u8 id;                          //pl330 dmac处理线程id,即通道id

   479         int ev;                         //pl330 dmac事件
   480         /* If the channel is not yet acquired by any client */
   481         bool free;                       //该线程是否被分配
   482         /* Parent DMAC */
   483         struct pl330_dmac *dmac;           //pl330 dmac
   484         /* Only two at a time */       
   485         struct _pl330_req req[2];      //pl330 请求
   486         /* Index of the last enqueued request */
   487         unsigned lstenq;                           //最后进入队列的请求索引
   488         /* Index of the last submitted request or -1 if the DMA is stopped */
   489         int req_running;  //最后被执行的请求索引
   490 };

该结构体是pl330 dmac处理线程的抽象


   461 struct _pl330_req {
   462         u32 mc_bus;          //指令缓存物理地址
   463         void *mc_cpu;       //指令缓存虚拟地址
   464         /* Number of bytes taken to setup MC for the req */
   465         u32 mc_len;         //指令缓存长度
   466         struct pl330_req *r;
   467 };

该结构体也是pl330 dmac请求数据结构,包括了指令缓存的物理和虚拟地址以及长度信息。



   498 /* A DMAC */
   499 struct pl330_dmac {
   500         spinlock_t              lock;
   501         /* Holds list of reqs with due callbacks */
   502         struct list_head        req_done;                //dmac请求完成链表
   503         /* Pointer to platform specific stuff */
   504         struct pl330_info       *pinfo;                      //pl330信息
   505         /* Maximum possible events/irqs */
   506         int                     events[32];                        //pl330 事件
   507         /* BUS address of MicroCode buffer */
   508         u32                     mcode_bus;                       //指令缓存物理地址
   509         /* CPU address of MicroCode buffer */
   510         void                    *mcode_cpu;                        //指令缓存虚拟地址
   511         /* List of all Channel threads */
   512         struct pl330_thread     *channels;                    //pl330处理线程指针数组
   513         /* Pointer to the MANAGER thread */
   514         struct pl330_thread     *manager;                      //pl330管理线程
   515         /* To handle bad news in interrupt */
   516         struct tasklet_struct   tasks;                           
   517         struct _pl330_tbd       dmac_tbd;                   //pl330 dmac将要进行的操作
   518         /* State of DMAC operation */
   519         enum pl330_dmac_state   state;            //pl330 dmac状态
   520 };


该结构是pl330 dmac的抽象,是底层实现的抽象




   



























你可能感兴趣的:(linux,驱动)