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 9235e4d8caSElizabeth Ferdman */ 931282badeSMike Rapoport 9481dee67eSSudip Mukherjee /* Change wait algorithm to use PCI bus clock, 9535e4d8caSElizabeth Ferdman * it's more reliable than counter loop .. 9635e4d8caSElizabeth Ferdman * 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 40606a4f429SMoshe Green if (sm750_get_chip_type() == 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 50435e4d8caSElizabeth Ferdman * 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