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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : fpgaconf333.c
00003 *! DESCRIPTION: TBD
00004 *! Copyright (C) 2002-2004 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: fpgaconf333.c,v $
00021 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00022 *!  This is a fresh tree based on elphel353-2.10
00023 *!
00024 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00025 *!  switch to GPL3 license
00026 *!
00027 *!  Revision 1.6  2007/07/20 10:17:45  spectr_rain
00028 *!  *** empty log message ***
00029 *!
00030 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00031 *!  initial import into CVS
00032 *!
00033 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00034 *!  *** empty log message ***
00035 *!
00036 */
00037 /****************** INCLUDE FILES SECTION ***********************************/
00038 
00039 
00040 #include <linux/module.h>
00041 #include <linux/sched.h>
00042 #include <linux/slab.h>
00043 #include <linux/errno.h>
00044 #include <linux/kernel.h>
00045 #include <linux/fs.h>
00046 #include <linux/string.h>
00047 #include <linux/init.h>
00048 #include <linux/autoconf.h>
00049 
00050 #include <asm/system.h>
00051 #include <asm/svinto.h>
00052 #include <asm/io.h>
00053 
00054 #include <asm/irq.h>
00055 
00056 #include <asm/delay.h>
00057 #include <asm/uaccess.h>
00058 #include <asm/fpgaconfa.h>
00059 
00060 #include "fpgaconf.h"
00061 #include "fpgaconfi2c.h"
00062 #include "fpgajtag.h"
00063 #include "fpga_io.h"
00064 #include "fpga_sdram.h"
00065 #include "x313.h"
00066 
00067 
00068 // TODO: Add default clock programming when powered up
00069 // return FPGA status (and clocks) (blank, loaded + rev #), also if it is initialized (as SDRAM)
00070 // 
00071 
00072 
00073 
00074 #define D(x)
00075 #define D1(x)
00076 #define FPGA_MAJOR 129  /* LOCAL/EXPERIMENTAL */
00077 #define MY_MODULE_DESCRIPTION "Elphel model 313 fpga/clock configuration driver"
00078 #define FPGACONF_DRIVER_NAME "fpga/clock configuration driver v1.0n"
00079 #define FPGACONF_MAXMINOR 10
00080 static const char fpga_name[] = "fpga_loader";
00081 static int minors[FPGACONF_MAXMINOR+1]; // each minor can be opened only once
00082 static int     fpga_open   (struct inode *inode, struct file *filp);
00083 static int     fpga_release(struct inode *inode, struct file *filp);
00084 static int     fpga_ioctl  (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00085 static ssize_t fpga_write  (struct file * file, const char * buf, size_t count, loff_t *off);
00086 static loff_t  fpga_lseek  (struct file * file, loff_t offset, int orig);
00087 static ssize_t fpga_read   (struct file * file, char * buf, size_t count, loff_t *off);
00088 
00089 //static loff_t fpga_lseek(struct file * file, loff_t offset, int orig);
00090 //static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off);
00091 
00092 //static int __init fpga_init(void);
00093 
00094 static struct file_operations fpga_fops = {
00095         owner:    THIS_MODULE,
00096         open:     fpga_open,
00097         release:  fpga_release,
00098         ioctl:    fpga_ioctl,
00099         llseek:   fpga_lseek,
00100         read:     fpga_read,
00101         write:    fpga_write
00102 };
00103 
00104 //#define FPGA_STATE_LOADED       0x0000FFFF; //
00105 //#define FPGA_STATE_CLOCKS       0x000F0000; // 
00106 //#define FPGA_STATE_INITIALIZED  0x00100000; //
00107 //FPGA_STATE_SDRAM_INIT 
00108 static int fpga_state=0; 
00109 // **************************************************************
00110 int     initClockDefault(void) { // program clock0 to 75 MHz, clock1 - 60MHz
00111   int i,r;
00112   unsigned char d[2];
00113  // high byte - address, low - data
00114     unsigned int clocks_inits[]= \
00115 /*      {0x1640, 0x150c, 0x1402, 0x0902, 0x0802, // clock 0 to 75 MHz
00116      0x42c0, 0x4109, 0x4002,
00117      0x45c0, 0x4409, 0x4302,
00118      0x48c0, 0x4709, 0x4602,
00119      0x4bc0, 0x4a09, 0x4902,
00120      0x4ec0, 0x4d09, 0x4c02,
00121      0x51c0, 0x5009, 0x4f02,
00122      0x54c0, 0x5309, 0x5202,
00123      0x57c0, 0x5609, 0x5502,
00124      0x0a02, 0x0b02    };   // clock1 to 60 MHz
00125 */     
00126         {0x1640, 0x150c, 0x1402, 0x0902, 0x0802, // clock 0 to 75 MHz   (PLL3/clkA)
00127      0x42c4, 0x4109, 0x4003,               // PLL1
00128      0x45c4, 0x4409, 0x4303,
00129      0x48c4, 0x4709, 0x4603,
00130      0x4bc4, 0x4a09, 0x4903,
00131      0x4ec4, 0x4d09, 0x4c03,
00132      0x51c4, 0x5009, 0x4f03,
00133      0x54c4, 0x5309, 0x5203,
00134      0x57c4, 0x5609, 0x5503,
00135      0x0a05, 0x0b05,              // clock1 to 20 MHz   (clkB)
00136      0x0e87    };   // PLL3->clkA, PLL1->clkB, REF->clkC, PLL2->clkD
00137      
00138         for (i=0;i<sizeof( clocks_inits)/sizeof( clocks_inits[0]);i++) {
00139           d[0]=((clocks_inits[i]>>8) & 0xff); // i2c address
00140           d[1]=( clocks_inits[i]     & 0xff); // i2c data
00141           if ((r=fi2c_writeData(0xd2, d, 2))) return r; // error writing to clock
00142         }
00143   fpga_state |= 0x00020000;           //#define FPGA_STATE_CLOCKS       0x000F0000; // 
00144   return 0;
00145 }
00146 
00147 /* ======================================== Top level file operations =================================================================== */
00148 static int fpga_open(struct inode *inode, struct file *filp) {
00149         int p;
00150         int res;
00151 
00152         p = MINOR(inode->i_rdev);
00153      D1(printk("fpga_open: minor=%x\r\n",p) );
00154      D1(printk("filp=%lx\r\n",(unsigned long)filp) );
00155 
00156         switch ( p ) {
00157         case FPGACONF_MINOR_SDRAM : {
00158               if (minors[p])  return -EACCES;
00159 // is fpga loaded?
00160           if ((fpga_state & FPGA_STATE_LOADED) ==     0) return -EACCES; // change to particular fpga revision
00161           if ((fpga_state & FPGA_STATE_CLOCKS) ==     0) return -EACCES; // clocks not running
00162           if ((fpga_state & FPGA_STATE_SDRAM_INIT) == 0) {
00163                fpga_initSDRAM();
00164                fpga_state |= FPGA_STATE_SDRAM_INIT;
00165           }
00166   D(printk("fsdram_open\n"));
00167           if ((res=fsdram_open(inode, filp))<0)return res;
00168           break;
00169         }
00170             case FPGACONF_MINOR_IORW :
00171         case FPGACONF_MINOR_I2C :
00172           {
00173            if (minors[p])  return -EACCES;
00174            break;
00175           }
00176 
00177         case FPGACONF_MINOR_JTAG :
00178           {
00179            if (minors[p])  return -EACCES;
00180 // reset fpga_state
00181           fpga_state &= ~FPGA_STATE_LOADED;
00182           fpga_state &= ~FPGA_STATE_SDRAM_INIT; // not needed
00183 
00184 // disable camera interrupts here (while reprogramming FPGA could generate interrupts;
00185 
00186 
00187 
00188         *R_IRQ_MASK0_CLR = 0x10;        //1 << irq_int_vector_nr
00189 //      *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_SET, irq_int_vector_nr, set);
00190         printk ("Camera interrupts disabled\n");
00191 
00192 
00193 
00194 
00195            if ((res =fjtag_open())) return res;
00196            break;      
00197           }
00198 
00199         default: return -EINVAL;
00200         }
00201 
00202         minors[p]=p;
00203 
00204         filp->private_data = &minors[p];
00205 
00206         return 0;
00207 }
00208 //#define FPGA_STATE_LOADED       0x0000FFFF; //
00209 //#define FPGA_STATE_CLOCKS       0x000F0000; // 
00210 //#define FPGA_STATE_INITIALIZED  0x00100000; // 
00211 
00212 static int fpga_release(struct inode *inode, struct file *filp) {
00213    int res=0;
00214         int p = MINOR(inode->i_rdev);
00215         switch ( p ) {
00216         case FPGACONF_MINOR_SDRAM : {
00217           res= fsdram_release();
00218           minors[p]=0;
00219           return res;
00220         }
00221 
00222         case FPGACONF_MINOR_JTAG :
00223             if ((res=fjtag_close ()) >=0) {
00224                fpga_state|=1; // Add 16-bit revision number here? (from file header)
00225         }
00226 // reset initializing in any case:
00227         fpga_state &=~FPGA_STATE_INITIALIZED;   // and fall farther...
00228         case FPGACONF_MINOR_I2C :
00229             case FPGACONF_MINOR_IORW :
00230           {
00231            minors[p]=0;
00232            break;
00233           }
00234         default: return -EINVAL;
00235         }
00236 
00237    D(printk("fpga_release:  done\r\n"));
00238         return 0;
00239 }
00240 
00241 
00242 
00243 static int fpga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { // switch by minor
00244    int res=0;
00245    D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00246 
00247           switch (((int *)filp->private_data)[0]) {
00248 
00249           case FPGACONF_MINOR_I2C :     // use for JTAG access ioctl also (debugging only)
00250            {
00251              switch (_IOC_NR(cmd)) {
00252                case I2C_WRITEREG: {
00253 // for now - clocks are considered programmed after any successfull write to their i2c register.
00254 // after driver will program clocks - modify that
00255 
00256              res=fi2c_ioctl (inode, filp, cmd, arg);
00257                  if (res >=0) fpga_state|=0x10000; // #define FPGA_STATE_CLOCKS       0x000F0000; // 
00258              return res;
00259            }
00260                case I2C_READREG: {
00261                    return fi2c_ioctl (inode, filp, cmd, arg);
00262                 }
00263                 case FPGA_PGM:
00264                 case FPGA_STAT:
00265                 case FPGA_JTAG:
00266                 case FPGA_PA_RD:
00267                 case FPGA_PA_WR:
00268                    return fjtag_ioctl (inode, filp, cmd, arg);
00269                 default:return -EINVAL;
00270              } 
00271            }
00272       case FPGACONF_MINOR_IORW : // read write FPGA registers
00273            {
00274    D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00275 
00276                 if(_IOC_TYPE(cmd) == FPGACONF_GETSTATE) {
00277 // just temporary...
00278 
00279  D(printk ("R_PORT_PA_READ=%x\r\n",(int) *R_PORT_PA_READ));
00280 
00281  D(printk ("R_PORT_PB_READ=%x\r\n",(int) *R_PORT_PB_READ));
00282 
00283                   return fpga_state;
00284                 }
00285             return fpga_io_ioctl (inode, filp, cmd, arg);
00286            }
00287 
00288           default:return -EINVAL;
00289           }
00290 }
00291 
00292 
00293 
00294 static ssize_t fpga_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00295 // printk("fpga_write: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]);
00296     switch (((int *)file->private_data)[0]) {
00297        case FPGACONF_MINOR_SDRAM :      return         fsdram_write (file, buf, count, off);
00298        case FPGACONF_MINOR_JTAG  :      return         fjtag_write (file, buf, count, off);
00299        default:                 return -EINVAL;
00300     }
00301 
00302 }
00303 
00304 static loff_t  fpga_lseek(struct file * file, loff_t offset, int orig) {
00305 //    printk (" file=%x, offset=%x, orig=%x, ((int *)file->private_data)[0]=%x\r\n", (int) file, (int) offset, (int) orig, ((int *)file->private_data)[0]);
00306     D(printk (" file=%x, offset=%x, orig=%x\r\n", (int) file, (int) offset, (int) orig));
00307      switch (((int *)file->private_data)[0]) {
00308        case FPGACONF_MINOR_SDRAM :      return         fsdram_lseek(file, offset, orig);
00309        default:                 return -EINVAL;
00310     }
00311 }
00312 
00313 static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off) {
00314 //    return -1;
00315     switch (((int *)file->private_data)[0]) {
00316        case FPGACONF_MINOR_SDRAM :      return         fsdram_read(file, buf, count, off);
00317        default:                 return -EINVAL;
00318     }
00319 }
00320 
00321 
00322 
00323 
00324 //loff_t  fsdram_lseek(struct file * file, loff_t offset, int orig);
00325 //ssize_t fsdram_read(struct file * file, char * buf, size_t count, loff_t *off);
00326 
00327 
00328 
00329 
00330 static int __init 
00331 fpga_init(void)
00332 {
00333 //  extern void init_ioremap(void);
00334         int i,res;
00335         res = register_chrdev(FPGA_MAJOR, fpga_name, &fpga_fops);
00336         if(res < 0) {
00337                 printk(KERN_ERR "fpga_init: couldn't get a major number.\n");
00338                 return res;
00339         }
00340         printk(FPGACONF_DRIVER_NAME);
00341 
00342 
00343         for (i=0;i<=FPGACONF_MAXMINOR;i++) minors[i]=0;
00344 //        init_ioremap();
00345 // Initialize ports A and B to it's default values
00346         initPortA();
00347         initPortB();
00348 
00349         printk("Ports A and B initialized\r\n");
00350         fpga_state=0;    // bit 0 - FPGA state, 1 - Clocks, 2 - SDRAM
00351         printk("FPGA is not loaded, clocks are not programmed, SDRAM is not initialized\r\n");
00352         if (initClockDefault()==0) printk("Clocks initialized (clk0=75MHz, clk1=60MHz)\r\n");
00353         else                       printk("Clocks initialization failed\r\n");
00354         return 0;
00355 }
00356 
00357 
00358 
00359 /* this makes sure that fpga_init is called during boot */
00360 
00361 module_init(fpga_init);
00362 MODULE_LICENSE("GPL");
00363 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00364 MODULE_DESCRIPTION(MY_MODULE_DESCRIPTION);
00365 MODULE_DESCRIPTION("Elphel model 333 fpga download driver");

Generated on Thu Aug 7 16:19:00 2008 for elphel by  doxygen 1.5.1