diff options
Diffstat (limited to 'drivers/staging/sm750fb/ddk750_hwi2c.c')
-rw-r--r-- | drivers/staging/sm750fb/ddk750_hwi2c.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c new file mode 100644 index 0000000..7826376 --- /dev/null +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -0,0 +1,271 @@ +#define USE_HW_I2C +#ifdef USE_HW_I2C +#include "ddk750_help.h" +#include "ddk750_reg.h" +#include "ddk750_hwi2c.h" +#include "ddk750_power.h" + +#define MAX_HWI2C_FIFO 16 +#define HWI2C_WAIT_TIMEOUT 0xF0000 + + +int hwI2CInit( + unsigned char busSpeedMode +) +{ + unsigned int value; + + /* Enable GPIO 30 & 31 as IIC clock & data */ + value = PEEK32(GPIO_MUX); + + value = FIELD_SET(value, GPIO_MUX, 30, I2C) | + FIELD_SET(0, GPIO_MUX, 31, I2C); + POKE32(GPIO_MUX, value); + + /* Enable Hardware I2C power. + TODO: Check if we need to enable GPIO power? + */ + enableI2C(1); + + /* Enable the I2C Controller and set the bus speed mode */ + value = PEEK32(I2C_CTRL); + if (busSpeedMode == 0) + value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD); + else + value = FIELD_SET(value, I2C_CTRL, MODE, FAST); + value = FIELD_SET(value, I2C_CTRL, EN, ENABLE); + POKE32(I2C_CTRL, value); + + return 0; +} + + +void hwI2CClose(void) +{ + unsigned int value; + + /* Disable I2C controller */ + value = PEEK32(I2C_CTRL); + value = FIELD_SET(value, I2C_CTRL, EN, DISABLE); + POKE32(I2C_CTRL, value); + + /* Disable I2C Power */ + enableI2C(0); + + /* Set GPIO 30 & 31 back as GPIO pins */ + value = PEEK32(GPIO_MUX); + value = FIELD_SET(value, GPIO_MUX, 30, GPIO); + value = FIELD_SET(value, GPIO_MUX, 31, GPIO); + POKE32(GPIO_MUX, value); +} + + +static long hwI2CWaitTXDone(void) +{ + unsigned int timeout; + + /* Wait until the transfer is completed. */ + timeout = HWI2C_WAIT_TIMEOUT; + while ((FIELD_GET(PEEK32(I2C_STATUS), I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) && + (timeout != 0)) + timeout--; + + if (timeout == 0) + return (-1); + + return 0; +} + + + +/* + * This function writes data to the i2c slave device registers. + * + * Parameters: + * deviceAddress - i2c Slave device address + * length - Total number of bytes to be written to the device + * pBuffer - The buffer that contains the data to be written to the + * i2c device. + * + * Return Value: + * Total number of bytes those are actually written. + */ +static unsigned int hwI2CWriteData( + unsigned char deviceAddress, + unsigned int length, + unsigned char *pBuffer +) +{ + unsigned char count, i; + unsigned int totalBytes = 0; + + /* Set the Device Address */ + POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01); + + /* Write data. + * Note: + * Only 16 byte can be accessed per i2c start instruction. + */ + do + { + /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */ + POKE32(I2C_RESET, 0); + + /* Set the number of bytes to be written */ + if (length < MAX_HWI2C_FIFO) + count = length - 1; + else + count = MAX_HWI2C_FIFO - 1; + POKE32(I2C_BYTE_COUNT, count); + + /* Move the data to the I2C data register */ + for (i = 0; i <= count; i++) + POKE32(I2C_DATA0 + i, *pBuffer++); + + /* Start the I2C */ + POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); + + /* Wait until the transfer is completed. */ + if (hwI2CWaitTXDone() != 0) + break; + + /* Substract length */ + length -= (count + 1); + + /* Total byte written */ + totalBytes += (count + 1); + + } while (length > 0); + + return totalBytes; +} + + + + +/* + * This function reads data from the slave device and stores them + * in the given buffer + * + * Parameters: + * deviceAddress - i2c Slave device address + * length - Total number of bytes to be read + * pBuffer - Pointer to a buffer to be filled with the data read + * from the slave device. It has to be the same size as the + * length to make sure that it can keep all the data read. + * + * Return Value: + * Total number of actual bytes read from the slave device + */ +static unsigned int hwI2CReadData( + unsigned char deviceAddress, + unsigned int length, + unsigned char *pBuffer +) +{ + unsigned char count, i; + unsigned int totalBytes = 0; + + /* Set the Device Address */ + POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01); + + /* Read data and save them to the buffer. + * Note: + * Only 16 byte can be accessed per i2c start instruction. + */ + do + { + /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */ + POKE32(I2C_RESET, 0); + + /* Set the number of bytes to be read */ + if (length <= MAX_HWI2C_FIFO) + count = length - 1; + else + count = MAX_HWI2C_FIFO - 1; + POKE32(I2C_BYTE_COUNT, count); + + /* Start the I2C */ + POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); + + /* Wait until transaction done. */ + if (hwI2CWaitTXDone() != 0) + break; + + /* Save the data to the given buffer */ + for (i = 0; i <= count; i++) + *pBuffer++ = PEEK32(I2C_DATA0 + i); + + /* Substract length by 16 */ + length -= (count + 1); + + /* Number of bytes read. */ + totalBytes += (count + 1); + + } while (length > 0); + + return totalBytes; +} + + + + +/* + * This function reads the slave device's register + * + * Parameters: + * deviceAddress - i2c Slave device address which register + * to be read from + * registerIndex - Slave device's register to be read + * + * Return Value: + * Register value + */ +unsigned char hwI2CReadReg( + unsigned char deviceAddress, + unsigned char registerIndex +) +{ + unsigned char value = (0xFF); + + if (hwI2CWriteData(deviceAddress, 1, ®isterIndex) == 1) + hwI2CReadData(deviceAddress, 1, &value); + + return value; +} + + + + + +/* + * This function writes a value to the slave device's register + * + * Parameters: + * deviceAddress - i2c Slave device address which register + * to be written + * registerIndex - Slave device's register to be written + * data - Data to be written to the register + * + * Result: + * 0 - Success + * -1 - Fail + */ +int hwI2CWriteReg( + unsigned char deviceAddress, + unsigned char registerIndex, + unsigned char data +) +{ + unsigned char value[2]; + + value[0] = registerIndex; + value[1] = data; + if (hwI2CWriteData(deviceAddress, 2, value) == 2) + return 0; + + return (-1); +} + + +#endif |