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