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

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : fpgaclocks353.c
00003 *! provides control of the FPGA clocks based on 3-pll generator
00004 *! Direct r/w of the CY22393 over the I2C interface (connected to PB.16 and PB.17 of the CPU)
00005 *! supports 3 PLLs connected to 3 outputs (clk0, clk1 and clk2)
00006 *! clk3 can be only turned on to Xtal frequency (12MHz) or off
00007 *! Input parameter specifies frequency in Hz, internally data is rounded to 100Hz
00008 *!
00009 *!
00010 *! Copyright (C) 2002-2006 Elphel, Inc.
00011 *! -----------------------------------------------------------------------------**
00012 *!
00013 *!  This program is free software: you can redistribute it and/or modify
00014 *!  it under the terms of the GNU General Public License as published by
00015 *!  the Free Software Foundation, either version 3 of the License, or
00016 *!  (at your option) any later version.
00017 *!
00018 *!  This program is distributed in the hope that it will be useful,
00019 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 *!  GNU General Public License for more details.
00022 *!
00023 *!  You should have received a copy of the GNU General Public License
00024 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025 *! -----------------------------------------------------------------------------**
00026 *!  $Log: fpgaclocks353.c,v $
00027 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00028 *!
00029 *!
00030 *!  Revision 1.3  2008/09/22 22:55:48  elphel
00031 *!  snapshot
00032 *!
00033 *!  Revision 1.2  2008/09/20 00:29:49  elphel
00034 *!  moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
00035 *!
00036 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00037 *!  This is a fresh tree based on elphel353-2.10
00038 *!
00039 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00040 *!  switch to GPL3 license
00041 *!
00042 *!  Revision 1.6  2007/07/20 10:17:45  spectr_rain
00043 *!  *** empty log message ***
00044 *!
00045 *!  Revision 1.2  2007/06/28 02:23:49  elphel
00046 *!  removed initilaization to some frequencies during Linux booting (they are programmed in other places)
00047 *!
00048 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00049 *!  initial import into CVS
00050 *!
00051 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00052 *!  *** empty log message ***
00053 *!
00054 
00055 */
00056 
00057 /****************** INCLUDE FILES SECTION ***********************************/
00058 #include <linux/autoconf.h>
00059 
00060 #include <linux/module.h>
00061 #include <linux/sched.h>
00062 #include <linux/slab.h>
00063    #include <linux/ioport.h> // needed?
00064 #include <linux/errno.h>
00065 #include <linux/kernel.h>
00066 #include <linux/fs.h>
00067 #include <linux/string.h>
00068 //#include <linux/poll.h>
00069 #include <linux/init.h>
00070 
00071 //#include <linux/interrupt.h>
00072 //#include <linux/spinlock.h>
00073 
00074 
00075 //#include <asm/svinto.h> - obsolete
00076 
00077 // #include <asm/etraxgpio.h> // probably just for gpio driver
00078 #include <asm/arch/hwregs/reg_map.h>
00079 #include <asm/arch/hwregs/reg_rdwr.h>
00080 #include <asm/arch/hwregs/gio_defs.h>
00081 #include <asm/arch/hwregs/intr_vect_defs.h>
00082 #include <asm/arch/hwregs/pinmux_defs.h>
00083 
00084 
00085 #include <asm/io.h>
00086 #include <asm/system.h>
00087 #include <asm/irq.h>
00088 
00089 
00090 
00091 #include <asm/delay.h>
00092 #include <asm/uaccess.h>
00093 
00094 #include <asm/elphel/driver_numbers.h>
00095 #include <asm/elphel/fpgaconfa.h>
00096 #include <asm/elphel/fpgaclocks.h>
00097 
00098 #include "fpgactrl.h" // extern fpga_state
00099 
00100 #define D(x)
00101 //#define D(x) printk("%s:%d:",__FILE__,__LINE__);x
00102 //#define D(x) x
00103 #define D1(x)
00104 //#define D1(x) printk("%s:%d:",__FILE__,__LINE__);x
00105 
00106 #define D2(x)
00107 //#define D2(x) x
00108 
00109 #define D3(x)
00110 //#define D3(x) printk("%s:%d:",__FILE__,__LINE__);x
00111 
00112 // add to other drivers to use clock change function
00113 //extern int setClockFreq(int nclock, int freq) { // freq now in Hz
00114 
00115 //#define D5(x) printk("%s:%d:",__FILE__,__LINE__);x
00116 #define D5(x)
00117 
00118 
00119 //=========================
00120 #define FPGA_CLOCK_DRIVER_NAME "Elphel (R) model 353 system clocks (PLL frequency synth.) driver"
00121 #define FPGA_CLOCK_MAXMINOR 10
00122 
00123 
00124 
00125 
00126 /****************** I2C DEFINITION SECTION *************************/
00127 #define XCLOCK_LOW_TIME            8
00128 #define XCLOCK_HIGH_TIME           8
00129 #define XSTART_CONDITION_HOLD_TIME 8
00130 #define XSTOP_CONDITION_HOLD_TIME  8
00131 #define XENABLE_OUTPUT             0x01
00132 #define XENABLE_INPUT              0x00
00133 #define XI2C_CLOCK_HIGH            1
00134 #define XI2C_CLOCK_LOW             0
00135 #define XI2C_DATA_HIGH             1
00136 #define XI2C_DATA_LOW              0
00137 /*
00138 port B:
00139  16 - I2C SDA
00140  17 - I2C SCL
00141 */
00142 
00143 #define xi2c_delay(usecs) udelay(usecs)
00144 
00145 static int clock_frequency[4]; // in Hz
00146 typedef struct {
00147   unsigned int p :   11; // p - 16..1600
00148   unsigned int q :   8;  // q - 0.. 255
00149   unsigned int dv:   7;  // dv - 1.. 127
00150   unsigned int corr: 3;  // 0/1/2/3/4
00151   unsigned int rslt:   3;  // 0 - OK, 1 - frequency low, 2 - frequency high, 3 - other
00152 } t_pll_params;
00153  
00154 
00155 int xi2c_diagnose(void);
00156 int   xi2c_start(void);
00157 void xi2c_stop(void);
00158 void xi2c_nostop(void);
00159 int xi2c_outbyte(unsigned char d);
00160 unsigned char xi2c_inbyte(void);
00161 void xi2c_sendack(void);
00162 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size, int nostop);
00163 int fi2c_readData(unsigned char theSlave, unsigned char *theData, int size);
00164 
00165 int fi2c_ioctl(struct inode *inode, struct file *file,  unsigned int cmd, unsigned long arg);
00166 int calc_pll_params (unsigned int f, t_pll_params * pars); // f -in Hz
00167 
00168 int setCYField (int addr, int mask, int value);
00169 int setClockFreq(int nclock, int freq); // freq now in Hz
00170 
00171 // interface functions
00172 static const char fpga_clock_name[] = "fpga_clock_control";
00173 static int minors[FPGA_CLOCK_MAXMINOR+1]; // each minor can be opened only once
00174 static int     fpga_clock_open   (struct inode *inode, struct file *filp);
00175 static int     fpga_clock_release(struct inode *inode, struct file *filp);
00176 static int     fpga_clock_ioctl  (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00177 static int __init fpga_clock_init(void);
00178 
00179 
00180 static struct file_operations fpga_clock_fops = {
00181   owner:    THIS_MODULE,
00182   open:     fpga_clock_open,
00183   release:  fpga_clock_release,
00184   ioctl:    fpga_clock_ioctl,
00185 };
00186 
00187 
00188 
00189 
00190 
00191 #define CY223933_SA 0xd2
00192 // in Hz
00193 #define CY22393_SCALE 100 // precision will be 100Hz
00194 #define CY22393_PLLMIN (100000000/CY22393_SCALE)
00195 #define CY22393_PLLMAX (400000000/CY22393_SCALE)
00196 #define CY22393_XTAL   ( 12000000/CY22393_SCALE)
00197 #define CY22393_OUTMAX (166000000/CY22393_SCALE)
00198 #define CY22393_PMIN 16
00199 #define CY22393_PMAX 1600
00200 
00201 
00202 int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
00203 //   t_pll_params pars;
00204    unsigned int f0= CY22393_XTAL;
00205    unsigned int f0_2= CY22393_XTAL/2;
00206    unsigned int fpmn= CY22393_XTAL * (CY22393_PMIN + 6);
00207    unsigned int fpmx= CY22393_XTAL * (CY22393_PMAX + 6);
00208    int divmn, divmx, err1,err, div,q,qmn,qmx,qmx1,fdv,p, e,fdvq;
00209    pars->rslt=3; // other error
00210    D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00211    f/=CY22393_SCALE; // to fit into 32-bit calcualtions
00212    D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00213    if (f>CY22393_OUTMAX) {
00214      pars->rslt=2;
00215      D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00216      return pars->rslt;
00217    }
00218    if (f <=0 ) {
00219      pars->rslt=1;
00220      D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00221      return pars->rslt;
00222    }
00223    divmx=CY22393_PLLMAX/f; if (divmx > 127) divmx=127; // could not be <1
00224    divmn=CY22393_PLLMIN/f; if (divmn < 1)   divmn=1;
00225    if (divmn >127) {
00226      pars->rslt=1;
00227      D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d, divmn=%d\r\n",f0,f,CY22393_OUTMAX,divmn));
00228      return pars->rslt;
00229    }
00230    err1=f;
00231    qmx1=0;
00232    for (div=divmn;div<=divmx;div++) {
00233      err=err1*div;
00234      fdv=f*div;
00235      qmn=fpmn/fdv-2; if (qmn < 0) qmn=0;
00236      qmx=fpmx/fdv-2; if (qmx >255) qmx=255;
00237 // recalculate qmn to avoid same div*qmn as already tried with lover div
00238      D1(printk("div=%d,qmn=%d, qmx=%d\r\n",div,qmn,qmx));
00239      if (div==1) qmx1=qmx;
00240      else if ((qmn*div) < qmx1) qmn=qmx1/div;
00241      for (q=qmn+2;q<=qmx+2; q++) {
00242        fdvq=fdv*q;
00243        p= (fdvq+f0_2)/f0; // can p be out of range here?
00244        e= fdvq-f0*p; if (e<0) e=-e;
00245        if (e< (err*q)) { // better solution found
00246          pars->rslt=0;
00247          pars->p=p-6;
00248          pars->q=q-2;
00249          pars->dv=div;
00250          err1=e/q/div;
00251          err=err1*div;
00252          D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d\r\n", (f0*p)/q/div, div,p, q, err1));
00253          if (err1==0) {
00254            pars->corr=(pars->p<226)?0:((pars->p<621)?1:((pars->p<829)?2:((pars->p<1038)?3:4)));
00255            D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
00256            (f0*(pars->p+6))/(pars->q+2)/pars->dv,
00257            pars->dv,
00258            (pars->p+6),
00259            (pars->q+2),
00260            err1,
00261            pars->rslt));
00262            return pars->rslt;
00263          }
00264        }
00265      }
00266    }
00267    D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
00268            (f0*(pars->p+6))/(pars->q+2)/pars->dv,
00269            pars->dv,
00270            (pars->p+6),
00271            (pars->q+2),
00272            err1,
00273            pars->rslt));
00274    pars->corr=(pars->p<226)?0:((pars->p<621)?1:((pars->p<829)?2:((pars->p<1038)?3:4)));
00275    return pars->rslt;
00276 }
00277 
00278 
00279 
00280 
00281 
00282 
00283 int setCYField (int addr, int mask, int value);
00284 
00285 /* I2C functions */
00286 
00287 #if 0
00288 inline void xi2c_disable(void){
00289     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00290     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00291     pb_dout.data |=  0x20000;
00292     pb_oe.oe &= ~0x10000; //SDA - in 
00293     pb_oe.oe |=  0x20000; //SCL out
00294     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00295     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00296 D2(printk("x"));
00297  }; // *R_PORT_PB_SET=(portb_shadow  = 0x0203)
00298 inline void xi2c_dir_out(void){ // is it really needed (only in start)
00299     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00300     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00301     pb_dout.data |=  0x20000;
00302     pb_dout.data &= ~0x10000;
00303     pb_oe.oe     |=  0x30000; //SCL out, SDA out
00304     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00305     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00306 D2(printk(">"));
00307 }; // *R_PORT_PB_SET=(portb_shadow  = 0x0303)
00308 inline void xi2c_dir_in(void){
00309     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00310     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00311     pb_dout.data |=  0x20000;
00312     pb_dout.data &= ~0x10000;
00313     pb_oe.oe &= ~0x10000; //SDA - in 
00314     pb_oe.oe |=  0x20000; //SCL out
00315     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00316     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00317 D2(printk("<"));
00318 }; //  *R_PORT_PB_SET=(portb_shadow  = 0x0203)
00319 inline void xi2c_scl_0(void){
00320     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00321     pb_dout.data &= ~0x20000;
00322     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00323 D2(printk("\\"));
00324 }; //   *R_PORT_PB_SET=(portb_shadow &= 0x0301)
00325 inline void xi2c_scl_1(void){
00326     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00327     pb_dout.data |= 0x20000;
00328     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00329 D2(printk("/"));
00330 }; //   *R_PORT_PB_SET=(portb_shadow |= 0x0002)
00331 inline void xi2c_sda(int x){
00332 /*
00333     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00334     pb_dout.data &= ~0x10000;
00335     pb_dout.data |= x? 0x10000:0;
00336     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00337 */
00338 // add acceleration here ?
00339 
00340     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00341     if (x) pb_oe.oe     &= ~0x10000; //SDA disabled (1)
00342     else   pb_oe.oe     |= ~0x10000; //SDAenabled (0)
00343 
00344     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00345 
00346 D2(printk("%d",x?1:0));
00347 }; //  *R_PORT_PB_SET=(portb_shadow = (portb_shadow & 0x0002) | 0x0300 | ((x)? 1:0));
00348 inline int  xi2c_getbit(void){
00349 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'H':'L'));
00350     return (((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1;
00351 }; //  (*R_PORT_PB_READ & 1)
00352 inline int  xi2c_getscl(void){
00353 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'+':'-'));
00354     return (((REG_RD(gio, regi_gio, r_pb_din)).data) >> 17) & 1;
00355 }; //  ((*R_PORT_PB_READ >>1) & 1)
00356 
00357 
00358 #endif
00359 
00360 
00361 inline void xi2c_disable(void){ //initial condition, no fast pull up for data scl=1, sda=z (==1)
00362     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00363     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00364     pb_dout.data |=  0x30000;
00365     pb_oe.oe &=     ~0x10000; //SDA - in 
00366     pb_oe.oe |=      0x20000; //SCL out
00367     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00368     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00369 D2(printk("x"));
00370  };
00371 
00372 inline void xi2c_scl(int x){ // sst SCL line to x (oe supposed to be setup earlier)
00373     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00374     if (x) pb_dout.data |=  0x20000;
00375     else   pb_dout.data &= ~0x20000;
00376     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00377 D2(if (x) printk("/"); else printk("\\"));
00378  }
00379 
00380 inline void xi2c_sda (int x){ // sst SDA line to x (accelerate with active high)
00381     reg_gio_rw_pb_dout      pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);  
00382     reg_gio_rw_pb_oe        pb_oe =   REG_RD(gio, regi_gio, rw_pb_oe);
00383     if (x) {
00384         pb_dout.data |=  0x10000; // SDA=1
00385         pb_oe.oe     |=  0x10000; // SDA out enable
00386         REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00387         REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00388         pb_oe.oe     &= ~0x10000; // SDA out disable
00389         D2(printk("1"));
00390 
00391     } else {
00392         pb_dout.data &= ~0x10000; // SDA=0
00393         pb_oe.oe     |=  0x10000; // SDA out enable
00394         REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00395         REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00396         D2(printk("0"));
00397     }
00398     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout); // just extra delay
00399     REG_WR(gio, regi_gio, rw_pb_dout, pb_dout); // just extra delay
00400     REG_WR(gio, regi_gio, rw_pb_oe, pb_oe); // now - disable active pullup for SDA line (when sda=1, nop if sda=0)
00401  }
00402 
00403 inline int  xi2c_getbit(void){
00404 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'H':'L'));
00405     return (((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1;
00406 }; //  (*R_PORT_PB_READ & 1)
00407 inline int  xi2c_getscl(void){
00408 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'+':'-'));
00409     return (((REG_RD(gio, regi_gio, r_pb_din)).data) >> 17) & 1;
00410 }; //  ((*R_PORT_PB_READ >>1) & 1)
00411 
00412 /*
00413 inline void xi2c_disable(void);
00414 inline void xi2c_scl(int x);
00415 inline void xi2c_sda (int x);
00416 inline int  xi2c_getbit(void);
00417 inline int  xi2c_getscl(void);
00418 */
00419 
00420 
00421 
00422 void initPortB(void) {
00423 // connect 2 lower bits of port B to GPIO, disconnect from IOP
00424     unsigned long tmp;
00425     reg_pinmux_rw_pb_iop    pinmux_b_iop;
00426     reg_pinmux_rw_pb_gio    pinmux_b_gio;
00427 
00428     pinmux_b_iop= REG_RD(pinmux, regi_pinmux, rw_pb_iop);
00429     tmp = REG_TYPE_CONV(unsigned long, reg_pinmux_rw_pb_iop, pinmux_b_iop);
00430     tmp &= ~0x030000;
00431     pinmux_b_iop = REG_TYPE_CONV(reg_pinmux_rw_pb_iop, unsigned long, tmp);
00432     REG_WR(pinmux, regi_pinmux, rw_pb_iop, pinmux_b_iop);
00433 
00434     pinmux_b_gio= REG_RD(pinmux, regi_pinmux, rw_pb_gio);
00435     tmp = REG_TYPE_CONV(unsigned long, reg_pinmux_rw_pb_gio, pinmux_b_gio);
00436     tmp |=  0x030000;
00437     pinmux_b_gio = REG_TYPE_CONV(reg_pinmux_rw_pb_gio, unsigned long, tmp);
00438     REG_WR(pinmux, regi_pinmux, rw_pb_gio, pinmux_b_gio);
00439     xi2c_disable();
00440 }
00441 
00442 /* diagnose i2c bus problems. Will always return non-zero
00443 Normally is called from xi2c_start, if it detects problem  */
00444 int xi2c_diagnose(void) {
00445    int error=0;
00446   D(printk("diagnose\r\n"));
00447 
00448    while (!error) {
00449       xi2c_disable();xi2c_sda (1);  // will force high SCL, SDA
00450       xi2c_delay(XCLOCK_HIGH_TIME);
00451       if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00452       if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00453       if (error) break;
00454       xi2c_scl (0);
00455       xi2c_sda (0);
00456       xi2c_delay(XCLOCK_LOW_TIME);
00457       if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00458       if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00459       if (error) break;
00460       xi2c_disable(); // first disables, then sets high
00461       xi2c_delay(XCLOCK_HIGH_TIME*2);
00462       if (!xi2c_getbit) error |= ERR_I2C_SDA_NOPULLUP;
00463       if (!xi2c_getscl) error |= ERR_I2C_SCL_NOPULLUP;
00464       if (error) break;
00465       xi2c_sda(0);   // scl will be left disabled (high)
00466       if (!xi2c_getscl) error |= ERR_I2C_SHORT;
00467       break;
00468    }
00469    if (!error) error =   ERR_I2C_NOTDETECTED;
00470    /* try start-stop to reset effects of playing with sda/scl lines */
00471    xi2c_disable();  // will force high SCL, SDA
00472    xi2c_sda (0);
00473    xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00474    xi2c_scl(0);
00475    xi2c_delay(XCLOCK_LOW_TIME*2);
00476    xi2c_scl(1);
00477    xi2c_delay(XCLOCK_HIGH_TIME*2);
00478    xi2c_sda (1);
00479    xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00480    xi2c_disable();
00481    return error;
00482 }
00483 
00484 /* generate i2c start condition and test bus */
00485 
00486 int   xi2c_start(void) {
00487 // int error=0;
00488    int i;
00489   D(for(i=0;i<300;i++) udelay(1000); printk("start:\r\n"); for(i=0;i<300;i++) udelay(1000));
00490    /* SCL=1 SDA=1 */
00491    xi2c_disable();  // will set high SCL, SDA
00492    xi2c_delay(XCLOCK_HIGH_TIME/2);
00493    /* if the periferial (?) driving sda low (after being interrupted)? - try to recover */
00494 //   xi2c_dir_in();
00495    xi2c_delay(XCLOCK_HIGH_TIME/2);
00496    if (!xi2c_getbit()) {
00497       for (i=0;(i<9) && !xi2c_getbit();i++) {
00498          xi2c_scl(0);
00499          xi2c_delay(XCLOCK_LOW_TIME);
00500          xi2c_scl(1);
00501          xi2c_delay(XCLOCK_HIGH_TIME);
00502       }
00503       if (!xi2c_getbit) return  xi2c_diagnose(); // did not help - really stuck
00504       /* it is breathing - try "START"-"STOP" */
00505       xi2c_sda (0);
00506       xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00507       xi2c_scl(0);
00508       xi2c_delay(XCLOCK_LOW_TIME*2);
00509       xi2c_scl(1);
00510       xi2c_delay(XCLOCK_HIGH_TIME*2);
00511       xi2c_sda (1);
00512       xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00513    }
00514    /* SCL=1 SDA=1 */
00515    xi2c_delay(XCLOCK_HIGH_TIME/2);
00516    if ((!xi2c_getbit()) || (!xi2c_getscl())) return  xi2c_diagnose();
00517    /* SCL=1 SDA=0 */
00518    xi2c_sda(0);
00519    xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00520    if (( xi2c_getbit()) || (!xi2c_getscl())) return  xi2c_diagnose();
00521    /* SCL=0 SDA=0 */
00522    xi2c_scl(0);
00523    xi2c_delay(XCLOCK_LOW_TIME);
00524    if (( xi2c_getbit()) || ( xi2c_getscl())) return  xi2c_diagnose();
00525    return 0;
00526 }
00527 
00528 /* generate i2c stop condition */
00529 void xi2c_stop(void) {  // assumed to be enabled
00530    /* SCL=0 SDA=0  */
00531   D(int i;)
00532   D( for (i=0;i<300;i++) udelay(1000); printk("stop:\r\n"); for(i=0;i<300;i++) udelay(1000));
00533 
00534    xi2c_scl (0);
00535    xi2c_sda (0);
00536    xi2c_delay(XCLOCK_LOW_TIME*2);
00537    /* SCL=1 SDA=0 */
00538    xi2c_scl(1);
00539    xi2c_delay(XCLOCK_HIGH_TIME*2);
00540    /* SCL=1 SDA=1 */
00541    xi2c_sda (1);
00542    xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00543 //   xi2c_disable();  // both high with resistor pull-up
00544 }
00545 
00546 /* generate i2c "no-stop" condition before repeated start */
00547 void xi2c_nostop(void) {  // assumed to be enabled
00548    /* SCL=0 SDA=0  */
00549   D(int i;)
00550   D( for (i=0;i<300;i++) udelay(1000); printk("nostop:\r\n"); for(i=0;i<300;i++) udelay(1000));
00551 
00552    xi2c_scl (0);
00553    xi2c_sda (0);
00554    xi2c_delay(XCLOCK_LOW_TIME*2);
00555    /* SCL=0 SDA=1 */
00556    xi2c_sda (1);
00557    xi2c_delay(XCLOCK_HIGH_TIME*2);
00558    /* SCL=1 SDA=1 */
00559    xi2c_scl(1);
00560    xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00561    xi2c_disable();  // both high with resistor pull-up
00562 }
00563 
00564 
00565 
00566 
00567 /* write a byte to the i2c interface , return acknowledge */
00568 int xi2c_outbyte(unsigned char d) { 
00569    int i;
00570    unsigned char x=d;   // make it non-destructive
00571   D(printk("outbyte: byte=%x\r\n",  (int) x));
00572 
00573    for (i = 0; i < 8; i++) { // assumed to be with SCL=0;
00574       xi2c_sda (x & 0x80); // checks only on non-zero, so no need to '>>'
00575 //portb_shadow
00576 //  D(printk("%x ",  (int) portb_shadow));
00577 
00578       xi2c_delay(XCLOCK_LOW_TIME/2);
00579       xi2c_scl (1);
00580       xi2c_delay(XCLOCK_HIGH_TIME);
00581       xi2c_scl (0);
00582       xi2c_delay(XCLOCK_LOW_TIME/2);
00583       x <<= 1;
00584    }
00585   D(printk("  "));
00586 
00587    /* enable input    */
00588 //   xi2c_dir_in();
00589    xi2c_sda (1);
00590    xi2c_delay(XCLOCK_LOW_TIME/2);
00591    xi2c_scl (1);
00592    xi2c_delay(XCLOCK_HIGH_TIME);
00593    i= (1-xi2c_getbit());
00594    xi2c_scl (0);
00595    xi2c_delay(XCLOCK_LOW_TIME/2);
00596   D(printk("ACK=%x ", i));
00597 
00598 
00599    return i;
00600 }
00601 
00602 /* read a byte from the i2c interface */
00603 
00604 unsigned char xi2c_inbyte(void) { // assumed SCL=0, SDA=X
00605    unsigned char aBitByte = 0;
00606    int i;
00607    /* enable input */
00608   D(printk("inbyte: "));
00609 
00610 //   xi2c_dir_in();
00611    xi2c_sda (1);
00612    /* get bits  */
00613    for (i = 0; i < 8; i++) {
00614       xi2c_delay(XCLOCK_LOW_TIME/2);
00615       /* low clock period   */
00616       xi2c_scl (1);
00617       xi2c_delay(XCLOCK_HIGH_TIME);
00618       aBitByte = (aBitByte << 1) | xi2c_getbit();
00619       xi2c_scl (0);
00620       xi2c_delay(XCLOCK_LOW_TIME/2);
00621    }
00622   D(printk(" data=%x\r\n", aBitByte));
00623    return aBitByte;  // returns with SCL=0, SDA - OFF
00624 }
00625 
00626 /*#---------------------------------------------------------------------------
00627 *#
00628 *# FUNCTION NAME: I2C::sendAck
00629 *#
00630 *# DESCRIPTION  : Send ACK on received data
00631 *#
00632 *#--------------------------------------------------------------------------*/
00633 void xi2c_sendack(void) {
00634     D(printk("sendack\r\n"));
00635 
00636       xi2c_sda (0);
00637       xi2c_delay(XCLOCK_LOW_TIME/2);
00638       xi2c_scl (1);
00639       xi2c_delay(XCLOCK_HIGH_TIME);
00640       xi2c_scl (0);
00641       xi2c_delay(XCLOCK_LOW_TIME/2);
00642 }
00643 
00644 /*#---------------------------------------------------------------------------
00645 *#
00646 *# FUNCTION NAME: fi2c_writeData
00647 *#
00648 *# DESCRIPTION  : Writes a sequence of bytes to an I2C device
00649 *# removed retries, will add test-ready later as a separate function
00650 *# removed all "dummy stuff" - I never needed that
00651 *#
00652 *#--------------------------------------------------------------------------*/
00653 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size, int nostop) {
00654    int i,error=0;
00655    /* we don't like to be interrupted  *** WHY??? ***     */
00656    D3(printk("i2c_writeData:  theSlave=%x data=%x %x size=%x\r\n", theSlave, theData[0], theData[1], size));
00657    D(printk("writeData: %x %x %x %x\r\n", theSlave, theData[0], theData[1], size));
00658 
00659    /* generate start condition, test bus */
00660    if ((error=xi2c_start())) return error;
00661    /* send slave address, wait for ack */
00662    if(!xi2c_outbyte(theSlave)) {
00663        xi2c_stop();
00664        return ERR_I2C_BSY; // device does not exist or not ready
00665    }
00666 // OK, now send theData verifying ACK goes after each byte
00667    for (i=0;i<size;i++) {
00668       if(!xi2c_outbyte(theData[i])) {
00669          xi2c_stop();
00670          return ERR_I2C_NACK; // device failure
00671       }
00672    }
00673    if (nostop) xi2c_nostop();
00674    else xi2c_stop();
00675    return 0;
00676 }
00677 
00678 
00679 
00680 
00681 /*#---------------------------------------------------------------------------
00682 *#
00683 *# FUNCTION NAME: i2c_readData
00684 *#
00685 *# DESCRIPTION  : Reads a data from the i2c device, returns 0- OK, else - error code
00686 *#
00687 *#--------------------------------------------------------------------------*/
00688 
00689 int fi2c_readData(unsigned char theSlave, unsigned char *theData, int size) {
00690    int i, error=0;
00691    if ((error=xi2c_start())) return error;
00692    /* send slave address, wait for ack */
00693    D3(printk("i2c_readData:  theSlave=%x size=%x\r\n", theSlave, size));
00694    D(printk("readData:  %x %x\r\n", theSlave, size));
00695 
00696    if(!xi2c_outbyte(theSlave)) {
00697        xi2c_stop();
00698        return ERR_I2C_BSY; // device does not exist or not ready
00699    }
00700    for (i=0;i<size;i++) {
00701       theData[i]=xi2c_inbyte();
00702       xi2c_sendack();
00703    }
00704     xi2c_stop();
00705     return 0;
00706    
00707 }
00708 
00709 
00710 
00711 
00712 
00713 
00714 // for now - single register read/write only
00715 int fi2c_ioctl(struct inode *inode, struct file *file,
00716      unsigned int cmd, unsigned long arg) {
00717 //     unsigned char data[2];
00718      unsigned char data[10]; // for test purposes
00719 
00720      int error=0;
00721    D3(printk("i2c_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00722    D3(printk("i2c_ioctl:  ((int *)file->private_data)[0]= %x\n\r",((int *)file->private_data)[0]));
00723    if(_IOC_TYPE(cmd) !=FPGA_CLOCK_IOCTYPE) {
00724       return -EINVAL;
00725    }
00726 
00727    switch (_IOC_NR(cmd)) {
00728       case FPGA_CLOCK_I2C_WRITEREG:
00729 
00730          /* write to an i2c slave */
00731          D3(printk("i2cw slave=%d, reg=%d, value=%d\n", 
00732              (int) I2C_ARGSLAVE(arg),
00733              (int) I2C_ARGREG(arg),
00734              (int) I2C_ARGVALUE(arg)));
00735          data[0]=I2C_ARGREG(arg);
00736          data[1]=I2C_ARGVALUE(arg);
00737          return -fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 2,0); // stop at the end
00738       case FPGA_CLOCK_I2C_READREG:
00739       {
00740          /* read from an i2c slave */
00741          D3(printk("i2cr slave=%d, reg=%d ", 
00742              (int) I2C_ARGSLAVE(arg),
00743              (int) I2C_ARGREG(arg)));
00744 
00745          data[0]=I2C_ARGREG(arg);
00746          error=fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 1,1); // nostop at the end
00747          if (error) return -error;
00748 
00749 //         error=fi2c_readData(I2C_ARGSLAVE(arg) | 0x01, &data[1], 1);
00750          error=fi2c_readData(I2C_ARGSLAVE(arg) | 0x01, &data[1], 8); // just testing
00751          if (error) return -error;
00752          D3(printk("returned %d\n", data[1]));
00753 
00754          return data[1];
00755       }
00756       default:
00757          return -EINVAL;
00758 
00759    }
00760    return 0;
00761 }
00762 
00763 
00764 int setCYField (int addr, int mask, int value) {
00765     unsigned char data[2];
00766     int error;
00767     data[0]=addr;
00768     error=fi2c_writeData(CY223933_SA,       &data[0], 1, 1); // nostop
00769     if (error) return -error;
00770     error=fi2c_readData(CY223933_SA | 0x01, &data[1], 1);
00771     if (error) return -error;
00772     data[1]^=(data[1] ^ (unsigned long) value) & (unsigned long) mask;
00773     error=fi2c_writeData(CY223933_SA,       &data[0], 2, 0); // stop
00774     return error;
00775 }
00776 
00777 int getClockFreq(int nclock) {
00778   if ((nclock <0) || (nclock >3)) return -1; // bad clock number
00779   else return clock_frequency[nclock];
00780 }
00781 //TODO: add one more clock 
00782 int setClockFreq(int nclock, int freq) { // freq now in Hz
00783   t_pll_params  pll_params;
00784   int i,bp,bq,bdiv,pllc,fact;
00785   bp=0; bq=0; bdiv=0; pllc= 0; // just to make gcc happy
00786   fact=0;
00787   D5(printk("setClockFreq(%d,%d)\r\n",nclock,freq));
00788   if ((freq!=0) && (nclock!=3) ){
00789     if ( (i=calc_pll_params (freq, &pll_params)) !=0) {
00790       printk("bad frequency for clock %d - %d Hz, err=%d\n",nclock,freq,i);
00791       return -2;
00792     }
00793     fact=CY22393_SCALE*(CY22393_XTAL*(pll_params.p+6)/(pll_params.q+2)/pll_params.dv);
00794     bp=  pll_params.p;    // (freqtab[freq]>>20)&0x7ff;
00795     bq=  pll_params.q;    // (freqtab[freq]>>12)&0xff;
00796     bdiv=pll_params.dv;   // (freqtab[freq]>> 4)&0xff;
00797     pllc=pll_params.corr; // freqtab[freq]     &0x0f;
00798 
00799 //    printk ("fpgaclocks353.c::setClockFreq(clock=%d, freq=%d) bp=0x%x, bq=0x%x, bdiv=0x%x, pllc=0x%x\r\n", nclock, freq,bp,bq,bdiv,pllc);
00800   }
00801   switch (nclock) {
00802        case 0: 
00803           if (freq==0) {
00804             setCYField (0x16, 0x40, 0x00); // turn off pll3
00805             setCYField (0x09, 0x7f, 0x00); // turn off divider- A
00806             setCYField (0x08, 0x7f, 0x00); // turn off divider- A
00807           } else {
00808           setCYField (0x16, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00809           setCYField (0x15, 0xff, ((bp & 0x1fe)>>1) );
00810           setCYField (0x14, 0xff, bq );
00811           setCYField (0x09, 0x7f, bdiv); // set divider- A
00812           setCYField (0x08, 0x7f, bdiv); // set divider- A
00813           setCYField (0x0e, 0x03, 0x03); // set PLL3 as source for ClkA
00814           }
00815           fpga_state |= FPGA_STATE_CLOCKS;
00816           break;
00817        case 1:
00818           if (freq==0) {
00819             setCYField (0x0b, 0x7f, 0x00); // turn off divider- B
00820             setCYField (0x0a, 0x7f, 0x00); // turn off divider- B
00821             for (i=0;i<24;i+=3) setCYField (0x42+i, 0x40, 0x00); // turn off pll1
00822           } else {
00823 // progam all variants
00824             for (i=0;i<24;i+=3) {
00825               setCYField (0x42+i, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00826               setCYField (0x41+i, 0xff, ((bp & 0x1fe)>>1) );
00827               setCYField (0x40+i, 0xff, bq );
00828             }
00829             setCYField (0x0b, 0x7f, bdiv); // set divider- B
00830             setCYField (0x0a, 0x7f, bdiv); // set divider- B
00831             setCYField (0x0e, 0x0c, 0x04); // set PLL1 as source for ClkB
00832           }
00833           break;
00834        case 2:
00835           if (freq==0) {
00836             setCYField (0x13, 0x40, 0x00); // turn off pll2
00837             setCYField (0x0d, 0x7f, 0x00); // turn off divider- D
00838           } else {
00839             setCYField (0x13, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00840             setCYField (0x12, 0xff, ((bp & 0x1fe)>>1) );
00841             setCYField (0x11, 0xff, bq );
00842             setCYField (0x0d, 0x7f, bdiv); // set divider- D
00843             setCYField (0x0e, 0xc0, 0x80); // set PLL2 as source for ClkD
00844           }
00845           break;
00846        case 3: 
00847          if ((freq!=0) && (freq!=CY22393_SCALE*CY22393_XTAL)) {
00848             printk("Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\r\n",CY22393_SCALE*CY22393_XTAL);
00849             return -2;
00850           } else {
00851 //  int setCYField (int devfd, int addr, int mask, int value) O_RDWR
00852             if (freq==0) {
00853               setCYField (0x0f, 0x04, 0x00); 
00854             } else {
00855               setCYField (0x0f, 0x04, 0x04); 
00856               fact= CY22393_SCALE*CY22393_XTAL;
00857             }
00858           }
00859           break;
00860        default: return -1; // wrong clock number
00861   }
00862   D5(printk("nclock=%d fact=%d\n",nclock,fact));
00863   clock_frequency[nclock]=fact;
00864   return fact;
00865 }
00866 
00867 
00868 
00869 //==============================================================================================================
00870 
00871 //============================= driver interface =========================
00872 
00873 static int fpga_clock_open(struct inode *inode, struct file *filp) {
00874    int p;
00875    p = MINOR(inode->i_rdev);
00876    D(printk("fpga_clock_open: minor=%x\r\n",p) );
00877    D(printk("filp=%lx\r\n",(unsigned long)filp) );
00878    switch ( p ) {
00879      case FPGA_CLOCK_MINOR_I2C :
00880      case FPGA_CLOCK_MINOR_CLOCKS :
00881       {
00882          if (minors[p])  return -EACCES;
00883          break;
00884       }
00885      default: return -EINVAL;
00886    }
00887    minors[p]=p;
00888    filp->private_data = &minors[p];
00889    return 0;
00890 }
00891 
00892 static int fpga_clock_release(struct inode *inode, struct file *filp) {
00893    int p = MINOR(inode->i_rdev);
00894    D(printk("fpga_clock_release:  done\r\n"));
00895    minors[p]=0;
00896    return 0;
00897 }
00898 
00899 static int fpga_clock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {// switch by minor
00900 
00901    int res=0;
00902    D(printk("fpga_clock_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00903    D5(printk("fpga_clock_ioctl cmd= %x, arg= %x, _IOC_TYPE(cmd)=%x, nclock=%x\n\r",cmd,(int) arg, (int) _IOC_TYPE(cmd), (int) (_IOC_NR(cmd) & 7)));
00904 
00905      switch (((int *)filp->private_data)[0]) {
00906 
00907        case FPGA_CLOCK_MINOR_I2C : 
00908            {
00909              res=fi2c_ioctl (inode, filp, cmd, arg);
00910              return res;
00911            }
00912        case FPGA_CLOCK_MINOR_CLOCKS : 
00913            {
00914              if(_IOC_TYPE(cmd) ==FPGA_CLOCK_IOCTYPE_RD)   return getClockFreq(_IOC_NR(cmd) & 7);
00915              else if(_IOC_TYPE(cmd) !=FPGA_CLOCK_IOCTYPE) return -EINVAL;
00916              res=setClockFreq(_IOC_NR(cmd) & 7, arg); //clock number, value in Hz
00917              if (res<0) return -EINVAL;
00918              else return res; // actual frequency  
00919            }
00920      default:return -EINVAL;
00921      }
00922 }
00923 
00924 //
00925 
00926 static int __init fpga_clock_init(void) {
00927    int i,res;
00928    res = register_chrdev(FPGA_CLOCK_MAJOR, fpga_clock_name, &fpga_clock_fops);
00929    if(res < 0) {
00930      printk(KERN_ERR "\nfpga_clock_init: couldn't get a major number %d.\n", FPGA_CLOCK_MAJOR);
00931      return res;
00932    }
00933    printk(FPGA_CLOCK_DRIVER_NAME" - %d\n",FPGA_CLOCK_MAJOR);
00934    for (i=0;i<=FPGA_CLOCK_MAXMINOR;i++) minors[i]=0;
00935    initPortB();
00936 // Will initialize clocks in initscript
00937 //   setClockFreq(0, 125000000);
00938 //   setClockFreq(1,  20000000);
00939    fpga_state |= 0x10000; //mask 0xf0000
00940    return 0;
00941 }
00942 
00943 
00944 
00945 /* this makes sure that fpga_init is called during boot */
00946 
00947 module_init(fpga_clock_init);
00948 MODULE_LICENSE("GPL");
00949 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00950 MODULE_DESCRIPTION(FPGA_CLOCK_DRIVER_NAME);
00951 

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