blob: fc3b8aebdd9544816c10fab9dba9dff9e693d248 [file] [log] [blame]
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/completion.h>
#include <asm/mach-atheros/atheros.h>
#include "ath_i2c.h"
static int ath_i2c_major = CONFIG_ATH_I2C_MAJOR;
int ath_i2c_10bit_slave = 0;
int ath_i2c_10bit_master = 0;
int ath_i2c_slave_index = 0;
module_param(ath_i2c_10bit_slave, int, S_IRUGO);
module_param(ath_i2c_10bit_master, int, S_IRUGO);
module_param(ath_i2c_slave_index, int, S_IRUGO);
MODULE_AUTHOR("Charanya@Atheros");
MODULE_LICENSE("Dual BSD/GPL");
/* Tx abort source strings */
static char *tx_abort_source_str[] = {
[TX_ABRT_7B_ADDR_NOACK] =
"7 bit slave address not acknowledged",
[TX_ABRT_10ADDR1_NOACK] =
"10 bit slave first address byte not acknowledged",
[TX_ABRT_10ADDR2_NOACK] =
"10 bit slave second address byte not acknowledged",
[TX_ABRT_TXDATA_NOACK] =
"Transmitted data is not acknowledged",
[TX_ABRT_GCALL_NOACK] =
"General call is not acknowledged",
[TX_ABRT_GCALL_READ] =
"Read command issued after general call",
[TX_ABRT_HS_ACKDET] =
"Master in HS mode and HS master code acknowledged",
[TX_ABRT_SBYTE_ACKDET] =
"Masters start byte is acknowledged",
[TX_ABRT_HS_NORSTRT] =
"Master sending data in HS mode with restart disabled",
[TX_ABRT_SBYTE_NORSTRT] =
"User trying to send start byte when restart is disabled",
[TX_ABRT_10B_RD_NORSTRT] =
"Master trying to read in 10 bit mode when restart is disabled",
[TX_ARB_MASTER_DIS] =
"User attempted to use disabled master",
[TX_ARB_LOST] =
"Master has lost arbitration",
[TX_ABRT_SLVFLUSH_TXFIFO] =
"Slave received read when data exisits in tx fifo",
[TX_ABRT_SLV_ARBLOST] =
"Slave lost bus while transmitting",
[TX_ABRT_SLVRD_INTX] =
"Slave requesting data to Tx and user wrote a read command"
};
static int ath_i2c_open(struct inode *inode, struct file *filp)
{
/* Do nothing */
return 0;
}
/* Issue a soft reset to reset the state machine */
static void ath_i2c_soft_reset( void )
{
ath_reg_wr(ATH_I2C_SRESET, I2C_SRESET);
while(ath_reg_rd(ATH_I2C_SRESET) & I2C_SRESET);
}
/* Enable I2C. Few registers are to be
written only with I2C disabled */
static void ath_i2c_enable(void)
{
ath_reg_wr(ATH_I2C_ENABLE, I2C_ENABLE);
}
/* Disable I2C */
static void ath_i2c_disable(void)
{
ath_reg_wr(ATH_I2C_ENABLE, I2C_DISABLE);
}
/* Function to set clk configuration. This sets the HIGH and LOW
* periods of the clock for Standard, Fast or High speed mode */
void ath_i2c_set_clk(unsigned int data)
{
unsigned int rd_data = 0;
/* Disable I2C controller to initialize registers */
ath_i2c_disable();
switch(data) {
case IC_SS_MODE_100MHZ:
/* Set I2C_CLK_SEL bit in Switch clock spare for 100 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(1))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_SS));
ath_reg_wr((ATH_I2C_SS_SCL_HCNT), ATH_I2C_SS_SCL_HCNT_100);
ath_reg_wr((ATH_I2C_SS_SCL_LCNT), ATH_I2C_SS_SCL_LCNT_100);
break;
case IC_SS_MODE_40MHZ :
/* Clear I2C_CLK_SEL bit in Switch clock spare for 40 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(0))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_SS));
ath_reg_wr((ATH_I2C_SS_SCL_HCNT), ATH_I2C_SS_SCL_HCNT_40);
ath_reg_wr((ATH_I2C_SS_SCL_LCNT), ATH_I2C_SS_SCL_LCNT_40);
break;
case IC_FS_MODE_100MHZ :
/* Set I2C_CLK_SEL bit in Switch clock spare for 100 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(1))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_FS));
ath_reg_wr((ATH_I2C_FS_SCL_HCNT), ATH_I2C_FS_SCL_HCNT_100);
ath_reg_wr((ATH_I2C_FS_SCL_LCNT), ATH_I2C_FS_SCL_LCNT_100);
break;
case IC_FS_MODE_40MHZ :
/* Clear I2C_CLK_SEL bit in Switch clock spare for 40 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(0))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_FS));
ath_reg_wr((ATH_I2C_FS_SCL_HCNT), ATH_I2C_FS_SCL_HCNT_40);
ath_reg_wr((ATH_I2C_FS_SCL_LCNT), ATH_I2C_FS_SCL_LCNT_40);
break;
case IC_HS_MODE_100MHZ :
/* Set I2C_CLK_SEL bit in Switch clock spare for 100 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(1))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_HS));
ath_reg_wr((ATH_I2C_HS_SCL_HCNT), ATH_I2C_HS_SCL_HCNT_100);
ath_reg_wr((ATH_I2C_HS_SCL_LCNT), ATH_I2C_HS_SCL_LCNT_100);
break;
case IC_HS_MODE_40MHZ :
/* Clear I2C_CLK_SEL bit in Switch clock spare for 100 MHZ */
rd_data = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS);
rd_data = rd_data & ~(SWITCH_CLOCK_SPARE_I2C_CLK_SEL_MASK);
ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, ((rd_data | SWITCH_CLOCK_SPARE_I2C_CLK_SEL_SET(0))));
rd_data = ath_reg_rd(ATH_I2C_I2CON);
rd_data = rd_data & ~(ATH_I2C_CON_SPEED_MASK);
ath_reg_wr(ATH_I2C_I2CON, (rd_data | ATH_I2C_CON_SPEED_HS));
ath_reg_wr((ATH_I2C_HS_SCL_HCNT), ATH_I2C_HS_SCL_HCNT_40);
ath_reg_wr((ATH_I2C_HS_SCL_LCNT), ATH_I2C_HS_SCL_LCNT_40);
break;
}
ath_i2c_enable();
}
/* Function to set 7/10 bit addressing mode
* as a master */
static int ath_i2c_set_addrmode(unsigned int addr_mode)
{
int ret = 0;
/* Addr mode can be set only if bus is not busy */
/* Make sure that the ioctl is not called during
the middle of a transaction. It should be called
only during init */
ret = ath_i2c_bus_busy();
if ( ret < 0 ) {
return ret;
}
ath_i2c_disable();
/* 7 bit master/10 bit master */
if (addr_mode == ATH_I2C_7BIT_ADDR_MAS) {
ath_reg_rmw_clear(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_MASTER);
}
else if (addr_mode == ATH_I2C_10BIT_ADDR_MAS) {
ath_reg_rmw_set(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_MASTER);
}
/* Ideally these are not used since the slave
* operates with interrupts. Hence a user interaction with
* ioctl is not required */
else if (addr_mode == ATH_I2C_7BIT_ADDR_SLA) {
ath_reg_rmw_clear(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_SLAVE);
}
else if (addr_mode == ATH_I2C_10BIT_ADDR_SLA) {
ath_reg_rmw_set(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_SLAVE);
}
ath_i2c_enable();
return 0;
}
/* Function to change I2C parameters from user space.
* To be used only before initiating any transaction since
* the I2C controller would be disabled and then renabled
* to write certain registers */
static int ath_i2c_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
unsigned int data;
int ret;
switch(cmd) {
case I2C_SET_CLK:
data = arg;
ath_i2c_set_clk(data);
break;
case I2C_SET_ADDRMODE:
data = arg;
ret = ath_i2c_set_addrmode(data);
if (ret < 0)
return -_I2C_ERR_IOCTL;
break;
default:
return -ENOTSUPP;
}
return 0;
}
/* Tasklet callback to transfer bytes more than the
* FIFO Depth and to read the data for the corresponding
* number of READ commands transferred
*/
static void ath_i2c_xfer_more(unsigned long data)
{
ath_i2c_dev_t *dev = (ath_i2c_dev_t *)data;
if (dev == NULL)
return;
if (dev->trans_type == I2C_READ) {
do_i2c_read();
}
/* Call low level xfer function
* to transfer more data bytes or more READ
* commands */
ath_i2c_xfer();
if (dev->tx_len != 0)
ath_reg_wr(ATH_I2C_INTR_MASK, (ATH_I2C_INTR_MASK_STOP |
ATH_I2C_INTR_MASK_TXABRT |
ATH_I2C_INTR_MASK_TXEMPTY));
else
ath_reg_wr(ATH_I2C_INTR_MASK, (ATH_I2C_INTR_MASK_STOP |
ATH_I2C_INTR_MASK_TXABRT));
}
/* Interrupt handler */
irqreturn_t ath_i2c_intr(void)
{
ath_i2c_dev_t *dev = &i2c_dev;
unsigned char rd_data_from_reg;
unsigned char i;
unsigned int int_status;
int_status = ath_reg_rd(ATH_I2C_RAW_INTR_STAT);
ath_reg_wr(ATH_I2C_INTR_MASK, 0);
if (dev->master == 1) {
/* Tx ABRT: Occurs due to one of the many reasons mentioned in
* Tx ABRT Source register. Set tx_err when such an error occurs */
if ((int_status & ATH_I2C_INTR_MASK_TXABRT) == ATH_I2C_INTR_MASK_TXABRT) {
dev->tx_abort_source = ath_reg_rd(ATH_I2C_TX_ABRT_SOURCE);
dev->tx_err = _I2C_ERR_ABORT;
ath_reg_rd(ATH_I2C_CLR_TX_ABRT);
} else if ((int_status & ATH_I2C_INTR_MASK_TXEMPTY) == ATH_I2C_INTR_MASK_TXEMPTY) {
/* Burst transaction more than the FIFO DEPTH */
tasklet_schedule(&dev->xfer_more);
}
}
/* RxFULL: Occurs when there are entries more than the RX_TL. Used only
* in slave mode to frame the address offset and to identify a Write/Read
* transaction. A write transaction involves more than 2 RxFULL interrupts.
* Read transaction involves 2 RxFull interrupts for address offsets
* followed by Read request interrupt */
/* The number of address offset bytes and the register space accessible
* for read by another master is fixed for now. Scorpion I2C slave
* requires that the address offset is of 2 bytes and can read only
* the SLIC register space */
if ((int_status & ATH_I2C_INTR_MASK_RXFULL) == ATH_I2C_INTR_MASK_RXFULL) {
/* Disable Rx Full */
ath_reg_rmw_clear(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
/* Read data cmd register and get the data */
dev->rx_data[dev->data_count] = ath_reg_rd(ATH_I2C_DATA_CMD) & ATH_I2C_DAT_MASK;
dev->data_count++;
ath_reg_rmw_set(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
}
/* RD REQ: Received whenever a master wants to read
* data from a slave. This should occur after receiving 2 bytes
* of address offset */
else if ((int_status & ATH_I2C_INTR_MASK_RDREQ) == ATH_I2C_INTR_MASK_RDREQ) {
/* Clear red request interrupt */
ath_reg_rd(ATH_I2C_CLR_RD_REQ);
/* A RD REQ was received before receiving the offset bytes */
if (dev->data_count < MAX_ADDRESS_OFFSET_BYTES) {
printk("No proper offset received \n");
}
dev->reg_addr = ((dev->rx_data[0]) << 8 | (dev->rx_data[1]));
/* SLIC register space is made accessible for read from a master.
* Proper care needs to be taken not to modify any critical SLIC
register data */
/* Read data continuously from the offset till a STOP is received. Holds good
* for both single/burst transaction */
for ( i = 0; i < MAX_READ_COUNT; i++) {
rd_data_from_reg = ath_reg_rd((ATH_SLIC_BASE + (dev->reg_addr) + (dev->rd_req_count)));
/* Offset address increment for a burst transaction */
dev->rd_req_count = (dev->rd_req_count + 4);
ath_reg_wr(ATH_I2C_DATA_CMD, ((rd_data_from_reg) & 0xff));
}
}
/* STOP: Indicates that a transaction has been completed. For
* Slave Rx mode, the received bytes are written to the address offset
* For master mode, specifies that a transaction is complete by setting the
* complete flag */
else if ((int_status & ATH_I2C_INTR_MASK_STOP) == ATH_I2C_INTR_MASK_STOP) {
/* Slave Rx. More than 2 bytes of received data indicates a write
* transaction. 2 bytes addrress offset + data bytes */
if (dev->data_count > (MAX_ADDRESS_OFFSET_BYTES)) {
dev->reg_addr = ((dev->rx_data[0]) << 8 | (dev->rx_data[1]));
for ( i = MAX_ADDRESS_OFFSET_BYTES; i < (dev->data_count); i++) {
/* Write the data stored in the array during RX FULL interrupt
* to SLIC registers */
ath_reg_wr((ATH_SLIC_BASE + (dev->reg_addr)), dev->rx_data[i]);
dev->reg_addr = (dev->reg_addr + 4);
}
}
dev->reg_addr = 0;
dev->data_count = 0;
dev->rd_req_count = 0;
ath_reg_rd(ATH_I2C_CLR_STOP_DET);
}
if (dev->master == 1) {
/* Set completion */
if ((int_status) & (ATH_I2C_INTR_MASK_TXABRT | ATH_I2C_INTR_MASK_STOP)) {
ath_reg_wr(ATH_I2C_INTR_MASK, 0);
complete(&dev->cmd_complete);
}
}
else {
/* Enable Slave mode interrupts */
ath_reg_wr(ATH_I2C_INTR_MASK, (ATH_I2C_INTR_MASK_STOP |
ATH_I2C_INTR_MASK_RXFULL |
ATH_I2C_INTR_MASK_RDREQ));
}
return IRQ_HANDLED;
}
/* Bus busy check. Masters should ensure that the
* bus is checked for busy status before initiating
* a transaction */
static int ath_i2c_bus_busy(void)
{
int timeout = ATH_I2C_TIMEOUT;
while ((ath_reg_rd(ATH_I2C_STATUS)) & ATH_I2C_STAT_ACTIVITY) {
if (timeout <= 0) {
printk("Timeout waiting for bus ready \n");
return -_I2C_ERR_BUSY;
}
timeout--;
mdelay(1);
}
return 0;
}
/* Read function to read the data present in the
* Rx FIFO. Supports burst read, that is read data len
* greater than the Rx FIFO Depth */
void do_i2c_read(void)
{
int rx_threshold;
ath_i2c_dev_t *dev = &i2c_dev;
unsigned long rx_buf_len;
unsigned char *rd_buf;
rx_threshold = ath_reg_rd(ATH_I2C_RXFLR);
rx_buf_len = dev->rx_len;
rd_buf = dev->rx_buffer;
/* Read the DATA_CMD register to get the data in the Rx FIFO */
for(; rx_buf_len > 0 && rx_threshold > 0; rx_buf_len--, rx_threshold--)
*rd_buf++ = ath_reg_rd(ATH_I2C_DATA_CMD);
dev->rx_len = rx_buf_len;
if (rx_buf_len > 0) {
dev->rx_buffer = rd_buf;
}
}
/* Low level xfer function to transmit required
* bytes/commands. This function is required for both
* write/read transaction since a READ transaction also
* involves writing of offset bytes and READ commands.
* The first gets called from the write function as well as
* from the tasklet to transmit data more than the FIFO DEPTH */
int ath_i2c_xfer(void)
{
ath_i2c_dev_t *dev = &i2c_dev;
int ret;
int tx_threshold, tx_cur_entries;
int rx_threshold, rx_cur_entries;
unsigned long tx_buf_len;
int offset_write = 0;
tx_cur_entries = ath_reg_rd(ATH_I2C_TXFLR);
tx_threshold = TX_FIFO_DEPTH - tx_cur_entries;
rx_cur_entries = ath_reg_rd(ATH_I2C_RXFLR);
rx_threshold = RX_FIFO_DEPTH - rx_cur_entries;
if (dev->first == 1) {
/* Check if the I2C bus is busy before initiating
* any transaction. The SDA and SCL would be high
* before the start of a transaction. The master
* can then pull the SDA low to aquire the bus */
ret = ath_i2c_bus_busy();
if ( ret < 0 ) {
goto do_xfer_done;
}
/* Disable I2C */
ath_i2c_disable();
/* Follow master read sequence as per protocol. Send I2C slave
* address first, write the offset_size offset bytes,
* initiate a read sequence by writing READ command for data_size
* times and read data_size bytes from the buffer.
* This is covered under Master Transmit and Master Receive
section in the data sheet */
/* Write Slave addr */
ath_reg_wr(ATH_I2C_TAR, dev->slave);
ath_i2c_enable();
}
/* Handle burst transactions of more than the FIFO DEPTH using the
* TX EMPTY interrupt. When FIFO_DEPTH bytes are transmitted, wait
* for TX EMPTY and then keep transmitting further bytes with the
* xfer_more tasklet */
tx_buf_len = dev->tx_len;
while(tx_buf_len > 0 && tx_threshold > 0 && rx_threshold > 0) {
if (dev->trans_type == I2C_WRITE) {
if ((dev->tx_off_buf == NULL) || (dev->tx_buffer == NULL)) {
ret = _I2C_ERR_PARAM;
goto do_xfer_done;
}
if (dev->first == 1) {
/* The first burst transaction involves writing the
offset bytes before the transmit data */
ath_reg_wr((ATH_I2C_DATA_CMD), *(dev->tx_off_buf++));
offset_write++;
}
else {
ath_reg_wr(ATH_I2C_DATA_CMD, *(dev->tx_buffer++));
}
} else if (dev->trans_type == I2C_READ) {
if ((dev->rx_off_buf == NULL) || (dev->rx_buffer == NULL)) {
ret = _I2C_ERR_PARAM;
goto do_xfer_done;
}
if (dev->first == 1) {
/* The first burst transaction involves writing the
offset bytes before the READ command */
ath_reg_wr((ATH_I2C_DATA_CMD), *(dev->rx_off_buf++));
offset_write++;
}
else {
ath_reg_wr(ATH_I2C_DATA_CMD, ATH_I2C_CMD_READ);
rx_threshold--;
}
}
tx_threshold--;
tx_buf_len--;
if (offset_write == dev->off_len)
dev->first = 0;
}
/* Enable Required interrupts */
ath_reg_wr(ATH_I2C_INTR_MASK, (ATH_I2C_INTR_MASK_STOP |
ATH_I2C_INTR_MASK_TXABRT));
/* More data to be transmitted */
if (tx_buf_len > 0) {
ath_reg_rmw_set(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_TXEMPTY);
}
dev->tx_len = tx_buf_len;
ret = dev->tx_len;
do_xfer_done:
return ret;
}
/* Copy required paramters from the user, check for errors
* and call the low level bus specific xfer function.
* Called through the write() system call from the application */
ssize_t ath_i2c_write(struct file * filp, const char __user * buf,
size_t count, loff_t * f_pos)
{
ath_i2c_dev_t *dev = &i2c_dev;
i2c_rw_t wrparam;
int ret = 0, wr_bytes;
char *offset_ptr;
char *data_ptr;
mutex_lock(&dev->i2c_lock);
INIT_COMPLETION(dev->cmd_complete);
/* Rx FULL interrupt required only for slave mode operation */
ath_reg_rmw_clear(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
/* Device is a master and should initiate transaction
* with a slave device */
dev->master = 1;
/* The first burst */
dev->first = 1;
/* Transaction type: Write Transaction */
dev->trans_type = I2C_WRITE;
/* Initialize tx err to No Error */
dev->tx_err = 0;
/* Copy write parameters from user. The params contain the
target slave addr, number of bytes of offset, the offset pointer ,
number of bytes of data and the data pointer */
if (copy_from_user(&wrparam, (i2c_rw_t *)buf, sizeof(i2c_rw_t))) {
ret = -EINVAL;
return ret;
} else {
/* Allocate needed memories to hold the offsets and data */
offset_ptr = kmalloc(wrparam.offset_size, GFP_KERNEL);
if (offset_ptr == NULL) {
ret = -ENOMEM;
return ret;
}
/* Cleanly handle failures in copy to make sure there are
no allocated dangling buffers */
if( copy_from_user(offset_ptr, wrparam.offset, wrparam.offset_size) ) {
ret = -EINVAL;
kfree(offset_ptr);
return ret;
}
wrparam.offset = offset_ptr;
data_ptr = kmalloc(wrparam.data_size, GFP_KERNEL);
if (data_ptr == NULL) {
/* Free offset ptr */
kfree(offset_ptr);
ret = -ENOMEM;
return ret;
}
if( copy_from_user(data_ptr, wrparam.data, wrparam.data_size) ) {
ret = -EINVAL;
kfree(offset_ptr);
kfree(data_ptr);
return ret;
}
wrparam.data = data_ptr;
/* Make a copy of the write parameters in the
* dev structure */
dev->slave = wrparam.slave;
dev->tx_buffer = wrparam.data;
dev->tx_off_buf = wrparam.offset;
dev->data_len = wrparam.data_size;
dev->off_len = wrparam.offset_size;
/* The total tx len includes the offset len and
* the data len */
dev->tx_len = (dev->data_len + dev->off_len);
/* Call the low level xfer function to transmit both
* the offset bytes and the data bytes */
ret = ath_i2c_xfer();
if (ret < 0) {
goto wr_done;
}
else {
/* Save return value from xfer function */
wr_bytes = ret;
}
/* Wait for tx to complete. Completion happens when a STOP or TX ABRT
* is received on the bus */
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
if (ret == 0) {
printk("controller timed out\n");
ath_i2c_init_reg();
ret = -ETIMEDOUT;
goto wr_done;
}
/* A faulty completion due to TX ABRT. Return the reason
* for Tx ABRT */
if (dev->tx_err == _I2C_ERR_ABORT) {
int i = 0;
unsigned long source = dev->tx_abort_source;
for_each_bit(i, &source, ARRAY_SIZE(tx_abort_source_str)) {
printk(" %s %s\n", __func__, tx_abort_source_str[i]);
}
ret = -EIO;
goto wr_done;
}
}
/* A clean return. Number of bytes remaining to be written */
ret = wr_bytes;
wr_done:
/* Enable RX FULL interrupt since it is required
* for slave mode operation */
ath_reg_rmw_set(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
dev->master = 0;
dev->first = 0;
dev->trans_type = 0;
mutex_unlock(&dev->i2c_lock);
kfree(offset_ptr);
kfree(data_ptr);
return ret;
}
/* Function to copy the paramters from user space
* and call the low level bus specific transfer function
*/
ssize_t ath_i2c_read(struct file * filp, char __user * buf,
size_t count, loff_t * f_pos)
{
ath_i2c_dev_t *dev = &i2c_dev;
i2c_rw_t rdparam;
int ret = 0;
char *offset_ptr;
char *param_base;
/* Device is a master since the read is
* triggered from user space */
dev->master = 1;
/* The first burst */
dev->first = 1;
/* Transaction type: A read transaction */
dev->trans_type = I2C_READ;
/* Rx Full interrupt is required only for slave mode
* operation */
ath_reg_rmw_clear(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
/* Initialize tx err to no errros */
dev->tx_err = 0;
mutex_lock(&dev->i2c_lock);
INIT_COMPLETION(dev->cmd_complete);
/* Copy Parameters from user. The params contain the
target slave addr, number of bytes of offset, the offset pointer ,
number of bytes of data and the data pointer where read data
is to be stored */
if ( copy_from_user(&rdparam, (i2c_rw_t *)buf, sizeof(i2c_rw_t)) ) {
ret = -EINVAL;
return ret;
} else {
/* Allocate required memories */
offset_ptr = kmalloc(rdparam.offset_size, GFP_KERNEL);
if (offset_ptr == NULL) {
ret = -ENOMEM;
return ret;
}
if( copy_from_user(offset_ptr, rdparam.offset, rdparam.offset_size) ) {
ret = -EINVAL;
kfree(offset_ptr);
return ret;
}
rdparam.offset = offset_ptr;
rdparam.data = kmalloc((rdparam.data_size) , GFP_KERNEL);
if (rdparam.data == NULL) {
/* Free offset ptr */
kfree(offset_ptr);
ret = -ENOMEM;
return ret;
}
param_base = rdparam.data;
/* Make a copy of the required params in the
* dev structure */
dev->slave = rdparam.slave;
dev->rx_buffer = rdparam.data;
dev->rx_off_buf = rdparam.offset;
dev->data_len = rdparam.data_size;
dev->off_len = rdparam.offset_size;
/* Total Transmit len includes both the
* offset len and the data len */
dev->tx_len = (dev->data_len + dev->off_len);
dev->rx_len = dev->data_len;
/* Call xfer function to transmit the data
* out. Typically this involves transmitting the
* address offset and the READ commands to the slave
*/
ret = ath_i2c_xfer();
if (ret < 0) {
goto rd_done;
}
/* Wait for tx to complete. Completion happens when a STOP or TX ABRT
* is received on the bus */
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
if (ret == 0) {
printk("controller timed out\n");
ath_i2c_init_reg();
ret = -ETIMEDOUT;
goto rd_done;
}
/* Read the data in the Rx FIFO only if the transmission
* of offset bytes and READ commands are successful */
if (dev->tx_err == 0) {
do {
do_i2c_read();
}while(dev->rx_len > 0);
}
/* A faulty completion due to TX ABRT. Return the reason
* for Tx ABRT */
if (dev->tx_err == _I2C_ERR_ABORT) {
int i = 0;
unsigned long source = dev->tx_abort_source;
for_each_bit(i, &source, ARRAY_SIZE(tx_abort_source_str)) {
printk(" %s %s\n", __func__, tx_abort_source_str[i]);
}
ret = -EIO;
goto rd_done;
}
/* Copt the read data to user space */
if ( copy_to_user(((i2c_rw_t *)buf)->data, param_base, rdparam.data_size) ) {
ret = -EINVAL;
goto rd_done;
}
}
/* Clean return. Return the number of bytes remaining to be
* read */
ret = dev->rx_len;
rd_done:
/* Enable RxFULL interrupt since it it required for
* slave mode */
ath_reg_rmw_set(ATH_I2C_INTR_MASK, ATH_I2C_INTR_MASK_RXFULL);
dev->master = 0;
dev->first = 0;
dev->trans_type = 0;
mutex_unlock(&dev->i2c_lock);
kfree(offset_ptr);
kfree(rdparam.data);
return ret;
}
/* File operations structure */
struct file_operations ath_i2c_fops = {
.owner = THIS_MODULE,
.read = ath_i2c_read,
.write = ath_i2c_write,
.ioctl = ath_i2c_ioctl,
.open = ath_i2c_open,
};
/* Function to initialize GPIOs and registers
* with required defaults */
void ath_i2c_init_reg(void)
{
unsigned int rddata = 0;
unsigned int base_slave_addr = 0;
/* Initialize the GPIOs. GPIO 19 and 20 are used for SCL and SDA
* respectively. This is board specific */
rddata = ath_reg_rd(ATH_GPIO_IN_ENABLE4) & ~(0x00ff0000);
ath_reg_wr(ATH_GPIO_IN_ENABLE4, rddata | GPIO_IN_ENABLE4_I2C_CLK_SET(0x13));
rddata = ath_reg_rd(ATH_GPIO_IN_ENABLE4) & ~(0xff000000);
ath_reg_wr(ATH_GPIO_IN_ENABLE4, rddata | GPIO_IN_ENABLE4_I2C_DATA_SET(0x14));
rddata = ((ath_reg_rd(ATH_GPIO_OUT_FUNCTION4)) & (~(GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_MASK)));
ath_reg_wr(ATH_GPIO_OUT_FUNCTION4, (rddata | GPIO_OUT_FUNCTION4_ENABLE_GPIO_19_SET(0x7)));
rddata = ((ath_reg_rd(ATH_GPIO_OUT_FUNCTION5)) & (~(GPIO_OUT_FUNCTION5_ENABLE_GPIO_20_MASK)));
ath_reg_wr(ATH_GPIO_OUT_FUNCTION5, (rddata | GPIO_OUT_FUNCTION5_ENABLE_GPIO_20_SET(0x6)));
ath_reg_wr(ATH_GPIO_OE, ath_reg_rd(ATH_GPIO_OE)& (~0x180000));
/* Issue a Soft reset */
ath_i2c_soft_reset();
/* Disable I2C controller to initialize registers.
* Few registers should be written only with the
* controller disabled */
ath_i2c_disable();
/* Set Default Parameters for Control and Clock
* Clock 40 MHZ, Master mode, Restart Enable ,
* Slow Speed */
ath_reg_wr((ATH_I2C_I2CON), ATH_I2C_DEF_CON);
ath_reg_wr((ATH_I2C_SS_SCL_HCNT), ATH_I2C_SS_SCL_HCNT_40);
ath_reg_wr((ATH_I2C_SS_SCL_LCNT), ATH_I2C_SS_SCL_LCNT_40);
base_slave_addr = I2C_BASE_SLAVE_ADDR;
/* Master to address a 7/10 bit slave??? */
if (ath_i2c_10bit_master) {
ath_reg_rmw_set(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_MASTER);
}
/* Slave to respond to a 7/10 bit address
* access from a master??? */
if (ath_i2c_10bit_slave) {
ath_reg_rmw_set(ATH_I2C_I2CON, ATH_I2C_CON_10BITADDR_SLAVE);
base_slave_addr = I2C_10BIT_BASE_ADDR;
}
/* Write our slave address to which we respond to any access
* from a master. An ACK is sent whenever another master puts this
* address on the I2C bus. The base slave address is fixed
* as 0x20 and can be modified with mod param */
ath_reg_wr(ATH_I2C_SAR, base_slave_addr + ath_i2c_slave_index);
/* Set Rx Threshold so that the slave can respond when there is
* incoming data from the master. Trigger an Rx FULL interrupt when
* there is 1 data in the receive buffer. Needed here since for slave
* mode there is no interaction from the app for read/write and is purely
* based on interrupts */
ath_reg_wr(ATH_I2C_RX_TL, 0x0);
/* Enable only interrupts required for slave mode. Master mode
* interrupts are to be enabled in the respective
* read/write routines */
ath_reg_wr(ATH_I2C_INTR_MASK, (ATH_I2C_INTR_MASK_RXFULL | ATH_I2C_INTR_MASK_RDREQ |
ATH_I2C_INTR_MASK_STOP | ATH_I2C_INTR_MASK_TXABRT));
/* Enable the controller */
ath_i2c_enable();
}
/* Cleanup module called during rmmod */
void ath_i2c_cleanup_module(void)
{
ath_i2c_dev_t *dev = &i2c_dev;
free_irq(dev->irq, NULL);
unregister_chrdev(ath_i2c_major, "ath_i2c");
}
/* Init module called during insmod */
int __init ath_i2c_init_module(void)
{
int result = 0;
ath_i2c_dev_t *dev = &i2c_dev;;
result = register_chrdev(ath_i2c_major, "ath_i2c",
&ath_i2c_fops);
if (result > 0 ) {
ath_i2c_major = result;
}else if (result < 0) {
printk(KERN_WARNING "ath_i2c: can't get major %d\n",
ath_i2c_major);
goto err_reg;
}
/* Initialize dev structure */
dev->irq = ATH_MISC_IRQ_I2C;
dev->data_count = 0;
dev->reg_addr = 0;
dev->rd_req_count = 0;
dev->tx_abort_source = 0;
dev->tx_err = 0;
dev->master = 0;
/* For synchronization */
init_completion(&dev->cmd_complete);
/* Initialize tasklet for burst transactions */
tasklet_init(&dev->xfer_more, ath_i2c_xfer_more, (unsigned long) dev);
mutex_init(&dev->i2c_lock);
/* Disable all interrupts */
ath_reg_wr(ATH_I2C_INTR_MASK, 0);
/* Resigter ISR */
result = request_irq(dev->irq, (void *) ath_i2c_intr, IRQF_DISABLED,
"ath_i2c", NULL);
if (result) {
printk(KERN_INFO "i2c: can't get assigned irq %d returns %d\n",
dev->irq, result);
goto err_irq;
}
/* GPIO and reg init */
ath_i2c_init_reg();
return 0;
/* Cleanly handle errors encountered while inserting module */
err_irq:
unregister_chrdev(ath_i2c_major, "ath_i2c");
err_reg:
return result;
}
module_init(ath_i2c_init_module);
module_exit(ath_i2c_cleanup_module);