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 /* 221 * This function sends ACK signal 222 */ 223 static void swI2CAck(void) 224 { 225 return; /* Single byte read is ok without it. */ 226 } 227 228 /* 229 * This function sends the start command to the slave device 230 */ 231 void swI2CStart(void) 232 { 233 /* Start I2C */ 234 swI2CSDA(1); 235 swI2CSCL(1); 236 swI2CSDA(0); 237 } 238 239 /* 240 * This function sends the stop command to the slave device 241 */ 242 void swI2CStop(void) 243 { 244 /* Stop the I2C */ 245 swI2CSCL(1); 246 swI2CSDA(0); 247 swI2CSDA(1); 248 } 249 250 /* 251 * This function writes one byte to the slave device 252 * 253 * Parameters: 254 * data - Data to be write to the slave device 255 * 256 * Return Value: 257 * 0 - Success 258 * -1 - Fail to write byte 259 */ 260 long swI2CWriteByte(unsigned char data) 261 { 262 unsigned char value = data; 263 int i; 264 265 /* Sending the data bit by bit */ 266 for (i=0; i<8; i++) 267 { 268 /* Set SCL to low */ 269 swI2CSCL(0); 270 271 /* Send data bit */ 272 if ((value & 0x80) != 0) 273 swI2CSDA(1); 274 else 275 swI2CSDA(0); 276 277 swI2CWait(); 278 279 /* Toggle clk line to one */ 280 swI2CSCL(1); 281 swI2CWait(); 282 283 /* Shift byte to be sent */ 284 value = value << 1; 285 } 286 287 /* Set the SCL Low and SDA High (prepare to get input) */ 288 swI2CSCL(0); 289 swI2CSDA(1); 290 291 /* Set the SCL High for ack */ 292 swI2CWait(); 293 swI2CSCL(1); 294 swI2CWait(); 295 296 /* Read SDA, until SDA==0 */ 297 for(i=0; i<0xff; i++) 298 { 299 if (!swI2CReadSDA()) 300 break; 301 302 swI2CSCL(0); 303 swI2CWait(); 304 swI2CSCL(1); 305 swI2CWait(); 306 } 307 308 /* Set the SCL Low and SDA High */ 309 swI2CSCL(0); 310 swI2CSDA(1); 311 312 if (i<0xff) 313 return 0; 314 else 315 return (-1); 316 } 317 318 /* 319 * This function reads one byte from the slave device 320 * 321 * Parameters: 322 * ack - Flag to indicate either to send the acknowledge 323 * message to the slave device or not 324 * 325 * Return Value: 326 * One byte data read from the Slave device 327 */ 328 unsigned char swI2CReadByte(unsigned char ack) 329 { 330 int i; 331 unsigned char data = 0; 332 333 for(i=7; i>=0; i--) 334 { 335 /* Set the SCL to Low and SDA to High (Input) */ 336 swI2CSCL(0); 337 swI2CSDA(1); 338 swI2CWait(); 339 340 /* Set the SCL High */ 341 swI2CSCL(1); 342 swI2CWait(); 343 344 /* Read data bits from SDA */ 345 data |= (swI2CReadSDA() << i); 346 } 347 348 if (ack) 349 swI2CAck(); 350 351 /* Set the SCL Low and SDA High */ 352 swI2CSCL(0); 353 swI2CSDA(1); 354 355 return data; 356 } 357 358 /* 359 * This function initializes GPIO port for SW I2C communication. 360 * 361 * Parameters: 362 * i2cClkGPIO - The GPIO pin to be used as i2c SCL 363 * i2cDataGPIO - The GPIO pin to be used as i2c SDA 364 * 365 * Return Value: 366 * -1 - Fail to initialize the i2c 367 * 0 - Success 368 */ 369 long swI2CInit_SM750LE( 370 unsigned char i2cClkGPIO, 371 unsigned char i2cDataGPIO 372 ) 373 { 374 int i; 375 376 /* Initialize the GPIO pin for the i2c Clock Register */ 377 g_i2cClkGPIODataReg = GPIO_DATA_SM750LE; 378 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 379 380 /* Initialize the Clock GPIO Offset */ 381 g_i2cClockGPIO = i2cClkGPIO; 382 383 /* Initialize the GPIO pin for the i2c Data Register */ 384 g_i2cDataGPIODataReg = GPIO_DATA_SM750LE; 385 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 386 387 /* Initialize the Data GPIO Offset */ 388 g_i2cDataGPIO = i2cDataGPIO; 389 390 /* Note that SM750LE don't have GPIO MUX and power is always on */ 391 392 /* Clear the i2c lines. */ 393 for(i=0; i<9; i++) 394 swI2CStop(); 395 396 return 0; 397 } 398 399 /* 400 * This function initializes the i2c attributes and bus 401 * 402 * Parameters: 403 * i2cClkGPIO - The GPIO pin to be used as i2c SCL 404 * i2cDataGPIO - The GPIO pin to be used as i2c SDA 405 * 406 * Return Value: 407 * -1 - Fail to initialize the i2c 408 * 0 - Success 409 */ 410 long swI2CInit( 411 unsigned char i2cClkGPIO, 412 unsigned char i2cDataGPIO 413 ) 414 { 415 int i; 416 417 /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */ 418 if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31)) 419 return (-1); 420 421 if (getChipType() == SM750LE) 422 return( swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO) ); 423 424 /* Initialize the GPIO pin for the i2c Clock Register */ 425 g_i2cClkGPIOMuxReg = GPIO_MUX; 426 g_i2cClkGPIODataReg = GPIO_DATA; 427 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; 428 429 /* Initialize the Clock GPIO Offset */ 430 g_i2cClockGPIO = i2cClkGPIO; 431 432 /* Initialize the GPIO pin for the i2c Data Register */ 433 g_i2cDataGPIOMuxReg = GPIO_MUX; 434 g_i2cDataGPIODataReg = GPIO_DATA; 435 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; 436 437 /* Initialize the Data GPIO Offset */ 438 g_i2cDataGPIO = i2cDataGPIO; 439 440 /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ 441 POKE32(g_i2cClkGPIOMuxReg, 442 PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO)); 443 POKE32(g_i2cDataGPIOMuxReg, 444 PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO)); 445 446 /* Enable GPIO power */ 447 enableGPIO(1); 448 449 /* Clear the i2c lines. */ 450 for(i=0; i<9; i++) 451 swI2CStop(); 452 453 return 0; 454 } 455 456 /* 457 * This function reads the slave device's register 458 * 459 * Parameters: 460 * deviceAddress - i2c Slave device address which register 461 * to be read from 462 * registerIndex - Slave device's register to be read 463 * 464 * Return Value: 465 * Register value 466 */ 467 unsigned char swI2CReadReg( 468 unsigned char deviceAddress, 469 unsigned char registerIndex 470 ) 471 { 472 unsigned char data; 473 474 /* Send the Start signal */ 475 swI2CStart(); 476 477 /* Send the device address */ 478 swI2CWriteByte(deviceAddress); 479 480 /* Send the register index */ 481 swI2CWriteByte(registerIndex); 482 483 /* Get the bus again and get the data from the device read address */ 484 swI2CStart(); 485 swI2CWriteByte(deviceAddress + 1); 486 data = swI2CReadByte(1); 487 488 /* Stop swI2C and release the bus */ 489 swI2CStop(); 490 491 return data; 492 } 493 494 /* 495 * This function writes a value to the slave device's register 496 * 497 * Parameters: 498 * deviceAddress - i2c Slave device address which register 499 * to be written 500 * registerIndex - Slave device's register to be written 501 * data - Data to be written to the register 502 * 503 * Result: 504 * 0 - Success 505 * -1 - Fail 506 */ 507 long swI2CWriteReg( 508 unsigned char deviceAddress, 509 unsigned char registerIndex, 510 unsigned char data 511 ) 512 { 513 long returnValue = 0; 514 515 /* Send the Start signal */ 516 swI2CStart(); 517 518 /* Send the device address and read the data. All should return success 519 in order for the writing processed to be successful 520 */ 521 if ((swI2CWriteByte(deviceAddress) != 0) || 522 (swI2CWriteByte(registerIndex) != 0) || 523 (swI2CWriteByte(data) != 0)) 524 { 525 returnValue = -1; 526 } 527 528 /* Stop i2c and release the bus */ 529 swI2CStop(); 530 531 return returnValue; 532 } 533