您的位置:首页 > 理论基础 > 数据结构算法

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

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

pl330驱动程序:

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

      驱动的关键数据结构:



 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的抽象,是底层实现的抽象

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: