arch\arm\mach-zynq\pl330.c#define PL330_DBGSTATUS_OFFSET 0xD00 /* Debug StatusRegister */#define PL330_DBGCMD_OFFSET 0xD04 /* Debug Command Register*/ module_init(pl330_init);   ->  pl330_init()   ->  pl330_driver_init();///////////////////////////////////////////////////////////////////////** *pl330_driver_init - Initialize the dma_struct array and store thepointer * to array */static void pl330_driver_init(void){ unsigned inti; PDEBUG("inside pl330_driver_init, dma_chan is %x\n",        (unsignedint)dma_chan); driver_data.dma_chan = dma_chan; memset(dma_chan, 0, sizeof(dma_chan[MAX_DMA_CHANNELS])); for (i = 0; i  dma_chan[i].d_ops =&pl330_ops;  isa_dma_add(i, dma_chan+ i); }}/////////////////////////////////////////////////////////////////////// /* *Platform bus binding */static struct dma_ops pl330_ops = { .request     =pl330_request_dma, .free        = pl330_free_dma, .enable      = pl330_enable_dma, .disable     =pl330_disable_dma, .setspeed    = pl330_setspeed_dma, .residue     =pl330_get_residue_dma, .type        ="PL330",};//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////** *pl330_enable_dma - Implementation of enable_dma. It translates the * DMAparameters to a DMA program if the DMA program is not provided, * thenstarts the DMA program on a channel thread. * @channel: DMA channelnumber * @indexed_dma_chan: Instance of the dma_struct. */staticvoid pl330_enable_dma(unsigned intchannel,        struct dma_struct *indexed_dma_chan){ structdma_struct *dma = indexed_dma_chan; struct pl330_channel_data*channel_data; struct pl330_channel_static_data*channel_static_data; struct pl330_client_data *client_data; structpl330_device_data *device_data; unsigned int dev_chan; struct pl330_bus_des *src_bus_des = NULL; struct pl330_bus_des*dst_bus_des = NULL; struct default_src_bus_des; structdefault_dst_bus_des; unsigned src_inc = 1; unsigned dst_inc = 1; u32 src_addr; u32 dst_addr; u32 dma_prog; char *dma_prog_buf; int dma_prog_bytes; u32 inten; unsigned long spin_flags; struct prog_build_args build_args; channel_static_data = driver_data.channel_static_data +channel; device_data = driver_data.device_data +channel_static_data->dev_id; channel_data = driver_data.channel_data +channel; client_data =driver_data.channel_data[channel].client_data; if (!client_data) {  printk(KERN_ERR         "client data isnot set for DMA channel %d\n",        channel);  BUG();  return; } /*  * find out which one is source which one is destination */ if (dma->dma_mode == DMA_MODE_READ) {  PDEBUG("dma_mode isDMA_MODE_READ\n");  src_bus_des = &client_data->dev_bus_des;  dst_bus_des =&client_data->mem_bus_des;  src_addr = (u32)client_data->dev_addr;  dst_addr =(u32)virt_to_bus(dma->addr);  src_inc = channel_data->incr_dev_addr;  dst_inc = 1; }else if (dma->dma_mode == DMA_MODE_WRITE) {  PDEBUG("dma_mode isDMA_MODE_WRITE\n");  src_bus_des = &client_data->mem_bus_des;  dst_bus_des =&client_data->dev_bus_des;  src_addr = (u32)virt_to_bus(dma->addr);  dst_addr =(u32)client_data->dev_addr;  src_inc = 1;  dst_inc =channel_data->incr_dev_addr; } else {  printk(KERN_ERR "Error: mode%x is not supported\n",         dma->dma_mode);  return; } if (dma->count == 0) {  printk(KERN_ERR "Error: DMA count forchannel %d is zero",         channel);  return; } /* print some debugging messages */ PDEBUG("count is %ld\n",dma->count); PDEBUG("dev_addr = %x\n",  (unsignedint)client_data->dev_addr); PDEBUG("dev_bus_des ={\n"); print_pl330_bus_des(&client_data->dev_bus_des); PDEBUG("}\n"); PDEBUG("mem_bus_des ={\n"); print_pl330_bus_des(&client_data->mem_bus_des); PDEBUG("}\n"); PDEBUG("endian_swap_size = %d\n",       client_data->endian_swap_size); PDEBUG("incr_dev_addr = %d\n",       channel_data->incr_dev_addr); dma_prog = channel_data->dma_program; dev_chan = channel_static_data->dev_chan; if (dma_prog == 0) {  /*   * if the DMA program is not setby a user,   * construct the dma program   */  PDEBUG("constructingDMA program\n");  if (!channel_data->dma_prog_buf) {   /* allocatethe dma prog buffer */   channel_data->dma_prog_buf=    dma_alloc_coherent(device_data->dev,         0x1000,        &channel_data->dma_prog_phy,        GFP_KERNEL);  }  PDEBUG("channel %d DMA program: vir %#08x, phy%#08x\n",         channel,        (u32)channel_data->dma_prog_buf,        (u32)channel_data->dma_prog_phy);  dma_prog_buf = (char *)channel_data->dma_prog_buf;  /*   * setup the arguments   */  build_args.channel =channel;  build_args.dma_prog_buf = dma_prog_buf;  build_args.dev_chan =dev_chan;  build_args.dma_count = dma->count;  build_args.src_addr =src_addr;  build_args.src_bus_des = src_bus_des;  build_args.src_inc =src_inc;  build_args.dst_addr = dst_addr;  build_args.dst_bus_des =dst_bus_des;  build_args.dst_inc = dst_inc;  build_args.src_is_mem =dma->dma_mode == DMA_MODE_WRITE;  build_args.endian_swap_size =client_data->endian_swap_size;  build_args.cache_length =device_data->i_cache_len;  dma_prog_bytes =pl330_build_dma_prog(&build_args);  /*   * using physical address for DMA prog  */  dma_prog = channel_data->dma_prog_phy;  channel_data->dma_prog_len = dma_prog_bytes;  PDEBUG("DMA program constructed\n"); } else{  PDEBUG("channel %d user defined DMA program %#08x\n",        channel, (u32)dma_prog); } PDEBUG("enable_dma:spin_lock_irqsave\n"); spin_lock_irqsave(&device_data->lock,spin_flags); /* enable the interrupt */ PDEBUG("enable_dma: enablinginterrupt\n"); inten = pl330_readreg(device_data->base,PL330_INTEN_OFFSET); inten |= 0x01 pl330_writereg(inten, device_data->base,PL330_INTEN_OFFSET); PDEBUG("pl330 interrupt enabled for channel %d\n",channel); pl330_exec_dmago(device_data->dev_id,   device_data->base,    dev_chan,    dma_prog); spin_unlock_irqrestore(&device_data->lock,spin_flags); return;}//////////////////////////////////////////////////////////////////////////////////** *pl33_exec_dmago - Execute the DMAGO to start a channel. * @dev_id: PL330device ID indicating which PL330, the ID starts at 0. * @base: PL330 devicebase address * @dev_chan: Channel number for the device * @dma_prog: DMAprogram starting address, this should be DMA address * * Returns 0 onsuccess, -1 on time out */int pl330_exec_dmago(unsigned int dev_id,       void __iomem *base,        unsigned int dev_chan,        u32dma_prog){ char dma_go_prog[8]; u32 dbginst0; u32dbginst1; int wait_count; PDEBUG("pl330_exec_dmago: entering\n"); pl330_instr_dmago(dma_go_prog, dev_chan, dma_prog, 0); dbginst0 = PL330_DBGINST0(*(dma_go_prog + 1), *dma_go_prog, 0,0); dbginst1 = (u32)dma_prog; PDEBUG("inside pl330_exec_dmago: base %x, dev_chan %d, dma_prog%x\n",        (u32)base, dev_chan, dma_prog); /* wait while debug status is busy */ wait_count = 0; while(pl330_readreg(base, PL330_DBGSTATUS_OFFSET)        & PL330_DBGSTATUS_BUSY       && wait_count  PDEBUG("dbgstatus%x\n",         pl330_readreg(base, PL330_DBGSTATUS_OFFSET));  wait_count++; } if (wait_count >= PL330_MAX_WAIT){  printk(KERN_ERR         "PL330 device %d debug status busy timeout\n",         dev_id);  return -1; } PDEBUG("dbgstatus idle\n"); /* write debug instruction 0 */ pl330_writereg(dbginst0, base,PL330_DBGINST0_OFFSET); /* write debug instruction 1*/ pl330_writereg(dbginst1, base, PL330_DBGINST1_OFFSET); /* wait while the DMA Manager is busy */ wait_count = 0; while((pl330_readreg(base, PL330_DS_OFFSET) & PL330_DS_DMA_STATUS)        !=PL330_DS_DMA_STATUS_STOPPED        && wait_count  PDEBUG("ds %x\n",         pl330_readreg(base,PL330_DS_OFFSET));  wait_count++; } if (wait_count >= PL330_MAX_WAIT) {  printk(KERN_ERR        "PL330 device %d debug status busy time out\n",         dev_id);  return-1; } /* run the command in dbginst0 and dbginst1 */ pl330_writereg(0, base, PL330_DBGCMD_OFFSET); PDEBUG("pl330_exec_dmago done\n"); return 0;}////////////////////#define pl330_writereg(data, base, offset)\ __raw_writel(data, (void __iomem *)((u32)(base) +(u32)(offset)))//////////////////////////////////////////////////////
12-09 21:19