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 /******************************************************************* 2081dee67eSSudip Mukherjee * I2C Software Master Driver: 2181dee67eSSudip Mukherjee * =========================== 2281dee67eSSudip Mukherjee * Each i2c cycle is split into 4 sections. Each of these section marks 2381dee67eSSudip Mukherjee * a point in time where the SCL or SDA may be changed. 2481dee67eSSudip Mukherjee * 2581dee67eSSudip Mukherjee * 1 Cycle == | Section I. | Section 2. | Section 3. | Section 4. | 2681dee67eSSudip Mukherjee * +-------------+-------------+-------------+-------------+ 2781dee67eSSudip Mukherjee * | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| 2881dee67eSSudip Mukherjee * 2981dee67eSSudip Mukherjee * ____________ _____________ 3081dee67eSSudip Mukherjee * SCL == XXXX _____________ ____________ / 3181dee67eSSudip Mukherjee * 3281dee67eSSudip Mukherjee * I.e. the SCL may only be changed in section 1. and section 3. while 3381dee67eSSudip Mukherjee * the SDA may only be changed in section 2. and section 4. The table 3481dee67eSSudip Mukherjee * below gives the changes for these 2 lines in the varios sections. 3581dee67eSSudip Mukherjee * 3681dee67eSSudip Mukherjee * Section changes Table: 3781dee67eSSudip Mukherjee * ====================== 3881dee67eSSudip Mukherjee * blank = no change, L = set bit LOW, H = set bit HIGH 3981dee67eSSudip Mukherjee * 4081dee67eSSudip Mukherjee * | 1.| 2.| 3.| 4.| 4181dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4281dee67eSSudip Mukherjee * Tx Start SDA | | H | | L | 4381dee67eSSudip Mukherjee * SCL | L | | H | | 4481dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4581dee67eSSudip Mukherjee * Tx Stop SDA | | L | | H | 4681dee67eSSudip Mukherjee * SCL | L | | H | | 4781dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 4881dee67eSSudip Mukherjee * Tx bit H SDA | | H | | | 4981dee67eSSudip Mukherjee * SCL | L | | H | | 5081dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 5181dee67eSSudip Mukherjee * Tx bit L SDA | | L | | | 5281dee67eSSudip Mukherjee * SCL | L | | H | | 5381dee67eSSudip Mukherjee * ---------------+---+---+---+---+ 5481dee67eSSudip Mukherjee * 5581dee67eSSudip Mukherjee ******************************************************************/ 5681dee67eSSudip Mukherjee 5781dee67eSSudip Mukherjee /* GPIO pins used for this I2C. It ranges from 0 to 63. */ 5881dee67eSSudip Mukherjee static unsigned char g_i2cClockGPIO = DEFAULT_I2C_SCL; 5981dee67eSSudip Mukherjee static unsigned char g_i2cDataGPIO = DEFAULT_I2C_SDA; 6081dee67eSSudip Mukherjee 6181dee67eSSudip Mukherjee /* 6281dee67eSSudip Mukherjee * Below is the variable declaration for the GPIO pin register usage 6381dee67eSSudip Mukherjee * for the i2c Clock and i2c Data. 6481dee67eSSudip Mukherjee * 6581dee67eSSudip Mukherjee * Note: 6681dee67eSSudip Mukherjee * Notice that the GPIO usage for the i2c clock and i2c Data are 6781dee67eSSudip Mukherjee * separated. This is to make this code flexible enough when 6881dee67eSSudip Mukherjee * two separate GPIO pins for the clock and data are located 6981dee67eSSudip Mukherjee * in two different GPIO register set (worst case). 7081dee67eSSudip Mukherjee */ 7181dee67eSSudip Mukherjee 7281dee67eSSudip Mukherjee /* i2c Clock GPIO Register usage */ 7381dee67eSSudip Mukherjee static unsigned long g_i2cClkGPIOMuxReg = GPIO_MUX; 7481dee67eSSudip Mukherjee static unsigned long g_i2cClkGPIODataReg = GPIO_DATA; 7581dee67eSSudip Mukherjee static unsigned long g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; 7681dee67eSSudip Mukherjee 7781dee67eSSudip Mukherjee /* i2c Data GPIO Register usage */ 7881dee67eSSudip Mukherjee static unsigned long g_i2cDataGPIOMuxReg = GPIO_MUX; 7981dee67eSSudip Mukherjee static unsigned long g_i2cDataGPIODataReg = GPIO_DATA; 8081dee67eSSudip Mukherjee static unsigned long g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; 8181dee67eSSudip Mukherjee 8281dee67eSSudip Mukherjee static unsigned char peekIO(unsigned short port,unsigned short index) 8381dee67eSSudip Mukherjee { 8481dee67eSSudip Mukherjee #if defined(__i386__) || defined( __x86_64__) 8581dee67eSSudip Mukherjee outb_p(index,port); 8681dee67eSSudip Mukherjee return inb_p(port+1); 8781dee67eSSudip Mukherjee #endif 8881dee67eSSudip Mukherjee } 8981dee67eSSudip Mukherjee 9081dee67eSSudip Mukherjee /* 9181dee67eSSudip Mukherjee * This function puts a delay between command 9281dee67eSSudip Mukherjee */ 9381dee67eSSudip Mukherjee static void swI2CWait(void) 9481dee67eSSudip Mukherjee { 9581dee67eSSudip Mukherjee /* find a bug: 9681dee67eSSudip Mukherjee * peekIO method works well before suspend/resume 9781dee67eSSudip Mukherjee * but after suspend, peekIO(0x3ce,0x61) & 0x10 9881dee67eSSudip Mukherjee * always be non-zero,which makes the while loop 9981dee67eSSudip Mukherjee * never finish. 10081dee67eSSudip Mukherjee * use non-ultimate for loop below is safe 10181dee67eSSudip Mukherjee * */ 10281dee67eSSudip Mukherjee #if 0 10381dee67eSSudip Mukherjee /* Change wait algorithm to use PCI bus clock, 10481dee67eSSudip Mukherjee it's more reliable than counter loop .. 10581dee67eSSudip Mukherjee write 0x61 to 0x3ce and read from 0x3cf 10681dee67eSSudip Mukherjee */ 10781dee67eSSudip Mukherjee while(peekIO(0x3ce,0x61) & 0x10); 10881dee67eSSudip Mukherjee #else 10981dee67eSSudip Mukherjee int i, Temp; 11081dee67eSSudip Mukherjee 11181dee67eSSudip Mukherjee for(i=0; i<600; i++) 11281dee67eSSudip Mukherjee { 11381dee67eSSudip Mukherjee Temp = i; 11481dee67eSSudip Mukherjee Temp += i; 11581dee67eSSudip Mukherjee } 11681dee67eSSudip Mukherjee #endif 11781dee67eSSudip Mukherjee } 11881dee67eSSudip Mukherjee 11981dee67eSSudip Mukherjee /* 12081dee67eSSudip Mukherjee * This function set/reset the SCL GPIO pin 12181dee67eSSudip Mukherjee * 12281dee67eSSudip Mukherjee * Parameters: 12381dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 12481dee67eSSudip Mukherjee * 12581dee67eSSudip Mukherjee * Notes: 12681dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up 12781dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the 12881dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the 12981dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high. 13081dee67eSSudip Mukherjee */ 13181dee67eSSudip Mukherjee void swI2CSCL(unsigned char value) 13281dee67eSSudip Mukherjee { 13381dee67eSSudip Mukherjee unsigned long ulGPIOData; 13481dee67eSSudip Mukherjee unsigned long ulGPIODirection; 13581dee67eSSudip Mukherjee 13681dee67eSSudip Mukherjee ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg); 13781dee67eSSudip Mukherjee if (value) /* High */ 13881dee67eSSudip Mukherjee { 13981dee67eSSudip Mukherjee /* Set direction as input. This will automatically pull the signal up. */ 14081dee67eSSudip Mukherjee ulGPIODirection &= ~(1 << g_i2cClockGPIO); 14181dee67eSSudip Mukherjee POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); 14281dee67eSSudip Mukherjee } 14381dee67eSSudip Mukherjee else /* Low */ 14481dee67eSSudip Mukherjee { 14581dee67eSSudip Mukherjee /* Set the signal down */ 14681dee67eSSudip Mukherjee ulGPIOData = PEEK32(g_i2cClkGPIODataReg); 14781dee67eSSudip Mukherjee ulGPIOData &= ~(1 << g_i2cClockGPIO); 14881dee67eSSudip Mukherjee POKE32(g_i2cClkGPIODataReg, ulGPIOData); 14981dee67eSSudip Mukherjee 15081dee67eSSudip Mukherjee /* Set direction as output */ 15181dee67eSSudip Mukherjee ulGPIODirection |= (1 << g_i2cClockGPIO); 15281dee67eSSudip Mukherjee POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); 15381dee67eSSudip Mukherjee } 15481dee67eSSudip Mukherjee } 15581dee67eSSudip Mukherjee 15681dee67eSSudip Mukherjee /* 15781dee67eSSudip Mukherjee * This function set/reset the SDA GPIO pin 15881dee67eSSudip Mukherjee * 15981dee67eSSudip Mukherjee * Parameters: 16081dee67eSSudip Mukherjee * value - Bit value to set to the SCL or SDA (0 = low, 1 = high) 16181dee67eSSudip Mukherjee * 16281dee67eSSudip Mukherjee * Notes: 16381dee67eSSudip Mukherjee * When setting SCL to high, just set the GPIO as input where the pull up 16481dee67eSSudip Mukherjee * resistor will pull the signal up. Do not use software to pull up the 16581dee67eSSudip Mukherjee * signal because the i2c will fail when other device try to drive the 16681dee67eSSudip Mukherjee * signal due to SM50x will drive the signal to always high. 16781dee67eSSudip Mukherjee */ 16881dee67eSSudip Mukherjee void swI2CSDA(unsigned char value) 16981dee67eSSudip Mukherjee { 17081dee67eSSudip Mukherjee unsigned long ulGPIOData; 17181dee67eSSudip Mukherjee unsigned long ulGPIODirection; 17281dee67eSSudip Mukherjee 17381dee67eSSudip Mukherjee ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); 17481dee67eSSudip Mukherjee if (value) /* High */ 17581dee67eSSudip Mukherjee { 17681dee67eSSudip Mukherjee /* Set direction as input. This will automatically pull the signal up. */ 17781dee67eSSudip Mukherjee ulGPIODirection &= ~(1 << g_i2cDataGPIO); 17881dee67eSSudip Mukherjee POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 17981dee67eSSudip Mukherjee } 18081dee67eSSudip Mukherjee else /* Low */ 18181dee67eSSudip Mukherjee { 18281dee67eSSudip Mukherjee /* Set the signal down */ 18381dee67eSSudip Mukherjee ulGPIOData = PEEK32(g_i2cDataGPIODataReg); 18481dee67eSSudip Mukherjee ulGPIOData &= ~(1 << g_i2cDataGPIO); 18581dee67eSSudip Mukherjee POKE32(g_i2cDataGPIODataReg, ulGPIOData); 18681dee67eSSudip Mukherjee 18781dee67eSSudip Mukherjee /* Set direction as output */ 18881dee67eSSudip Mukherjee ulGPIODirection |= (1 << g_i2cDataGPIO); 18981dee67eSSudip Mukherjee POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 19081dee67eSSudip Mukherjee } 19181dee67eSSudip Mukherjee } 19281dee67eSSudip Mukherjee 19381dee67eSSudip Mukherjee /* 19481dee67eSSudip Mukherjee * This function read the data from the SDA GPIO pin 19581dee67eSSudip Mukherjee * 19681dee67eSSudip Mukherjee * Return Value: 19781dee67eSSudip Mukherjee * The SDA data bit sent by the Slave 19881dee67eSSudip Mukherjee */ 19981dee67eSSudip Mukherjee static unsigned char swI2CReadSDA(void) 20081dee67eSSudip Mukherjee { 20181dee67eSSudip Mukherjee unsigned long ulGPIODirection; 20281dee67eSSudip Mukherjee unsigned long ulGPIOData; 20381dee67eSSudip Mukherjee 20481dee67eSSudip Mukherjee /* Make sure that the direction is input (High) */ 20581dee67eSSudip Mukherjee ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); 20681dee67eSSudip Mukherjee if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO))) 20781dee67eSSudip Mukherjee { 20881dee67eSSudip Mukherjee ulGPIODirection &= ~(1 << g_i2cDataGPIO); 20981dee67eSSudip Mukherjee POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); 21081dee67eSSudip Mukherjee } 21181dee67eSSudip Mukherjee 21281dee67eSSudip Mukherjee /* Now read the SDA line */ 21381dee67eSSudip Mukherjee ulGPIOData = PEEK32(g_i2cDataGPIODataReg); 21481dee67eSSudip Mukherjee if (ulGPIOData & (1 << g_i2cDataGPIO)) 21581dee67eSSudip Mukherjee return 1; 21681dee67eSSudip Mukherjee else 21781dee67eSSudip Mukherjee return 0; 21881dee67eSSudip Mukherjee } 21981dee67eSSudip Mukherjee 22081dee67eSSudip Mukherjee #pragma optimize( "", off ) 22181dee67eSSudip Mukherjee 22281dee67eSSudip Mukherjee /* 22381dee67eSSudip Mukherjee * This function sends ACK signal 22481dee67eSSudip Mukherjee */ 22581dee67eSSudip Mukherjee static void swI2CAck(void) 22681dee67eSSudip Mukherjee { 22781dee67eSSudip Mukherjee return; /* Single byte read is ok without it. */ 22881dee67eSSudip Mukherjee } 22981dee67eSSudip Mukherjee 23081dee67eSSudip Mukherjee /* 23181dee67eSSudip Mukherjee * This function sends the start command to the slave device 23281dee67eSSudip Mukherjee */ 23381dee67eSSudip Mukherjee void swI2CStart(void) 23481dee67eSSudip Mukherjee { 23581dee67eSSudip Mukherjee /* Start I2C */ 23681dee67eSSudip Mukherjee swI2CSDA(1); 23781dee67eSSudip Mukherjee swI2CSCL(1); 23881dee67eSSudip Mukherjee swI2CSDA(0); 23981dee67eSSudip Mukherjee } 24081dee67eSSudip Mukherjee 24181dee67eSSudip Mukherjee /* 24281dee67eSSudip Mukherjee * This function sends the stop command to the slave device 24381dee67eSSudip Mukherjee */ 24481dee67eSSudip Mukherjee void swI2CStop(void) 24581dee67eSSudip Mukherjee { 24681dee67eSSudip Mukherjee /* Stop the I2C */ 24781dee67eSSudip Mukherjee swI2CSCL(1); 24881dee67eSSudip Mukherjee swI2CSDA(0); 24981dee67eSSudip Mukherjee swI2CSDA(1); 25081dee67eSSudip Mukherjee } 25181dee67eSSudip Mukherjee 25281dee67eSSudip Mukherjee /* 25381dee67eSSudip Mukherjee * This function writes one byte to the slave device 25481dee67eSSudip Mukherjee * 25581dee67eSSudip Mukherjee * Parameters: 25681dee67eSSudip Mukherjee * data - Data to be write to the slave device 25781dee67eSSudip Mukherjee * 25881dee67eSSudip Mukherjee * Return Value: 25981dee67eSSudip Mukherjee * 0 - Success 26081dee67eSSudip Mukherjee * -1 - Fail to write byte 26181dee67eSSudip Mukherjee */ 26281dee67eSSudip Mukherjee long swI2CWriteByte(unsigned char data) 26381dee67eSSudip Mukherjee { 26481dee67eSSudip Mukherjee unsigned char value = data; 26581dee67eSSudip Mukherjee int i; 26681dee67eSSudip Mukherjee 26781dee67eSSudip Mukherjee /* Sending the data bit by bit */ 26881dee67eSSudip Mukherjee for (i=0; i<8; i++) 26981dee67eSSudip Mukherjee { 27081dee67eSSudip Mukherjee /* Set SCL to low */ 27181dee67eSSudip Mukherjee swI2CSCL(0); 27281dee67eSSudip Mukherjee 27381dee67eSSudip Mukherjee /* Send data bit */ 27481dee67eSSudip Mukherjee if ((value & 0x80) != 0) 27581dee67eSSudip Mukherjee swI2CSDA(1); 27681dee67eSSudip Mukherjee else 27781dee67eSSudip Mukherjee swI2CSDA(0); 27881dee67eSSudip Mukherjee 27981dee67eSSudip Mukherjee swI2CWait(); 28081dee67eSSudip Mukherjee 28181dee67eSSudip Mukherjee /* Toggle clk line to one */ 28281dee67eSSudip Mukherjee swI2CSCL(1); 28381dee67eSSudip Mukherjee swI2CWait(); 28481dee67eSSudip Mukherjee 28581dee67eSSudip Mukherjee /* Shift byte to be sent */ 28681dee67eSSudip Mukherjee value = value << 1; 28781dee67eSSudip Mukherjee } 28881dee67eSSudip Mukherjee 28981dee67eSSudip Mukherjee /* Set the SCL Low and SDA High (prepare to get input) */ 29081dee67eSSudip Mukherjee swI2CSCL(0); 29181dee67eSSudip Mukherjee swI2CSDA(1); 29281dee67eSSudip Mukherjee 29381dee67eSSudip Mukherjee /* Set the SCL High for ack */ 29481dee67eSSudip Mukherjee swI2CWait(); 29581dee67eSSudip Mukherjee swI2CSCL(1); 29681dee67eSSudip Mukherjee swI2CWait(); 29781dee67eSSudip Mukherjee 29881dee67eSSudip Mukherjee /* Read SDA, until SDA==0 */ 29981dee67eSSudip Mukherjee for(i=0; i<0xff; i++) 30081dee67eSSudip Mukherjee { 30181dee67eSSudip Mukherjee if (!swI2CReadSDA()) 30281dee67eSSudip Mukherjee break; 30381dee67eSSudip Mukherjee 30481dee67eSSudip Mukherjee swI2CSCL(0); 30581dee67eSSudip Mukherjee swI2CWait(); 30681dee67eSSudip Mukherjee swI2CSCL(1); 30781dee67eSSudip Mukherjee swI2CWait(); 30881dee67eSSudip Mukherjee } 30981dee67eSSudip Mukherjee 31081dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */ 31181dee67eSSudip Mukherjee swI2CSCL(0); 31281dee67eSSudip Mukherjee swI2CSDA(1); 31381dee67eSSudip Mukherjee 31481dee67eSSudip Mukherjee if (i<0xff) 31581dee67eSSudip Mukherjee return 0; 31681dee67eSSudip Mukherjee else 31781dee67eSSudip Mukherjee return (-1); 31881dee67eSSudip Mukherjee } 31981dee67eSSudip Mukherjee 32081dee67eSSudip Mukherjee /* 32181dee67eSSudip Mukherjee * This function reads one byte from the slave device 32281dee67eSSudip Mukherjee * 32381dee67eSSudip Mukherjee * Parameters: 32481dee67eSSudip Mukherjee * ack - Flag to indicate either to send the acknowledge 32581dee67eSSudip Mukherjee * message to the slave device or not 32681dee67eSSudip Mukherjee * 32781dee67eSSudip Mukherjee * Return Value: 32881dee67eSSudip Mukherjee * One byte data read from the Slave device 32981dee67eSSudip Mukherjee */ 33081dee67eSSudip Mukherjee unsigned char swI2CReadByte(unsigned char ack) 33181dee67eSSudip Mukherjee { 33281dee67eSSudip Mukherjee int i; 33381dee67eSSudip Mukherjee unsigned char data = 0; 33481dee67eSSudip Mukherjee 33581dee67eSSudip Mukherjee for(i=7; i>=0; i--) 33681dee67eSSudip Mukherjee { 33781dee67eSSudip Mukherjee /* Set the SCL to Low and SDA to High (Input) */ 33881dee67eSSudip Mukherjee swI2CSCL(0); 33981dee67eSSudip Mukherjee swI2CSDA(1); 34081dee67eSSudip Mukherjee swI2CWait(); 34181dee67eSSudip Mukherjee 34281dee67eSSudip Mukherjee /* Set the SCL High */ 34381dee67eSSudip Mukherjee swI2CSCL(1); 34481dee67eSSudip Mukherjee swI2CWait(); 34581dee67eSSudip Mukherjee 34681dee67eSSudip Mukherjee /* Read data bits from SDA */ 34781dee67eSSudip Mukherjee data |= (swI2CReadSDA() << i); 34881dee67eSSudip Mukherjee } 34981dee67eSSudip Mukherjee 35081dee67eSSudip Mukherjee if (ack) 35181dee67eSSudip Mukherjee swI2CAck(); 35281dee67eSSudip Mukherjee 35381dee67eSSudip Mukherjee /* Set the SCL Low and SDA High */ 35481dee67eSSudip Mukherjee swI2CSCL(0); 35581dee67eSSudip Mukherjee swI2CSDA(1); 35681dee67eSSudip Mukherjee 35781dee67eSSudip Mukherjee return data; 35881dee67eSSudip Mukherjee } 35981dee67eSSudip Mukherjee #pragma optimize( "", on ) 36081dee67eSSudip Mukherjee 36181dee67eSSudip Mukherjee /* 36281dee67eSSudip Mukherjee * This function initializes GPIO port for SW I2C communication. 36381dee67eSSudip Mukherjee * 36481dee67eSSudip Mukherjee * Parameters: 36581dee67eSSudip Mukherjee * i2cClkGPIO - The GPIO pin to be used as i2c SCL 36681dee67eSSudip Mukherjee * i2cDataGPIO - The GPIO pin to be used as i2c SDA 36781dee67eSSudip Mukherjee * 36881dee67eSSudip Mukherjee * Return Value: 36981dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c 37081dee67eSSudip Mukherjee * 0 - Success 37181dee67eSSudip Mukherjee */ 37281dee67eSSudip Mukherjee long swI2CInit_SM750LE( 37381dee67eSSudip Mukherjee unsigned char i2cClkGPIO, 37481dee67eSSudip Mukherjee unsigned char i2cDataGPIO 37581dee67eSSudip Mukherjee ) 37681dee67eSSudip Mukherjee { 37781dee67eSSudip Mukherjee int i; 37881dee67eSSudip Mukherjee 37981dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */ 38081dee67eSSudip Mukherjee g_i2cClkGPIODataReg = GPIO_DATA_SM750LE; 38181dee67eSSudip Mukherjee g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 38281dee67eSSudip Mukherjee 38381dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */ 38481dee67eSSudip Mukherjee g_i2cClockGPIO = i2cClkGPIO; 38581dee67eSSudip Mukherjee 38681dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */ 38781dee67eSSudip Mukherjee g_i2cDataGPIODataReg = GPIO_DATA_SM750LE; 38881dee67eSSudip Mukherjee g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; 38981dee67eSSudip Mukherjee 39081dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */ 39181dee67eSSudip Mukherjee g_i2cDataGPIO = i2cDataGPIO; 39281dee67eSSudip Mukherjee 39381dee67eSSudip Mukherjee /* Note that SM750LE don't have GPIO MUX and power is always on */ 39481dee67eSSudip Mukherjee 39581dee67eSSudip Mukherjee /* Clear the i2c lines. */ 39681dee67eSSudip Mukherjee for(i=0; i<9; i++) 39781dee67eSSudip Mukherjee swI2CStop(); 39881dee67eSSudip Mukherjee 39981dee67eSSudip Mukherjee return 0; 40081dee67eSSudip Mukherjee } 40181dee67eSSudip Mukherjee 40281dee67eSSudip Mukherjee /* 40381dee67eSSudip Mukherjee * This function initializes the i2c attributes and bus 40481dee67eSSudip Mukherjee * 40581dee67eSSudip Mukherjee * Parameters: 40681dee67eSSudip Mukherjee * i2cClkGPIO - The GPIO pin to be used as i2c SCL 40781dee67eSSudip Mukherjee * i2cDataGPIO - The GPIO pin to be used as i2c SDA 40881dee67eSSudip Mukherjee * 40981dee67eSSudip Mukherjee * Return Value: 41081dee67eSSudip Mukherjee * -1 - Fail to initialize the i2c 41181dee67eSSudip Mukherjee * 0 - Success 41281dee67eSSudip Mukherjee */ 41381dee67eSSudip Mukherjee long swI2CInit( 41481dee67eSSudip Mukherjee unsigned char i2cClkGPIO, 41581dee67eSSudip Mukherjee unsigned char i2cDataGPIO 41681dee67eSSudip Mukherjee ) 41781dee67eSSudip Mukherjee { 41881dee67eSSudip Mukherjee int i; 41981dee67eSSudip Mukherjee 42081dee67eSSudip Mukherjee /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */ 42181dee67eSSudip Mukherjee if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31)) 42281dee67eSSudip Mukherjee return (-1); 42381dee67eSSudip Mukherjee 42481dee67eSSudip Mukherjee if (getChipType() == SM750LE) 42581dee67eSSudip Mukherjee return( swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO) ); 42681dee67eSSudip Mukherjee 42781dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Clock Register */ 42881dee67eSSudip Mukherjee g_i2cClkGPIOMuxReg = GPIO_MUX; 42981dee67eSSudip Mukherjee g_i2cClkGPIODataReg = GPIO_DATA; 43081dee67eSSudip Mukherjee g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; 43181dee67eSSudip Mukherjee 43281dee67eSSudip Mukherjee /* Initialize the Clock GPIO Offset */ 43381dee67eSSudip Mukherjee g_i2cClockGPIO = i2cClkGPIO; 43481dee67eSSudip Mukherjee 43581dee67eSSudip Mukherjee /* Initialize the GPIO pin for the i2c Data Register */ 43681dee67eSSudip Mukherjee g_i2cDataGPIOMuxReg = GPIO_MUX; 43781dee67eSSudip Mukherjee g_i2cDataGPIODataReg = GPIO_DATA; 43881dee67eSSudip Mukherjee g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; 43981dee67eSSudip Mukherjee 44081dee67eSSudip Mukherjee /* Initialize the Data GPIO Offset */ 44181dee67eSSudip Mukherjee g_i2cDataGPIO = i2cDataGPIO; 44281dee67eSSudip Mukherjee 44381dee67eSSudip Mukherjee /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ 44481dee67eSSudip Mukherjee POKE32(g_i2cClkGPIOMuxReg, 44581dee67eSSudip Mukherjee PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO)); 44681dee67eSSudip Mukherjee POKE32(g_i2cDataGPIOMuxReg, 44781dee67eSSudip Mukherjee PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO)); 44881dee67eSSudip Mukherjee 44981dee67eSSudip Mukherjee /* Enable GPIO power */ 45081dee67eSSudip Mukherjee enableGPIO(1); 45181dee67eSSudip Mukherjee 45281dee67eSSudip Mukherjee /* Clear the i2c lines. */ 45381dee67eSSudip Mukherjee for(i=0; i<9; i++) 45481dee67eSSudip Mukherjee swI2CStop(); 45581dee67eSSudip Mukherjee 45681dee67eSSudip Mukherjee return 0; 45781dee67eSSudip Mukherjee } 45881dee67eSSudip Mukherjee 45981dee67eSSudip Mukherjee /* 46081dee67eSSudip Mukherjee * This function reads the slave device's register 46181dee67eSSudip Mukherjee * 46281dee67eSSudip Mukherjee * Parameters: 46381dee67eSSudip Mukherjee * deviceAddress - i2c Slave device address which register 46481dee67eSSudip Mukherjee * to be read from 46581dee67eSSudip Mukherjee * registerIndex - Slave device's register to be read 46681dee67eSSudip Mukherjee * 46781dee67eSSudip Mukherjee * Return Value: 46881dee67eSSudip Mukherjee * Register value 46981dee67eSSudip Mukherjee */ 47081dee67eSSudip Mukherjee unsigned char swI2CReadReg( 47181dee67eSSudip Mukherjee unsigned char deviceAddress, 47281dee67eSSudip Mukherjee unsigned char registerIndex 47381dee67eSSudip Mukherjee ) 47481dee67eSSudip Mukherjee { 47581dee67eSSudip Mukherjee unsigned char data; 47681dee67eSSudip Mukherjee 47781dee67eSSudip Mukherjee /* Send the Start signal */ 47881dee67eSSudip Mukherjee swI2CStart(); 47981dee67eSSudip Mukherjee 48081dee67eSSudip Mukherjee /* Send the device address */ 48181dee67eSSudip Mukherjee swI2CWriteByte(deviceAddress); 48281dee67eSSudip Mukherjee 48381dee67eSSudip Mukherjee /* Send the register index */ 48481dee67eSSudip Mukherjee swI2CWriteByte(registerIndex); 48581dee67eSSudip Mukherjee 48681dee67eSSudip Mukherjee /* Get the bus again and get the data from the device read address */ 48781dee67eSSudip Mukherjee swI2CStart(); 48881dee67eSSudip Mukherjee swI2CWriteByte(deviceAddress + 1); 48981dee67eSSudip Mukherjee data = swI2CReadByte(1); 49081dee67eSSudip Mukherjee 49181dee67eSSudip Mukherjee /* Stop swI2C and release the bus */ 49281dee67eSSudip Mukherjee swI2CStop(); 49381dee67eSSudip Mukherjee 49481dee67eSSudip Mukherjee return data; 49581dee67eSSudip Mukherjee } 49681dee67eSSudip Mukherjee 49781dee67eSSudip Mukherjee /* 49881dee67eSSudip Mukherjee * This function writes a value to the slave device's register 49981dee67eSSudip Mukherjee * 50081dee67eSSudip Mukherjee * Parameters: 50181dee67eSSudip Mukherjee * deviceAddress - i2c Slave device address which register 50281dee67eSSudip Mukherjee * to be written 50381dee67eSSudip Mukherjee * registerIndex - Slave device's register to be written 50481dee67eSSudip Mukherjee * data - Data to be written to the register 50581dee67eSSudip Mukherjee * 50681dee67eSSudip Mukherjee * Result: 50781dee67eSSudip Mukherjee * 0 - Success 50881dee67eSSudip Mukherjee * -1 - Fail 50981dee67eSSudip Mukherjee */ 51081dee67eSSudip Mukherjee long swI2CWriteReg( 51181dee67eSSudip Mukherjee unsigned char deviceAddress, 51281dee67eSSudip Mukherjee unsigned char registerIndex, 51381dee67eSSudip Mukherjee unsigned char data 51481dee67eSSudip Mukherjee ) 51581dee67eSSudip Mukherjee { 51681dee67eSSudip Mukherjee long returnValue = 0; 51781dee67eSSudip Mukherjee 51881dee67eSSudip Mukherjee /* Send the Start signal */ 51981dee67eSSudip Mukherjee swI2CStart(); 52081dee67eSSudip Mukherjee 52181dee67eSSudip Mukherjee /* Send the device address and read the data. All should return success 52281dee67eSSudip Mukherjee in order for the writing processed to be successful 52381dee67eSSudip Mukherjee */ 52481dee67eSSudip Mukherjee if ((swI2CWriteByte(deviceAddress) != 0) || 52581dee67eSSudip Mukherjee (swI2CWriteByte(registerIndex) != 0) || 52681dee67eSSudip Mukherjee (swI2CWriteByte(data) != 0)) 52781dee67eSSudip Mukherjee { 52881dee67eSSudip Mukherjee returnValue = -1; 52981dee67eSSudip Mukherjee } 53081dee67eSSudip Mukherjee 53181dee67eSSudip Mukherjee /* Stop i2c and release the bus */ 53281dee67eSSudip Mukherjee swI2CStop(); 53381dee67eSSudip Mukherjee 53481dee67eSSudip Mukherjee return returnValue; 53581dee67eSSudip Mukherjee } 536