125338628SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2f5016082SEric S. Stone /*
381dee67eSSudip Mukherjee * Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
481dee67eSSudip Mukherjee *
581dee67eSSudip Mukherjee * swi2c.c --- SM750/SM718 DDK
681dee67eSSudip Mukherjee * This file contains the source code for I2C using software
781dee67eSSudip Mukherjee * implementation.
8f5016082SEric S. Stone */
9f5016082SEric S. Stone
10efe9bc08SElise Lennion #include "ddk750_chip.h"
1181dee67eSSudip Mukherjee #include "ddk750_reg.h"
1281dee67eSSudip Mukherjee #include "ddk750_swi2c.h"
1381dee67eSSudip Mukherjee #include "ddk750_power.h"
1481dee67eSSudip Mukherjee
15f5016082SEric S. Stone /*
1681dee67eSSudip Mukherjee * I2C Software Master Driver:
1781dee67eSSudip Mukherjee * ===========================
1881dee67eSSudip Mukherjee * Each i2c cycle is split into 4 sections. Each of these section marks
1981dee67eSSudip Mukherjee * a point in time where the SCL or SDA may be changed.
2081dee67eSSudip Mukherjee *
2181dee67eSSudip Mukherjee * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. |
2281dee67eSSudip Mukherjee * +-------------+-------------+-------------+-------------+
2381dee67eSSudip Mukherjee * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change|
2481dee67eSSudip Mukherjee *
2581dee67eSSudip Mukherjee * ____________ _____________
2681dee67eSSudip Mukherjee * SCL == XXXX _____________ ____________ /
2781dee67eSSudip Mukherjee *
2881dee67eSSudip Mukherjee * I.e. the SCL may only be changed in section 1. and section 3. while
2981dee67eSSudip Mukherjee * the SDA may only be changed in section 2. and section 4. The table
3081dee67eSSudip Mukherjee * below gives the changes for these 2 lines in the varios sections.
3181dee67eSSudip Mukherjee *
3281dee67eSSudip Mukherjee * Section changes Table:
3381dee67eSSudip Mukherjee * ======================
3481dee67eSSudip Mukherjee * blank = no change, L = set bit LOW, H = set bit HIGH
3581dee67eSSudip Mukherjee *
3681dee67eSSudip Mukherjee * | 1.| 2.| 3.| 4.|
3781dee67eSSudip Mukherjee * ---------------+---+---+---+---+
3881dee67eSSudip Mukherjee * Tx Start SDA | | H | | L |
3981dee67eSSudip Mukherjee * SCL | L | | H | |
4081dee67eSSudip Mukherjee * ---------------+---+---+---+---+
4181dee67eSSudip Mukherjee * Tx Stop SDA | | L | | H |
4281dee67eSSudip Mukherjee * SCL | L | | H | |
4381dee67eSSudip Mukherjee * ---------------+---+---+---+---+
4481dee67eSSudip Mukherjee * Tx bit H SDA | | H | | |
4581dee67eSSudip Mukherjee * SCL | L | | H | |
4681dee67eSSudip Mukherjee * ---------------+---+---+---+---+
4781dee67eSSudip Mukherjee * Tx bit L SDA | | L | | |
4881dee67eSSudip Mukherjee * SCL | L | | H | |
4981dee67eSSudip Mukherjee * ---------------+---+---+---+---+
5081dee67eSSudip Mukherjee *
51f5016082SEric S. Stone */
5281dee67eSSudip Mukherjee
5381dee67eSSudip Mukherjee /* GPIO pins used for this I2C. It ranges from 0 to 63. */
5453bc6b6eSMike Rapoport static unsigned char sw_i2c_clk_gpio = DEFAULT_I2C_SCL;
5553bc6b6eSMike Rapoport static unsigned char sw_i2c_data_gpio = DEFAULT_I2C_SDA;
5681dee67eSSudip Mukherjee
5781dee67eSSudip Mukherjee /*
5881dee67eSSudip Mukherjee * Below is the variable declaration for the GPIO pin register usage
5981dee67eSSudip Mukherjee * for the i2c Clock and i2c Data.
6081dee67eSSudip Mukherjee *
6181dee67eSSudip Mukherjee * Note:
6281dee67eSSudip Mukherjee * Notice that the GPIO usage for the i2c clock and i2c Data are
6381dee67eSSudip Mukherjee * separated. This is to make this code flexible enough when
6481dee67eSSudip Mukherjee * two separate GPIO pins for the clock and data are located
6581dee67eSSudip Mukherjee * in two different GPIO register set (worst case).
6681dee67eSSudip Mukherjee */
6781dee67eSSudip Mukherjee
6881dee67eSSudip Mukherjee /* i2c Clock GPIO Register usage */
6953bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_mux_reg = GPIO_MUX;
7053bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_reg = GPIO_DATA;
7153bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
7281dee67eSSudip Mukherjee
7381dee67eSSudip Mukherjee /* i2c Data GPIO Register usage */
7453bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_mux_reg = GPIO_MUX;
7553bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_reg = GPIO_DATA;
7653bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
7781dee67eSSudip Mukherjee
7881dee67eSSudip Mukherjee /*
7981dee67eSSudip Mukherjee * This function puts a delay between command
8081dee67eSSudip Mukherjee */
sw_i2c_wait(void)816c78f4ceSMike Rapoport static void sw_i2c_wait(void)
8281dee67eSSudip Mukherjee {
8381dee67eSSudip Mukherjee /* find a bug:
8481dee67eSSudip Mukherjee * peekIO method works well before suspend/resume
8581dee67eSSudip Mukherjee * but after suspend, peekIO(0x3ce,0x61) & 0x10
8681dee67eSSudip Mukherjee * always be non-zero,which makes the while loop
8781dee67eSSudip Mukherjee * never finish.
8881dee67eSSudip Mukherjee * use non-ultimate for loop below is safe
8935e4d8caSElizabeth Ferdman */
901282badeSMike Rapoport
9181dee67eSSudip Mukherjee /* Change wait algorithm to use PCI bus clock,
9235e4d8caSElizabeth Ferdman * it's more reliable than counter loop ..
9335e4d8caSElizabeth Ferdman * write 0x61 to 0x3ce and read from 0x3cf
9481dee67eSSudip Mukherjee */
95fe820044SMike Rapoport int i, tmp;
9681dee67eSSudip Mukherjee
97d3f431d0SIsaac Assegai for (i = 0; i < 600; i++) {
98fe820044SMike Rapoport tmp = i;
99fe820044SMike Rapoport tmp += i;
10081dee67eSSudip Mukherjee }
10181dee67eSSudip Mukherjee }
10281dee67eSSudip Mukherjee
10381dee67eSSudip Mukherjee /*
10481dee67eSSudip Mukherjee * This function set/reset the SCL GPIO pin
10581dee67eSSudip Mukherjee *
10681dee67eSSudip Mukherjee * Parameters:
10781dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high)
10881dee67eSSudip Mukherjee *
10981dee67eSSudip Mukherjee * Notes:
11081dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up
11181dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the
11281dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the
11381dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high.
11481dee67eSSudip Mukherjee */
sw_i2c_scl(unsigned char value)1156c78f4ceSMike Rapoport static void sw_i2c_scl(unsigned char value)
11681dee67eSSudip Mukherjee {
117fe820044SMike Rapoport unsigned long gpio_data;
118fe820044SMike Rapoport unsigned long gpio_dir;
11981dee67eSSudip Mukherjee
120c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_clk_gpio_data_dir_reg);
121d3f431d0SIsaac Assegai if (value) { /* High */
1229137f812SMike Rapoport /*
1239137f812SMike Rapoport * Set direction as input. This will automatically
1249137f812SMike Rapoport * pull the signal up.
1259137f812SMike Rapoport */
126fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_clk_gpio);
127c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir);
128d3f431d0SIsaac Assegai } else { /* Low */
12981dee67eSSudip Mukherjee /* Set the signal down */
130c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_clk_gpio_data_reg);
131fe820044SMike Rapoport gpio_data &= ~(1 << sw_i2c_clk_gpio);
132c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_reg, gpio_data);
13381dee67eSSudip Mukherjee
13481dee67eSSudip Mukherjee /* Set direction as output */
135fe820044SMike Rapoport gpio_dir |= (1 << sw_i2c_clk_gpio);
136c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir);
13781dee67eSSudip Mukherjee }
13881dee67eSSudip Mukherjee }
13981dee67eSSudip Mukherjee
14081dee67eSSudip Mukherjee /*
14181dee67eSSudip Mukherjee * This function set/reset the SDA GPIO pin
14281dee67eSSudip Mukherjee *
14381dee67eSSudip Mukherjee * Parameters:
14481dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high)
14581dee67eSSudip Mukherjee *
14681dee67eSSudip Mukherjee * Notes:
14781dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up
14881dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the
14981dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the
15081dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high.
15181dee67eSSudip Mukherjee */
sw_i2c_sda(unsigned char value)1526c78f4ceSMike Rapoport static void sw_i2c_sda(unsigned char value)
15381dee67eSSudip Mukherjee {
154fe820044SMike Rapoport unsigned long gpio_data;
155fe820044SMike Rapoport unsigned long gpio_dir;
15681dee67eSSudip Mukherjee
157c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_data_gpio_data_dir_reg);
158d3f431d0SIsaac Assegai if (value) { /* High */
1599137f812SMike Rapoport /*
1609137f812SMike Rapoport * Set direction as input. This will automatically
1619137f812SMike Rapoport * pull the signal up.
1629137f812SMike Rapoport */
163fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_data_gpio);
164c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
165d3f431d0SIsaac Assegai } else { /* Low */
16681dee67eSSudip Mukherjee /* Set the signal down */
167c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_data_gpio_data_reg);
168fe820044SMike Rapoport gpio_data &= ~(1 << sw_i2c_data_gpio);
169c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_reg, gpio_data);
17081dee67eSSudip Mukherjee
17181dee67eSSudip Mukherjee /* Set direction as output */
172fe820044SMike Rapoport gpio_dir |= (1 << sw_i2c_data_gpio);
173c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
17481dee67eSSudip Mukherjee }
17581dee67eSSudip Mukherjee }
17681dee67eSSudip Mukherjee
17781dee67eSSudip Mukherjee /*
17881dee67eSSudip Mukherjee * This function read the data from the SDA GPIO pin
17981dee67eSSudip Mukherjee *
18081dee67eSSudip Mukherjee * Return Value:
18181dee67eSSudip Mukherjee * The SDA data bit sent by the Slave
18281dee67eSSudip Mukherjee */
sw_i2c_read_sda(void)1836c78f4ceSMike Rapoport static unsigned char sw_i2c_read_sda(void)
18481dee67eSSudip Mukherjee {
185fe820044SMike Rapoport unsigned long gpio_dir;
186fe820044SMike Rapoport unsigned long gpio_data;
1879137f812SMike Rapoport unsigned long dir_mask = 1 << sw_i2c_data_gpio;
18881dee67eSSudip Mukherjee
18981dee67eSSudip Mukherjee /* Make sure that the direction is input (High) */
190c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_data_gpio_data_dir_reg);
1919137f812SMike Rapoport if ((gpio_dir & dir_mask) != ~dir_mask) {
192fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_data_gpio);
193c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir);
19481dee67eSSudip Mukherjee }
19581dee67eSSudip Mukherjee
19681dee67eSSudip Mukherjee /* Now read the SDA line */
197c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_data_gpio_data_reg);
198fe820044SMike Rapoport if (gpio_data & (1 << sw_i2c_data_gpio))
19981dee67eSSudip Mukherjee return 1;
20081dee67eSSudip Mukherjee else
20181dee67eSSudip Mukherjee return 0;
20281dee67eSSudip Mukherjee }
20381dee67eSSudip Mukherjee
20481dee67eSSudip Mukherjee /*
20581dee67eSSudip Mukherjee * This function sends ACK signal
20681dee67eSSudip Mukherjee */
sw_i2c_ack(void)2076c78f4ceSMike Rapoport static void sw_i2c_ack(void)
20881dee67eSSudip Mukherjee {
20981dee67eSSudip Mukherjee return; /* Single byte read is ok without it. */
21081dee67eSSudip Mukherjee }
21181dee67eSSudip Mukherjee
21281dee67eSSudip Mukherjee /*
21381dee67eSSudip Mukherjee * This function sends the start command to the slave device
21481dee67eSSudip Mukherjee */
sw_i2c_start(void)2156c78f4ceSMike Rapoport static void sw_i2c_start(void)
21681dee67eSSudip Mukherjee {
21781dee67eSSudip Mukherjee /* Start I2C */
2186c78f4ceSMike Rapoport sw_i2c_sda(1);
2196c78f4ceSMike Rapoport sw_i2c_scl(1);
2206c78f4ceSMike Rapoport sw_i2c_sda(0);
22181dee67eSSudip Mukherjee }
22281dee67eSSudip Mukherjee
22381dee67eSSudip Mukherjee /*
22481dee67eSSudip Mukherjee * This function sends the stop command to the slave device
22581dee67eSSudip Mukherjee */
sw_i2c_stop(void)2266c78f4ceSMike Rapoport static void sw_i2c_stop(void)
22781dee67eSSudip Mukherjee {
22881dee67eSSudip Mukherjee /* Stop the I2C */
2296c78f4ceSMike Rapoport sw_i2c_scl(1);
2306c78f4ceSMike Rapoport sw_i2c_sda(0);
2316c78f4ceSMike Rapoport sw_i2c_sda(1);
23281dee67eSSudip Mukherjee }
23381dee67eSSudip Mukherjee
23481dee67eSSudip Mukherjee /*
23581dee67eSSudip Mukherjee * This function writes one byte to the slave device
23681dee67eSSudip Mukherjee *
23781dee67eSSudip Mukherjee * Parameters:
23881dee67eSSudip Mukherjee * data - Data to be write to the slave device
23981dee67eSSudip Mukherjee *
24081dee67eSSudip Mukherjee * Return Value:
24181dee67eSSudip Mukherjee * 0 - Success
24281dee67eSSudip Mukherjee * -1 - Fail to write byte
24381dee67eSSudip Mukherjee */
sw_i2c_write_byte(unsigned char data)2446c78f4ceSMike Rapoport static long sw_i2c_write_byte(unsigned char data)
24581dee67eSSudip Mukherjee {
24681dee67eSSudip Mukherjee unsigned char value = data;
24781dee67eSSudip Mukherjee int i;
24881dee67eSSudip Mukherjee
24981dee67eSSudip Mukherjee /* Sending the data bit by bit */
250d3f431d0SIsaac Assegai for (i = 0; i < 8; i++) {
25181dee67eSSudip Mukherjee /* Set SCL to low */
2526c78f4ceSMike Rapoport sw_i2c_scl(0);
25381dee67eSSudip Mukherjee
25481dee67eSSudip Mukherjee /* Send data bit */
25581dee67eSSudip Mukherjee if ((value & 0x80) != 0)
2566c78f4ceSMike Rapoport sw_i2c_sda(1);
25781dee67eSSudip Mukherjee else
2586c78f4ceSMike Rapoport sw_i2c_sda(0);
25981dee67eSSudip Mukherjee
2606c78f4ceSMike Rapoport sw_i2c_wait();
26181dee67eSSudip Mukherjee
26281dee67eSSudip Mukherjee /* Toggle clk line to one */
2636c78f4ceSMike Rapoport sw_i2c_scl(1);
2646c78f4ceSMike Rapoport sw_i2c_wait();
26581dee67eSSudip Mukherjee
26681dee67eSSudip Mukherjee /* Shift byte to be sent */
26781dee67eSSudip Mukherjee value = value << 1;
26881dee67eSSudip Mukherjee }
26981dee67eSSudip Mukherjee
27081dee67eSSudip Mukherjee /* Set the SCL Low and SDA High (prepare to get input) */
2716c78f4ceSMike Rapoport sw_i2c_scl(0);
2726c78f4ceSMike Rapoport sw_i2c_sda(1);
27381dee67eSSudip Mukherjee
27481dee67eSSudip Mukherjee /* Set the SCL High for ack */
2756c78f4ceSMike Rapoport sw_i2c_wait();
2766c78f4ceSMike Rapoport sw_i2c_scl(1);
2776c78f4ceSMike Rapoport sw_i2c_wait();
27881dee67eSSudip Mukherjee
27981dee67eSSudip Mukherjee /* Read SDA, until SDA==0 */
280d3f431d0SIsaac Assegai for (i = 0; i < 0xff; i++) {
2816c78f4ceSMike Rapoport if (!sw_i2c_read_sda())
28281dee67eSSudip Mukherjee break;
28381dee67eSSudip Mukherjee
2846c78f4ceSMike Rapoport sw_i2c_scl(0);
2856c78f4ceSMike Rapoport sw_i2c_wait();
2866c78f4ceSMike Rapoport sw_i2c_scl(1);
2876c78f4ceSMike Rapoport sw_i2c_wait();
28881dee67eSSudip Mukherjee }
28981dee67eSSudip Mukherjee
29081dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */
2916c78f4ceSMike Rapoport sw_i2c_scl(0);
2926c78f4ceSMike Rapoport sw_i2c_sda(1);
29381dee67eSSudip Mukherjee
29481dee67eSSudip Mukherjee if (i < 0xff)
29581dee67eSSudip Mukherjee return 0;
29681dee67eSSudip Mukherjee else
2976946edd0SSupriya Karanth return -1;
29881dee67eSSudip Mukherjee }
29981dee67eSSudip Mukherjee
30081dee67eSSudip Mukherjee /*
30181dee67eSSudip Mukherjee * This function reads one byte from the slave device
30281dee67eSSudip Mukherjee *
30381dee67eSSudip Mukherjee * Parameters:
30481dee67eSSudip Mukherjee * ack - Flag to indicate either to send the acknowledge
30581dee67eSSudip Mukherjee * message to the slave device or not
30681dee67eSSudip Mukherjee *
30781dee67eSSudip Mukherjee * Return Value:
30881dee67eSSudip Mukherjee * One byte data read from the Slave device
30981dee67eSSudip Mukherjee */
sw_i2c_read_byte(unsigned char ack)3106c78f4ceSMike Rapoport static unsigned char sw_i2c_read_byte(unsigned char ack)
31181dee67eSSudip Mukherjee {
31281dee67eSSudip Mukherjee int i;
31381dee67eSSudip Mukherjee unsigned char data = 0;
31481dee67eSSudip Mukherjee
315d3f431d0SIsaac Assegai for (i = 7; i >= 0; i--) {
31681dee67eSSudip Mukherjee /* Set the SCL to Low and SDA to High (Input) */
3176c78f4ceSMike Rapoport sw_i2c_scl(0);
3186c78f4ceSMike Rapoport sw_i2c_sda(1);
3196c78f4ceSMike Rapoport sw_i2c_wait();
32081dee67eSSudip Mukherjee
32181dee67eSSudip Mukherjee /* Set the SCL High */
3226c78f4ceSMike Rapoport sw_i2c_scl(1);
3236c78f4ceSMike Rapoport sw_i2c_wait();
32481dee67eSSudip Mukherjee
32581dee67eSSudip Mukherjee /* Read data bits from SDA */
3266c78f4ceSMike Rapoport data |= (sw_i2c_read_sda() << i);
32781dee67eSSudip Mukherjee }
32881dee67eSSudip Mukherjee
32981dee67eSSudip Mukherjee if (ack)
3306c78f4ceSMike Rapoport sw_i2c_ack();
33181dee67eSSudip Mukherjee
33281dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */
3336c78f4ceSMike Rapoport sw_i2c_scl(0);
3346c78f4ceSMike Rapoport sw_i2c_sda(1);
33581dee67eSSudip Mukherjee
33681dee67eSSudip Mukherjee return data;
33781dee67eSSudip Mukherjee }
33881dee67eSSudip Mukherjee
33981dee67eSSudip Mukherjee /*
34081dee67eSSudip Mukherjee * This function initializes GPIO port for SW I2C communication.
34181dee67eSSudip Mukherjee *
34281dee67eSSudip Mukherjee * Parameters:
343fe820044SMike Rapoport * clk_gpio - The GPIO pin to be used as i2c SCL
344fe820044SMike Rapoport * data_gpio - The GPIO pin to be used as i2c SDA
34581dee67eSSudip Mukherjee *
34681dee67eSSudip Mukherjee * Return Value:
34781dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c
34881dee67eSSudip Mukherjee * 0 - Success
34981dee67eSSudip Mukherjee */
sm750le_i2c_init(unsigned char clk_gpio,unsigned char data_gpio)350c9750456SMatej Dujava static long sm750le_i2c_init(unsigned char clk_gpio, unsigned char data_gpio)
35181dee67eSSudip Mukherjee {
35281dee67eSSudip Mukherjee int i;
35381dee67eSSudip Mukherjee
35481dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */
35553bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_reg = GPIO_DATA_SM750LE;
35653bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE;
35781dee67eSSudip Mukherjee
35881dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */
359fe820044SMike Rapoport sw_i2c_clk_gpio = clk_gpio;
36081dee67eSSudip Mukherjee
36181dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */
36253bc6b6eSMike Rapoport sw_i2c_data_gpio_data_reg = GPIO_DATA_SM750LE;
36353bc6b6eSMike Rapoport sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE;
36481dee67eSSudip Mukherjee
36581dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */
366fe820044SMike Rapoport sw_i2c_data_gpio = data_gpio;
36781dee67eSSudip Mukherjee
36881dee67eSSudip Mukherjee /* Note that SM750LE don't have GPIO MUX and power is always on */
36981dee67eSSudip Mukherjee
37081dee67eSSudip Mukherjee /* Clear the i2c lines. */
37181dee67eSSudip Mukherjee for (i = 0; i < 9; i++)
3726c78f4ceSMike Rapoport sw_i2c_stop();
37381dee67eSSudip Mukherjee
37481dee67eSSudip Mukherjee return 0;
37581dee67eSSudip Mukherjee }
37681dee67eSSudip Mukherjee
37781dee67eSSudip Mukherjee /*
37881dee67eSSudip Mukherjee * This function initializes the i2c attributes and bus
37981dee67eSSudip Mukherjee *
38081dee67eSSudip Mukherjee * Parameters:
381fe820044SMike Rapoport * clk_gpio - The GPIO pin to be used as i2c SCL
382fe820044SMike Rapoport * data_gpio - The GPIO pin to be used as i2c SDA
38381dee67eSSudip Mukherjee *
38481dee67eSSudip Mukherjee * Return Value:
38581dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c
38681dee67eSSudip Mukherjee * 0 - Success
38781dee67eSSudip Mukherjee */
sm750_sw_i2c_init(unsigned char clk_gpio,unsigned char data_gpio)388c9750456SMatej Dujava long sm750_sw_i2c_init(unsigned char clk_gpio, unsigned char data_gpio)
38981dee67eSSudip Mukherjee {
39081dee67eSSudip Mukherjee int i;
39181dee67eSSudip Mukherjee
3929137f812SMike Rapoport /*
3939137f812SMike Rapoport * Return 0 if the GPIO pins to be used is out of range. The
3949137f812SMike Rapoport * range is only from [0..63]
3959137f812SMike Rapoport */
396fe820044SMike Rapoport if ((clk_gpio > 31) || (data_gpio > 31))
3976946edd0SSupriya Karanth return -1;
39881dee67eSSudip Mukherjee
39906a4f429SMoshe Green if (sm750_get_chip_type() == SM750LE)
400fe820044SMike Rapoport return sm750le_i2c_init(clk_gpio, data_gpio);
40181dee67eSSudip Mukherjee
40281dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */
40353bc6b6eSMike Rapoport sw_i2c_clk_gpio_mux_reg = GPIO_MUX;
40453bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_reg = GPIO_DATA;
40553bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
40681dee67eSSudip Mukherjee
40781dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */
408fe820044SMike Rapoport sw_i2c_clk_gpio = clk_gpio;
40981dee67eSSudip Mukherjee
41081dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */
41153bc6b6eSMike Rapoport sw_i2c_data_gpio_mux_reg = GPIO_MUX;
41253bc6b6eSMike Rapoport sw_i2c_data_gpio_data_reg = GPIO_DATA;
41353bc6b6eSMike Rapoport sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION;
41481dee67eSSudip Mukherjee
41581dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */
416fe820044SMike Rapoport sw_i2c_data_gpio = data_gpio;
41781dee67eSSudip Mukherjee
41881dee67eSSudip Mukherjee /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
419c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_mux_reg,
420c075b6f2SMatthieu Simon peek32(sw_i2c_clk_gpio_mux_reg) & ~(1 << sw_i2c_clk_gpio));
421c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_mux_reg,
422c075b6f2SMatthieu Simon peek32(sw_i2c_data_gpio_mux_reg) & ~(1 << sw_i2c_data_gpio));
42381dee67eSSudip Mukherjee
42481dee67eSSudip Mukherjee /* Enable GPIO power */
42552d0744dSArnd Bergmann sm750_enable_gpio(1);
42681dee67eSSudip Mukherjee
42781dee67eSSudip Mukherjee /* Clear the i2c lines. */
42881dee67eSSudip Mukherjee for (i = 0; i < 9; i++)
4296c78f4ceSMike Rapoport sw_i2c_stop();
43081dee67eSSudip Mukherjee
43181dee67eSSudip Mukherjee return 0;
43281dee67eSSudip Mukherjee }
43381dee67eSSudip Mukherjee
43481dee67eSSudip Mukherjee /*
43581dee67eSSudip Mukherjee * This function reads the slave device's register
43681dee67eSSudip Mukherjee *
43781dee67eSSudip Mukherjee * Parameters:
438fe820044SMike Rapoport * addr - i2c Slave device address which register
43981dee67eSSudip Mukherjee * to be read from
440fe820044SMike Rapoport * reg - Slave device's register to be read
44181dee67eSSudip Mukherjee *
44281dee67eSSudip Mukherjee * Return Value:
44381dee67eSSudip Mukherjee * Register value
44481dee67eSSudip Mukherjee */
sm750_sw_i2c_read_reg(unsigned char addr,unsigned char reg)445c9750456SMatej Dujava unsigned char sm750_sw_i2c_read_reg(unsigned char addr, unsigned char reg)
44681dee67eSSudip Mukherjee {
44781dee67eSSudip Mukherjee unsigned char data;
44881dee67eSSudip Mukherjee
44981dee67eSSudip Mukherjee /* Send the Start signal */
4506c78f4ceSMike Rapoport sw_i2c_start();
45181dee67eSSudip Mukherjee
45281dee67eSSudip Mukherjee /* Send the device address */
453fe820044SMike Rapoport sw_i2c_write_byte(addr);
45481dee67eSSudip Mukherjee
45581dee67eSSudip Mukherjee /* Send the register index */
456fe820044SMike Rapoport sw_i2c_write_byte(reg);
45781dee67eSSudip Mukherjee
45881dee67eSSudip Mukherjee /* Get the bus again and get the data from the device read address */
4596c78f4ceSMike Rapoport sw_i2c_start();
460fe820044SMike Rapoport sw_i2c_write_byte(addr + 1);
4616c78f4ceSMike Rapoport data = sw_i2c_read_byte(1);
46281dee67eSSudip Mukherjee
46381dee67eSSudip Mukherjee /* Stop swI2C and release the bus */
4646c78f4ceSMike Rapoport sw_i2c_stop();
46581dee67eSSudip Mukherjee
46681dee67eSSudip Mukherjee return data;
46781dee67eSSudip Mukherjee }
46881dee67eSSudip Mukherjee
46981dee67eSSudip Mukherjee /*
47081dee67eSSudip Mukherjee * This function writes a value to the slave device's register
47181dee67eSSudip Mukherjee *
47281dee67eSSudip Mukherjee * Parameters:
473fe820044SMike Rapoport * addr - i2c Slave device address which register
47481dee67eSSudip Mukherjee * to be written
475fe820044SMike Rapoport * reg - Slave device's register to be written
47681dee67eSSudip Mukherjee * data - Data to be written to the register
47781dee67eSSudip Mukherjee *
47881dee67eSSudip Mukherjee * Result:
47981dee67eSSudip Mukherjee * 0 - Success
48081dee67eSSudip Mukherjee * -1 - Fail
48181dee67eSSudip Mukherjee */
sm750_sw_i2c_write_reg(unsigned char addr,unsigned char reg,unsigned char data)482c9750456SMatej Dujava long sm750_sw_i2c_write_reg(unsigned char addr,
483fe820044SMike Rapoport unsigned char reg,
484c9750456SMatej Dujava unsigned char data)
48581dee67eSSudip Mukherjee {
486fe820044SMike Rapoport long ret = 0;
48781dee67eSSudip Mukherjee
48881dee67eSSudip Mukherjee /* Send the Start signal */
4896c78f4ceSMike Rapoport sw_i2c_start();
49081dee67eSSudip Mukherjee
49181dee67eSSudip Mukherjee /* Send the device address and read the data. All should return success
49235e4d8caSElizabeth Ferdman * in order for the writing processed to be successful
49381dee67eSSudip Mukherjee */
494fe820044SMike Rapoport if ((sw_i2c_write_byte(addr) != 0) ||
495fe820044SMike Rapoport (sw_i2c_write_byte(reg) != 0) ||
4966c78f4ceSMike Rapoport (sw_i2c_write_byte(data) != 0)) {
497fe820044SMike Rapoport ret = -1;
49881dee67eSSudip Mukherjee }
49981dee67eSSudip Mukherjee
50081dee67eSSudip Mukherjee /* Stop i2c and release the bus */
5016c78f4ceSMike Rapoport sw_i2c_stop();
50281dee67eSSudip Mukherjee
503fe820044SMike Rapoport return ret;
50481dee67eSSudip Mukherjee }
505