00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <linux/autoconf.h>
00050
00051 #include <linux/module.h>
00052 #include <linux/sched.h>
00053 #include <linux/slab.h>
00054 #include <linux/ioport.h>
00055 #include <linux/errno.h>
00056 #include <linux/kernel.h>
00057 #include <linux/fs.h>
00058 #include <linux/string.h>
00059
00060 #include <linux/init.h>
00061
00062
00063
00064
00065
00066
00067
00068
00069 #include <asm/arch/hwregs/reg_map.h>
00070 #include <asm/arch/hwregs/reg_rdwr.h>
00071 #include <asm/arch/hwregs/gio_defs.h>
00072 #include <asm/arch/hwregs/intr_vect_defs.h>
00073 #include <asm/arch/hwregs/pinmux_defs.h>
00074
00075
00076 #include <asm/io.h>
00077 #include <asm/system.h>
00078 #include <asm/irq.h>
00079
00080
00081
00082 #include <asm/delay.h>
00083 #include <asm/uaccess.h>
00084
00085
00086 #include <asm/elphel/fpgaclocks.h>
00087
00088 #include "fpgactrl.h"
00089
00090 #define D(x)
00091
00092
00093 #define D1(x)
00094
00095
00096 #define D2(x)
00097
00098
00099 #define D3(x)
00100
00101
00102
00103
00104
00105
00106 #define D5(x)
00107
00108
00109
00110 #define FPGA_CLOCK_MAJOR 133
00111 #define FPGA_CLOCK_DRIVER_NAME "Elphel (R) model 353 system clocks (PLL frequency synth.) driver"
00112 #define FPGA_CLOCK_MAXMINOR 10
00113 #define FPGA_CLOCK_MINOR 2
00114
00115 #define FPGA_CLOCK_MINOR_I2C 2
00116 #define FPGA_CLOCK_MINOR_CLOCKS 3
00117
00118
00119
00120
00121
00122 #define XCLOCK_LOW_TIME 8
00123 #define XCLOCK_HIGH_TIME 8
00124 #define XSTART_CONDITION_HOLD_TIME 8
00125 #define XSTOP_CONDITION_HOLD_TIME 8
00126 #define XENABLE_OUTPUT 0x01
00127 #define XENABLE_INPUT 0x00
00128 #define XI2C_CLOCK_HIGH 1
00129 #define XI2C_CLOCK_LOW 0
00130 #define XI2C_DATA_HIGH 1
00131 #define XI2C_DATA_LOW 0
00132
00133
00134
00135
00136
00137
00138 #define xi2c_delay(usecs) udelay(usecs)
00139
00140 static int clock_frequency[4];
00141 typedef struct {
00142 unsigned int p : 11;
00143 unsigned int q : 8;
00144 unsigned int dv: 7;
00145 unsigned int corr: 3;
00146 unsigned int rslt: 3;
00147 } t_pll_params;
00148
00149
00150 int xi2c_diagnose(void);
00151 int xi2c_start(void);
00152 void xi2c_stop(void);
00153 void xi2c_nostop(void);
00154 int xi2c_outbyte(unsigned char d);
00155 unsigned char xi2c_inbyte(void);
00156 void xi2c_sendack(void);
00157 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size, int nostop);
00158 int fi2c_readData(unsigned char theSlave, unsigned char *theData, int size);
00159
00160 int fi2c_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
00161 int calc_pll_params (unsigned int f, t_pll_params * pars);
00162
00163 int setCYField (int addr, int mask, int value);
00164 int setClockFreq(int nclock, int freq);
00165
00166
00167 static const char fpga_clock_name[] = "fpga_clock_control";
00168 static int minors[FPGA_CLOCK_MAXMINOR+1];
00169 static int fpga_clock_open (struct inode *inode, struct file *filp);
00170 static int fpga_clock_release(struct inode *inode, struct file *filp);
00171 static int fpga_clock_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
00172 static int __init fpga_clock_init(void);
00173
00174
00175 static struct file_operations fpga_clock_fops = {
00176 owner: THIS_MODULE,
00177 open: fpga_clock_open,
00178 release: fpga_clock_release,
00179 ioctl: fpga_clock_ioctl,
00180 };
00181
00182
00183
00184
00185
00186 #define CY223933_SA 0xd2
00187
00188 #define CY22393_SCALE 100 // precision will be 100Hz
00189 #define CY22393_PLLMIN (100000000/CY22393_SCALE)
00190 #define CY22393_PLLMAX (400000000/CY22393_SCALE)
00191 #define CY22393_XTAL ( 12000000/CY22393_SCALE)
00192 #define CY22393_OUTMAX (166000000/CY22393_SCALE)
00193 #define CY22393_PMIN 16
00194 #define CY22393_PMAX 1600
00195
00196
00197 int calc_pll_params (unsigned int f, t_pll_params * pars) {
00198
00199 unsigned int f0= CY22393_XTAL;
00200 unsigned int f0_2= CY22393_XTAL/2;
00201 unsigned int fpmn= CY22393_XTAL * (CY22393_PMIN + 6);
00202 unsigned int fpmx= CY22393_XTAL * (CY22393_PMAX + 6);
00203 int divmn, divmx, err1,err, div,q,qmn,qmx,qmx1,fdv,p, e,fdvq;
00204 pars->rslt=3;
00205 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00206 f/=CY22393_SCALE;
00207 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00208 if (f>CY22393_OUTMAX) {
00209 pars->rslt=2;
00210 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00211 return pars->rslt;
00212 }
00213 if (f <=0 ) {
00214 pars->rslt=1;
00215 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00216 return pars->rslt;
00217 }
00218 divmx=CY22393_PLLMAX/f; if (divmx > 127) divmx=127;
00219 divmn=CY22393_PLLMIN/f; if (divmn < 1) divmn=1;
00220 if (divmn >127) {
00221 pars->rslt=1;
00222 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d, divmn=%d\r\n",f0,f,CY22393_OUTMAX,divmn));
00223 return pars->rslt;
00224 }
00225 err1=f;
00226 qmx1=0;
00227 for (div=divmn;div<=divmx;div++) {
00228 err=err1*div;
00229 fdv=f*div;
00230 qmn=fpmn/fdv-2; if (qmn < 0) qmn=0;
00231 qmx=fpmx/fdv-2; if (qmx >255) qmx=255;
00232
00233 D1(printk("div=%d,qmn=%d, qmx=%d\r\n",div,qmn,qmx));
00234 if (div==1) qmx1=qmx;
00235 else if ((qmn*div) < qmx1) qmn=qmx1/div;
00236 for (q=qmn+2;q<=qmx+2; q++) {
00237 fdvq=fdv*q;
00238 p= (fdvq+f0_2)/f0;
00239 e= fdvq-f0*p; if (e<0) e=-e;
00240 if (e< (err*q)) {
00241 pars->rslt=0;
00242 pars->p=p-6;
00243 pars->q=q-2;
00244 pars->dv=div;
00245 err1=e/q/div;
00246 err=err1*div;
00247 D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d\r\n", (f0*p)/q/div, div,p, q, err1));
00248 if (err1==0) {
00249 pars->corr=(pars->p<226)?0:((pars->p<621)?1:((pars->p<829)?2:((pars->p<1038)?3:4)));
00250 D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
00251 (f0*(pars->p+6))/(pars->q+2)/pars->dv,
00252 pars->dv,
00253 (pars->p+6),
00254 (pars->q+2),
00255 err1,
00256 pars->rslt));
00257 return pars->rslt;
00258 }
00259 }
00260 }
00261 }
00262 D1(printk("f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
00263 (f0*(pars->p+6))/(pars->q+2)/pars->dv,
00264 pars->dv,
00265 (pars->p+6),
00266 (pars->q+2),
00267 err1,
00268 pars->rslt));
00269 pars->corr=(pars->p<226)?0:((pars->p<621)?1:((pars->p<829)?2:((pars->p<1038)?3:4)));
00270 return pars->rslt;
00271 }
00272
00273
00274
00275
00276
00277
00278 int setCYField (int addr, int mask, int value);
00279
00280
00281
00282 #if 0
00283 inline void xi2c_disable(void){
00284 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00285 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00286 pb_dout.data |= 0x20000;
00287 pb_oe.oe &= ~0x10000;
00288 pb_oe.oe |= 0x20000;
00289 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00290 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00291 D2(printk("x"));
00292 };
00293 inline void xi2c_dir_out(void){
00294 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00295 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00296 pb_dout.data |= 0x20000;
00297 pb_dout.data &= ~0x10000;
00298 pb_oe.oe |= 0x30000;
00299 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00300 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00301 D2(printk(">"));
00302 };
00303 inline void xi2c_dir_in(void){
00304 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00305 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00306 pb_dout.data |= 0x20000;
00307 pb_dout.data &= ~0x10000;
00308 pb_oe.oe &= ~0x10000;
00309 pb_oe.oe |= 0x20000;
00310 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00311 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00312 D2(printk("<"));
00313 };
00314 inline void xi2c_scl_0(void){
00315 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00316 pb_dout.data &= ~0x20000;
00317 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00318 D2(printk("\\"));
00319 };
00320 inline void xi2c_scl_1(void){
00321 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00322 pb_dout.data |= 0x20000;
00323 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00324 D2(printk("/"));
00325 };
00326 inline void xi2c_sda(int x){
00327
00328
00329
00330
00331
00332
00333
00334
00335 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00336 if (x) pb_oe.oe &= ~0x10000;
00337 else pb_oe.oe |= ~0x10000;
00338
00339 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00340
00341 D2(printk("%d",x?1:0));
00342 };
00343 inline int xi2c_getbit(void){
00344 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'H':'L'));
00345 return (((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1;
00346 };
00347 inline int xi2c_getscl(void){
00348 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'+':'-'));
00349 return (((REG_RD(gio, regi_gio, r_pb_din)).data) >> 17) & 1;
00350 };
00351
00352
00353 #endif
00354
00355
00356 inline void xi2c_disable(void){
00357 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00358 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00359 pb_dout.data |= 0x30000;
00360 pb_oe.oe &= ~0x10000;
00361 pb_oe.oe |= 0x20000;
00362 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00363 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00364 D2(printk("x"));
00365 };
00366
00367 inline void xi2c_scl(int x){
00368 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00369 if (x) pb_dout.data |= 0x20000;
00370 else pb_dout.data &= ~0x20000;
00371 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00372 D2(if (x) printk("/"); else printk("\\"));
00373 }
00374
00375 inline void xi2c_sda (int x){
00376 reg_gio_rw_pb_dout pb_dout=REG_RD(gio, regi_gio, rw_pb_dout);
00377 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00378 if (x) {
00379 pb_dout.data |= 0x10000;
00380 pb_oe.oe |= 0x10000;
00381 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00382 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00383 pb_oe.oe &= ~0x10000;
00384 D2(printk("1"));
00385
00386 } else {
00387 pb_dout.data &= ~0x10000;
00388 pb_oe.oe |= 0x10000;
00389 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00390 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00391 D2(printk("0"));
00392 }
00393 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00394 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00395 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00396 }
00397
00398 inline int xi2c_getbit(void){
00399 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'H':'L'));
00400 return (((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1;
00401 };
00402 inline int xi2c_getscl(void){
00403 D2(printk("%c",(((REG_RD(gio, regi_gio, r_pb_din)).data)>>16) & 1?'+':'-'));
00404 return (((REG_RD(gio, regi_gio, r_pb_din)).data) >> 17) & 1;
00405 };
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void initPortB(void) {
00418
00419 unsigned long tmp;
00420 reg_pinmux_rw_pb_iop pinmux_b_iop;
00421 reg_pinmux_rw_pb_gio pinmux_b_gio;
00422
00423 pinmux_b_iop= REG_RD(pinmux, regi_pinmux, rw_pb_iop);
00424 tmp = REG_TYPE_CONV(unsigned long, reg_pinmux_rw_pb_iop, pinmux_b_iop);
00425 tmp &= ~0x030000;
00426 pinmux_b_iop = REG_TYPE_CONV(reg_pinmux_rw_pb_iop, unsigned long, tmp);
00427 REG_WR(pinmux, regi_pinmux, rw_pb_iop, pinmux_b_iop);
00428
00429 pinmux_b_gio= REG_RD(pinmux, regi_pinmux, rw_pb_gio);
00430 tmp = REG_TYPE_CONV(unsigned long, reg_pinmux_rw_pb_gio, pinmux_b_gio);
00431 tmp |= 0x030000;
00432 pinmux_b_gio = REG_TYPE_CONV(reg_pinmux_rw_pb_gio, unsigned long, tmp);
00433 REG_WR(pinmux, regi_pinmux, rw_pb_gio, pinmux_b_gio);
00434 xi2c_disable();
00435 }
00436
00437
00438
00439 int xi2c_diagnose(void) {
00440 int error=0;
00441 D(printk("diagnose\r\n"));
00442
00443 while (!error) {
00444 xi2c_disable();xi2c_sda (1);
00445 xi2c_delay(XCLOCK_HIGH_TIME);
00446 if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00447 if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00448 if (error) break;
00449 xi2c_scl (0);
00450 xi2c_sda (0);
00451 xi2c_delay(XCLOCK_LOW_TIME);
00452 if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00453 if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00454 if (error) break;
00455 xi2c_disable();
00456 xi2c_delay(XCLOCK_HIGH_TIME*2);
00457 if (!xi2c_getbit) error |= ERR_I2C_SDA_NOPULLUP;
00458 if (!xi2c_getscl) error |= ERR_I2C_SCL_NOPULLUP;
00459 if (error) break;
00460 xi2c_sda(0);
00461 if (!xi2c_getscl) error |= ERR_I2C_SHORT;
00462 break;
00463 }
00464 if (!error) error = ERR_I2C_NOTDETECTED;
00465
00466 xi2c_disable();
00467 xi2c_sda (0);
00468 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00469 xi2c_scl(0);
00470 xi2c_delay(XCLOCK_LOW_TIME*2);
00471 xi2c_scl(1);
00472 xi2c_delay(XCLOCK_HIGH_TIME*2);
00473 xi2c_sda (1);
00474 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00475 xi2c_disable();
00476 return error;
00477 }
00478
00479
00480
00481 int xi2c_start(void) {
00482
00483 int i;
00484 D(for(i=0;i<300;i++) udelay(1000); printk("start:\r\n"); for(i=0;i<300;i++) udelay(1000));
00485
00486 xi2c_disable();
00487 xi2c_delay(XCLOCK_HIGH_TIME/2);
00488
00489
00490 xi2c_delay(XCLOCK_HIGH_TIME/2);
00491 if (!xi2c_getbit()) {
00492 for (i=0;(i<9) && !xi2c_getbit();i++) {
00493 xi2c_scl(0);
00494 xi2c_delay(XCLOCK_LOW_TIME);
00495 xi2c_scl(1);
00496 xi2c_delay(XCLOCK_HIGH_TIME);
00497 }
00498 if (!xi2c_getbit) return xi2c_diagnose();
00499
00500 xi2c_sda (0);
00501 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00502 xi2c_scl(0);
00503 xi2c_delay(XCLOCK_LOW_TIME*2);
00504 xi2c_scl(1);
00505 xi2c_delay(XCLOCK_HIGH_TIME*2);
00506 xi2c_sda (1);
00507 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00508 }
00509
00510 xi2c_delay(XCLOCK_HIGH_TIME/2);
00511 if ((!xi2c_getbit()) || (!xi2c_getscl())) return xi2c_diagnose();
00512
00513 xi2c_sda(0);
00514 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00515 if (( xi2c_getbit()) || (!xi2c_getscl())) return xi2c_diagnose();
00516
00517 xi2c_scl(0);
00518 xi2c_delay(XCLOCK_LOW_TIME);
00519 if (( xi2c_getbit()) || ( xi2c_getscl())) return xi2c_diagnose();
00520 return 0;
00521 }
00522
00523
00524 void xi2c_stop(void) {
00525
00526 D(int i;)
00527 D( for (i=0;i<300;i++) udelay(1000); printk("stop:\r\n"); for(i=0;i<300;i++) udelay(1000));
00528
00529 xi2c_scl (0);
00530 xi2c_sda (0);
00531 xi2c_delay(XCLOCK_LOW_TIME*2);
00532
00533 xi2c_scl(1);
00534 xi2c_delay(XCLOCK_HIGH_TIME*2);
00535
00536 xi2c_sda (1);
00537 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00538
00539 }
00540
00541
00542 void xi2c_nostop(void) {
00543
00544 D(int i;)
00545 D( for (i=0;i<300;i++) udelay(1000); printk("nostop:\r\n"); for(i=0;i<300;i++) udelay(1000));
00546
00547 xi2c_scl (0);
00548 xi2c_sda (0);
00549 xi2c_delay(XCLOCK_LOW_TIME*2);
00550
00551 xi2c_sda (1);
00552 xi2c_delay(XCLOCK_HIGH_TIME*2);
00553
00554 xi2c_scl(1);
00555 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00556 xi2c_disable();
00557 }
00558
00559
00560
00561
00562
00563 int xi2c_outbyte(unsigned char d) {
00564 int i;
00565 unsigned char x=d;
00566 D(printk("outbyte: byte=%x\r\n", (int) x));
00567
00568 for (i = 0; i < 8; i++) {
00569 xi2c_sda (x & 0x80);
00570
00571
00572
00573 xi2c_delay(XCLOCK_LOW_TIME/2);
00574 xi2c_scl (1);
00575 xi2c_delay(XCLOCK_HIGH_TIME);
00576 xi2c_scl (0);
00577 xi2c_delay(XCLOCK_LOW_TIME/2);
00578 x <<= 1;
00579 }
00580 D(printk(" "));
00581
00582
00583
00584 xi2c_sda (1);
00585 xi2c_delay(XCLOCK_LOW_TIME/2);
00586 xi2c_scl (1);
00587 xi2c_delay(XCLOCK_HIGH_TIME);
00588 i= (1-xi2c_getbit());
00589 xi2c_scl (0);
00590 xi2c_delay(XCLOCK_LOW_TIME/2);
00591 D(printk("ACK=%x ", i));
00592
00593
00594 return i;
00595 }
00596
00597
00598
00599 unsigned char xi2c_inbyte(void) {
00600 unsigned char aBitByte = 0;
00601 int i;
00602
00603 D(printk("inbyte: "));
00604
00605
00606 xi2c_sda (1);
00607
00608 for (i = 0; i < 8; i++) {
00609 xi2c_delay(XCLOCK_LOW_TIME/2);
00610
00611 xi2c_scl (1);
00612 xi2c_delay(XCLOCK_HIGH_TIME);
00613 aBitByte = (aBitByte << 1) | xi2c_getbit();
00614 xi2c_scl (0);
00615 xi2c_delay(XCLOCK_LOW_TIME/2);
00616 }
00617 D(printk(" data=%x\r\n", aBitByte));
00618 return aBitByte;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628 void xi2c_sendack(void) {
00629 D(printk("sendack\r\n"));
00630
00631 xi2c_sda (0);
00632 xi2c_delay(XCLOCK_LOW_TIME/2);
00633 xi2c_scl (1);
00634 xi2c_delay(XCLOCK_HIGH_TIME);
00635 xi2c_scl (0);
00636 xi2c_delay(XCLOCK_LOW_TIME/2);
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size, int nostop) {
00649 int i,error=0;
00650
00651 D3(printk("i2c_writeData: theSlave=%x data=%x %x size=%x\r\n", theSlave, theData[0], theData[1], size));
00652 D(printk("writeData: %x %x %x %x\r\n", theSlave, theData[0], theData[1], size));
00653
00654
00655 if ((error=xi2c_start())) return error;
00656
00657 if(!xi2c_outbyte(theSlave)) {
00658 xi2c_stop();
00659 return ERR_I2C_BSY;
00660 }
00661
00662 for (i=0;i<size;i++) {
00663 if(!xi2c_outbyte(theData[i])) {
00664 xi2c_stop();
00665 return ERR_I2C_NACK;
00666 }
00667 }
00668 if (nostop) xi2c_nostop();
00669 else xi2c_stop();
00670 return 0;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 int fi2c_readData(unsigned char theSlave, unsigned char *theData, int size) {
00685 int i, error=0;
00686 if ((error=xi2c_start())) return error;
00687
00688 D3(printk("i2c_readData: theSlave=%x size=%x\r\n", theSlave, size));
00689 D(printk("readData: %x %x\r\n", theSlave, size));
00690
00691 if(!xi2c_outbyte(theSlave)) {
00692 xi2c_stop();
00693 return ERR_I2C_BSY;
00694 }
00695 for (i=0;i<size;i++) {
00696 theData[i]=xi2c_inbyte();
00697 xi2c_sendack();
00698 }
00699 xi2c_stop();
00700 return 0;
00701
00702 }
00703
00704
00705
00706
00707
00708
00709
00710 int fi2c_ioctl(struct inode *inode, struct file *file,
00711 unsigned int cmd, unsigned long arg) {
00712
00713 unsigned char data[10];
00714
00715 int error=0;
00716 D3(printk("i2c_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00717 D3(printk("i2c_ioctl: ((int *)file->private_data)[0]= %x\n\r",((int *)file->private_data)[0]));
00718 if(_IOC_TYPE(cmd) !=FPGA_CLOCK_IOCTYPE) {
00719 return -EINVAL;
00720 }
00721
00722 switch (_IOC_NR(cmd)) {
00723 case FPGA_CLOCK_I2C_WRITEREG:
00724
00725
00726 D3(printk("i2cw slave=%d, reg=%d, value=%d\n",
00727 (int) I2C_ARGSLAVE(arg),
00728 (int) I2C_ARGREG(arg),
00729 (int) I2C_ARGVALUE(arg)));
00730 data[0]=I2C_ARGREG(arg);
00731 data[1]=I2C_ARGVALUE(arg);
00732 return -fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 2,0);
00733 case FPGA_CLOCK_I2C_READREG:
00734 {
00735
00736 D3(printk("i2cr slave=%d, reg=%d ",
00737 (int) I2C_ARGSLAVE(arg),
00738 (int) I2C_ARGREG(arg)));
00739
00740 data[0]=I2C_ARGREG(arg);
00741 error=fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 1,1);
00742 if (error) return -error;
00743
00744
00745 error=fi2c_readData(I2C_ARGSLAVE(arg) | 0x01, &data[1], 8);
00746 if (error) return -error;
00747 D3(printk("returned %d\n", data[1]));
00748
00749 return data[1];
00750 }
00751 default:
00752 return -EINVAL;
00753
00754 }
00755 return 0;
00756 }
00757
00758
00759 int setCYField (int addr, int mask, int value) {
00760 unsigned char data[2];
00761 int error;
00762 data[0]=addr;
00763 error=fi2c_writeData(CY223933_SA, &data[0], 1, 1);
00764 if (error) return -error;
00765 error=fi2c_readData(CY223933_SA | 0x01, &data[1], 1);
00766 if (error) return -error;
00767 data[1]^=(data[1] ^ (unsigned long) value) & (unsigned long) mask;
00768 error=fi2c_writeData(CY223933_SA, &data[0], 2, 0);
00769 return error;
00770 }
00771
00772 int getClockFreq(int nclock) {
00773 if ((nclock <0) || (nclock >3)) return -1;
00774 else return clock_frequency[nclock];
00775 }
00776
00777 int setClockFreq(int nclock, int freq) {
00778 t_pll_params pll_params;
00779 int i,bp,bq,bdiv,pllc,fact;
00780 bp=0; bq=0; bdiv=0; pllc= 0;
00781 fact=0;
00782 D5(printk("setClockFreq(%d,%d)\r\n",nclock,freq));
00783 if ((freq!=0) && (nclock!=3) ){
00784 if ( (i=calc_pll_params (freq, &pll_params)) !=0) {
00785 printk("bad frequency for clock %d - %d Hz, err=%d\n",nclock,freq,i);
00786 return -2;
00787 }
00788 fact=CY22393_SCALE*(CY22393_XTAL*(pll_params.p+6)/(pll_params.q+2)/pll_params.dv);
00789 bp= pll_params.p;
00790 bq= pll_params.q;
00791 bdiv=pll_params.dv;
00792 pllc=pll_params.corr;
00793
00794
00795 }
00796 switch (nclock) {
00797 case 0: {
00798 if (freq==0) {
00799 setCYField (0x16, 0x40, 0x00);
00800 setCYField (0x09, 0x7f, 0x00);
00801 setCYField (0x08, 0x7f, 0x00);
00802 } else {
00803 setCYField (0x16, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00804 setCYField (0x15, 0xff, ((bp & 0x1fe)>>1) );
00805 setCYField (0x14, 0xff, bq );
00806 setCYField (0x09, 0x7f, bdiv);
00807 setCYField (0x08, 0x7f, bdiv);
00808 setCYField (0x0e, 0x03, 0x03);
00809 }
00810 break;
00811 }
00812 case 1: {
00813 if (freq==0) {
00814 setCYField (0x0b, 0x7f, 0x00);
00815 setCYField (0x0a, 0x7f, 0x00);
00816 for (i=0;i<24;i+=3) setCYField (0x42+i, 0x40, 0x00);
00817 } else {
00818
00819 for (i=0;i<24;i+=3) {
00820 setCYField (0x42+i, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00821 setCYField (0x41+i, 0xff, ((bp & 0x1fe)>>1) );
00822 setCYField (0x40+i, 0xff, bq );
00823 }
00824 setCYField (0x0b, 0x7f, bdiv);
00825 setCYField (0x0a, 0x7f, bdiv);
00826 setCYField (0x0e, 0x0c, 0x04);
00827 }
00828 break;
00829 }
00830 case 2: {
00831 if (freq==0) {
00832 setCYField (0x13, 0x40, 0x00);
00833 setCYField (0x0d, 0x7f, 0x00);
00834 } else {
00835 setCYField (0x13, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00836 setCYField (0x12, 0xff, ((bp & 0x1fe)>>1) );
00837 setCYField (0x11, 0xff, bq );
00838 setCYField (0x0d, 0x7f, bdiv);
00839 setCYField (0x0e, 0xc0, 0x80);
00840 }
00841 break;
00842 }
00843
00844 case 3: {
00845 if ((freq!=0) && (freq!=CY22393_SCALE*CY22393_XTAL)) {
00846 printk("Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\r\n",CY22393_SCALE*CY22393_XTAL);
00847 return -2;
00848 } else {
00849
00850 if (freq==0) {
00851 setCYField (0x0f, 0x04, 0x00);
00852 } else {
00853 setCYField (0x0f, 0x04, 0x04);
00854 fact= CY22393_SCALE*CY22393_XTAL;
00855 }
00856 }
00857 break;
00858 }
00859 default: return -1;
00860 }
00861 D5(printk("nclock=%d fact=%d\n",nclock,fact));
00862 clock_frequency[nclock]=fact;
00863 return fact;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 static int fpga_clock_open(struct inode *inode, struct file *filp) {
00873 int p;
00874 p = MINOR(inode->i_rdev);
00875 D(printk("fpga_clock_open: minor=%x\r\n",p) );
00876 D(printk("filp=%lx\r\n",(unsigned long)filp) );
00877 switch ( p ) {
00878 case FPGA_CLOCK_MINOR_I2C :
00879 case FPGA_CLOCK_MINOR_CLOCKS :
00880 {
00881 if (minors[p]) return -EACCES;
00882 break;
00883 }
00884 default: return -EINVAL;
00885 }
00886 minors[p]=p;
00887 filp->private_data = &minors[p];
00888 return 0;
00889 }
00890
00891 static int fpga_clock_release(struct inode *inode, struct file *filp) {
00892 int p = MINOR(inode->i_rdev);
00893 D(printk("fpga_clock_release: done\r\n"));
00894 minors[p]=0;
00895 return 0;
00896 }
00897
00898 static int fpga_clock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {
00899
00900 int res=0;
00901 D(printk("fpga_clock_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00902 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)));
00903
00904 switch (((int *)filp->private_data)[0]) {
00905
00906 case FPGA_CLOCK_MINOR_I2C :
00907 {
00908 res=fi2c_ioctl (inode, filp, cmd, arg);
00909 return res;
00910 }
00911 case FPGA_CLOCK_MINOR_CLOCKS :
00912 {
00913 if(_IOC_TYPE(cmd) ==FPGA_CLOCK_IOCTYPE_RD) return getClockFreq(_IOC_NR(cmd) & 7);
00914 else if(_IOC_TYPE(cmd) !=FPGA_CLOCK_IOCTYPE) return -EINVAL;
00915 res=setClockFreq(_IOC_NR(cmd) & 7, arg);
00916 if (res<0) return -EINVAL;
00917 else return res;
00918 }
00919 default:return -EINVAL;
00920 }
00921 }
00922
00923
00924
00925 static int __init fpga_clock_init(void) {
00926 int i,res;
00927 res = register_chrdev(FPGA_CLOCK_MAJOR, fpga_clock_name, &fpga_clock_fops);
00928 if(res < 0) {
00929 printk(KERN_ERR "fpga_clock_init: couldn't get a major number.\n");
00930 return res;
00931 }
00932 printk(FPGA_CLOCK_DRIVER_NAME"\r\n");
00933 for (i=0;i<=FPGA_CLOCK_MAXMINOR;i++) minors[i]=0;
00934 initPortB();
00935
00936
00937
00938 fpga_state |= 0x10000;
00939 return 0;
00940 }
00941
00942
00943
00944
00945
00946 module_init(fpga_clock_init);
00947 MODULE_LICENSE("GPL");
00948 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00949 MODULE_DESCRIPTION(FPGA_CLOCK_DRIVER_NAME);
00950