00001
00002
00003
00004
00005
00006
00007 #include <linux/module.h>
00008 #include <linux/sched.h>
00009 #include <linux/slab.h>
00010 #include <linux/errno.h>
00011 #include <linux/kernel.h>
00012 #include <linux/fs.h>
00013 #include <linux/string.h>
00014 #include <linux/init.h>
00015 #include <linux/autoconf.h>
00016
00017 #include <asm/system.h>
00018 #include <asm/svinto.h>
00019 #include <asm/io.h>
00020
00021 #include <asm/irq.h>
00022
00023
00024
00025 #include <asm/delay.h>
00026 #include <asm/uaccess.h>
00027 #include <asm/fpgaconfa.h>
00028
00029 #include "fpgaconf.h"
00030 #include "fpgaconfi2c.h"
00031
00032 #define D(x)
00033
00034
00035 #define XCLOCK_LOW_TIME 8
00036 #define XCLOCK_HIGH_TIME 8
00037 #define XSTART_CONDITION_HOLD_TIME 8
00038 #define XSTOP_CONDITION_HOLD_TIME 8
00039 #define XENABLE_OUTPUT 0x01
00040 #define XENABLE_INPUT 0x00
00041 #define XI2C_CLOCK_HIGH 1
00042 #define XI2C_CLOCK_LOW 0
00043 #define XI2C_DATA_HIGH 1
00044 #define XI2C_DATA_LOW 0
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define xi2c_delay(usecs) udelay(usecs)
00064
00065 int xi2c_diagnose(void);
00066 int xi2c_start(void);
00067 void xi2c_stop(void);
00068 int xi2c_outbyte(unsigned char d);
00069 unsigned char xi2c_inbyte(void);
00070
00071 void xi2c_sendack(void);
00072 int setCYField (int addr, int mask, int value);
00073
00074
00075 static unsigned long portb_shadow=0x0000fe03;
00076 void initPortB(void) {
00077 *R_PORT_PB_SET=portb_shadow;
00078 }
00079
00080
00081
00082 #define xi2c_disable *R_PORT_PB_SET=(portb_shadow = 0x0203)
00083 #define xi2c_dir_out *R_PORT_PB_SET=(portb_shadow = 0x0303)
00084 #define xi2c_dir_in *R_PORT_PB_SET=(portb_shadow = 0x0203)
00085 #define xi2c_scl_0 *R_PORT_PB_SET=(portb_shadow &= 0x0301)
00086 #define xi2c_scl_1 *R_PORT_PB_SET=(portb_shadow |= 0x0002)
00087 #define xi2c_sda(x) *R_PORT_PB_SET=(portb_shadow = (portb_shadow & 0x0002) | 0x0300 | ((x)? 1:0));
00088 #define xi2c_getbit (*R_PORT_PB_READ & 1)
00089 #define xi2c_getscl ((*R_PORT_PB_READ >>1) & 1)
00090
00091
00092
00093 int xi2c_diagnose(void) {
00094 int error=0;
00095 D(printk("xi2c_diagnose\r\n"));
00096
00097 while (!error) {
00098 xi2c_dir_out;
00099 xi2c_delay(XCLOCK_HIGH_TIME);
00100 if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00101 if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00102 if (error) break;
00103 xi2c_scl_0;
00104 xi2c_sda (0);
00105 xi2c_delay(XCLOCK_LOW_TIME);
00106 if (!xi2c_getbit) error |= ERR_I2C_SDA_ST0;
00107 if (!xi2c_getscl) error |= ERR_I2C_SCL_ST0;
00108 if (error) break;
00109 xi2c_disable;
00110 xi2c_delay(XCLOCK_HIGH_TIME*2);
00111 if (!xi2c_getbit) error |= ERR_I2C_SDA_NOPULLUP;
00112 if (!xi2c_getscl) error |= ERR_I2C_SCL_NOPULLUP;
00113 if (error) break;
00114 xi2c_sda(0);
00115 if (!xi2c_getscl) error |= ERR_I2C_SHORT;
00116 break;
00117 }
00118 if (!error) error = ERR_I2C_NOTDETECTED;
00119
00120 xi2c_dir_out;
00121 xi2c_sda (0);
00122 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00123 xi2c_scl_0;
00124 xi2c_delay(XCLOCK_LOW_TIME*2);
00125 xi2c_scl_1;
00126 xi2c_delay(XCLOCK_HIGH_TIME*2);
00127 xi2c_sda (1);
00128 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00129 xi2c_disable;
00130
00131 return error;
00132 }
00133
00134
00135
00136 int xi2c_start(void) {
00137
00138 int i;
00139 D(printk("xi2c_start:\r\n"));
00140
00141 xi2c_dir_out;
00142 xi2c_delay(XCLOCK_HIGH_TIME/2);
00143
00144 xi2c_dir_in;
00145 xi2c_delay(XCLOCK_HIGH_TIME/2);
00146 if (!xi2c_getbit) {
00147 for (i=0;(i<9) && !xi2c_getbit;i++) {
00148 xi2c_scl_0;
00149 xi2c_delay(XCLOCK_LOW_TIME);
00150 xi2c_scl_1;
00151 xi2c_delay(XCLOCK_HIGH_TIME);
00152 }
00153 if (!xi2c_getbit) return xi2c_diagnose();
00154
00155 xi2c_sda (0);
00156 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00157 xi2c_scl_0;
00158 xi2c_delay(XCLOCK_LOW_TIME*2);
00159 xi2c_scl_1;
00160 xi2c_delay(XCLOCK_HIGH_TIME*2);
00161 xi2c_sda (1);
00162 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00163 }
00164
00165 xi2c_dir_out;
00166 xi2c_delay(XCLOCK_HIGH_TIME/2);
00167
00168 if ((!xi2c_getbit) || (!xi2c_getscl)) return xi2c_diagnose();
00169
00170 xi2c_sda(0);
00171 xi2c_delay(XSTART_CONDITION_HOLD_TIME);
00172 if (( xi2c_getbit) || (!xi2c_getscl)) return xi2c_diagnose();
00173
00174 xi2c_scl_0;
00175 xi2c_delay(XCLOCK_LOW_TIME);
00176 if (( xi2c_getbit) || ( xi2c_getscl)) return xi2c_diagnose();
00177 return 0;
00178 }
00179
00180
00181 void xi2c_stop(void) {
00182
00183 D(printk("xi2c_stop\r\n"));
00184
00185 xi2c_scl_0;
00186 xi2c_sda (0);
00187 xi2c_delay(XCLOCK_LOW_TIME*2);
00188
00189 xi2c_scl_1;
00190 xi2c_delay(XCLOCK_HIGH_TIME*2);
00191
00192 xi2c_sda (1);
00193 xi2c_delay(XSTOP_CONDITION_HOLD_TIME);
00194 xi2c_disable;
00195 }
00196
00197
00198 int xi2c_outbyte(unsigned char d) {
00199 int i;
00200 unsigned char x=d;
00201 D(printk("xi2c_outbyte: byte=%x\r\n", (int) x));
00202
00203 for (i = 0; i < 8; i++) {
00204 xi2c_sda (x & 0x80);
00205
00206 D(printk("%x ", (int) portb_shadow));
00207
00208 xi2c_delay(XCLOCK_LOW_TIME/2);
00209 xi2c_scl_1;
00210 xi2c_delay(XCLOCK_HIGH_TIME);
00211 xi2c_scl_0;
00212 xi2c_delay(XCLOCK_LOW_TIME/2);
00213 x <<= 1;
00214 }
00215 D(printk("\r\n"));
00216
00217
00218 xi2c_dir_in;
00219 xi2c_delay(XCLOCK_LOW_TIME/2);
00220 xi2c_scl_1;
00221 xi2c_delay(XCLOCK_HIGH_TIME);
00222 i= (1-xi2c_getbit);
00223 xi2c_scl_0;
00224 xi2c_delay(XCLOCK_LOW_TIME/2);
00225 D(printk("xi2c_outbyte: ACK=%x\r\n", i));
00226
00227
00228 return i;
00229 }
00230
00231
00232
00233 unsigned char xi2c_inbyte(void) {
00234 unsigned char aBitByte = 0;
00235 int i;
00236
00237 D(printk("xi2c_inbyte\r\n"));
00238
00239 xi2c_dir_in;
00240
00241 for (i = 0; i < 8; i++) {
00242 xi2c_delay(XCLOCK_LOW_TIME/2);
00243
00244 xi2c_scl_1;
00245 xi2c_delay(XCLOCK_HIGH_TIME);
00246 aBitByte = (aBitByte << 1) | xi2c_getbit;
00247 xi2c_scl_0;
00248 xi2c_delay(XCLOCK_LOW_TIME/2);
00249 }
00250 D(printk("xi2c_inbyte: data=%x\r\n", aBitByte));
00251 return aBitByte;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261 void xi2c_sendack(void) {
00262 D(printk("xi2c_sendack\r\n"));
00263
00264 xi2c_sda (0);
00265 xi2c_delay(XCLOCK_LOW_TIME/2);
00266 xi2c_scl_1;
00267 xi2c_delay(XCLOCK_HIGH_TIME);
00268 xi2c_scl_0;
00269 xi2c_delay(XCLOCK_LOW_TIME/2);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 int fi2c_writeData(unsigned char theSlave, unsigned char *theData, int size) {
00282 int i,error=0;
00283
00284 D(printk("i2c_writeData: theSlave=%x data=%x %x size=%x\r\n", theSlave, theData[0], theData[1], size));
00285
00286
00287 if ((error=xi2c_start())) return error;
00288
00289 if(!xi2c_outbyte(theSlave)) {
00290 xi2c_stop();
00291 return ERR_I2C_BSY;
00292 }
00293
00294 for (i=0;i<size;i++) {
00295 if(!xi2c_outbyte(theData[i])) {
00296 xi2c_stop();
00297 return ERR_I2C_NACK;
00298 }
00299 }
00300 xi2c_stop();
00301 return 0;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 int fi2c_readData(unsigned char theSlave, unsigned char *theData, int size) {
00313 int i, error=0;
00314 if ((error=xi2c_start())) return error;
00315
00316 D(printk("i2c_readData: theSlave=%x size=%x\r\n", theSlave, size));
00317
00318 if(!xi2c_outbyte(theSlave)) {
00319 xi2c_stop();
00320 return ERR_I2C_BSY;
00321 }
00322 for (i=0;i<size;i++) {
00323 theData[i]=xi2c_inbyte();
00324 xi2c_sendack();
00325 }
00326 xi2c_stop();
00327 return 0;
00328
00329 }
00330
00331
00332
00333
00334 int fi2c_ioctl(struct inode *inode, struct file *file,
00335 unsigned int cmd, unsigned long arg) {
00336 unsigned char data[2];
00337
00338
00339 int error=0;
00340 D(printk("i2c_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
00341 D(printk("i2c_ioctl: ((int *)file->private_data)[0]= %x\n\r",((int *)file->private_data)[0]));
00342 if(_IOC_TYPE(cmd) != FPGACONF_IOCTYPE) {
00343 return -EINVAL;
00344 }
00345
00346 switch (_IOC_NR(cmd)) {
00347 case I2C_WRITEREG:
00348
00349
00350 D(printk("i2cw slave=%d, reg=%d, value=%d\n",
00351 (int) I2C_ARGSLAVE(arg),
00352 (int) I2C_ARGREG(arg),
00353 (int) I2C_ARGVALUE(arg)));
00354 data[0]=I2C_ARGREG(arg);
00355 data[1]=I2C_ARGVALUE(arg);
00356 return -fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 2);
00357 case I2C_READREG:
00358 {
00359
00360 D(printk("i2cr slave=%d, reg=%d ",
00361 (int) I2C_ARGSLAVE(arg),
00362 (int) I2C_ARGREG(arg)));
00363
00364 data[0]=I2C_ARGREG(arg);
00365 error=fi2c_writeData(I2C_ARGSLAVE(arg) & 0xfe, &data[0], 1);
00366 if (error) return -error;
00367
00368 error=fi2c_readData(I2C_ARGSLAVE(arg) | 0x01, &data[1], 1);
00369 if (error) return -error;
00370 D(printk("returned %d\n", data[1]));
00371
00372 return data[1];
00373 }
00374 default:
00375 return -EINVAL;
00376
00377 }
00378
00379 return 0;
00380 }
00381
00382
00383
00384 #define CY223933_SA 0xd2
00385
00386 int setCYField (int addr, int mask, int value) {
00387 unsigned char data[2];
00388 int error;
00389 data[0]=addr;
00390 error=fi2c_writeData(CY223933_SA, &data[0], 1);
00391 if (error) return -error;
00392 error=fi2c_readData(CY223933_SA | 0x01, &data[1], 1);
00393 if (error) return -error;
00394 data[1]^=(data[1] ^ (unsigned long) value) & (unsigned long) mask;
00395 error=fi2c_writeData(CY223933_SA, &data[0], 2);
00396 return error;
00397 }
00398
00399
00400 int setClockFreq(int nclock, int freq) {
00401 int i,bp,bq,bdiv,pllc;
00402 const int freqtab[]=
00403 { 0x0, 0x1303640, 0x1303320, 0x2d08220, 0x1303190, 0x1303140, 0x2d08110, 0x24060f0,
00404 0x14030d0, 0x15030c0, 0x13030a0, 0x10020a0, 0x1503090, 0x1403080, 0x1603080, 0x2406070,
00405 0x1603070, 0x2d08060, 0x1503060, 0x3308060, 0x1303050, 0x2406050, 0x1002050, 0x1102050,
00406 0x1202050, 0x1303040, 0x1403040, 0x1503040, 0x1603040, 0x1703040, 0x1202040, 0x1903040,
00407 0x1a03040, 0x1b03040, 0x2d08030, 0x2406030, 0x1503030, 0x6912030, 0x3308030, 0x6f12030,
00408 0x1202030, 0x7512030, 0x3908030, 0x7b12030, 0x1b03030, 0x1502030, 0x3f08030, 0x8712030,
00409 0x1e03030, 0x8d12030, 0x1303020, 0x2d08020, 0x1403020, 0x2f08020, 0x1503020, 0x1002020,
00410 0x1603020, 0x3308020, 0x1703020, 0x3508020, 0x1202020, 0x3708020, 0x1903020, 0x3908020,
00411 0x1a03020, 0x1402020, 0x1b03020, 0x3d08020, 0x1c03020, 0x3f08020, 0x1602020, 0x4108020,
00412 0x1e03020, 0x4308020, 0x1f03020, 0x1802020, 0x2003020, 0x4708020, 0x2103020, 0x4908020,
00413 0x1201020, 0x4b08020, 0x2303020, 0x4d08020, 0x2403020, 0x1c02020, 0x2503020, 0x5108020,
00414 0x2603020, 0x5308020, 0x1501020, 0x5508020, 0x2803020, 0x5708020, 0x2903020, 0x2002020,
00415 0x2a03020, 0x5b08020, 0x2b03020, 0x5d08020, 0x1303010, 0x5f12010, 0x2d08010, 0x6112010,
00416 0x1403010, 0x2406010, 0x2f08010, 0x6512010, 0x1503010, 0x6712010, 0x1002010, 0x6912010,
00417 0x1603010, 0x6b12010, 0x3308010, 0x1102010, 0x1703010, 0x6f12010, 0x3508010, 0x7112010,
00418 0x1202010, 0x7312010, 0x3708010, 0x7512010, 0x1903010, 0x1302010, 0x3908010, 0x7912010};
00419 if ((freq<0) || (freq>127)) {printk("bad frequency for clock %d - %d MHz\n",nclock,freq);return -2;}
00420
00421 bp= (freqtab[freq]>>20)&0x7ff;
00422 bq= (freqtab[freq]>>12)&0xff;
00423 bdiv=(freqtab[freq]>> 4)&0xff;
00424 pllc= freqtab[freq] &0x0f;
00425 printk ("fpgaconfi2c.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);
00426 switch (nclock) {
00427 case 0: {
00428 if (freq==0) {
00429 setCYField (0x16, 0x40, 0x00);
00430 setCYField (0x09, 0x7f, 0x00);
00431 setCYField (0x08, 0x7f, 0x00);
00432 return 0;
00433 }
00434 setCYField (0x16, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00435 setCYField (0x15, 0xff, ((bp & 0x1fe)>>1) );
00436 setCYField (0x14, 0xff, bq );
00437 setCYField (0x09, 0x7f, bdiv);
00438 setCYField (0x08, 0x7f, bdiv);
00439 setCYField (0x0e, 0x03, 0x03);
00440 return 0;
00441 }
00442 case 1: {
00443 if (freq==0) {
00444 setCYField (0x0b, 0x7f, 0x00);
00445 setCYField (0x0a, 0x7f, 0x00);
00446 for (i=0;i<24;i+=3) setCYField (0x42+i, 0x40, 0x00);
00447 return 0;
00448 }
00449
00450 for (i=0;i<24;i+=3) {
00451 setCYField (0x42+i, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
00452 setCYField (0x41+i, 0xff, ((bp & 0x1fe)>>1) );
00453 setCYField (0x40+i, 0xff, bq );
00454 }
00455 setCYField (0x0b, 0x7f, bdiv);
00456 setCYField (0x0a, 0x7f, bdiv);
00457 setCYField (0x0e, 0x0c, 0x04);
00458 return 0;
00459 }
00460 default: return -1;
00461 }
00462 }
00463