1 /******************************************************************* 2 * 3 * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) 4 * 5 * All rights are reserved. Reproduction or in part is prohibited 6 * without the written consent of the copyright owner. 7 * 8 * swi2c.c --- SM750/SM718 DDK 9 * This file contains the source code for I2C using software 10 * implementation. 11 * 12 *******************************************************************/ 13 #include "ddk750_help.h" 14 #include "ddk750_reg.h" 15 #include "ddk750_swi2c.h" 16 #include "ddk750_power.h" 17 18 19 /******************************************************************* 20 * I2C Software Master Driver: 21 * =========================== 22 * Each i2c cycle is split into 4 sections. Each of these section marks 23 * a point in time where the SCL or SDA may be changed. 24 * 25 * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. | 26 * +-------------+-------------+-------------+-------------+ 27 * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| 28 * 29 * ____________ _____________ 30 * SCL == XXXX _____________ ____________ / 31 * 32 * I.e. the SCL may only be changed in section 1. and section 3. while 33 * the SDA may only be changed in section 2. and section 4. The table 34 * below gives the changes for these 2 lines in the varios sections. 35 * 36 * Section changes Table: 37 * ====================== 38 * blank = no change, L = set bit LOW, H = set bit HIGH 39 * 40 * | 1.| 2.| 3.| 4.| 41 * ---------------+---+---+---+---+ 42 * Tx Start SDA | | H | | L | 43 * SCL | L | | H | | 44 * ---------------+---+---+---+---+ 45 * Tx Stop SDA | | L | | H | 46 * SCL | L | | H | | 47 * ---------------+---+---+---+---+ 48 * Tx bit H SDA | | H | | | 49 * SCL | L | | H | | 50 * ---------------+---+---+---+---+ 51 * Tx bit L SDA | | L | | | 52 * SCL | L | | H | | 53 * ---------------+---+---+---+---+ 54 * 55 ******************************************************************/ 56 57 /* GPIO pins used for this I2C. It ranges from 0 to 63. */ 58 static unsigned char g_i2cClockGPIO = DEFAULT_I2C_SCL; 59 static unsigned char g_i2cDataGPIO = DEFAULT_I2C_SDA; 60 61 /* 62 * Below is the variable declaration for the GPIO pin register usage 63 * for the i2c Clock and i2c Data. 64 * 65 * Note: 66 * Notice that the GPIO usage for the i2c clock and i2c Data are 67 * separated. This is to make this code flexible enough when 68 * two separate GPIO pins for the clock and data are located 69 * in two different GPIO register set (worst case). 70 */ 71 72 /* i2c Clock GPIO Register usage */ 73 static unsigned long g_i2cClkGPIOMuxReg = GPIO_MUX; 74 static unsigned long g_i2cClkGPIODataReg = GPIO_DATA; 75 static unsigned long g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; 76 77 /* i2c Data GPIO Register usage */ 78 static unsigned long g_i2cDataGPIOMuxReg = GPIO_MUX; 79 static unsigned long g_i2cDataGPIODataReg = GPIO_DATA; 80 static unsigned long g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; 81 82 static unsigned char peekIO(unsigned short port,unsigned short index) 83 { 84 #if defined(__i386__) || defined( __x86_64__) 85 outb_p(index,port); 86 return inb_p(port+1); 87 #endif 88 } 89 90 /* 91 * This function puts a delay between command 92 */ 93 static void swI2CWait(void) 94 { 95 /* find a bug: 96 * peekIO method works well before suspend/resume 97 * but after suspend, peekIO(0x3ce,0x61) & 0x10 98 * always be non-zero,which makes the while loop 99 * never finish. 100 * use non-ultimate for loop below is safe 101 * */ 102 #if 0 103 /* Change wait algorithm to use PCI bus clock, 104 it's more reliable than counter loop .. 105 write 0x61 to 0x3ce and read from 0x3cf 106 */ 107 while(peekIO(0x3ce,0x61) & 0x10); 108 #else 109 int i, Temp; 110 111 for(i=0; i<600; i++) 112 { 113 Temp = i; 114 Temp += i; 115 } 116 #endif 117 } 118 119 /* 120 * This function set/reset the SCL GPIO pin 121 * 122 * Parameters: 123 * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 124 * 125 * Notes: 126 * When setting SCL to high, just set the GPIO as input where the pull up 127 * resistor will pull the signal up. Do not use software to pull up the 128 * signal because the i2c will fail when other device try to drive the 129 * signal due to SM50x will drive the signal to always high. 130 */ 131 void swI2CSCL(unsigned char value) 132 { 133 unsigned long ulGPIOData; 134 unsigned long ulGPIODirection; 135 136 ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg); 137 if (value) /* High */ 138 { 139 /* Set direction as input. This will automatically pull the signal up. */ 140 ulGPIODirection &= ~(1 << g_i2cClockGPIO); 141 POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); 142 } 143 else /* Low */ 144 { 145 /* Set the signal down */ 146 ulGPIOData = PEEK32(g_i2cClkGPIODataReg); 147 ulGPIOData &= ~(1 << g_i2cClockGPIO); 148 POKE32(g_i2cClkGPIODataReg, ulGPIOData); 149 150 /* Set direction as output */ 151 ulGPIODirection |= (1 << g_i2cClockGPIO); 152 POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); 153 } 154 } 155 156 /* 157 * This function set/reset the SDA GPIO pin 158 * 159 * Parameters: 160 * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 161 * 162 * Notes: 163 * When setting SCL to high, just set the GPIO as input where the pull up 164 * resistor will pull the signal up. Do not use software to pull up the 165 * signal because the i2c will fail when other device try to drive the 166 * signal due to SM50x will drive the signal to always high. 167 */ 168 void swI2CSDA(unsigned char value) 169 { 170 unsigned long ulGPIOData; 171 unsigned long ulGPIODirection; 172 173 ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); 174 if (value) /* High */ 175 { 176 /* Set direction as input. This will automatically pull the signal up. */ 177 ulGPIODirection &= ~(1 << g_i2cDataGPIO); 178 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 179 } 180 else /* Low */ 181 { 182 /* Set the signal down */ 183 ulGPIOData = PEEK32(g_i2cDataGPIODataReg); 184 ulGPIOData &= ~(1 << g_i2cDataGPIO); 185 POKE32(g_i2cDataGPIODataReg, ulGPIOData); 186 187 /* Set direction as output */ 188 ulGPIODirection |= (1 << g_i2cDataGPIO); 189 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 190 } 191 } 192 193 /* 194 * This function read the data from the SDA GPIO pin 195 * 196 * Return Value: 197 * The SDA data bit sent by the Slave 198 */ 199 static unsigned char swI2CReadSDA(void) 200 { 201 unsigned long ulGPIODirection; 202 unsigned long ulGPIOData; 203 204 /* Make sure that the direction is input (High) */ 205 ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); 206 if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO))) 207 { 208 ulGPIODirection &= ~(1 << g_i2cDataGPIO); 209 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 210 } 211 212 /* Now read the SDA line */ 213 ulGPIOData = PEEK32(g_i2cDataGPIODataReg); 214 if (ulGPIOData & (1 << g_i2cDataGPIO)) 215 return 1; 216 else 217 return 0; 218 } 219 220 #pragma optimize( "", off ) 221 222 /* 223 * This function sends ACK signal 224 */ 225 static void swI2CAck(void) 226 { 227 return; /* Single byte read is ok without it. */ 228 } 229 230 /* 231 * This function sends the start command to the slave device 232 */ 233 void swI2CStart(void) 234 { 235 /* Start I2C */ 236 swI2CSDA(1); 237 swI2CSCL(1); 238 swI2CSDA(0); 239 } 240 241 /* 242 * This function sends the stop command to the slave device 243 */ 244 void swI2CStop(void) 245 { 246 /* Stop the I2C */ 247 swI2CSCL(1); 248 swI2CSDA(0); 249 swI2CSDA(1); 250 } 251 252 /* 253 * This function writes one byte to the slave device 254 * 255 * Parameters: 256 * data - Data to be write to the slave device 257 * 258 * Return Value: 259 * 0 - Success 260 * -1 - Fail to write byte 261 */ 262 long swI2CWriteByte(unsigned char data) 263 { 264 unsigned char value = data; 265 int i; 266 267 /* Sending the data bit by bit */ 268 for (i=0; i<8; i++) 269 { 270 /* Set SCL to low */ 271 swI2CSCL(0); 272 273 /* Send data bit */ 274 if ((value & 0x80) != 0) 275 swI2CSDA(1); 276 else 277 swI2CSDA(0); 278 279 swI2CWait(); 280 281 /* Toggle clk line to one */ 282 swI2CSCL(1); 283 swI2CWait(); 284 285 /* Shift byte to be sent */ 286 value = value << 1; 287 } 288 289 /* Set the SCL Low and SDA High (prepare to get input) */ 290 swI2CSCL(0); 291 swI2CSDA(1); 292 293 /* Set the SCL High for ack */ 294 swI2CWait(); 295 swI2CSCL(1); 296 swI2CWait(); 297 298 /* Read SDA, until SDA==0 */ 299 for(i=0; i<0xff; i++) 300 { 301 if (!swI2CReadSDA()) 302 break; 303 304 swI2CSCL(0); 305 swI2CWait(); 306 swI2CSCL(1); 307 swI2CWait(); 308 } 309 310 /* Set the SCL Low and SDA High */ 311 swI2CSCL(0); 312 swI2CSDA(1); 313 314 if (i<0xff) 315 return 0; 316 else 317 return (-1); 318 } 319 320 /* 321 * This function reads one byte from the slave device 322 * 323 * Parameters: 324 * ack - Flag to indicate either to send the acknowledge 325 * message to the slave device or not 326 * 327 * Return Value: 328 * One byte data read from the Slave device 329 */ 330 unsigned char swI2CReadByte(unsigned char ack) 331 { 332 int i; 333 unsigned char data = 0; 334 335 for(i=7; i>=0; i--) 336 { 337 /* Set the SCL to Low and SDA to High (Input) */ 338 swI2CSCL(0); 339 swI2CSDA(1); 340 swI2CWait(); 341 342 /* Set the SCL High */ 343 swI2CSCL(1); 344 swI2CWait(); 345 346 /* Read data bits from SDA */ 347 data |= (swI2CReadSDA() << i); 348 } 349 350 if (ack) 351 swI2CAck(); 352 353 /* Set the SCL Low and SDA High */ 354 swI2CSCL(0); 355 swI2CSDA(1); 356 357 return data; 358 } 359 #pragma optimize( "", on ) 360 361 /* 362 * This function initializes GPIO port for SW I2C communication. 363 * 364 * Parameters: 365 * i2cClkGPIO - The GPIO pin to be used as i2c SCL 366 * i2cDataGPIO - The GPIO pin to be used as i2c SDA 367 * 368 * Return Value: 369 * -1 - Fail to initialize the i2c 370 * 0 - Success 371 */ 372 long swI2CInit_SM750LE( 373 unsigned char i2cClkGPIO, 374 unsigned char i2cDataGPIO 375 ) 376 { 377 int i; 378 379 /* Initialize the GPIO pin for the i2c Clock Register */ 380 g_i2cClkGPIODataReg = GPIO_DATA_SM750LE; 381 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 382 383 /* Initialize the Clock GPIO Offset */ 384 g_i2cClockGPIO = i2cClkGPIO; 385 386 /* Initialize the GPIO pin for the i2c Data Register */ 387 g_i2cDataGPIODataReg = GPIO_DATA_SM750LE; 388 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 389 390 /* Initialize the Data GPIO Offset */ 391 g_i2cDataGPIO = i2cDataGPIO; 392 393 /* Note that SM750LE don't have GPIO MUX and power is always on */ 394 395 /* Clear the i2c lines. */ 396 for(i=0; i<9; i++) 397 swI2CStop(); 398 399 return 0; 400 } 401 402 /* 403 * This function initializes the i2c attributes and bus 404 * 405 * Parameters: 406 * i2cClkGPIO - The GPIO pin to be used as i2c SCL 407 * i2cDataGPIO - The GPIO pin to be used as i2c SDA 408 * 409 * Return Value: 410 * -1 - Fail to initialize the i2c 411 * 0 - Success 412 */ 413 long swI2CInit( 414 unsigned char i2cClkGPIO, 415 unsigned char i2cDataGPIO 416 ) 417 { 418 int i; 419 420 /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */ 421 if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31)) 422 return (-1); 423 424 if (getChipType() == SM750LE) 425 return( swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO) ); 426 427 /* Initialize the GPIO pin for the i2c Clock Register */ 428 g_i2cClkGPIOMuxReg = GPIO_MUX; 429 g_i2cClkGPIODataReg = GPIO_DATA; 430 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; 431 432 /* Initialize the Clock GPIO Offset */ 433 g_i2cClockGPIO = i2cClkGPIO; 434 435 /* Initialize the GPIO pin for the i2c Data Register */ 436 g_i2cDataGPIOMuxReg = GPIO_MUX; 437 g_i2cDataGPIODataReg = GPIO_DATA; 438 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; 439 440 /* Initialize the Data GPIO Offset */ 441 g_i2cDataGPIO = i2cDataGPIO; 442 443 /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ 444 POKE32(g_i2cClkGPIOMuxReg, 445 PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO)); 446 POKE32(g_i2cDataGPIOMuxReg, 447 PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO)); 448 449 /* Enable GPIO power */ 450 enableGPIO(1); 451 452 /* Clear the i2c lines. */ 453 for(i=0; i<9; i++) 454 swI2CStop(); 455 456 return 0; 457 } 458 459 /* 460 * This function reads the slave device's register 461 * 462 * Parameters: 463 * deviceAddress - i2c Slave device address which register 464 * to be read from 465 * registerIndex - Slave device's register to be read 466 * 467 * Return Value: 468 * Register value 469 */ 470 unsigned char swI2CReadReg( 471 unsigned char deviceAddress, 472 unsigned char registerIndex 473 ) 474 { 475 unsigned char data; 476 477 /* Send the Start signal */ 478 swI2CStart(); 479 480 /* Send the device address */ 481 swI2CWriteByte(deviceAddress); 482 483 /* Send the register index */ 484 swI2CWriteByte(registerIndex); 485 486 /* Get the bus again and get the data from the device read address */ 487 swI2CStart(); 488 swI2CWriteByte(deviceAddress + 1); 489 data = swI2CReadByte(1); 490 491 /* Stop swI2C and release the bus */ 492 swI2CStop(); 493 494 return data; 495 } 496 497 /* 498 * This function writes a value to the slave device's register 499 * 500 * Parameters: 501 * deviceAddress - i2c Slave device address which register 502 * to be written 503 * registerIndex - Slave device's register to be written 504 * data - Data to be written to the register 505 * 506 * Result: 507 * 0 - Success 508 * -1 - Fail 509 */ 510 long swI2CWriteReg( 511 unsigned char deviceAddress, 512 unsigned char registerIndex, 513 unsigned char data 514 ) 515 { 516 long returnValue = 0; 517 518 /* Send the Start signal */ 519 swI2CStart(); 520 521 /* Send the device address and read the data. All should return success 522 in order for the writing processed to be successful 523 */ 524 if ((swI2CWriteByte(deviceAddress) != 0) || 525 (swI2CWriteByte(registerIndex) != 0) || 526 (swI2CWriteByte(data) != 0)) 527 { 528 returnValue = -1; 529 } 530 531 /* Stop i2c and release the bus */ 532 swI2CStop(); 533 534 return returnValue; 535 } 536