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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : fpga_io.c
00003 *! DESCRIPTION: TBD
00004 *! Copyright (C) 2002-2006 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!  This program is free software: you can redistribute it and/or modify
00007 *!  it under the terms of the GNU General Public License as published by
00008 *!  the Free Software Foundation, either version 3 of the License, or
00009 *!  (at your option) any later version.
00010 *!
00011 *!  This program is distributed in the hope that it will be useful,
00012 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *!  GNU General Public License for more details.
00015 *!
00016 *!  You should have received a copy of the GNU General Public License
00017 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 *! -----------------------------------------------------------------------------**
00019 *!  $Log: fpga_io.c,v $
00020 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00021 *!
00022 *!
00023 *!  Revision 1.10  2008/10/29 04:18:28  elphel
00024 *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00025 *!
00026 *!  Revision 1.9  2008/10/25 20:01:00  elphel
00027 *!  bug fixed: removed reference to file->f_pos in write() and replaced with *ofs
00028 *!
00029 *!  Revision 1.8  2008/10/23 08:02:23  elphel
00030 *!  fpga_read_hist_nice() bug fix
00031 *!
00032 *!  Revision 1.7  2008/10/04 16:10:12  elphel
00033 *!  snapshot
00034 *!
00035 *!  Revision 1.6  2008/09/16 00:49:30  elphel
00036 *!  snapshot
00037 *!
00038 *!  Revision 1.5  2008/09/12 00:23:59  elphel
00039 *!  removed cc353.c, cc353.h
00040 *!
00041 *!  Revision 1.4  2008/08/25 19:07:23  elphel
00042 *!  just a snapshot
00043 *!
00044 *!  Revision 1.3  2008/07/27 23:25:07  elphel
00045 *!  next snapshot
00046 *!
00047 *!  Revision 1.2  2008/07/27 04:27:49  elphel
00048 *!  next snapshot
00049 *!
00050 *!  Revision 1.1.1.1  2008/05/12 01:00:59  elphel
00051 *!
00052 *!
00053 *!  Revision 1.6  2008/04/29 05:49:27  elphel
00054 *!  typo
00055 *!
00056 *!  Revision 1.5  2008/04/14 17:15:52  spectr_rain
00057 *!  200 gamma tables, correct 257 values tables
00058 *!
00059 *!  Revision 1.4  2008/04/11 23:16:51  elphel
00060 *!  removed unneeded local_irq_disable() after local_irq_save_flags()
00061 *!
00062 *!  Revision 1.3  2008/04/09 21:01:25  elphel
00063 *!  added access to individual wait state registers
00064 *!
00065 *!  Revision 1.2  2007/10/23 16:58:51  elphel
00066 *!  Improved r/w access to FPGA registers (available from PHP)
00067 *!
00068 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00069 *!  This is a fresh tree based on elphel353-2.10
00070 *!
00071 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00072 *!  switch to GPL3 license
00073 *!
00074 *!  Revision 1.6  2007/07/20 10:17:46  spectr_rain
00075 *!  *** empty log message ***
00076 *!
00077 *!  Revision 1.2  2007/05/21 17:45:10  elphel
00078 *!  boundary scan support, added 359/347 detection
00079 *!
00080 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00081 *!  initial import into CVS
00082 *!
00083 *!  Revision 1.3  2006/04/06 07:46:33  elphel
00084 *!  control for canon lenses
00085 *!
00086 */
00087 
00088 /****************** INCLUDE FILES SECTION ***********************************/
00089 
00090 #include <linux/module.h>
00091 #include <linux/sched.h>
00092 #include <linux/slab.h>
00093 #include <linux/errno.h>
00094 #include <linux/kernel.h>
00095 #include <linux/fs.h>
00096 #include <linux/string.h>
00097 #include <linux/init.h>
00098 #include <linux/autoconf.h>
00099 
00100 #include <asm/system.h>
00101 //#include <asm/svinto.h>
00102 #include <asm/io.h>
00103 //#include <linux/interrupt.h>
00104 
00105 
00106 #include <asm/irq.h>
00107 
00108 #include <asm/delay.h>
00109 #include <asm/uaccess.h>
00110 #include <asm/elphel/fpgaconfa.h> // defines port_csp0_addr, port_csp4_addr
00111 #include <asm/elphel/c313a.h> // just for CX313_FPGA_TABLES_SIZE, DEBUG
00112 #include "framepars.h"        // for debug mask
00113 
00114 #include <asm/arch/hwregs/reg_map.h>
00115 #include <asm/arch/hwregs/bif_core_defs.h>
00116 
00117 #include "x3x3.h"
00118 
00119 #include "fpgactrl.h"
00120 #include "fpga_io.h"
00121 
00122 #define D(x)
00123 //#define D(x) printk("%s:%d:",__FILE__,__LINE__);x
00124 
00125 // extern volatile unsigned long ccam_cr_shadow;
00126 
00127 
00128 
00129 //#define FPGACONF_RD_WAITSTATES     150    // read R_WAITSTATES
00130 //#define FPGACONF_WR_WAITSTATES     151    // write R_WAITSTATES
00133 #if ELPHEL_DEBUG
00134   #define D12(x) { if (GLOBALPARS(G_DEBUG) & (1 <<12)) { x ;} }
00135   #define D13(x) { if (GLOBALPARS(G_DEBUG) & (1 <<13)) { x ;} }
00136   #define MDF12(x) { if (GLOBALPARS(G_DEBUG) & (1 <<12)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00137 // read_nice
00138   #define MDF13(x) { if (GLOBALPARS(G_DEBUG) & (1 <<13)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
00139 #else
00140   #define D12(x)
00141   #define MDF12(x)
00142   #define MDF13(x)
00143 #endif
00144 
00145 unsigned long fpga_tables_buffer[CX313_FPGA_TABLES_SIZE];
00146 
00147 #define CAPTURE_SIZE 8192
00148 static char capture_buf[CAPTURE_SIZE];
00149 static int capture_length;
00150 static int capture_pointer;
00151 int fpga_io_open(void) {
00152   return 0;
00153 }
00154 int fpga_io_close (void){
00155   return 0;
00156 }
00157 
00158 // will use 1.2-us "debounce/metastability" filter, so minimal pulse width detected will be 2.5us
00159 int canon_lens_io (int d) {
00160   unsigned long flags;
00161   int res,i,j;
00162 
00163 // make sure pins initialized
00164    if ((port_csp0_addr[0x70] & 5) !=5) {
00165      port_csp0_addr[0x70]=0x33;
00166      udelay (200);
00167    } 
00168    res=0;
00169 // start condition   
00170    port_csp0_addr[0x70]=0x23;
00171    udelay (60);
00172    local_irq_save(flags);
00173    //local_irq_disable();  //disable all interrupts for the time of capture
00174    for (i=0; i<8; i++) {
00175      port_csp0_addr[0x70]= 0x22 | ((d & 0x80)?0x10:0);
00176      udelay (6);
00177      res=(res<<1) | ( (port_csp0_addr[0x70] & 2)>>1);
00178      port_csp0_addr[0x70]= 0x23 | ((d & 0x80)?0x10:0);
00179      udelay (6);
00180 // wait clock is high here
00181      for (j=0;j<1000000;j++) {  // timeout
00182        if (port_csp0_addr[0x70] & 8) break;
00183        udelay (1);
00184      }  
00185      d<<=1;
00186    }
00187 // wait clock low (by the lens)
00188    for (j=0;j<1000000;j++) {  // timeout
00189      if (!(port_csp0_addr[0x70] & 8)) break;
00190      udelay (1);
00191    }
00192    udelay (6);  
00193    port_csp0_addr[0x70]=0x33;
00194    local_irq_restore(flags);
00195    udelay (200);  
00196    return res;
00197 }
00198 
00199 
00200 int capture_pins (int n, int m) {
00201   int i;
00202   unsigned long flags;
00203   char b0,b1,b;
00204   int msk;
00205   msk=0xff& ((m!=0)?m:0xff);
00206 
00207   capture_length=0;
00208   capture_pointer=0;
00209   b0=b1=0xff;
00210   
00211    local_irq_save(flags);
00212    //local_irq_disable();  //disable all interrupts for the time of capture
00213    for (i=0; (i < n) && (capture_length < CAPTURE_SIZE); i++) {
00214     b=msk & port_csp0_addr[0x70]; //X313__RA__IOPINS
00215     if (b==b1) {
00216      if (b!=b0) capture_buf[capture_length++]=b;
00217      b0=b;
00218     }
00219     b1=b; 
00220     udelay(1);
00221    }
00222    local_irq_restore(flags);
00223    return capture_length;
00224 }
00225 
00226 int capture_read (void) {
00227   if (capture_pointer < capture_length) {
00228     return capture_buf[capture_pointer++];
00229   } else return -EINVAL;
00230 }
00231 #if 0
00232 /* Register rw_grp2_cfg, scope bif_core, type rw */
00233 typedef struct {
00234   unsigned int lw        : 6;
00235   unsigned int ew        : 3;
00236   unsigned int zw        : 3;
00237   unsigned int aw        : 2;
00238   unsigned int dw        : 2;
00239   unsigned int ewb       : 2;
00240   unsigned int bw        : 1;
00241   unsigned int wr_extend : 1;
00242   unsigned int erc_en    : 1;
00243   unsigned int mode      : 1;
00244   unsigned int dummy1    : 10;
00245 } reg_bif_core_rw_grp2_cfg;
00246 #define REG_RD_ADDR_bif_core_rw_grp2_cfg 4
00247 #define REG_WR_ADDR_bif_core_rw_grp2_cfg 4
00248    reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
00249    REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
00250 
00251 
00252 #endif
00253 
00254 
00255 
00256 
00257 
00258 int fpga_io_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
00259   reg_bif_core_rw_grp1_cfg csr1_cfg;
00260   reg_bif_core_rw_grp2_cfg csr2_cfg;
00261   reg_bif_core_rw_grp3_cfg csr3_cfg;
00262   reg_bif_core_rw_grp4_cfg csr4_cfg;
00263 //  unsigned long flags;
00264 //  int i1;
00265   int d;
00266    D(printk("csp0rw_ioctl cmd= %x, arg= %x\n\r",cmd,arg));
00267    D(printk("csp0rw_ioctl:  ((int *)file->private_data)[0]= %x\n\r",((int *)file->private_data)[0]));
00268   D(printk("fpga_io.c:fpga_io_ioctl:_IOC_NR(cmd)=%x\n",(int) _IOC_NR(cmd)));
00269         switch (_IOC_TYPE(cmd)) {
00270 
00271                 case FPGACONF_READREG:
00272                         d=(int)port_csp0_addr[_IOC_NR(cmd)];
00273                          D(printk ("port_csp0_addr[%x]=%x\n",(int) _IOC_NR(cmd),d));
00274                         return d;
00275                 case FPGACONF_READREG_L:
00276                         d=(int)port_csp0_addr[_IOC_NR(cmd)] & 0x0000ffff;
00277                          D(printk ("port_csp0_addr[%x]=%x\n",(int) _IOC_NR(cmd),d));
00278                         return d;
00279                 case FPGACONF_READREG_H:
00280                         d=((int)port_csp0_addr[_IOC_NR(cmd)]>>16) & 0x0000ffff;
00281                          D(printk ("port_csp0_addr[%x]=%x\n",(int) _IOC_NR(cmd),d));
00282                         return d;
00283                 case FPGACONF_READREG4:
00284                         d=(int)port_csp4_addr[_IOC_NR(cmd)];
00285                          D(printk ("port_csp4_addr[%x]=%x\n",(int) _IOC_NR(cmd),d));
00286                         return d;
00287                 case FPGACONF_READREG_L4:
00288                         return (long ) ( port_csp4_addr[_IOC_NR(cmd)] & 0x0000ffff);
00289                 case FPGACONF_READREG_H4:
00290                         return (long ) ((port_csp4_addr[_IOC_NR(cmd)]>>16) & 0x0000ffff);
00291 
00292                 case FPGACONF_WRITEREG:
00293                         if (_IOC_NR(cmd)==0) arg |= ((arg & 0x40000000)<<1);    // control MSB of CR
00294 //                      return (long )   port_csp0_addr[_IOC_NR(cmd)]=arg; // read back after write
00295                         port_csp0_addr[_IOC_NR(cmd)]=arg;
00296                         return (long )   arg;
00297                 case FPGACONF_WRITEREG4:
00298 //                      return (long )   port_csp4_addr[_IOC_NR(cmd)]=arg; // read back after write
00299                         port_csp4_addr[_IOC_NR(cmd)]=arg;
00300                         return (long )  arg;
00301       case FPGACONF_WR_WAITSTATES:
00302          ((int *) &csr1_cfg)[0]=arg;
00303          ((int *) &csr2_cfg)[0]=arg;
00304          ((int *) &csr3_cfg)[0]=arg;
00305          ((int *) &csr4_cfg)[0]=arg;
00306          switch (_IOC_NR(cmd)) {
00307            case 1:
00308             REG_WR(bif_core, regi_bif_core, rw_grp1_cfg, csr1_cfg); // and fall through
00309             break;
00310            case 2:
00311             REG_WR(bif_core, regi_bif_core, rw_grp2_cfg, csr2_cfg); // and fall through
00312             break;
00313            case 3:
00314             REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, csr3_cfg); // and fall through
00315             break;
00316            case 4:
00317             REG_WR(bif_core, regi_bif_core, rw_grp4_cfg, csr4_cfg); // and fall through
00318             break;
00319            default:
00320             printk ("address should be 1,2,3, or 4\n");
00321             return -EINVAL;
00322          }
00323                 case FPGACONF_RD_WAITSTATES:
00324          switch (_IOC_NR(cmd)) {
00325            case 1:
00326             csr1_cfg=REG_RD(bif_core, regi_bif_core, rw_grp1_cfg);
00327             d=((int *) &csr1_cfg)[0];
00328             break;
00329            case 2:
00330             csr2_cfg=REG_RD(bif_core, regi_bif_core, rw_grp2_cfg);
00331             d=((int *) &csr2_cfg)[0];
00332             break;
00333            case 3:
00334             csr3_cfg=REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
00335             d=((int *) &csr3_cfg)[0];
00336             break;
00337            case 4:
00338             csr4_cfg=REG_RD(bif_core, regi_bif_core, rw_grp4_cfg);
00339             d=((int *) &csr4_cfg)[0];
00340             break;
00341            default:
00342              printk ("address should be 1,2,3, or 4\n");
00343              return -EINVAL;
00344          }
00345                         printk ("rw_grp%d_cfg=%x\n",_IOC_NR(cmd),d);
00346                         return d;
00347       case FPGACONF_CANON_IOBYTE:
00348          return canon_lens_io (arg); // second agrument - mask. 0 will be the same as 0xff
00349       case FPGACONF_START_CAPTURE:
00350          return capture_pins (arg, _IOC_NR(cmd)); // second agrument - mask. 0 will be the same as 0xff
00351       case FPGACONF_READ_CAPTURE:
00352          return capture_read();
00353       default:
00354          return -EINVAL;
00355       }
00356   return 0;
00357 }
00358 
00359 loff_t  fpga_io_lseek  (struct file * file, loff_t offset, int orig) {
00360    size_t size=0x4000; 
00361    switch (orig) {
00362    case SEEK_SET:
00363       file->f_pos = offset;
00364       break;
00365    case SEEK_CUR:
00366       file->f_pos += offset;
00367       break;
00368    case SEEK_END:
00369       file->f_pos = size + offset;
00370       break;
00371    default:
00372       return -EINVAL;
00373    }
00374    /* truncate position */
00375    if (file->f_pos < 0) {
00376       file->f_pos = 0;
00377       return (-EOVERFLOW);
00378    }
00379    if (file->f_pos > size) {
00380       file->f_pos = size;
00381       return (-EOVERFLOW);
00382    }
00383    D(printk("fpga_io_lseek, file->f_pos= 0x%x\n", (int) file->f_pos));
00384    return (file->f_pos);
00385 }
00386 
00391 
00392 
00394 
00395 
00396 ssize_t fpga_io_read   (struct file * file, char * buf, size_t count, loff_t *off){
00397   int l;
00398   unsigned long rbuf[1024]; // up to 4096 bytes/read
00399  D(printk("fpga_io_read: buf address=%lx count=%lx *offs=%lx\r\n", (long) buf, (long) count, (long) *off));
00401   if (count > sizeof(rbuf)) count =sizeof(rbuf);
00403   for (l=0; (l<<2) < count; l++)
00404    rbuf[l]=((*off) & 0x2000)?
00405             (unsigned long) port_csp4_addr[(*off) & 0x1fff]:
00406             (unsigned long) port_csp0_addr[(*off) & 0x1fff];
00408    if (copy_to_user(buf,rbuf,count)) return -EFAULT;
00410   return count;
00411 }
00412 
00413 
00414 ssize_t fpga_io_write  (struct file * file, const char * buf, size_t count, loff_t *off){
00415   int l,n;
00416   unsigned long wbuf[1024]; // up to 4096 bytes/write
00417   D(printk("fpga_io_write: buf address=%lx count=%lx *offs=%lx\r\n",(long) buf, (long) count, (long) *off));
00419   if (count > sizeof(wbuf)) count =sizeof(wbuf);
00421   n=count>>2;
00422   if (count & 3) {
00423      wbuf[count>>2]=0; 
00424      n++;
00425   }
00426   if (copy_from_user(wbuf,buf,count)) return -EFAULT;
00428   if ((*off) & 0x2000) for (l=0; l < n; l++)  port_csp4_addr[(*off) & 0x1fff]= wbuf[l];
00429   else                 for (l=0; l < n; l++)  port_csp0_addr[(*off) & 0x1fff]= wbuf[l];
00431   return count;
00432 }
00433 
00434 
00437 #define FPGA_TABLE_CHUNK 64 // up to 64 words to send to the table/from histogram on a single IRQ-off transfer
00438 void fpga_table_write_nice (int addr, int len, unsigned long * data) {
00439   unsigned long flags;
00440   int l,i;
00441   MDF12(printk("addr=0x%x, len=0x%x, data=0x%08lx 0x%08lx 0x%08lx 0x%08lx...\n", addr, len, data[0], data[1], data[2], data[3]));
00442   while (len>0) {
00443     l=(len < FPGA_TABLE_CHUNK)?len:FPGA_TABLE_CHUNK;
00444     local_irq_save(flags);
00445     port_csp0_addr[X313_WA_COMP_TA]=addr; // open fpga for writing table(s)
00446     for (i=0; i<l; i++) port_csp0_addr[X313_WA_COMP_TD]=data[i]; 
00447     local_irq_restore(flags);
00448     len  -=l;
00449     addr +=l;
00450     data +=l;
00451   }
00452 }
00453 
00457 void fpga_hist_read_nice (int addr, int len, unsigned long * data) {
00458   unsigned long flags;
00459   int l,i;
00460   MDF13(printk("addr=0x%x, len=0x%x, ",addr, len));
00461   while (len>0) {
00462     l=(len < FPGA_TABLE_CHUNK)?len:FPGA_TABLE_CHUNK;
00463     local_irq_save(flags);
00464 //  #define   X313_WA_HIST_ADDR   0x44
00465 //  #define   X313_RA_HIST_DATA   0x45  /// use CSP4 with wait cycles to have a pulse
00466     port_csp0_addr[X313_WA_HIST_ADDR]=addr; 
00467     X3X3_AFTERWRITE ; 
00468     for (i=0; i<l; i++) data[i]=port_csp4_addr[X313_RA_HIST_DATA]; 
00469     local_irq_restore(flags);
00470     len  -=l;
00471     addr +=l;
00472     data +=l;
00473   }
00474   D13(printk("data=0x%08lx 0x%08lx 0x%08lx 0x%08lx...\n", data[0], data[1], data[2], data[3]));
00475 }
00476 
00477 ssize_t fpga_io_table_write  (struct file * file, const char * buf, size_t count, loff_t *off) {
00478   unsigned long p;
00479   char * fpga_tables_char= (char *)  fpga_tables_buffer;
00480   int sa,l;
00481   D(printk("fpga_io_table_write, count= %x\n", (int) count));
00482   p = *off;
00483   if (p >= (CX313_FPGA_TABLES_SIZE<<2))  p = (CX313_FPGA_TABLES_SIZE<<2);
00484   if( (p + count) > (CX313_FPGA_TABLES_SIZE<<2)) { // truncate count
00485     count = (CX313_FPGA_TABLES_SIZE<<2) - p;
00486   }
00487   D(printk("fpga_io_table_write, p=%x, count= %x\n", (int) p,(int) count));
00488   if (count) {
00489     if (copy_from_user(&fpga_tables_char[p],buf, count)) return -EFAULT;
00490     *off+=count;
00491     sa= p>>2;
00492     l=count>>2;
00493     fpga_table_write_nice (sa, l, &fpga_tables_buffer[sa]);
00494   }
00495   return count;
00496 }
00497 
00498 
00499 loff_t  fpga_io_table_lseek  (struct file * file, loff_t offset, int orig) {
00500   int l;
00501   l=(CX313_FPGA_TABLES_SIZE<<2);
00502   switch (orig)
00503   {
00504    case 0:
00505      file->f_pos = offset;
00506      break;
00507    case 1:
00508      file->f_pos += offset;
00509      break;
00510    case 2:
00511      file->f_pos = l + offset;
00512      break;
00513    default:
00514      return -EINVAL;
00515   }
00516   // truncate position
00517   if (file->f_pos < 0) {
00518     file->f_pos = 0;
00519     return(-EOVERFLOW);
00520   }
00521   if (file->f_pos > l) {
00522     file->f_pos = l;
00523   }
00524   return ( file->f_pos );
00525 }

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