181dee67eSSudip Mukherjee /*******************************************************************
281dee67eSSudip Mukherjee *
381dee67eSSudip Mukherjee *         Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
481dee67eSSudip Mukherjee *
581dee67eSSudip Mukherjee *  All rights are reserved. Reproduction or in part is prohibited
681dee67eSSudip Mukherjee *  without the written consent of the copyright owner.
781dee67eSSudip Mukherjee *
881dee67eSSudip Mukherjee *  swi2c.c --- SM750/SM718 DDK
981dee67eSSudip Mukherjee *  This file contains the source code for I2C using software
1081dee67eSSudip Mukherjee *  implementation.
1181dee67eSSudip Mukherjee *
1281dee67eSSudip Mukherjee *******************************************************************/
1381dee67eSSudip Mukherjee #include "ddk750_help.h"
1481dee67eSSudip Mukherjee #include "ddk750_reg.h"
1581dee67eSSudip Mukherjee #include "ddk750_swi2c.h"
1681dee67eSSudip Mukherjee #include "ddk750_power.h"
1781dee67eSSudip Mukherjee 
1881dee67eSSudip Mukherjee /*******************************************************************
1981dee67eSSudip Mukherjee  * I2C Software Master Driver:
2081dee67eSSudip Mukherjee  * ===========================
2181dee67eSSudip Mukherjee  * Each i2c cycle is split into 4 sections. Each of these section marks
2281dee67eSSudip Mukherjee  * a point in time where the SCL or SDA may be changed.
2381dee67eSSudip Mukherjee  *
2481dee67eSSudip Mukherjee  * 1 Cycle == |  Section I. |  Section 2. |  Section 3. |  Section 4. |
2581dee67eSSudip Mukherjee  *            +-------------+-------------+-------------+-------------+
2681dee67eSSudip Mukherjee  *            | SCL set LOW |SCL no change| SCL set HIGH|SCL no change|
2781dee67eSSudip Mukherjee  *
2881dee67eSSudip Mukherjee  *                                          ____________ _____________
2981dee67eSSudip Mukherjee  * SCL == XXXX _____________ ____________ /
3081dee67eSSudip Mukherjee  *
3181dee67eSSudip Mukherjee  * I.e. the SCL may only be changed in section 1. and section 3. while
3281dee67eSSudip Mukherjee  * the SDA may only be changed in section 2. and section 4. The table
3381dee67eSSudip Mukherjee  * below gives the changes for these 2 lines in the varios sections.
3481dee67eSSudip Mukherjee  *
3581dee67eSSudip Mukherjee  * Section changes Table:
3681dee67eSSudip Mukherjee  * ======================
3781dee67eSSudip Mukherjee  * blank = no change, L = set bit LOW, H = set bit HIGH
3881dee67eSSudip Mukherjee  *
3981dee67eSSudip Mukherjee  *                                | 1.| 2.| 3.| 4.|
4081dee67eSSudip Mukherjee  *                 ---------------+---+---+---+---+
4181dee67eSSudip Mukherjee  *                 Tx Start   SDA |   | H |   | L |
4281dee67eSSudip Mukherjee  *                            SCL | L |   | H |   |
4381dee67eSSudip Mukherjee  *                 ---------------+---+---+---+---+
4481dee67eSSudip Mukherjee  *                 Tx Stop    SDA |   | L |   | H |
4581dee67eSSudip Mukherjee  *                            SCL | L |   | H |   |
4681dee67eSSudip Mukherjee  *                 ---------------+---+---+---+---+
4781dee67eSSudip Mukherjee  *                 Tx bit H   SDA |   | H |   |   |
4881dee67eSSudip Mukherjee  *                            SCL | L |   | H |   |
4981dee67eSSudip Mukherjee  *                 ---------------+---+---+---+---+
5081dee67eSSudip Mukherjee  *                 Tx bit L   SDA |   | L |   |   |
5181dee67eSSudip Mukherjee  *                            SCL | L |   | H |   |
5281dee67eSSudip Mukherjee  *                 ---------------+---+---+---+---+
5381dee67eSSudip Mukherjee  *
5481dee67eSSudip Mukherjee  ******************************************************************/
5581dee67eSSudip Mukherjee 
5681dee67eSSudip Mukherjee /* GPIO pins used for this I2C. It ranges from 0 to 63. */
5753bc6b6eSMike Rapoport static unsigned char sw_i2c_clk_gpio = DEFAULT_I2C_SCL;
5853bc6b6eSMike Rapoport static unsigned char sw_i2c_data_gpio = DEFAULT_I2C_SDA;
5981dee67eSSudip Mukherjee 
6081dee67eSSudip Mukherjee /*
6181dee67eSSudip Mukherjee  *  Below is the variable declaration for the GPIO pin register usage
6281dee67eSSudip Mukherjee  *  for the i2c Clock and i2c Data.
6381dee67eSSudip Mukherjee  *
6481dee67eSSudip Mukherjee  *  Note:
6581dee67eSSudip Mukherjee  *      Notice that the GPIO usage for the i2c clock and i2c Data are
6681dee67eSSudip Mukherjee  *      separated. This is to make this code flexible enough when
6781dee67eSSudip Mukherjee  *      two separate GPIO pins for the clock and data are located
6881dee67eSSudip Mukherjee  *      in two different GPIO register set (worst case).
6981dee67eSSudip Mukherjee  */
7081dee67eSSudip Mukherjee 
7181dee67eSSudip Mukherjee /* i2c Clock GPIO Register usage */
7253bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_mux_reg = GPIO_MUX;
7353bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_reg = GPIO_DATA;
7453bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
7581dee67eSSudip Mukherjee 
7681dee67eSSudip Mukherjee /* i2c Data GPIO Register usage */
7753bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_mux_reg = GPIO_MUX;
7853bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_reg = GPIO_DATA;
7953bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
8081dee67eSSudip Mukherjee 
8181dee67eSSudip Mukherjee /*
8281dee67eSSudip Mukherjee  *  This function puts a delay between command
8381dee67eSSudip Mukherjee  */
846c78f4ceSMike Rapoport static void sw_i2c_wait(void)
8581dee67eSSudip Mukherjee {
8681dee67eSSudip Mukherjee 	/* find a bug:
8781dee67eSSudip Mukherjee 	 * peekIO method works well before suspend/resume
8881dee67eSSudip Mukherjee 	 * but after suspend, peekIO(0x3ce,0x61) & 0x10
8981dee67eSSudip Mukherjee 	 * always be non-zero,which makes the while loop
9081dee67eSSudip Mukherjee 	 * never finish.
9181dee67eSSudip Mukherjee 	 * use non-ultimate for loop below is safe
9281dee67eSSudip Mukherjee 	 * */
931282badeSMike Rapoport 
9481dee67eSSudip Mukherjee     /* Change wait algorithm to use PCI bus clock,
9581dee67eSSudip Mukherjee        it's more reliable than counter loop ..
9681dee67eSSudip Mukherjee        write 0x61 to 0x3ce and read from 0x3cf
9781dee67eSSudip Mukherjee        */
98fe820044SMike Rapoport 	int i, tmp;
9981dee67eSSudip Mukherjee 
100d3f431d0SIsaac Assegai 	for (i = 0; i < 600; i++) {
101fe820044SMike Rapoport 		tmp = i;
102fe820044SMike Rapoport 		tmp += i;
10381dee67eSSudip Mukherjee 	}
10481dee67eSSudip Mukherjee }
10581dee67eSSudip Mukherjee 
10681dee67eSSudip Mukherjee /*
10781dee67eSSudip Mukherjee  *  This function set/reset the SCL GPIO pin
10881dee67eSSudip Mukherjee  *
10981dee67eSSudip Mukherjee  *  Parameters:
11081dee67eSSudip Mukherjee  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
11181dee67eSSudip Mukherjee  *
11281dee67eSSudip Mukherjee  *  Notes:
11381dee67eSSudip Mukherjee  *      When setting SCL to high, just set the GPIO as input where the pull up
11481dee67eSSudip Mukherjee  *      resistor will pull the signal up. Do not use software to pull up the
11581dee67eSSudip Mukherjee  *      signal because the i2c will fail when other device try to drive the
11681dee67eSSudip Mukherjee  *      signal due to SM50x will drive the signal to always high.
11781dee67eSSudip Mukherjee  */
1186c78f4ceSMike Rapoport static void sw_i2c_scl(unsigned char value)
11981dee67eSSudip Mukherjee {
120fe820044SMike Rapoport 	unsigned long gpio_data;
121fe820044SMike Rapoport 	unsigned long gpio_dir;
12281dee67eSSudip Mukherjee 
123fe820044SMike Rapoport 	gpio_dir = PEEK32(sw_i2c_clk_gpio_data_dir_reg);
124d3f431d0SIsaac Assegai 	if (value) {    /* High */
1259137f812SMike Rapoport 		/*
1269137f812SMike Rapoport 		 * Set direction as input. This will automatically
1279137f812SMike Rapoport 		 * pull the signal up.
1289137f812SMike Rapoport 		 */
129fe820044SMike Rapoport 		gpio_dir &= ~(1 << sw_i2c_clk_gpio);
130fe820044SMike Rapoport 		POKE32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir);
131d3f431d0SIsaac Assegai 	} else {        /* Low */
13281dee67eSSudip Mukherjee 		/* Set the signal down */
133fe820044SMike Rapoport 		gpio_data = PEEK32(sw_i2c_clk_gpio_data_reg);
134fe820044SMike Rapoport 		gpio_data &= ~(1 << sw_i2c_clk_gpio);
135fe820044SMike Rapoport 		POKE32(sw_i2c_clk_gpio_data_reg, gpio_data);
13681dee67eSSudip Mukherjee 
13781dee67eSSudip Mukherjee 		/* Set direction as output */
138fe820044SMike Rapoport 		gpio_dir |= (1 << sw_i2c_clk_gpio);
139fe820044SMike Rapoport 		POKE32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir);
14081dee67eSSudip Mukherjee 	}
14181dee67eSSudip Mukherjee }
14281dee67eSSudip Mukherjee 
14381dee67eSSudip Mukherjee /*
14481dee67eSSudip Mukherjee  *  This function set/reset the SDA GPIO pin
14581dee67eSSudip Mukherjee  *
14681dee67eSSudip Mukherjee  *  Parameters:
14781dee67eSSudip Mukherjee  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
14881dee67eSSudip Mukherjee  *
14981dee67eSSudip Mukherjee  *  Notes:
15081dee67eSSudip Mukherjee  *      When setting SCL to high, just set the GPIO as input where the pull up
15181dee67eSSudip Mukherjee  *      resistor will pull the signal up. Do not use software to pull up the
15281dee67eSSudip Mukherjee  *      signal because the i2c will fail when other device try to drive the
15381dee67eSSudip Mukherjee  *      signal due to SM50x will drive the signal to always high.
15481dee67eSSudip Mukherjee  */
1556c78f4ceSMike Rapoport static void sw_i2c_sda(unsigned char value)
15681dee67eSSudip Mukherjee {
157fe820044SMike Rapoport 	unsigned long gpio_data;
158fe820044SMike Rapoport 	unsigned long gpio_dir;
15981dee67eSSudip Mukherjee 
160fe820044SMike Rapoport 	gpio_dir = PEEK32(sw_i2c_data_gpio_data_dir_reg);
161d3f431d0SIsaac Assegai 	if (value) {    /* High */
1629137f812SMike Rapoport 		/*
1639137f812SMike Rapoport 		 * Set direction as input. This will automatically
1649137f812SMike Rapoport 		 * pull the signal up.
1659137f812SMike Rapoport 		 */
166fe820044SMike Rapoport 		gpio_dir &= ~(1 << sw_i2c_data_gpio);
167fe820044SMike Rapoport 		POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
168d3f431d0SIsaac Assegai 	} else {        /* Low */
16981dee67eSSudip Mukherjee 		/* Set the signal down */
170fe820044SMike Rapoport 		gpio_data = PEEK32(sw_i2c_data_gpio_data_reg);
171fe820044SMike Rapoport 		gpio_data &= ~(1 << sw_i2c_data_gpio);
172fe820044SMike Rapoport 		POKE32(sw_i2c_data_gpio_data_reg, gpio_data);
17381dee67eSSudip Mukherjee 
17481dee67eSSudip Mukherjee 		/* Set direction as output */
175fe820044SMike Rapoport 		gpio_dir |= (1 << sw_i2c_data_gpio);
176fe820044SMike Rapoport 		POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
17781dee67eSSudip Mukherjee 	}
17881dee67eSSudip Mukherjee }
17981dee67eSSudip Mukherjee 
18081dee67eSSudip Mukherjee /*
18181dee67eSSudip Mukherjee  *  This function read the data from the SDA GPIO pin
18281dee67eSSudip Mukherjee  *
18381dee67eSSudip Mukherjee  *  Return Value:
18481dee67eSSudip Mukherjee  *      The SDA data bit sent by the Slave
18581dee67eSSudip Mukherjee  */
1866c78f4ceSMike Rapoport static unsigned char sw_i2c_read_sda(void)
18781dee67eSSudip Mukherjee {
188fe820044SMike Rapoport 	unsigned long gpio_dir;
189fe820044SMike Rapoport 	unsigned long gpio_data;
1909137f812SMike Rapoport 	unsigned long dir_mask = 1 << sw_i2c_data_gpio;
19181dee67eSSudip Mukherjee 
19281dee67eSSudip Mukherjee 	/* Make sure that the direction is input (High) */
193fe820044SMike Rapoport 	gpio_dir = PEEK32(sw_i2c_data_gpio_data_dir_reg);
1949137f812SMike Rapoport 	if ((gpio_dir & dir_mask) != ~dir_mask) {
195fe820044SMike Rapoport 		gpio_dir &= ~(1 << sw_i2c_data_gpio);
196fe820044SMike Rapoport 		POKE32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
19781dee67eSSudip Mukherjee 	}
19881dee67eSSudip Mukherjee 
19981dee67eSSudip Mukherjee 	/* Now read the SDA line */
200fe820044SMike Rapoport 	gpio_data = PEEK32(sw_i2c_data_gpio_data_reg);
201fe820044SMike Rapoport 	if (gpio_data & (1 << sw_i2c_data_gpio))
20281dee67eSSudip Mukherjee 		return 1;
20381dee67eSSudip Mukherjee 	else
20481dee67eSSudip Mukherjee 		return 0;
20581dee67eSSudip Mukherjee }
20681dee67eSSudip Mukherjee 
20781dee67eSSudip Mukherjee /*
20881dee67eSSudip Mukherjee  *  This function sends ACK signal
20981dee67eSSudip Mukherjee  */
2106c78f4ceSMike Rapoport static void sw_i2c_ack(void)
21181dee67eSSudip Mukherjee {
21281dee67eSSudip Mukherjee 	return;  /* Single byte read is ok without it. */
21381dee67eSSudip Mukherjee }
21481dee67eSSudip Mukherjee 
21581dee67eSSudip Mukherjee /*
21681dee67eSSudip Mukherjee  *  This function sends the start command to the slave device
21781dee67eSSudip Mukherjee  */
2186c78f4ceSMike Rapoport static void sw_i2c_start(void)
21981dee67eSSudip Mukherjee {
22081dee67eSSudip Mukherjee 	/* Start I2C */
2216c78f4ceSMike Rapoport 	sw_i2c_sda(1);
2226c78f4ceSMike Rapoport 	sw_i2c_scl(1);
2236c78f4ceSMike Rapoport 	sw_i2c_sda(0);
22481dee67eSSudip Mukherjee }
22581dee67eSSudip Mukherjee 
22681dee67eSSudip Mukherjee /*
22781dee67eSSudip Mukherjee  *  This function sends the stop command to the slave device
22881dee67eSSudip Mukherjee  */
2296c78f4ceSMike Rapoport static void sw_i2c_stop(void)
23081dee67eSSudip Mukherjee {
23181dee67eSSudip Mukherjee 	/* Stop the I2C */
2326c78f4ceSMike Rapoport 	sw_i2c_scl(1);
2336c78f4ceSMike Rapoport 	sw_i2c_sda(0);
2346c78f4ceSMike Rapoport 	sw_i2c_sda(1);
23581dee67eSSudip Mukherjee }
23681dee67eSSudip Mukherjee 
23781dee67eSSudip Mukherjee /*
23881dee67eSSudip Mukherjee  *  This function writes one byte to the slave device
23981dee67eSSudip Mukherjee  *
24081dee67eSSudip Mukherjee  *  Parameters:
24181dee67eSSudip Mukherjee  *      data    - Data to be write to the slave device
24281dee67eSSudip Mukherjee  *
24381dee67eSSudip Mukherjee  *  Return Value:
24481dee67eSSudip Mukherjee  *       0   - Success
24581dee67eSSudip Mukherjee  *      -1   - Fail to write byte
24681dee67eSSudip Mukherjee  */
2476c78f4ceSMike Rapoport static long sw_i2c_write_byte(unsigned char data)
24881dee67eSSudip Mukherjee {
24981dee67eSSudip Mukherjee 	unsigned char value = data;
25081dee67eSSudip Mukherjee 	int i;
25181dee67eSSudip Mukherjee 
25281dee67eSSudip Mukherjee 	/* Sending the data bit by bit */
253d3f431d0SIsaac Assegai 	for (i = 0; i < 8; i++) {
25481dee67eSSudip Mukherjee 		/* Set SCL to low */
2556c78f4ceSMike Rapoport 		sw_i2c_scl(0);
25681dee67eSSudip Mukherjee 
25781dee67eSSudip Mukherjee 		/* Send data bit */
25881dee67eSSudip Mukherjee 		if ((value & 0x80) != 0)
2596c78f4ceSMike Rapoport 			sw_i2c_sda(1);
26081dee67eSSudip Mukherjee 		else
2616c78f4ceSMike Rapoport 			sw_i2c_sda(0);
26281dee67eSSudip Mukherjee 
2636c78f4ceSMike Rapoport 		sw_i2c_wait();
26481dee67eSSudip Mukherjee 
26581dee67eSSudip Mukherjee 		/* Toggle clk line to one */
2666c78f4ceSMike Rapoport 		sw_i2c_scl(1);
2676c78f4ceSMike Rapoport 		sw_i2c_wait();
26881dee67eSSudip Mukherjee 
26981dee67eSSudip Mukherjee 		/* Shift byte to be sent */
27081dee67eSSudip Mukherjee 		value = value << 1;
27181dee67eSSudip Mukherjee 	}
27281dee67eSSudip Mukherjee 
27381dee67eSSudip Mukherjee 	/* Set the SCL Low and SDA High (prepare to get input) */
2746c78f4ceSMike Rapoport 	sw_i2c_scl(0);
2756c78f4ceSMike Rapoport 	sw_i2c_sda(1);
27681dee67eSSudip Mukherjee 
27781dee67eSSudip Mukherjee 	/* Set the SCL High for ack */
2786c78f4ceSMike Rapoport 	sw_i2c_wait();
2796c78f4ceSMike Rapoport 	sw_i2c_scl(1);
2806c78f4ceSMike Rapoport 	sw_i2c_wait();
28181dee67eSSudip Mukherjee 
28281dee67eSSudip Mukherjee 	/* Read SDA, until SDA==0 */
283d3f431d0SIsaac Assegai 	for (i = 0; i < 0xff; i++) {
2846c78f4ceSMike Rapoport 		if (!sw_i2c_read_sda())
28581dee67eSSudip Mukherjee 			break;
28681dee67eSSudip Mukherjee 
2876c78f4ceSMike Rapoport 		sw_i2c_scl(0);
2886c78f4ceSMike Rapoport 		sw_i2c_wait();
2896c78f4ceSMike Rapoport 		sw_i2c_scl(1);
2906c78f4ceSMike Rapoport 		sw_i2c_wait();
29181dee67eSSudip Mukherjee 	}
29281dee67eSSudip Mukherjee 
29381dee67eSSudip Mukherjee 	/* Set the SCL Low and SDA High */
2946c78f4ceSMike Rapoport 	sw_i2c_scl(0);
2956c78f4ceSMike Rapoport 	sw_i2c_sda(1);
29681dee67eSSudip Mukherjee 
29781dee67eSSudip Mukherjee 	if (i < 0xff)
29881dee67eSSudip Mukherjee 		return 0;
29981dee67eSSudip Mukherjee 	else
3006946edd0SSupriya Karanth 		return -1;
30181dee67eSSudip Mukherjee }
30281dee67eSSudip Mukherjee 
30381dee67eSSudip Mukherjee /*
30481dee67eSSudip Mukherjee  *  This function reads one byte from the slave device
30581dee67eSSudip Mukherjee  *
30681dee67eSSudip Mukherjee  *  Parameters:
30781dee67eSSudip Mukherjee  *      ack    - Flag to indicate either to send the acknowledge
30881dee67eSSudip Mukherjee  *            message to the slave device or not
30981dee67eSSudip Mukherjee  *
31081dee67eSSudip Mukherjee  *  Return Value:
31181dee67eSSudip Mukherjee  *      One byte data read from the Slave device
31281dee67eSSudip Mukherjee  */
3136c78f4ceSMike Rapoport static unsigned char sw_i2c_read_byte(unsigned char ack)
31481dee67eSSudip Mukherjee {
31581dee67eSSudip Mukherjee 	int i;
31681dee67eSSudip Mukherjee 	unsigned char data = 0;
31781dee67eSSudip Mukherjee 
318d3f431d0SIsaac Assegai 	for (i = 7; i >= 0; i--) {
31981dee67eSSudip Mukherjee 		/* Set the SCL to Low and SDA to High (Input) */
3206c78f4ceSMike Rapoport 		sw_i2c_scl(0);
3216c78f4ceSMike Rapoport 		sw_i2c_sda(1);
3226c78f4ceSMike Rapoport 		sw_i2c_wait();
32381dee67eSSudip Mukherjee 
32481dee67eSSudip Mukherjee 		/* Set the SCL High */
3256c78f4ceSMike Rapoport 		sw_i2c_scl(1);
3266c78f4ceSMike Rapoport 		sw_i2c_wait();
32781dee67eSSudip Mukherjee 
32881dee67eSSudip Mukherjee 		/* Read data bits from SDA */
3296c78f4ceSMike Rapoport 		data |= (sw_i2c_read_sda() << i);
33081dee67eSSudip Mukherjee 	}
33181dee67eSSudip Mukherjee 
33281dee67eSSudip Mukherjee 	if (ack)
3336c78f4ceSMike Rapoport 		sw_i2c_ack();
33481dee67eSSudip Mukherjee 
33581dee67eSSudip Mukherjee 	/* Set the SCL Low and SDA High */
3366c78f4ceSMike Rapoport 	sw_i2c_scl(0);
3376c78f4ceSMike Rapoport 	sw_i2c_sda(1);
33881dee67eSSudip Mukherjee 
33981dee67eSSudip Mukherjee 	return data;
34081dee67eSSudip Mukherjee }
34181dee67eSSudip Mukherjee 
34281dee67eSSudip Mukherjee /*
34381dee67eSSudip Mukherjee  * This function initializes GPIO port for SW I2C communication.
34481dee67eSSudip Mukherjee  *
34581dee67eSSudip Mukherjee  * Parameters:
346fe820044SMike Rapoport  *      clk_gpio      - The GPIO pin to be used as i2c SCL
347fe820044SMike Rapoport  *      data_gpio     - The GPIO pin to be used as i2c SDA
34881dee67eSSudip Mukherjee  *
34981dee67eSSudip Mukherjee  * Return Value:
35081dee67eSSudip Mukherjee  *      -1   - Fail to initialize the i2c
35181dee67eSSudip Mukherjee  *       0   - Success
35281dee67eSSudip Mukherjee  */
353fe820044SMike Rapoport static long sm750le_i2c_init(unsigned char clk_gpio,
354fe820044SMike Rapoport 			     unsigned char data_gpio)
35581dee67eSSudip Mukherjee {
35681dee67eSSudip Mukherjee 	int i;
35781dee67eSSudip Mukherjee 
35881dee67eSSudip Mukherjee 	/* Initialize the GPIO pin for the i2c Clock Register */
35953bc6b6eSMike Rapoport 	sw_i2c_clk_gpio_data_reg = GPIO_DATA_SM750LE;
36053bc6b6eSMike Rapoport 	sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE;
36181dee67eSSudip Mukherjee 
36281dee67eSSudip Mukherjee 	/* Initialize the Clock GPIO Offset */
363fe820044SMike Rapoport 	sw_i2c_clk_gpio = clk_gpio;
36481dee67eSSudip Mukherjee 
36581dee67eSSudip Mukherjee 	/* Initialize the GPIO pin for the i2c Data Register */
36653bc6b6eSMike Rapoport 	sw_i2c_data_gpio_data_reg = GPIO_DATA_SM750LE;
36753bc6b6eSMike Rapoport 	sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE;
36881dee67eSSudip Mukherjee 
36981dee67eSSudip Mukherjee 	/* Initialize the Data GPIO Offset */
370fe820044SMike Rapoport 	sw_i2c_data_gpio = data_gpio;
37181dee67eSSudip Mukherjee 
37281dee67eSSudip Mukherjee 	/* Note that SM750LE don't have GPIO MUX and power is always on */
37381dee67eSSudip Mukherjee 
37481dee67eSSudip Mukherjee 	/* Clear the i2c lines. */
37581dee67eSSudip Mukherjee 	for (i = 0; i < 9; i++)
3766c78f4ceSMike Rapoport 		sw_i2c_stop();
37781dee67eSSudip Mukherjee 
37881dee67eSSudip Mukherjee 	return 0;
37981dee67eSSudip Mukherjee }
38081dee67eSSudip Mukherjee 
38181dee67eSSudip Mukherjee /*
38281dee67eSSudip Mukherjee  * This function initializes the i2c attributes and bus
38381dee67eSSudip Mukherjee  *
38481dee67eSSudip Mukherjee  * Parameters:
385fe820044SMike Rapoport  *      clk_gpio      - The GPIO pin to be used as i2c SCL
386fe820044SMike Rapoport  *      data_gpio     - The GPIO pin to be used as i2c SDA
38781dee67eSSudip Mukherjee  *
38881dee67eSSudip Mukherjee  * Return Value:
38981dee67eSSudip Mukherjee  *      -1   - Fail to initialize the i2c
39081dee67eSSudip Mukherjee  *       0   - Success
39181dee67eSSudip Mukherjee  */
392f2ea7733SMike Rapoport long sm750_sw_i2c_init(
393fe820044SMike Rapoport 	unsigned char clk_gpio,
394fe820044SMike Rapoport 	unsigned char data_gpio
39581dee67eSSudip Mukherjee )
39681dee67eSSudip Mukherjee {
39781dee67eSSudip Mukherjee 	int i;
39881dee67eSSudip Mukherjee 
3999137f812SMike Rapoport 	/*
4009137f812SMike Rapoport 	 * Return 0 if the GPIO pins to be used is out of range. The
4019137f812SMike Rapoport 	 * range is only from [0..63]
4029137f812SMike Rapoport 	 */
403fe820044SMike Rapoport 	if ((clk_gpio > 31) || (data_gpio > 31))
4046946edd0SSupriya Karanth 		return -1;
40581dee67eSSudip Mukherjee 
40681dee67eSSudip Mukherjee 	if (getChipType() == SM750LE)
407fe820044SMike Rapoport 		return sm750le_i2c_init(clk_gpio, data_gpio);
40881dee67eSSudip Mukherjee 
40981dee67eSSudip Mukherjee 	/* Initialize the GPIO pin for the i2c Clock Register */
41053bc6b6eSMike Rapoport 	sw_i2c_clk_gpio_mux_reg = GPIO_MUX;
41153bc6b6eSMike Rapoport 	sw_i2c_clk_gpio_data_reg = GPIO_DATA;
41253bc6b6eSMike Rapoport 	sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
41381dee67eSSudip Mukherjee 
41481dee67eSSudip Mukherjee 	/* Initialize the Clock GPIO Offset */
415fe820044SMike Rapoport 	sw_i2c_clk_gpio = clk_gpio;
41681dee67eSSudip Mukherjee 
41781dee67eSSudip Mukherjee 	/* Initialize the GPIO pin for the i2c Data Register */
41853bc6b6eSMike Rapoport 	sw_i2c_data_gpio_mux_reg = GPIO_MUX;
41953bc6b6eSMike Rapoport 	sw_i2c_data_gpio_data_reg = GPIO_DATA;
42053bc6b6eSMike Rapoport 	sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
42181dee67eSSudip Mukherjee 
42281dee67eSSudip Mukherjee 	/* Initialize the Data GPIO Offset */
423fe820044SMike Rapoport 	sw_i2c_data_gpio = data_gpio;
42481dee67eSSudip Mukherjee 
42581dee67eSSudip Mukherjee 	/* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
42653bc6b6eSMike Rapoport 	POKE32(sw_i2c_clk_gpio_mux_reg,
42753bc6b6eSMike Rapoport 	       PEEK32(sw_i2c_clk_gpio_mux_reg) & ~(1 << sw_i2c_clk_gpio));
42853bc6b6eSMike Rapoport 	POKE32(sw_i2c_data_gpio_mux_reg,
42953bc6b6eSMike Rapoport 	       PEEK32(sw_i2c_data_gpio_mux_reg) & ~(1 << sw_i2c_data_gpio));
43081dee67eSSudip Mukherjee 
43181dee67eSSudip Mukherjee 	/* Enable GPIO power */
43281dee67eSSudip Mukherjee 	enableGPIO(1);
43381dee67eSSudip Mukherjee 
43481dee67eSSudip Mukherjee 	/* Clear the i2c lines. */
43581dee67eSSudip Mukherjee 	for (i = 0; i < 9; i++)
4366c78f4ceSMike Rapoport 		sw_i2c_stop();
43781dee67eSSudip Mukherjee 
43881dee67eSSudip Mukherjee 	return 0;
43981dee67eSSudip Mukherjee }
44081dee67eSSudip Mukherjee 
44181dee67eSSudip Mukherjee /*
44281dee67eSSudip Mukherjee  *  This function reads the slave device's register
44381dee67eSSudip Mukherjee  *
44481dee67eSSudip Mukherjee  *  Parameters:
445fe820044SMike Rapoport  *      addr   - i2c Slave device address which register
44681dee67eSSudip Mukherjee  *                        to be read from
447fe820044SMike Rapoport  *      reg    - Slave device's register to be read
44881dee67eSSudip Mukherjee  *
44981dee67eSSudip Mukherjee  *  Return Value:
45081dee67eSSudip Mukherjee  *      Register value
45181dee67eSSudip Mukherjee  */
452288836b6SMike Rapoport unsigned char sm750_sw_i2c_read_reg(
453fe820044SMike Rapoport 	unsigned char addr,
454fe820044SMike Rapoport 	unsigned char reg
45581dee67eSSudip Mukherjee )
45681dee67eSSudip Mukherjee {
45781dee67eSSudip Mukherjee 	unsigned char data;
45881dee67eSSudip Mukherjee 
45981dee67eSSudip Mukherjee 	/* Send the Start signal */
4606c78f4ceSMike Rapoport 	sw_i2c_start();
46181dee67eSSudip Mukherjee 
46281dee67eSSudip Mukherjee 	/* Send the device address */
463fe820044SMike Rapoport 	sw_i2c_write_byte(addr);
46481dee67eSSudip Mukherjee 
46581dee67eSSudip Mukherjee 	/* Send the register index */
466fe820044SMike Rapoport 	sw_i2c_write_byte(reg);
46781dee67eSSudip Mukherjee 
46881dee67eSSudip Mukherjee 	/* Get the bus again and get the data from the device read address */
4696c78f4ceSMike Rapoport 	sw_i2c_start();
470fe820044SMike Rapoport 	sw_i2c_write_byte(addr + 1);
4716c78f4ceSMike Rapoport 	data = sw_i2c_read_byte(1);
47281dee67eSSudip Mukherjee 
47381dee67eSSudip Mukherjee 	/* Stop swI2C and release the bus */
4746c78f4ceSMike Rapoport 	sw_i2c_stop();
47581dee67eSSudip Mukherjee 
47681dee67eSSudip Mukherjee 	return data;
47781dee67eSSudip Mukherjee }
47881dee67eSSudip Mukherjee 
47981dee67eSSudip Mukherjee /*
48081dee67eSSudip Mukherjee  *  This function writes a value to the slave device's register
48181dee67eSSudip Mukherjee  *
48281dee67eSSudip Mukherjee  *  Parameters:
483fe820044SMike Rapoport  *      addr            - i2c Slave device address which register
48481dee67eSSudip Mukherjee  *                        to be written
485fe820044SMike Rapoport  *      reg             - Slave device's register to be written
48681dee67eSSudip Mukherjee  *      data            - Data to be written to the register
48781dee67eSSudip Mukherjee  *
48881dee67eSSudip Mukherjee  *  Result:
48981dee67eSSudip Mukherjee  *          0   - Success
49081dee67eSSudip Mukherjee  *         -1   - Fail
49181dee67eSSudip Mukherjee  */
492d33b4204SMike Rapoport long sm750_sw_i2c_write_reg(
493fe820044SMike Rapoport 	unsigned char addr,
494fe820044SMike Rapoport 	unsigned char reg,
49581dee67eSSudip Mukherjee 	unsigned char data
49681dee67eSSudip Mukherjee )
49781dee67eSSudip Mukherjee {
498fe820044SMike Rapoport 	long ret = 0;
49981dee67eSSudip Mukherjee 
50081dee67eSSudip Mukherjee 	/* Send the Start signal */
5016c78f4ceSMike Rapoport 	sw_i2c_start();
50281dee67eSSudip Mukherjee 
50381dee67eSSudip Mukherjee 	/* Send the device address and read the data. All should return success
50481dee67eSSudip Mukherjee 	   in order for the writing processed to be successful
50581dee67eSSudip Mukherjee 	*/
506fe820044SMike Rapoport 	if ((sw_i2c_write_byte(addr) != 0) ||
507fe820044SMike Rapoport 	    (sw_i2c_write_byte(reg) != 0) ||
5086c78f4ceSMike Rapoport 	    (sw_i2c_write_byte(data) != 0)) {
509fe820044SMike Rapoport 		ret = -1;
51081dee67eSSudip Mukherjee 	}
51181dee67eSSudip Mukherjee 
51281dee67eSSudip Mukherjee 	/* Stop i2c and release the bus */
5136c78f4ceSMike Rapoport 	sw_i2c_stop();
51481dee67eSSudip Mukherjee 
515fe820044SMike Rapoport 	return ret;
51681dee67eSSudip Mukherjee }
517