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 /*
83  *  This function puts a delay between command
84  */
85 static void swI2CWait(void)
86 {
87 	/* find a bug:
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
91 	 * never finish.
92 	 * use non-ultimate for loop below is safe
93 	 * */
94 #if 0
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
98        */
99 	while (peekIO(0x3ce, 0x61) & 0x10);
100 #else
101 	int i, Temp;
102 
103 	for (i = 0; i < 600; i++) {
104 		Temp = i;
105 		Temp += i;
106 	}
107 #endif
108 }
109 
110 /*
111  *  This function set/reset the SCL GPIO pin
112  *
113  *  Parameters:
114  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
115  *
116  *  Notes:
117  *      When setting SCL to high, just set the GPIO as input where the pull up
118  *      resistor will pull the signal up. Do not use software to pull up the
119  *      signal because the i2c will fail when other device try to drive the
120  *      signal due to SM50x will drive the signal to always high.
121  */
122 void swI2CSCL(unsigned char value)
123 {
124 	unsigned long ulGPIOData;
125 	unsigned long ulGPIODirection;
126 
127 	ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg);
128 	if (value) {    /* High */
129 		/* Set direction as input. This will automatically pull the signal up. */
130 		ulGPIODirection &= ~(1 << g_i2cClockGPIO);
131 		POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
132 	} else {        /* Low */
133 		/* Set the signal down */
134 		ulGPIOData = PEEK32(g_i2cClkGPIODataReg);
135 		ulGPIOData &= ~(1 << g_i2cClockGPIO);
136 		POKE32(g_i2cClkGPIODataReg, ulGPIOData);
137 
138 		/* Set direction as output */
139 		ulGPIODirection |= (1 << g_i2cClockGPIO);
140 		POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
141 	}
142 }
143 
144 /*
145  *  This function set/reset the SDA GPIO pin
146  *
147  *  Parameters:
148  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
149  *
150  *  Notes:
151  *      When setting SCL to high, just set the GPIO as input where the pull up
152  *      resistor will pull the signal up. Do not use software to pull up the
153  *      signal because the i2c will fail when other device try to drive the
154  *      signal due to SM50x will drive the signal to always high.
155  */
156 void swI2CSDA(unsigned char value)
157 {
158 	unsigned long ulGPIOData;
159 	unsigned long ulGPIODirection;
160 
161 	ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
162 	if (value) {    /* High */
163 		/* Set direction as input. This will automatically pull the signal up. */
164 		ulGPIODirection &= ~(1 << g_i2cDataGPIO);
165 		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
166 	} else {        /* Low */
167 		/* Set the signal down */
168 		ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
169 		ulGPIOData &= ~(1 << g_i2cDataGPIO);
170 		POKE32(g_i2cDataGPIODataReg, ulGPIOData);
171 
172 		/* Set direction as output */
173 		ulGPIODirection |= (1 << g_i2cDataGPIO);
174 		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
175 	}
176 }
177 
178 /*
179  *  This function read the data from the SDA GPIO pin
180  *
181  *  Return Value:
182  *      The SDA data bit sent by the Slave
183  */
184 static unsigned char swI2CReadSDA(void)
185 {
186 	unsigned long ulGPIODirection;
187 	unsigned long ulGPIOData;
188 
189 	/* Make sure that the direction is input (High) */
190 	ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
191 	if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO))) {
192 		ulGPIODirection &= ~(1 << g_i2cDataGPIO);
193 		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
194 	}
195 
196 	/* Now read the SDA line */
197 	ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
198 	if (ulGPIOData & (1 << g_i2cDataGPIO))
199 		return 1;
200 	else
201 		return 0;
202 }
203 
204 /*
205  *  This function sends ACK signal
206  */
207 static void swI2CAck(void)
208 {
209 	return;  /* Single byte read is ok without it. */
210 }
211 
212 /*
213  *  This function sends the start command to the slave device
214  */
215 static void swI2CStart(void)
216 {
217 	/* Start I2C */
218 	swI2CSDA(1);
219 	swI2CSCL(1);
220 	swI2CSDA(0);
221 }
222 
223 /*
224  *  This function sends the stop command to the slave device
225  */
226 static void swI2CStop(void)
227 {
228 	/* Stop the I2C */
229 	swI2CSCL(1);
230 	swI2CSDA(0);
231 	swI2CSDA(1);
232 }
233 
234 /*
235  *  This function writes one byte to the slave device
236  *
237  *  Parameters:
238  *      data    - Data to be write to the slave device
239  *
240  *  Return Value:
241  *       0   - Success
242  *      -1   - Fail to write byte
243  */
244 static long swI2CWriteByte(unsigned char data)
245 {
246 	unsigned char value = data;
247 	int i;
248 
249 	/* Sending the data bit by bit */
250 	for (i = 0; i < 8; i++) {
251 		/* Set SCL to low */
252 		swI2CSCL(0);
253 
254 		/* Send data bit */
255 		if ((value & 0x80) != 0)
256 			swI2CSDA(1);
257 		else
258 			swI2CSDA(0);
259 
260 		swI2CWait();
261 
262 		/* Toggle clk line to one */
263 		swI2CSCL(1);
264 		swI2CWait();
265 
266 		/* Shift byte to be sent */
267 		value = value << 1;
268 	}
269 
270 	/* Set the SCL Low and SDA High (prepare to get input) */
271 	swI2CSCL(0);
272 	swI2CSDA(1);
273 
274 	/* Set the SCL High for ack */
275 	swI2CWait();
276 	swI2CSCL(1);
277 	swI2CWait();
278 
279 	/* Read SDA, until SDA==0 */
280 	for (i = 0; i < 0xff; i++) {
281 		if (!swI2CReadSDA())
282 			break;
283 
284 		swI2CSCL(0);
285 		swI2CWait();
286 		swI2CSCL(1);
287 		swI2CWait();
288 	}
289 
290 	/* Set the SCL Low and SDA High */
291 	swI2CSCL(0);
292 	swI2CSDA(1);
293 
294 	if (i < 0xff)
295 		return 0;
296 	else
297 		return -1;
298 }
299 
300 /*
301  *  This function reads one byte from the slave device
302  *
303  *  Parameters:
304  *      ack    - Flag to indicate either to send the acknowledge
305  *            message to the slave device or not
306  *
307  *  Return Value:
308  *      One byte data read from the Slave device
309  */
310 static unsigned char swI2CReadByte(unsigned char ack)
311 {
312 	int i;
313 	unsigned char data = 0;
314 
315 	for (i = 7; i >= 0; i--) {
316 		/* Set the SCL to Low and SDA to High (Input) */
317 		swI2CSCL(0);
318 		swI2CSDA(1);
319 		swI2CWait();
320 
321 		/* Set the SCL High */
322 		swI2CSCL(1);
323 		swI2CWait();
324 
325 		/* Read data bits from SDA */
326 		data |= (swI2CReadSDA() << i);
327 	}
328 
329 	if (ack)
330 		swI2CAck();
331 
332 	/* Set the SCL Low and SDA High */
333 	swI2CSCL(0);
334 	swI2CSDA(1);
335 
336 	return data;
337 }
338 
339 /*
340  * This function initializes GPIO port for SW I2C communication.
341  *
342  * Parameters:
343  *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
344  *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
345  *
346  * Return Value:
347  *      -1   - Fail to initialize the i2c
348  *       0   - Success
349  */
350 static long swI2CInit_SM750LE(unsigned char i2cClkGPIO,
351 			      unsigned char i2cDataGPIO)
352 {
353 	int i;
354 
355 	/* Initialize the GPIO pin for the i2c Clock Register */
356 	g_i2cClkGPIODataReg = GPIO_DATA_SM750LE;
357 	g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
358 
359 	/* Initialize the Clock GPIO Offset */
360 	g_i2cClockGPIO = i2cClkGPIO;
361 
362 	/* Initialize the GPIO pin for the i2c Data Register */
363 	g_i2cDataGPIODataReg = GPIO_DATA_SM750LE;
364 	g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
365 
366 	/* Initialize the Data GPIO Offset */
367 	g_i2cDataGPIO = i2cDataGPIO;
368 
369 	/* Note that SM750LE don't have GPIO MUX and power is always on */
370 
371 	/* Clear the i2c lines. */
372 	for (i = 0; i < 9; i++)
373 		swI2CStop();
374 
375 	return 0;
376 }
377 
378 /*
379  * This function initializes the i2c attributes and bus
380  *
381  * Parameters:
382  *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
383  *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
384  *
385  * Return Value:
386  *      -1   - Fail to initialize the i2c
387  *       0   - Success
388  */
389 long sm750_sw_i2c_init(
390 	unsigned char i2cClkGPIO,
391 	unsigned char i2cDataGPIO
392 )
393 {
394 	int i;
395 
396 	/* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */
397 	if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31))
398 		return -1;
399 
400 	if (getChipType() == SM750LE)
401 		return swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO);
402 
403 	/* Initialize the GPIO pin for the i2c Clock Register */
404 	g_i2cClkGPIOMuxReg = GPIO_MUX;
405 	g_i2cClkGPIODataReg = GPIO_DATA;
406 	g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
407 
408 	/* Initialize the Clock GPIO Offset */
409 	g_i2cClockGPIO = i2cClkGPIO;
410 
411 	/* Initialize the GPIO pin for the i2c Data Register */
412 	g_i2cDataGPIOMuxReg = GPIO_MUX;
413 	g_i2cDataGPIODataReg = GPIO_DATA;
414 	g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
415 
416 	/* Initialize the Data GPIO Offset */
417 	g_i2cDataGPIO = i2cDataGPIO;
418 
419 	/* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
420 	POKE32(g_i2cClkGPIOMuxReg,
421 			PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO));
422 	POKE32(g_i2cDataGPIOMuxReg,
423 			PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO));
424 
425 	/* Enable GPIO power */
426 	enableGPIO(1);
427 
428 	/* Clear the i2c lines. */
429 	for (i = 0; i < 9; i++)
430 		swI2CStop();
431 
432 	return 0;
433 }
434 
435 /*
436  *  This function reads the slave device's register
437  *
438  *  Parameters:
439  *      deviceAddress   - i2c Slave device address which register
440  *                        to be read from
441  *      registerIndex   - Slave device's register to be read
442  *
443  *  Return Value:
444  *      Register value
445  */
446 unsigned char sm750_sw_i2c_read_reg(
447 	unsigned char deviceAddress,
448 	unsigned char registerIndex
449 )
450 {
451 	unsigned char data;
452 
453 	/* Send the Start signal */
454 	swI2CStart();
455 
456 	/* Send the device address */
457 	swI2CWriteByte(deviceAddress);
458 
459 	/* Send the register index */
460 	swI2CWriteByte(registerIndex);
461 
462 	/* Get the bus again and get the data from the device read address */
463 	swI2CStart();
464 	swI2CWriteByte(deviceAddress + 1);
465 	data = swI2CReadByte(1);
466 
467 	/* Stop swI2C and release the bus */
468 	swI2CStop();
469 
470 	return data;
471 }
472 
473 /*
474  *  This function writes a value to the slave device's register
475  *
476  *  Parameters:
477  *      deviceAddress   - i2c Slave device address which register
478  *                        to be written
479  *      registerIndex   - Slave device's register to be written
480  *      data            - Data to be written to the register
481  *
482  *  Result:
483  *          0   - Success
484  *         -1   - Fail
485  */
486 long sm750_sw_i2c_write_reg(
487 	unsigned char deviceAddress,
488 	unsigned char registerIndex,
489 	unsigned char data
490 )
491 {
492 	long returnValue = 0;
493 
494 	/* Send the Start signal */
495 	swI2CStart();
496 
497 	/* Send the device address and read the data. All should return success
498 	   in order for the writing processed to be successful
499 	*/
500 	if ((swI2CWriteByte(deviceAddress) != 0) ||
501 	    (swI2CWriteByte(registerIndex) != 0) ||
502 	    (swI2CWriteByte(data) != 0)) {
503 		returnValue = -1;
504 	}
505 
506 	/* Stop i2c and release the bus */
507 	swI2CStop();
508 
509 	return returnValue;
510 }
511