os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/cxdma353.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : cxdma353.c
00003 *! DESCRIPTION: Handling ETRAX DMA in Elphel model 353 camera
00004 *! Copyright (C) 2002-2008 Elphel, Inc
00005 *! -----------------------------------------------------------------------------**
00006 *!
00007 *!  This program is free software: you can redistribute it and/or modify
00008 *!  it under the terms of the GNU General Public License as published by
00009 *!  the Free Software Foundation, either version 3 of the License, or
00010 *!  (at your option) any later version.
00011 *!
00012 *!  This program is distributed in the hope that it will be useful,
00013 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 *!  GNU General Public License for more details.
00016 *!
00017 *!  You should have received a copy of the GNU General Public License
00018 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *! -----------------------------------------------------------------------------**
00020 *!  $Log: cxdma353.c,v $
00021 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00022 *!
00023 *!
00024 *!  Revision 1.12  2008/10/29 04:18:28  elphel
00025 *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00026 *!
00027 *!  Revision 1.11  2008/09/16 00:49:30  elphel
00028 *!  snapshot
00029 *!
00030 *!  Revision 1.10  2008/09/12 00:23:58  elphel
00031 *!  removed cc353.c, cc353.h
00032 *!
00033 *!  Revision 1.9  2008/09/11 01:05:31  elphel
00034 *!  snapshot
00035 *!
00036 *!  Revision 1.8  2008/09/07 19:48:08  elphel
00037 *!  snapshot
00038 *!
00039 */
00040 
00041 /****************** INCLUDE FILES SECTION ***********************************/
00042 
00043 
00044 #include <linux/module.h>
00045 #include <linux/mm.h>
00046 #include <linux/sched.h>
00047 #include <linux/slab.h>
00048 #include <linux/errno.h>
00049 #include <linux/kernel.h>
00050 #include <linux/fs.h>
00051 #include <linux/string.h>
00052 #include <linux/init.h>
00053 #include <linux/autoconf.h>
00054 #include <linux/time.h>
00055 
00056 #include <asm/system.h>
00057 #include <asm/arch/memmap.h>
00058 #include <asm/io.h>
00059 
00060 #include <asm/arch/dma.h>
00061 #include <asm/arch/hwregs/dma_defs.h>
00062 #include <asm/arch/hwregs/dma.h>
00063 #include <asm/arch/hwregs/reg_map.h>
00064 #include <asm/arch/hwregs/bif_dma_defs.h>
00065 
00066 
00067 #include <asm/irq.h>
00068 #include <asm/atomic.h>
00069 
00070 #include <asm/delay.h>
00071 #include <asm/uaccess.h>
00072 #include <asm/arch/cache.h>
00073 
00074 #include <asm/elphel/c313a.h>
00075 
00076 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00077 
00078 #include "x3x3.h"
00079 //#include "cc3x3.h"
00080 #include "framepars.h"
00081 #include "cxdma.h"
00082 #include "sensor_common.h"
00083 #include "circbuf.h"
00084 #include "exif.h"
00085 
00086 #if ELPHEL_DEBUG
00087  #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00088  #define MD12(x) printk("%s:%d:",__FILE__,__LINE__);x
00089   //#define MD12(x)
00090  #define MD13(x) printk("%s:%d:",__FILE__,__LINE__);x
00091   //#define MD13(x)
00092 #else
00093   #define MD1(x)
00094   #define MD12(x)
00095   #define MD13(x)
00096 #endif
00097 
00098 
00099 
00100 #define D(x)
00101 #define D1(x)
00102 //#define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00103 //#define MD1(x)
00104 #define MD2(x) printk("%s:%d:",__FILE__,__LINE__);x
00105 //#define MD2(x)
00106 
00107 //#define MD5(x) printk("%s:%d:",__FILE__,__LINE__);x
00108 #define MD5(x)
00109 //#define MD6(x) printk("%s:%d:",__FILE__,__LINE__);x
00110 #define MD6(x)
00111 //#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
00112 #define MD7(x)
00113 
00114 //#define D0(x) printk("%s:%d:",__FILE__,__LINE__);x
00115 #define D0(x)
00116 
00117 //#define MD8(x) printk("%s:%d:",__FILE__,__LINE__);x
00118 #define MD8(x)
00119 //#define MD9(x) printk("%s:%d:",__FILE__,__LINE__);x
00120 #define MD9(x)
00121 //#define MD10(x) printk("%s:%d:",__FILE__,__LINE__);x
00122 #define MD10(x)
00124 //#define MD11(x) printk("%s:%d:",__FILE__,__LINE__);x
00125 #define MD11(x)
00126 
00127 
00128 #define EXT_DMA_0_START \
00129    do { reg_bif_dma_rw_ch3_start c = {.run=1};\
00130         REG_WR(bif_dma, regi_bif_dma, rw_ch3_start, (reg_bif_dma_rw_ch3_start) c); } while( 0 )
00131 #define EXT_DMA_0_STOP \
00132    do { reg_bif_dma_rw_ch3_start c = {.run=0};\
00133         REG_WR(bif_dma, regi_bif_dma, rw_ch3_start, (reg_bif_dma_rw_ch3_start) c); } while( 0 )
00134 
00135 
00137 #define DMA_CHUNK 0x4000 // 32-bit words - may increase??
00138 #define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE  / DMA_CHUNK) +1 ) // number of data descriptors
00139 static dma_descr_data    ccam_dma_descr_data    [CCAM_DESCR_DATA_NUM]  __attribute__ ((__aligned__(16)));
00140 static dma_descr_context ccam_dma_descr_context __attribute__ ((__aligned__(32)));
00141 static int dma_on=0;
00142 
00143 int            x313_setDMABuffer(void);
00144 unsigned long  x313_DMA_size (void);
00145 
00150 int           x313_is_dma_on(void) {
00151   return dma_on;
00152 }
00153 
00158 int x313_dma_stop(void) {
00159     dma_on=0;
00160  MD12(printk("==========x313_dma_stop\n"));
00161     port_csp0_addr[X313_WA_DMACR] = 0;
00162     EXT_DMA_0_STOP ; 
00163     udelay(10) ; //?
00164     DMA_RESET( regi_dma9 );
00165   // put here restoring of the .after pointer ?
00166    return 0;
00167 }
00168 
00169 
00174 void x313_dma_start(void) {
00175     unsigned long dai;
00176     int i = 0;
00177  MD12(printk("----------x313_dma_start\n"));
00178 
00179     DMA_RESET(regi_dma9);
00181     for(dai = 0; dai < CCAM_DMA_SIZE; dai += DMA_CHUNK) { 
00182         if(dai + DMA_CHUNK >= CCAM_DMA_SIZE)  
00183             ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[CCAM_DMA_SIZE]);
00184         else  
00185             ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai + DMA_CHUNK]);
00187            flush_dma_descr( & ccam_dma_descr_data[i], 0);
00188         i++;
00189     }
00190     DMA_ENABLE(regi_dma9);
00191     port_csp0_addr[X313_WA_DMACR] = 0;
00193     DMA_WR_CMD(regi_dma9, regk_dma_set_w_size4);  
00194 
00195     ccam_dma_descr_context.saved_data = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[0]);
00196     ccam_dma_descr_context.saved_data_buf = ccam_dma_descr_data[0].buf;
00198    flush_dma_descr((dma_descr_data*) & ccam_dma_descr_context, 0);
00199     DMA_START_CONTEXT(regi_dma9, virt_to_phys(&ccam_dma_descr_context));
00200     EXT_DMA_0_START ;
00201     port_csp0_addr[X313_WA_DMACR] = 0x30000;
00203     dma_on=1;
00204 }
00205 
00207 unsigned long x313_dma_init(void) {
00208     dma_on=0;
00209     int rslt;
00210     reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; //  if disabled - will be busy and hang on attemt of DMA_WR_CMD
00211     reg_bif_dma_rw_ch3_ctrl exdma_ctrl = {
00212         .bw          = regk_bif_dma_bw32,
00213         .burst_len   = regk_bif_dma_burst8, // changed - updated FPGA to use 8-word bursts
00214         .cont        = 1,                   // continuous transfer mode (probably - don't care)
00215         .end_discard = 0,                   // discard end of burst date (don't care)
00216         .cnt         = 0,                   // transfer counter ignored
00217         .dreq_pin    = 0,                   // use hsh0
00218         .dreq_mode   = regk_bif_dma_norm,   // normal - active high DREQ from pin (see above)
00219         .tc_in_pin   = 0,                   // don't care - tc pin number
00220         .tc_in_mode  = 0,                   // no tc pin
00221         .bus_mode    = regk_bif_dma_master, // bus mode - master
00222         .rate_en     = 0                    // no rate limiting
00223     };
00224     reg_bif_dma_rw_ch3_addr exdma_addr = {.addr = MEM_CSR0_START | MEM_NON_CACHEABLE};
00225     reg_bif_dma_rw_pin0_cfg exdma_pin0 = {
00226         .master_ch   = 0,                   // don't care
00227         .master_mode = regk_bif_dma_off,    // off
00228         .slave_ch    = 0,                   // don't care
00229         .slave_mode  = regk_bif_dma_off     // off
00230     };
00231     reg_bif_dma_rw_pin1_cfg exdma_pin1 = {
00232         .master_ch   = 3,                   // ext DMA channel #
00233         .master_mode = regk_bif_dma_dack,   // use DACK, active high
00234         .slave_ch    = 3,                   // don't care
00235         .slave_mode  = regk_bif_dma_off     // off
00236     };
00237     // just in case - free DMA channel (we are only using it here)
00238     crisv32_free_dma(EXTDMA3_RX_DMA_NBR);
00239     printk("Initializing DMA registers for EXTDMA3 - ");
00240     MD7(printk("x313_dma_init(void)"));
00241 
00242     D0(printk ("before crisv32_request_dma\n");
00243     udelay (500000));
00244     rslt = crisv32_request_dma(EXTDMA3_RX_DMA_NBR,
00245                                "compressed data in from fpga",
00246                                DMA_VERBOSE_ON_ERROR,
00247                                0,
00248                                dma_ext3);
00249     D0(printk ("after crisv32_request_dma - result=%d\n",rslt);
00250     udelay(500000));
00251 
00252     if(rslt) {
00253         printk("failed\n");
00254         crisv32_free_dma(EXTDMA3_RX_DMA_NBR);
00255         printk(KERN_CRIT "Can't allocate external dma port for compressed data in from fpga");
00256     } else { 
00257 
00258         REG_WR(bif_dma, regi_bif_dma, rw_pin0_cfg, exdma_pin0); 
00259         REG_WR(bif_dma, regi_bif_dma, rw_pin1_cfg, exdma_pin1); 
00260 
00261         REG_WR(bif_dma, regi_bif_dma, rw_ch3_ctrl, exdma_ctrl);
00262         REG_WR(bif_dma, regi_bif_dma, rw_ch3_addr, exdma_addr);
00263         REG_WR(dma, regi_dma9, rw_cfg, cfg);   
00264     }
00266     x313_setDMABuffer();
00268     return ((unsigned long)virt_to_phys(ccam_dma_buf_ptr)) | 0x80000000;
00269 }
00270 
00271 int x313_setDMABuffer(void) {
00272     unsigned long dai;
00273     int i = 0;
00274     EXT_DMA_0_STOP; 
00275     for(dai = 0; dai < CCAM_DMA_SIZE; dai += DMA_CHUNK) { 
00276         ccam_dma_descr_data[i].buf = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai]);
00277         ccam_dma_descr_data[i].intr = 0;
00278         ccam_dma_descr_data[i].wait = 0;
00279         ccam_dma_descr_data[i].eol = 0; 
00280         if(dai + DMA_CHUNK >= CCAM_DMA_SIZE) { 
00281         ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[CCAM_DMA_SIZE]);
00282             ccam_dma_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[0]);
00283         } else { 
00284             ccam_dma_descr_data[i].after = (char *)virt_to_phys(&ccam_dma_buf_ptr[dai + DMA_CHUNK]);
00285             ccam_dma_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma_descr_data[i + 1]);
00286         }
00287         flush_dma_descr( & ccam_dma_descr_data[i], 0);
00288         i++;
00289     }
00290     set_globalParam (G_CIRCBUFSIZE,CCAM_DMA_SIZE<<2); 
00291 //*********************** TEMPORARY ********************************       
00292     MD8(printk ("filling DMA buffer with natural numbers - just test \n"));
00293     for(dai = 0; dai < CCAM_DMA_SIZE; dai++) ccam_dma_buf_ptr[dai] = dai;
00294     return 0;
00295 }
00296 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1