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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : fpgactrl353.c
00003 *! DESCRIPTION: Provides sensor-independent access to FPGA in Elphel mModel 353 camera
00004 *! Includes I/O for the dedicated (to FPGA) DDR SDRAM
00005 *! Copyright 2002-2007 (C) Elphel, Inc.
00006 *! -----------------------------------------------------------------------------**
00007 *!
00008 *!  This program is free software: you can redistribute it and/or modify
00009 *!  it under the terms of the GNU General Public License as published by
00010 *!  the Free Software Foundation, either version 3 of the License, or
00011 *!  (at your option) any later version.
00012 *!
00013 *!  This program is distributed in the hope that it will be useful,
00014 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 *!  GNU General Public License for more details.
00017 *!
00018 *!  You should have received a copy of the GNU General Public License
00019 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 *! -----------------------------------------------------------------------------**
00021 *!  $Log: fpgactrl353.c,v $
00022 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00023 *!
00024 *!
00025 *!  Revision 1.5  2008/09/22 22:55:48  elphel
00026 *!  snapshot
00027 *!
00028 *!  Revision 1.4  2008/09/20 00:29:50  elphel
00029 *!  moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
00030 *!
00031 *!  Revision 1.3  2008/09/16 00:49:30  elphel
00032 *!  snapshot
00033 *!
00034 *!  Revision 1.2  2008/09/12 00:23:59  elphel
00035 *!  removed cc353.c, cc353.h
00036 *!
00037 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00038 *!  This is a fresh tree based on elphel353-2.10
00039 *!
00040 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00041 *!  switch to GPL3 license
00042 *!
00043 *!  Revision 1.6  2007/07/20 10:17:46  spectr_rain
00044 *!  *** empty log message ***
00045 *!
00046 *!  Revision 1.2  2007/05/21 17:45:10  elphel
00047 *!  boundary scan support, added 359/347 detection
00048 *!
00049 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00050 *!  initial import into CVS
00051 *!
00052 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00053 *!  *** empty log message ***
00054 *!
00055 */
00056 /****************** INCLUDE FILES SECTION ***********************************/
00057 
00058 
00059 #include <linux/module.h>
00060 #include <linux/sched.h>
00061 #include <linux/slab.h>
00062 #include <linux/errno.h>
00063 #include <linux/kernel.h>
00064 #include <linux/fs.h>
00065 #include <linux/string.h>
00066 #include <linux/init.h>
00067 #include <linux/autoconf.h>
00068 
00069 #include <asm/system.h>
00070 #include <asm/arch/memmap.h>
00071 
00072 //#include <asm/svinto.h>
00073 #include <asm/io.h>
00074 
00075 #include <asm/irq.h>
00076 
00077 #include <asm/delay.h>
00078 #include <asm/uaccess.h>
00079 #include <asm/elphel/driver_numbers.h>
00080 #include <asm/elphel/fpgaconfa.h>
00081 #include <asm/elphel/c313a.h> // just for ELPHEL_DEBUG
00082 
00083 #include "fpgactrl.h"
00084 #include "fpga_io.h"
00085 #include "fpga_sdram.h"
00086 #include "x3x3.h"
00087 #define ELPHEL_DEBUG_THIS 0
00088 #if ELPHEL_DEBUG_THIS
00089 //#if ELPHEL_DEBUG
00090   #define D1(x) x
00091   #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00092   #define MDD1(x) printk("%s:%d:",__FILE__,__LINE__); x ; udelay (ELPHEL_DEBUG_DELAY)
00093   #define D1I(x)
00094 #else
00095   #define D1(x)
00096 //  #define MD1(x) printk("%s:%d:",__FILE__,__LINE__);x
00097   #define MD1(x)
00098   #define MDD1(x)
00099   #define D1I(x) x
00100 #endif
00101 
00102 
00103 #define FPGA_MODULE_DESCRIPTION "FPGA control driver for Elphel (R) Model 353 camera"
00104 #define FPGA_DRIVER_NAME "fpga_control"
00105 #define FPGA_MAXMINOR 10
00106 
00107 //extern volatile unsigned long ccam_cr_shadow;
00108 
00109 static const char fpga_name[] = "fpga_control";
00110 static int minors[FPGA_MAXMINOR+1];     // each minor can be opened only once
00111 static int     fpga_open   (struct inode *inode, struct file *filp);
00112 static int     fpga_release(struct inode *inode, struct file *filp);
00113 static int     fpga_ioctl  (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00114 static ssize_t fpga_write  (struct file * file, const char * buf, size_t count, loff_t *off);
00115 static loff_t  fpga_lseek  (struct file * file, loff_t offset, int orig);
00116 static ssize_t fpga_read   (struct file * file, char * buf, size_t count, loff_t *off);
00117 
00118 //static loff_t fpga_lseek(struct file * file, loff_t offset, int orig);
00119 //static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off);
00120 
00121 //static int __init fpga_init(void);
00122 
00123 static struct file_operations fpga_fops = {
00124         owner:    THIS_MODULE,
00125         open:     fpga_open,
00126         release:  fpga_release,
00127         ioctl:    fpga_ioctl,
00128         llseek:   fpga_lseek,
00129         read:     fpga_read,
00130         write:    fpga_write
00131 };
00132 
00133 /* ======================================== Top level file operations =================================================================== */
00134 static int fpga_open(struct inode *inode, struct file *filp) {
00135         int p;
00136         int res;
00137 
00138         p = MINOR(inode->i_rdev);
00139      D1(printk("fpga_open: minor=%x\r\n",p) );
00140      D1(printk("filp=%lx\r\n",(unsigned long)filp) );
00141 
00142         switch ( p ) {
00143         case FPGACONF_MINOR_SDRAM : {
00144               if (minors[p])  return -EACCES;
00145 // is fpga loaded?
00146      MD1(printk("fpga_open: fpga_state=0x%x\n",(int) fpga_state) );
00147           if ((fpga_state & FPGA_STATE_LOADED) ==     0) return -EACCES; // change to particular fpga revision
00148           if ((fpga_state & FPGA_STATE_CLOCKS) ==     0) return -EACCES; // clocks not running
00150           if (((fpga_state & FPGA_STATE_SDRAM_INIT) == 0)  || (!X313_IS_SDRAM_ON))fpga_initSDRAM();
00151 
00152      MD1(printk("fpga_open: fpga_state=0x%x\n",(int) fpga_state) );
00153           if ((res=fsdram_open(inode, filp))<0)return res;
00154           break;
00155         }
00156         case FPGACONF_MINOR_IORW :
00157         case FPGACONF_MINOR_TABLES:
00158           {
00159             if (minors[p])  return -EACCES;
00160             break;
00161           }
00162         default: return -EINVAL;
00163         }
00164         minors[p]=p;
00165 
00166         filp->private_data = &minors[p];
00167         return 0;
00168 }
00169 
00170 static int fpga_release(struct inode *inode, struct file *filp) {
00171    int res=0;
00172    int p = MINOR(inode->i_rdev);
00173    switch ( p ) {
00174      case FPGACONF_MINOR_SDRAM :
00175        res= fsdram_release();
00176        minors[p]=0;
00177        return res;
00178      case FPGACONF_MINOR_IORW :
00179      case FPGACONF_MINOR_TABLES:
00180        minors[p]=0;
00181        break;
00182      default: return -EINVAL;
00183    }
00184   D1(printk("fpga_release:  done\r\n"));
00185   return 0;
00186 }
00187 
00188 
00189 
00190 static int fpga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { // switch by minor
00191 //   int res=0;
00192    D1(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00193 
00194    switch (((int *)filp->private_data)[0]) {
00195       case FPGACONF_MINOR_IORW : {// read write FPGA registers
00196         D1(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00197         if(_IOC_TYPE(cmd) == FPGACONF_GETSTATE) {
00198             return fpga_state;
00199         }
00200         return fpga_io_ioctl (inode, filp, cmd, arg);
00201       }
00202       default:return -EINVAL;
00203    }
00204 }
00205 
00206 
00207 
00208 static ssize_t fpga_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00209     D1(printk("fpga_write: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]));
00210     switch (((int *)file->private_data)[0]) {
00211        case FPGACONF_MINOR_IORW :  return fpga_io_write      (file, buf, count, off);
00212        case FPGACONF_MINOR_SDRAM : return fsdram_write       (file, buf, count, off);
00213        case FPGACONF_MINOR_TABLES: return fpga_io_table_write(file, buf, count, off);
00214        default:                 return -EINVAL;
00215     }
00216 }
00217 
00218 static loff_t  fpga_lseek(struct file * file, loff_t offset, int orig) {
00219     D1(printk (" file=%x, offset=%x, orig=%x\r\n", (int) file, (int) offset, (int) orig));
00220      switch (((int *)file->private_data)[0]) {
00221        case FPGACONF_MINOR_IORW :   return fpga_io_lseek       (file, offset, orig);
00222        case FPGACONF_MINOR_SDRAM :  return fsdram_lseek        (file, offset, orig);
00223        case FPGACONF_MINOR_TABLES:  return fpga_io_table_lseek (file, offset, orig);
00224        default:                 return -EINVAL;
00225     }
00226 }
00227 
00228 static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off) {
00229     switch (((int *)file->private_data)[0]) {
00230        case FPGACONF_MINOR_IORW :   return fpga_io_read(file, buf, count, off);
00231        case FPGACONF_MINOR_SDRAM :      return fsdram_read(file, buf, count, off);
00232        default:                 return -EINVAL;
00233     }
00234 }
00235 
00236 
00237 
00238 
00239 void init_elphel_ioremap(void) {
00240 // Do not need to iounmap as these addersses will stay on with the camera
00241         port_csp0_addr = ioremap(MEM_CSR0_START | MEM_NON_CACHEABLE, 8192);
00242         port_csp4_addr = ioremap(MEM_CSP4_START | MEM_NON_CACHEABLE, 8192);
00243         if (!port_csp0_addr || !port_csp0_addr) {
00244                 printk(FPGA_MODULE_DESCRIPTION" failed to ioremap\n");
00245 // panic here?
00246         }
00247 }
00248 
00249 
00250 static int __init 
00251 fpga_init(void)
00252 {
00253         init_elphel_ioremap(); // map address ranges to use port0 and port4 in FPGA accesses.
00254         int i,res;
00255         res = register_chrdev(FPGA_MAJOR, fpga_name, &fpga_fops);
00256         if(res < 0) {
00257                 printk(KERN_ERR "\nfpga_init: couldn't get a major number  %d.\n ",FPGA_MAJOR);
00258                 return res;
00259         }
00260         printk(FPGA_DRIVER_NAME"- %d\n",FPGA_MAJOR);
00261 
00262 
00263         for (i=0;i<=FPGA_MAXMINOR;i++) minors[i]=0;
00264         fpga_state=0;    // bit 0 - FPGA state, 1 - Clocks, 2 - SDRAM
00265 //        printk("FPGA is not loaded, clocks are not programmed, SDRAM is not initialized\r\n");
00266         return 0;
00267 }
00268 
00269 
00270 
00271 /* this makes sure that fpga_init is called during boot */
00272 
00273 module_init(fpga_init);
00274 MODULE_LICENSE("GPL");
00275 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00276 MODULE_DESCRIPTION(FPGA_MODULE_DESCRIPTION);

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