1 /*******************************************************************
3 * Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
5 * All rights are reserved. Reproduction or in part is prohibited
6 * without the written consent of the copyright owner.
8 * swi2c.c --- SM750/SM718 DDK
9 * This file contains the source code for I2C using software
12 *******************************************************************/
13 #include "ddk750_help.h"
14 #include "ddk750_reg.h"
15 #include "ddk750_swi2c.h"
16 #include "ddk750_power.h"
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.
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|
29 * ____________ _____________
30 * SCL == XXXX _____________ ____________ /
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.
36 * Section changes Table:
37 * ======================
38 * blank = no change, L = set bit LOW, H = set bit HIGH
41 * ---------------+---+---+---+---+
42 * Tx Start SDA | | H | | L |
44 * ---------------+---+---+---+---+
45 * Tx Stop SDA | | L | | H |
47 * ---------------+---+---+---+---+
48 * Tx bit H SDA | | H | | |
50 * ---------------+---+---+---+---+
51 * Tx bit L SDA | | L | | |
53 * ---------------+---+---+---+---+
55 ******************************************************************/
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;
62 * Below is the variable declaration for the GPIO pin register usage
63 * for the i2c Clock and i2c Data.
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).
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;
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;
83 * This function puts a delay between command
85 static void swI2CWait(void)
88 * peekIO method works well before suspend/resume
89 * but after suspend, peekIO(0x3ce,0x61) & 0x10
90 * always be non-zero,which makes the while loop
92 * use non-ultimate for loop below is safe
95 /* Change wait algorithm to use PCI bus clock,
96 it's more reliable than counter loop ..
97 write 0x61 to 0x3ce and read from 0x3cf
99 while(peekIO(0x3ce,0x61) & 0x10);
112 * This function set/reset the SCL GPIO pin
115 * value - Bit value to set to the SCL or SDA (0 = low, 1 = high)
118 * When setting SCL to high, just set the GPIO as input where the pull up
119 * resistor will pull the signal up. Do not use software to pull up the
120 * signal because the i2c will fail when other device try to drive the
121 * signal due to SM50x will drive the signal to always high.
123 void swI2CSCL(unsigned char value)
125 unsigned long ulGPIOData;
126 unsigned long ulGPIODirection;
128 ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg);
129 if (value) /* High */
131 /* Set direction as input. This will automatically pull the signal up. */
132 ulGPIODirection &= ~(1 << g_i2cClockGPIO);
133 POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
137 /* Set the signal down */
138 ulGPIOData = PEEK32(g_i2cClkGPIODataReg);
139 ulGPIOData &= ~(1 << g_i2cClockGPIO);
140 POKE32(g_i2cClkGPIODataReg, ulGPIOData);
142 /* Set direction as output */
143 ulGPIODirection |= (1 << g_i2cClockGPIO);
144 POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
149 * This function set/reset the SDA GPIO pin
152 * value - Bit value to set to the SCL or SDA (0 = low, 1 = high)
155 * When setting SCL to high, just set the GPIO as input where the pull up
156 * resistor will pull the signal up. Do not use software to pull up the
157 * signal because the i2c will fail when other device try to drive the
158 * signal due to SM50x will drive the signal to always high.
160 void swI2CSDA(unsigned char value)
162 unsigned long ulGPIOData;
163 unsigned long ulGPIODirection;
165 ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
166 if (value) /* High */
168 /* Set direction as input. This will automatically pull the signal up. */
169 ulGPIODirection &= ~(1 << g_i2cDataGPIO);
170 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
174 /* Set the signal down */
175 ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
176 ulGPIOData &= ~(1 << g_i2cDataGPIO);
177 POKE32(g_i2cDataGPIODataReg, ulGPIOData);
179 /* Set direction as output */
180 ulGPIODirection |= (1 << g_i2cDataGPIO);
181 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
186 * This function read the data from the SDA GPIO pin
189 * The SDA data bit sent by the Slave
191 static unsigned char swI2CReadSDA(void)
193 unsigned long ulGPIODirection;
194 unsigned long ulGPIOData;
196 /* Make sure that the direction is input (High) */
197 ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
198 if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO)))
200 ulGPIODirection &= ~(1 << g_i2cDataGPIO);
201 POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
204 /* Now read the SDA line */
205 ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
206 if (ulGPIOData & (1 << g_i2cDataGPIO))
213 * This function sends ACK signal
215 static void swI2CAck(void)
217 return; /* Single byte read is ok without it. */
221 * This function sends the start command to the slave device
223 static void swI2CStart(void)
232 * This function sends the stop command to the slave device
234 static void swI2CStop(void)
243 * This function writes one byte to the slave device
246 * data - Data to be write to the slave device
250 * -1 - Fail to write byte
252 static long swI2CWriteByte(unsigned char data)
254 unsigned char value = data;
257 /* Sending the data bit by bit */
264 if ((value & 0x80) != 0)
271 /* Toggle clk line to one */
275 /* Shift byte to be sent */
279 /* Set the SCL Low and SDA High (prepare to get input) */
283 /* Set the SCL High for ack */
288 /* Read SDA, until SDA==0 */
289 for(i=0; i<0xff; i++)
300 /* Set the SCL Low and SDA High */
311 * This function reads one byte from the slave device
314 * ack - Flag to indicate either to send the acknowledge
315 * message to the slave device or not
318 * One byte data read from the Slave device
320 static unsigned char swI2CReadByte(unsigned char ack)
323 unsigned char data = 0;
327 /* Set the SCL to Low and SDA to High (Input) */
332 /* Set the SCL High */
336 /* Read data bits from SDA */
337 data |= (swI2CReadSDA() << i);
343 /* Set the SCL Low and SDA High */
351 * This function initializes GPIO port for SW I2C communication.
354 * i2cClkGPIO - The GPIO pin to be used as i2c SCL
355 * i2cDataGPIO - The GPIO pin to be used as i2c SDA
358 * -1 - Fail to initialize the i2c
361 static long swI2CInit_SM750LE(unsigned char i2cClkGPIO,
362 unsigned char i2cDataGPIO)
366 /* Initialize the GPIO pin for the i2c Clock Register */
367 g_i2cClkGPIODataReg = GPIO_DATA_SM750LE;
368 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
370 /* Initialize the Clock GPIO Offset */
371 g_i2cClockGPIO = i2cClkGPIO;
373 /* Initialize the GPIO pin for the i2c Data Register */
374 g_i2cDataGPIODataReg = GPIO_DATA_SM750LE;
375 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
377 /* Initialize the Data GPIO Offset */
378 g_i2cDataGPIO = i2cDataGPIO;
380 /* Note that SM750LE don't have GPIO MUX and power is always on */
382 /* Clear the i2c lines. */
390 * This function initializes the i2c attributes and bus
393 * i2cClkGPIO - The GPIO pin to be used as i2c SCL
394 * i2cDataGPIO - The GPIO pin to be used as i2c SDA
397 * -1 - Fail to initialize the i2c
401 unsigned char i2cClkGPIO,
402 unsigned char i2cDataGPIO
407 /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */
408 if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31))
411 if (getChipType() == SM750LE)
412 return swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO);
414 /* Initialize the GPIO pin for the i2c Clock Register */
415 g_i2cClkGPIOMuxReg = GPIO_MUX;
416 g_i2cClkGPIODataReg = GPIO_DATA;
417 g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
419 /* Initialize the Clock GPIO Offset */
420 g_i2cClockGPIO = i2cClkGPIO;
422 /* Initialize the GPIO pin for the i2c Data Register */
423 g_i2cDataGPIOMuxReg = GPIO_MUX;
424 g_i2cDataGPIODataReg = GPIO_DATA;
425 g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
427 /* Initialize the Data GPIO Offset */
428 g_i2cDataGPIO = i2cDataGPIO;
430 /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
431 POKE32(g_i2cClkGPIOMuxReg,
432 PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO));
433 POKE32(g_i2cDataGPIOMuxReg,
434 PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO));
436 /* Enable GPIO power */
439 /* Clear the i2c lines. */
447 * This function reads the slave device's register
450 * deviceAddress - i2c Slave device address which register
452 * registerIndex - Slave device's register to be read
457 unsigned char swI2CReadReg(
458 unsigned char deviceAddress,
459 unsigned char registerIndex
464 /* Send the Start signal */
467 /* Send the device address */
468 swI2CWriteByte(deviceAddress);
470 /* Send the register index */
471 swI2CWriteByte(registerIndex);
473 /* Get the bus again and get the data from the device read address */
475 swI2CWriteByte(deviceAddress + 1);
476 data = swI2CReadByte(1);
478 /* Stop swI2C and release the bus */
485 * This function writes a value to the slave device's register
488 * deviceAddress - i2c Slave device address which register
490 * registerIndex - Slave device's register to be written
491 * data - Data to be written to the register
498 unsigned char deviceAddress,
499 unsigned char registerIndex,
503 long returnValue = 0;
505 /* Send the Start signal */
508 /* Send the device address and read the data. All should return success
509 in order for the writing processed to be successful
511 if ((swI2CWriteByte(deviceAddress) != 0) ||
512 (swI2CWriteByte(registerIndex) != 0) ||
513 (swI2CWriteByte(data) != 0))
518 /* Stop i2c and release the bus */