1f5016082SEric S. Stone /* 281dee67eSSudip Mukherjee * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) 381dee67eSSudip Mukherjee * 481dee67eSSudip Mukherjee * All rights are reserved. Reproduction or in part is prohibited 581dee67eSSudip Mukherjee * without the written consent of the copyright owner. 681dee67eSSudip Mukherjee * 781dee67eSSudip Mukherjee * swi2c.c --- SM750/SM718 DDK 881dee67eSSudip Mukherjee * This file contains the source code for I2C using software 981dee67eSSudip Mukherjee * implementation. 10f5016082SEric S. Stone */ 11f5016082SEric S. Stone 12efe9bc08SElise Lennion #include "ddk750_chip.h" 1381dee67eSSudip Mukherjee #include "ddk750_reg.h" 1481dee67eSSudip Mukherjee #include "ddk750_swi2c.h" 1581dee67eSSudip Mukherjee #include "ddk750_power.h" 1681dee67eSSudip Mukherjee 17f5016082SEric S. Stone /* 1881dee67eSSudip Mukherjee * I2C Software Master Driver: 1981dee67eSSudip Mukherjee * =========================== 2081dee67eSSudip Mukherjee * Each i2c cycle is split into 4 sections. Each of these section marks 2181dee67eSSudip Mukherjee * a point in time where the SCL or SDA may be changed. 2281dee67eSSudip Mukherjee * 2381dee67eSSudip Mukherjee * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. | 2481dee67eSSudip Mukherjee * +-------------+-------------+-------------+-------------+ 2581dee67eSSudip Mukherjee * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| 2681dee67eSSudip Mukherjee * 2781dee67eSSudip Mukherjee * ____________ _____________ 2881dee67eSSudip Mukherjee * SCL == XXXX _____________ ____________ / 2981dee67eSSudip Mukherjee * 3081dee67eSSudip Mukherjee * I.e. the SCL may only be changed in section 1. and section 3. while 3181dee67eSSudip Mukherjee * the SDA may only be changed in section 2. and section 4. The table 3281dee67eSSudip Mukherjee * below gives the changes for these 2 lines in the varios sections. 3381dee67eSSudip Mukherjee * 3481dee67eSSudip Mukherjee * Section changes Table: 3581dee67eSSudip Mukherjee * ====================== 3681dee67eSSudip Mukherjee * blank = no change, L = set bit LOW, H = set bit HIGH 3781dee67eSSudip Mukherjee * 3881dee67eSSudip Mukherjee * | 1.| 2.| 3.| 4.| 3981dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4081dee67eSSudip Mukherjee * Tx Start SDA | | H | | L | 4181dee67eSSudip Mukherjee * SCL | L | | H | | 4281dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4381dee67eSSudip Mukherjee * Tx Stop SDA | | L | | H | 4481dee67eSSudip Mukherjee * SCL | L | | H | | 4581dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4681dee67eSSudip Mukherjee * Tx bit H SDA | | H | | | 4781dee67eSSudip Mukherjee * SCL | L | | H | | 4881dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4981dee67eSSudip Mukherjee * Tx bit L SDA | | L | | | 5081dee67eSSudip Mukherjee * SCL | L | | H | | 5181dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 5281dee67eSSudip Mukherjee * 53f5016082SEric S. Stone */ 5481dee67eSSudip Mukherjee 5581dee67eSSudip Mukherjee /* GPIO pins used for this I2C. It ranges from 0 to 63. */ 5653bc6b6eSMike Rapoport static unsigned char sw_i2c_clk_gpio = DEFAULT_I2C_SCL; 5753bc6b6eSMike Rapoport static unsigned char sw_i2c_data_gpio = DEFAULT_I2C_SDA; 5881dee67eSSudip Mukherjee 5981dee67eSSudip Mukherjee /* 6081dee67eSSudip Mukherjee * Below is the variable declaration for the GPIO pin register usage 6181dee67eSSudip Mukherjee * for the i2c Clock and i2c Data. 6281dee67eSSudip Mukherjee * 6381dee67eSSudip Mukherjee * Note: 6481dee67eSSudip Mukherjee * Notice that the GPIO usage for the i2c clock and i2c Data are 6581dee67eSSudip Mukherjee * separated. This is to make this code flexible enough when 6681dee67eSSudip Mukherjee * two separate GPIO pins for the clock and data are located 6781dee67eSSudip Mukherjee * in two different GPIO register set (worst case). 6881dee67eSSudip Mukherjee */ 6981dee67eSSudip Mukherjee 7081dee67eSSudip Mukherjee /* i2c Clock GPIO Register usage */ 7153bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_mux_reg = GPIO_MUX; 7253bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_reg = GPIO_DATA; 7353bc6b6eSMike Rapoport static unsigned long sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION; 7481dee67eSSudip Mukherjee 7581dee67eSSudip Mukherjee /* i2c Data GPIO Register usage */ 7653bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_mux_reg = GPIO_MUX; 7753bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_reg = GPIO_DATA; 7853bc6b6eSMike Rapoport static unsigned long sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION; 7981dee67eSSudip Mukherjee 8081dee67eSSudip Mukherjee /* 8181dee67eSSudip Mukherjee * This function puts a delay between command 8281dee67eSSudip Mukherjee */ 836c78f4ceSMike Rapoport static void sw_i2c_wait(void) 8481dee67eSSudip Mukherjee { 8581dee67eSSudip Mukherjee /* find a bug: 8681dee67eSSudip Mukherjee * peekIO method works well before suspend/resume 8781dee67eSSudip Mukherjee * but after suspend, peekIO(0x3ce,0x61) & 0x10 8881dee67eSSudip Mukherjee * always be non-zero,which makes the while loop 8981dee67eSSudip Mukherjee * never finish. 9081dee67eSSudip Mukherjee * use non-ultimate for loop below is safe 9135e4d8caSElizabeth Ferdman */ 921282badeSMike Rapoport 9381dee67eSSudip Mukherjee /* Change wait algorithm to use PCI bus clock, 9435e4d8caSElizabeth Ferdman * it's more reliable than counter loop .. 9535e4d8caSElizabeth Ferdman * write 0x61 to 0x3ce and read from 0x3cf 9681dee67eSSudip Mukherjee */ 97fe820044SMike Rapoport int i, tmp; 9881dee67eSSudip Mukherjee 99d3f431d0SIsaac Assegai for (i = 0; i < 600; i++) { 100fe820044SMike Rapoport tmp = i; 101fe820044SMike Rapoport tmp += i; 10281dee67eSSudip Mukherjee } 10381dee67eSSudip Mukherjee } 10481dee67eSSudip Mukherjee 10581dee67eSSudip Mukherjee /* 10681dee67eSSudip Mukherjee * This function set/reset the SCL GPIO pin 10781dee67eSSudip Mukherjee * 10881dee67eSSudip Mukherjee * Parameters: 10981dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 11081dee67eSSudip Mukherjee * 11181dee67eSSudip Mukherjee * Notes: 11281dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up 11381dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the 11481dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the 11581dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high. 11681dee67eSSudip Mukherjee */ 1176c78f4ceSMike Rapoport static void sw_i2c_scl(unsigned char value) 11881dee67eSSudip Mukherjee { 119fe820044SMike Rapoport unsigned long gpio_data; 120fe820044SMike Rapoport unsigned long gpio_dir; 12181dee67eSSudip Mukherjee 122c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_clk_gpio_data_dir_reg); 123d3f431d0SIsaac Assegai if (value) { /* High */ 1249137f812SMike Rapoport /* 1259137f812SMike Rapoport * Set direction as input. This will automatically 1269137f812SMike Rapoport * pull the signal up. 1279137f812SMike Rapoport */ 128fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_clk_gpio); 129c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir); 130d3f431d0SIsaac Assegai } else { /* Low */ 13181dee67eSSudip Mukherjee /* Set the signal down */ 132c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_clk_gpio_data_reg); 133fe820044SMike Rapoport gpio_data &= ~(1 << sw_i2c_clk_gpio); 134c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_reg, gpio_data); 13581dee67eSSudip Mukherjee 13681dee67eSSudip Mukherjee /* Set direction as output */ 137fe820044SMike Rapoport gpio_dir |= (1 << sw_i2c_clk_gpio); 138c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_data_dir_reg, gpio_dir); 13981dee67eSSudip Mukherjee } 14081dee67eSSudip Mukherjee } 14181dee67eSSudip Mukherjee 14281dee67eSSudip Mukherjee /* 14381dee67eSSudip Mukherjee * This function set/reset the SDA GPIO pin 14481dee67eSSudip Mukherjee * 14581dee67eSSudip Mukherjee * Parameters: 14681dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 14781dee67eSSudip Mukherjee * 14881dee67eSSudip Mukherjee * Notes: 14981dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up 15081dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the 15181dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the 15281dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high. 15381dee67eSSudip Mukherjee */ 1546c78f4ceSMike Rapoport static void sw_i2c_sda(unsigned char value) 15581dee67eSSudip Mukherjee { 156fe820044SMike Rapoport unsigned long gpio_data; 157fe820044SMike Rapoport unsigned long gpio_dir; 15881dee67eSSudip Mukherjee 159c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_data_gpio_data_dir_reg); 160d3f431d0SIsaac Assegai if (value) { /* High */ 1619137f812SMike Rapoport /* 1629137f812SMike Rapoport * Set direction as input. This will automatically 1639137f812SMike Rapoport * pull the signal up. 1649137f812SMike Rapoport */ 165fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_data_gpio); 166c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); 167d3f431d0SIsaac Assegai } else { /* Low */ 16881dee67eSSudip Mukherjee /* Set the signal down */ 169c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_data_gpio_data_reg); 170fe820044SMike Rapoport gpio_data &= ~(1 << sw_i2c_data_gpio); 171c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_reg, gpio_data); 17281dee67eSSudip Mukherjee 17381dee67eSSudip Mukherjee /* Set direction as output */ 174fe820044SMike Rapoport gpio_dir |= (1 << sw_i2c_data_gpio); 175c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); 17681dee67eSSudip Mukherjee } 17781dee67eSSudip Mukherjee } 17881dee67eSSudip Mukherjee 17981dee67eSSudip Mukherjee /* 18081dee67eSSudip Mukherjee * This function read the data from the SDA GPIO pin 18181dee67eSSudip Mukherjee * 18281dee67eSSudip Mukherjee * Return Value: 18381dee67eSSudip Mukherjee * The SDA data bit sent by the Slave 18481dee67eSSudip Mukherjee */ 1856c78f4ceSMike Rapoport static unsigned char sw_i2c_read_sda(void) 18681dee67eSSudip Mukherjee { 187fe820044SMike Rapoport unsigned long gpio_dir; 188fe820044SMike Rapoport unsigned long gpio_data; 1899137f812SMike Rapoport unsigned long dir_mask = 1 << sw_i2c_data_gpio; 19081dee67eSSudip Mukherjee 19181dee67eSSudip Mukherjee /* Make sure that the direction is input (High) */ 192c075b6f2SMatthieu Simon gpio_dir = peek32(sw_i2c_data_gpio_data_dir_reg); 1939137f812SMike Rapoport if ((gpio_dir & dir_mask) != ~dir_mask) { 194fe820044SMike Rapoport gpio_dir &= ~(1 << sw_i2c_data_gpio); 195c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_data_dir_reg, gpio_dir); 19681dee67eSSudip Mukherjee } 19781dee67eSSudip Mukherjee 19881dee67eSSudip Mukherjee /* Now read the SDA line */ 199c075b6f2SMatthieu Simon gpio_data = peek32(sw_i2c_data_gpio_data_reg); 200fe820044SMike Rapoport if (gpio_data & (1 << sw_i2c_data_gpio)) 20181dee67eSSudip Mukherjee return 1; 20281dee67eSSudip Mukherjee else 20381dee67eSSudip Mukherjee return 0; 20481dee67eSSudip Mukherjee } 20581dee67eSSudip Mukherjee 20681dee67eSSudip Mukherjee /* 20781dee67eSSudip Mukherjee * This function sends ACK signal 20881dee67eSSudip Mukherjee */ 2096c78f4ceSMike Rapoport static void sw_i2c_ack(void) 21081dee67eSSudip Mukherjee { 21181dee67eSSudip Mukherjee return; /* Single byte read is ok without it. */ 21281dee67eSSudip Mukherjee } 21381dee67eSSudip Mukherjee 21481dee67eSSudip Mukherjee /* 21581dee67eSSudip Mukherjee * This function sends the start command to the slave device 21681dee67eSSudip Mukherjee */ 2176c78f4ceSMike Rapoport static void sw_i2c_start(void) 21881dee67eSSudip Mukherjee { 21981dee67eSSudip Mukherjee /* Start I2C */ 2206c78f4ceSMike Rapoport sw_i2c_sda(1); 2216c78f4ceSMike Rapoport sw_i2c_scl(1); 2226c78f4ceSMike Rapoport sw_i2c_sda(0); 22381dee67eSSudip Mukherjee } 22481dee67eSSudip Mukherjee 22581dee67eSSudip Mukherjee /* 22681dee67eSSudip Mukherjee * This function sends the stop command to the slave device 22781dee67eSSudip Mukherjee */ 2286c78f4ceSMike Rapoport static void sw_i2c_stop(void) 22981dee67eSSudip Mukherjee { 23081dee67eSSudip Mukherjee /* Stop the I2C */ 2316c78f4ceSMike Rapoport sw_i2c_scl(1); 2326c78f4ceSMike Rapoport sw_i2c_sda(0); 2336c78f4ceSMike Rapoport sw_i2c_sda(1); 23481dee67eSSudip Mukherjee } 23581dee67eSSudip Mukherjee 23681dee67eSSudip Mukherjee /* 23781dee67eSSudip Mukherjee * This function writes one byte to the slave device 23881dee67eSSudip Mukherjee * 23981dee67eSSudip Mukherjee * Parameters: 24081dee67eSSudip Mukherjee * data - Data to be write to the slave device 24181dee67eSSudip Mukherjee * 24281dee67eSSudip Mukherjee * Return Value: 24381dee67eSSudip Mukherjee * 0 - Success 24481dee67eSSudip Mukherjee * -1 - Fail to write byte 24581dee67eSSudip Mukherjee */ 2466c78f4ceSMike Rapoport static long sw_i2c_write_byte(unsigned char data) 24781dee67eSSudip Mukherjee { 24881dee67eSSudip Mukherjee unsigned char value = data; 24981dee67eSSudip Mukherjee int i; 25081dee67eSSudip Mukherjee 25181dee67eSSudip Mukherjee /* Sending the data bit by bit */ 252d3f431d0SIsaac Assegai for (i = 0; i < 8; i++) { 25381dee67eSSudip Mukherjee /* Set SCL to low */ 2546c78f4ceSMike Rapoport sw_i2c_scl(0); 25581dee67eSSudip Mukherjee 25681dee67eSSudip Mukherjee /* Send data bit */ 25781dee67eSSudip Mukherjee if ((value & 0x80) != 0) 2586c78f4ceSMike Rapoport sw_i2c_sda(1); 25981dee67eSSudip Mukherjee else 2606c78f4ceSMike Rapoport sw_i2c_sda(0); 26181dee67eSSudip Mukherjee 2626c78f4ceSMike Rapoport sw_i2c_wait(); 26381dee67eSSudip Mukherjee 26481dee67eSSudip Mukherjee /* Toggle clk line to one */ 2656c78f4ceSMike Rapoport sw_i2c_scl(1); 2666c78f4ceSMike Rapoport sw_i2c_wait(); 26781dee67eSSudip Mukherjee 26881dee67eSSudip Mukherjee /* Shift byte to be sent */ 26981dee67eSSudip Mukherjee value = value << 1; 27081dee67eSSudip Mukherjee } 27181dee67eSSudip Mukherjee 27281dee67eSSudip Mukherjee /* Set the SCL Low and SDA High (prepare to get input) */ 2736c78f4ceSMike Rapoport sw_i2c_scl(0); 2746c78f4ceSMike Rapoport sw_i2c_sda(1); 27581dee67eSSudip Mukherjee 27681dee67eSSudip Mukherjee /* Set the SCL High for ack */ 2776c78f4ceSMike Rapoport sw_i2c_wait(); 2786c78f4ceSMike Rapoport sw_i2c_scl(1); 2796c78f4ceSMike Rapoport sw_i2c_wait(); 28081dee67eSSudip Mukherjee 28181dee67eSSudip Mukherjee /* Read SDA, until SDA==0 */ 282d3f431d0SIsaac Assegai for (i = 0; i < 0xff; i++) { 2836c78f4ceSMike Rapoport if (!sw_i2c_read_sda()) 28481dee67eSSudip Mukherjee break; 28581dee67eSSudip Mukherjee 2866c78f4ceSMike Rapoport sw_i2c_scl(0); 2876c78f4ceSMike Rapoport sw_i2c_wait(); 2886c78f4ceSMike Rapoport sw_i2c_scl(1); 2896c78f4ceSMike Rapoport sw_i2c_wait(); 29081dee67eSSudip Mukherjee } 29181dee67eSSudip Mukherjee 29281dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */ 2936c78f4ceSMike Rapoport sw_i2c_scl(0); 2946c78f4ceSMike Rapoport sw_i2c_sda(1); 29581dee67eSSudip Mukherjee 29681dee67eSSudip Mukherjee if (i < 0xff) 29781dee67eSSudip Mukherjee return 0; 29881dee67eSSudip Mukherjee else 2996946edd0SSupriya Karanth return -1; 30081dee67eSSudip Mukherjee } 30181dee67eSSudip Mukherjee 30281dee67eSSudip Mukherjee /* 30381dee67eSSudip Mukherjee * This function reads one byte from the slave device 30481dee67eSSudip Mukherjee * 30581dee67eSSudip Mukherjee * Parameters: 30681dee67eSSudip Mukherjee * ack - Flag to indicate either to send the acknowledge 30781dee67eSSudip Mukherjee * message to the slave device or not 30881dee67eSSudip Mukherjee * 30981dee67eSSudip Mukherjee * Return Value: 31081dee67eSSudip Mukherjee * One byte data read from the Slave device 31181dee67eSSudip Mukherjee */ 3126c78f4ceSMike Rapoport static unsigned char sw_i2c_read_byte(unsigned char ack) 31381dee67eSSudip Mukherjee { 31481dee67eSSudip Mukherjee int i; 31581dee67eSSudip Mukherjee unsigned char data = 0; 31681dee67eSSudip Mukherjee 317d3f431d0SIsaac Assegai for (i = 7; i >= 0; i--) { 31881dee67eSSudip Mukherjee /* Set the SCL to Low and SDA to High (Input) */ 3196c78f4ceSMike Rapoport sw_i2c_scl(0); 3206c78f4ceSMike Rapoport sw_i2c_sda(1); 3216c78f4ceSMike Rapoport sw_i2c_wait(); 32281dee67eSSudip Mukherjee 32381dee67eSSudip Mukherjee /* Set the SCL High */ 3246c78f4ceSMike Rapoport sw_i2c_scl(1); 3256c78f4ceSMike Rapoport sw_i2c_wait(); 32681dee67eSSudip Mukherjee 32781dee67eSSudip Mukherjee /* Read data bits from SDA */ 3286c78f4ceSMike Rapoport data |= (sw_i2c_read_sda() << i); 32981dee67eSSudip Mukherjee } 33081dee67eSSudip Mukherjee 33181dee67eSSudip Mukherjee if (ack) 3326c78f4ceSMike Rapoport sw_i2c_ack(); 33381dee67eSSudip Mukherjee 33481dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */ 3356c78f4ceSMike Rapoport sw_i2c_scl(0); 3366c78f4ceSMike Rapoport sw_i2c_sda(1); 33781dee67eSSudip Mukherjee 33881dee67eSSudip Mukherjee return data; 33981dee67eSSudip Mukherjee } 34081dee67eSSudip Mukherjee 34181dee67eSSudip Mukherjee /* 34281dee67eSSudip Mukherjee * This function initializes GPIO port for SW I2C communication. 34381dee67eSSudip Mukherjee * 34481dee67eSSudip Mukherjee * Parameters: 345fe820044SMike Rapoport * clk_gpio - The GPIO pin to be used as i2c SCL 346fe820044SMike Rapoport * data_gpio - The GPIO pin to be used as i2c SDA 34781dee67eSSudip Mukherjee * 34881dee67eSSudip Mukherjee * Return Value: 34981dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c 35081dee67eSSudip Mukherjee * 0 - Success 35181dee67eSSudip Mukherjee */ 352c9750456SMatej Dujava static long sm750le_i2c_init(unsigned char clk_gpio, unsigned char data_gpio) 35381dee67eSSudip Mukherjee { 35481dee67eSSudip Mukherjee int i; 35581dee67eSSudip Mukherjee 35681dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */ 35753bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_reg = GPIO_DATA_SM750LE; 35853bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE; 35981dee67eSSudip Mukherjee 36081dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */ 361fe820044SMike Rapoport sw_i2c_clk_gpio = clk_gpio; 36281dee67eSSudip Mukherjee 36381dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */ 36453bc6b6eSMike Rapoport sw_i2c_data_gpio_data_reg = GPIO_DATA_SM750LE; 36553bc6b6eSMike Rapoport sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION_SM750LE; 36681dee67eSSudip Mukherjee 36781dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */ 368fe820044SMike Rapoport sw_i2c_data_gpio = data_gpio; 36981dee67eSSudip Mukherjee 37081dee67eSSudip Mukherjee /* Note that SM750LE don't have GPIO MUX and power is always on */ 37181dee67eSSudip Mukherjee 37281dee67eSSudip Mukherjee /* Clear the i2c lines. */ 37381dee67eSSudip Mukherjee for (i = 0; i < 9; i++) 3746c78f4ceSMike Rapoport sw_i2c_stop(); 37581dee67eSSudip Mukherjee 37681dee67eSSudip Mukherjee return 0; 37781dee67eSSudip Mukherjee } 37881dee67eSSudip Mukherjee 37981dee67eSSudip Mukherjee /* 38081dee67eSSudip Mukherjee * This function initializes the i2c attributes and bus 38181dee67eSSudip Mukherjee * 38281dee67eSSudip Mukherjee * Parameters: 383fe820044SMike Rapoport * clk_gpio - The GPIO pin to be used as i2c SCL 384fe820044SMike Rapoport * data_gpio - The GPIO pin to be used as i2c SDA 38581dee67eSSudip Mukherjee * 38681dee67eSSudip Mukherjee * Return Value: 38781dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c 38881dee67eSSudip Mukherjee * 0 - Success 38981dee67eSSudip Mukherjee */ 390c9750456SMatej Dujava long sm750_sw_i2c_init(unsigned char clk_gpio, unsigned char data_gpio) 39181dee67eSSudip Mukherjee { 39281dee67eSSudip Mukherjee int i; 39381dee67eSSudip Mukherjee 3949137f812SMike Rapoport /* 3959137f812SMike Rapoport * Return 0 if the GPIO pins to be used is out of range. The 3969137f812SMike Rapoport * range is only from [0..63] 3979137f812SMike Rapoport */ 398fe820044SMike Rapoport if ((clk_gpio > 31) || (data_gpio > 31)) 3996946edd0SSupriya Karanth return -1; 40081dee67eSSudip Mukherjee 40106a4f429SMoshe Green if (sm750_get_chip_type() == SM750LE) 402fe820044SMike Rapoport return sm750le_i2c_init(clk_gpio, data_gpio); 40381dee67eSSudip Mukherjee 40481dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */ 40553bc6b6eSMike Rapoport sw_i2c_clk_gpio_mux_reg = GPIO_MUX; 40653bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_reg = GPIO_DATA; 40753bc6b6eSMike Rapoport sw_i2c_clk_gpio_data_dir_reg = GPIO_DATA_DIRECTION; 40881dee67eSSudip Mukherjee 40981dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */ 410fe820044SMike Rapoport sw_i2c_clk_gpio = clk_gpio; 41181dee67eSSudip Mukherjee 41281dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */ 41353bc6b6eSMike Rapoport sw_i2c_data_gpio_mux_reg = GPIO_MUX; 41453bc6b6eSMike Rapoport sw_i2c_data_gpio_data_reg = GPIO_DATA; 41553bc6b6eSMike Rapoport sw_i2c_data_gpio_data_dir_reg = GPIO_DATA_DIRECTION; 41681dee67eSSudip Mukherjee 41781dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */ 418fe820044SMike Rapoport sw_i2c_data_gpio = data_gpio; 41981dee67eSSudip Mukherjee 42081dee67eSSudip Mukherjee /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ 421c075b6f2SMatthieu Simon poke32(sw_i2c_clk_gpio_mux_reg, 422c075b6f2SMatthieu Simon peek32(sw_i2c_clk_gpio_mux_reg) & ~(1 << sw_i2c_clk_gpio)); 423c075b6f2SMatthieu Simon poke32(sw_i2c_data_gpio_mux_reg, 424c075b6f2SMatthieu Simon peek32(sw_i2c_data_gpio_mux_reg) & ~(1 << sw_i2c_data_gpio)); 42581dee67eSSudip Mukherjee 42681dee67eSSudip Mukherjee /* Enable GPIO power */ 42752d0744dSArnd Bergmann sm750_enable_gpio(1); 42881dee67eSSudip Mukherjee 42981dee67eSSudip Mukherjee /* Clear the i2c lines. */ 43081dee67eSSudip Mukherjee for (i = 0; i < 9; i++) 4316c78f4ceSMike Rapoport sw_i2c_stop(); 43281dee67eSSudip Mukherjee 43381dee67eSSudip Mukherjee return 0; 43481dee67eSSudip Mukherjee } 43581dee67eSSudip Mukherjee 43681dee67eSSudip Mukherjee /* 43781dee67eSSudip Mukherjee * This function reads the slave device's register 43881dee67eSSudip Mukherjee * 43981dee67eSSudip Mukherjee * Parameters: 440fe820044SMike Rapoport * addr - i2c Slave device address which register 44181dee67eSSudip Mukherjee * to be read from 442fe820044SMike Rapoport * reg - Slave device's register to be read 44381dee67eSSudip Mukherjee * 44481dee67eSSudip Mukherjee * Return Value: 44581dee67eSSudip Mukherjee * Register value 44681dee67eSSudip Mukherjee */ 447c9750456SMatej Dujava unsigned char sm750_sw_i2c_read_reg(unsigned char addr, unsigned char reg) 44881dee67eSSudip Mukherjee { 44981dee67eSSudip Mukherjee unsigned char data; 45081dee67eSSudip Mukherjee 45181dee67eSSudip Mukherjee /* Send the Start signal */ 4526c78f4ceSMike Rapoport sw_i2c_start(); 45381dee67eSSudip Mukherjee 45481dee67eSSudip Mukherjee /* Send the device address */ 455fe820044SMike Rapoport sw_i2c_write_byte(addr); 45681dee67eSSudip Mukherjee 45781dee67eSSudip Mukherjee /* Send the register index */ 458fe820044SMike Rapoport sw_i2c_write_byte(reg); 45981dee67eSSudip Mukherjee 46081dee67eSSudip Mukherjee /* Get the bus again and get the data from the device read address */ 4616c78f4ceSMike Rapoport sw_i2c_start(); 462fe820044SMike Rapoport sw_i2c_write_byte(addr + 1); 4636c78f4ceSMike Rapoport data = sw_i2c_read_byte(1); 46481dee67eSSudip Mukherjee 46581dee67eSSudip Mukherjee /* Stop swI2C and release the bus */ 4666c78f4ceSMike Rapoport sw_i2c_stop(); 46781dee67eSSudip Mukherjee 46881dee67eSSudip Mukherjee return data; 46981dee67eSSudip Mukherjee } 47081dee67eSSudip Mukherjee 47181dee67eSSudip Mukherjee /* 47281dee67eSSudip Mukherjee * This function writes a value to the slave device's register 47381dee67eSSudip Mukherjee * 47481dee67eSSudip Mukherjee * Parameters: 475fe820044SMike Rapoport * addr - i2c Slave device address which register 47681dee67eSSudip Mukherjee * to be written 477fe820044SMike Rapoport * reg - Slave device's register to be written 47881dee67eSSudip Mukherjee * data - Data to be written to the register 47981dee67eSSudip Mukherjee * 48081dee67eSSudip Mukherjee * Result: 48181dee67eSSudip Mukherjee * 0 - Success 48281dee67eSSudip Mukherjee * -1 - Fail 48381dee67eSSudip Mukherjee */ 484c9750456SMatej Dujava long sm750_sw_i2c_write_reg(unsigned char addr, 485fe820044SMike Rapoport unsigned char reg, 486c9750456SMatej Dujava unsigned char data) 48781dee67eSSudip Mukherjee { 488fe820044SMike Rapoport long ret = 0; 48981dee67eSSudip Mukherjee 49081dee67eSSudip Mukherjee /* Send the Start signal */ 4916c78f4ceSMike Rapoport sw_i2c_start(); 49281dee67eSSudip Mukherjee 49381dee67eSSudip Mukherjee /* Send the device address and read the data. All should return success 49435e4d8caSElizabeth Ferdman * in order for the writing processed to be successful 49581dee67eSSudip Mukherjee */ 496fe820044SMike Rapoport if ((sw_i2c_write_byte(addr) != 0) || 497fe820044SMike Rapoport (sw_i2c_write_byte(reg) != 0) || 4986c78f4ceSMike Rapoport (sw_i2c_write_byte(data) != 0)) { 499fe820044SMike Rapoport ret = -1; 50081dee67eSSudip Mukherjee } 50181dee67eSSudip Mukherjee 50281dee67eSSudip Mukherjee /* Stop i2c and release the bus */ 5036c78f4ceSMike Rapoport sw_i2c_stop(); 50481dee67eSSudip Mukherjee 505fe820044SMike Rapoport return ret; 50681dee67eSSudip Mukherjee } 507