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 */