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
00050
00051
00052
00053
00054
00055
00056
00057
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>
00064 #include <linux/errno.h>
00065 #include <linux/kernel.h>
00066 #include <linux/fs.h>
00067 #include <linux/string.h>
00068
00069 #include <linux/init.h>
00070
00071
00072
00073
00074
00075
00076
00077
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"
00099
00100 #define D(x)
00101
00102
00103 #define D1(x)
00104
00105
00106 #define D2(x)
00107
00108
00109 #define D3(x)
00110
00111
00112
00113
00114
00115
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
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
00139
00140
00141
00142
00143 #define xi2c_delay(usecs) udelay(usecs)
00144
00145 static int clock_frequency[4];
00146 typedef struct {
00147 unsigned int p : 11;
00148 unsigned int q : 8;
00149 unsigned int dv: 7;
00150 unsigned int corr: 3;
00151 unsigned int rslt: 3;
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);
00167
00168 int setCYField (int addr, int mask, int value);
00169 int setClockFreq(int nclock, int freq);
00170
00171
00172 static const char fpga_clock_name[] = "fpga_clock_control";
00173 static int minors[FPGA_CLOCK_MAXMINOR+1];
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
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) {
00203
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;
00210 D(printk("f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX));
00211 f/=CY22393_SCALE;
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;
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
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;
00244 e= fdvq-f0*p; if (e<0) e=-e;
00245 if (e< (err*q)) {
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
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;
00293 pb_oe.oe |= 0x20000;
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 };
00298 inline void xi2c_dir_out(void){
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;
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 };
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;
00314 pb_oe.oe |= 0x20000;
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 };
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 };
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 };
00331 inline void xi2c_sda(int x){
00332
00333
00334
00335
00336
00337
00338
00339
00340 reg_gio_rw_pb_oe pb_oe = REG_RD(gio, regi_gio, rw_pb_oe);
00341 if (x) pb_oe.oe &= ~0x10000;
00342 else pb_oe.oe |= ~0x10000;
00343
00344 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
00345
00346 D2(printk("%d",x?1:0));
00347 };
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 };
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 };
00356
00357
00358 #endif
00359
00360
00361 inline void xi2c_disable(void){
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;
00366 pb_oe.oe |= 0x20000;
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){
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){
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;
00385 pb_oe.oe |= 0x10000;
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;
00389 D2(printk("1"));
00390
00391 } else {
00392 pb_dout.data &= ~0x10000;
00393 pb_oe.oe |= 0x10000;
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);
00399 REG_WR(gio, regi_gio, rw_pb_dout, pb_dout);
00400 REG_WR(gio, regi_gio, rw_pb_oe, pb_oe);
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 };
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 };
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 void initPortB(void) {
00423
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
00443
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);
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();
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);
00466 if (!xi2c_getscl) error |= ERR_I2C_SHORT;
00467 break;
00468 }
00469 if (!error) error = ERR_I2C_NOTDETECTED;
00470
00471 xi2c_disable();
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
00485
00486 int xi2c_start(void) {
00487
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
00491 xi2c_disable();
00492 xi2c_delay(XCLOCK_HIGH_TIME/2);
00493
00494
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();
00504
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
00515 xi2c_delay(XCLOCK_HIGH_TIME/2);
00516 if ((!xi2c_getbit()) || (!xi2c_getscl())) return xi2c_diagnose();
00517
00518 xi2c_sda(0);
00519 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00520 if (( xi2c_getbit()) || (!xi2c_getscl())) return xi2c_diagnose();
00521
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
00529 void xi2c_stop(void) {
00530
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
00538 xi2c_scl(1);
00539 xi2c_delay(XCLOCK_HIGH_TIME*2);
00540
00541 xi2c_sda (1);
00542 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00543
00544 }
00545
00546
00547 void xi2c_nostop(void) {
00548
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
00556 xi2c_sda (1);
00557 xi2c_delay(XCLOCK_HIGH_TIME*2);
00558
00559 xi2c_scl(1);
00560 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00561 xi2c_disable();
00562 }
00563
00564
00565
00566
00567
00568 int xi2c_outbyte(unsigned char d) {
00569 int i;
00570 unsigned char x=d;
00571 D(printk("outbyte: byte=%x\r\n", (int) x));
00572
00573 for (i = 0; i < 8; i++) {
00574 xi2c_sda (x & 0x80);
00575
00576
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
00588
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
00603
00604 unsigned char xi2c_inbyte(void) {
00605 unsigned char aBitByte = 0;
00606 int i;
00607
00608 D(printk("inbyte: "));
00609
00610
00611 xi2c_sda (1);
00612
00613 for (i = 0; i < 8; i++) {
00614 xi2c_delay(XCLOCK_LOW_TIME/2);
00615
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;
00624 }
00625
00626
00627
00628
00629
00630
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
00647
00648
00649
00650
00651
00652
00653 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size, int nostop) {
00654 int i,error=0;
00655
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
00660 if ((error=xi2c_start())) return error;
00661
00662 if(!xi2c_outbyte(theSlave)) {
00663 xi2c_stop();
00664 return ERR_I2C_BSY;
00665 }
00666
00667 for (i=0;i<size;i++) {
00668 if(!xi2c_outbyte(theData[i])) {
00669 xi2c_stop();
00670 return ERR_I2C_NACK;
00671 }
00672 }
00673 if (nostop) xi2c_nostop();
00674 else xi2c_stop();
00675 return 0;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
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
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;
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
00715 int fi2c_ioctl(struct inode *inode, struct file *file,
00716 unsigned int cmd, unsigned long arg) {
00717
00718 unsigned char data[10];
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
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);
00738 case FPGA_CLOCK_I2C_READREG:
00739 {
00740
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);
00747 if (error) return -error;
00748
00749
00750 error=fi2c_readData(I2C_ARGSLAVE(arg) | 0x01, &data[1], 8);
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);
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);
00774 return error;
00775 }
00776
00777 int getClockFreq(int nclock) {
00778 if ((nclock <0) || (nclock >3)) return -1;
00779 else return clock_frequency[nclock];
00780 }
00781
00782 int setClockFreq(int nclock, int freq) {
00783 t_pll_params pll_params;
00784 int i,bp,bq,bdiv,pllc,fact;
00785 bp=0; bq=0; bdiv=0; pllc= 0;
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;
00795 bq= pll_params.q;
00796 bdiv=pll_params.dv;
00797 pllc=pll_params.corr;
00798
00799
00800 }
00801 switch (nclock) {
00802 case 0:
00803 if (freq==0) {
00804 setCYField (0x16, 0x40, 0x00);
00805 setCYField (0x09, 0x7f, 0x00);
00806 setCYField (0x08, 0x7f, 0x00);
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);
00812 setCYField (0x08, 0x7f, bdiv);
00813 setCYField (0x0e, 0x03, 0x03);
00814 }
00815 fpga_state |= FPGA_STATE_CLOCKS;
00816 break;
00817 case 1:
00818 if (freq==0) {
00819 setCYField (0x0b, 0x7f, 0x00);
00820 setCYField (0x0a, 0x7f, 0x00);
00821 for (i=0;i<24;i+=3) setCYField (0x42+i, 0x40, 0x00);
00822 } else {
00823
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);
00830 setCYField (0x0a, 0x7f, bdiv);
00831 setCYField (0x0e, 0x0c, 0x04);
00832 }
00833 break;
00834 case 2:
00835 if (freq==0) {
00836 setCYField (0x13, 0x40, 0x00);
00837 setCYField (0x0d, 0x7f, 0x00);
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);
00843 setCYField (0x0e, 0xc0, 0x80);
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
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;
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
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) {
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);
00917 if (res<0) return -EINVAL;
00918 else return res;
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
00937
00938
00939 fpga_state |= 0x10000;
00940 return 0;
00941 }
00942
00943
00944
00945
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