示例#1
0
/* Write Function of PROCFS attribute "/proc/b3450_reg" */
static ssize_t b3450_proc_write(struct file *file, const char __user *buffer,
                                  unsigned long count, void *data)
{
    int value, ret_val;
    int offset = (int)file->f_pos;

    /* Only 4-Byte writes are supported */
    if (count != REGISTER_LENGTH) {
        BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "Only 4 Byte writes are supported \n");
        return -EINVAL;
    }

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "The offset is %d; the count is %ld \n", 
                  offset, count);

#ifdef __LITTLE_ENDIAN
    value = *((int *)buffer);
#else
    value = swab32(*((int *)buffer));
#endif

    ret_val = bcm3450_write_reg(offset, value);

    /* If ret_val is less than 0, return ret_val; else return number
       of bytes read which is 4 */
    return ((ret_val < 0) ? ret_val : REGISTER_LENGTH);
}
示例#2
0
u16 bcm3450_read_word(u8 offset)
{
    struct i2c_msg msg[2];
    u8 off, buf[4];
    struct i2c_client *client = &pclient_data->client;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(offset, WORD_ALIGN))
        return -1;

    /* BCM3450 requires the offset to be the register number */
    off = offset/4;

    msg[0].addr = msg[1].addr = client->addr;
    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;

    msg[0].len = 1;
    msg[0].buf = (char *)&off;

    msg[1].flags |= I2C_M_RD;
    msg[1].len = 4;
    msg[1].buf = buf;

    if(i2c_transfer(client->adapter, msg, 2) == 2)
    {
        return swab16(*((u16 *)&buf[offset % 4]));
    }

    return -1;
}
示例#3
0
u8 bcm3450_read_byte(u8 offset)
{
    struct i2c_msg msg[2];
    u8 off, buf[4];
    struct i2c_client *client = &pclient_data->client;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if (offset > MAX_REG_OFFSET) 
    {
        BCM_LOG_ERROR(BCM_LOG_ID_I2C, "Invalid offset. It should be less than "
                      "%X \n", MAX_REG_OFFSET);
        return -1;
    }

    /* BCM3450 requires the offset to be the register number */
    off = offset/4;

    msg[0].addr = msg[1].addr = client->addr;
    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;

    msg[0].len = 1;
    msg[0].buf = (char *)&off;

    msg[1].flags |= I2C_M_RD;
    msg[1].len = 4;
    msg[1].buf = buf;

    if(i2c_transfer(client->adapter, msg, 2) == 2)
    {
        return buf[offset % 4];
    }

    return -1;
}
示例#4
0
int bcm3450_write_word(u8 offset, u16 val)
{
    u8 off;
    int tmp_val;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(offset, WORD_ALIGN))
        return -1;
 
    /* Make the offset WORD aligned */
    off = offset & 0xFC; 
    
    /* Read */
    tmp_val = bcm3450_read_reg(off);
    if (tmp_val < 0) 
    {
        return -1;
    }
    
    /* Modify */
    tmp_val = (tmp_val & (~(0xFFFF << ((offset % 4) * 8)))) 
                      | (val << ((offset % 4) * 8));
    
    /* Write */
    return bcm3450_write_reg(off, tmp_val); 

}
示例#5
0
int bcm3450_read_reg(u8 offset)
{
    struct i2c_msg msg[2];
    int val;
    struct i2c_client *client = &pclient_data->client;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(offset, DWORD_ALIGN)) {
        return -EINVAL;
    }

    /* BCM3450 requires the offset to be the register number */
    offset = offset/4;

    msg[0].addr = msg[1].addr = client->addr;
    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;

    msg[0].len = 1;
    msg[0].buf = (char *)&offset;

    msg[1].flags |= I2C_M_RD;
    msg[1].len = 4;
    msg[1].buf = (char *)&val;

    /* On I2C bus, we receive LS byte first. So swap bytes as necessary */
    if(i2c_transfer(client->adapter, msg, 2) == 2)
        return swab32(val);

    return -1;
}
示例#6
0
static int bcm3450_detach_client(struct i2c_client *client)
{
    int err;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

#ifdef SYSFS_HOOKS
    sysfs_remove_group(&client->dev.kobj, &bcm3450_attr_group);
#endif

#ifdef PROCFS_HOOKS
    remove_proc_entry(PROC_ENTRY_NAME1, NULL);
#ifdef MOCA_I2C_TEST
    remove_proc_entry(PROC_ENTRY_NAME2, NULL);
#endif
#endif

    err = i2c_detach_client(client);
    if (err)
        return err;

    kfree(i2c_get_clientdata(client));

    return 0;
}
/* Read the value from given bcm63000 register */
static inline int reg_read(uint32* offset)
{
    int ret;
    ret = *offset;
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "reg_read: offset = %lx, val is %x\n", 
                  (long int)offset, ret);
    return ret;
}
static u32 bcm63000_func(struct i2c_adapter *adap)
{
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);
    /*The SMBus commands are emulated on the I2C bus using i2c_xfer function*/
    /*TBD:For correct SMBus Emulation, need to use the NOSTOP b/w given 
      messges to the i2c_xfer */
    return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
/*  TBD: The HW supports 10 bit addressing and some protocol magling */
/*	I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MAGLING; */
}
示例#9
0
/*
 *------------------------------------------------------------------------------
 * Remove the L4 dest port from the Ingress QoS priority table
 *------------------------------------------------------------------------------
 */
uint8_t iqos_rem_L4port( iqos_ipproto_t ipProto, uint16_t destPort, 
        iqos_ent_t ent )
{
    unsigned long flags;
    uint8_t remIx = IQOS_INVALID_NEXT_IX;

    BCM_LOG_DEBUG( BCM_LOG_ID_IQ, "RemPort ent<%d> ipProto<%d> dport<%d> ", 
                ent, ipProto, destPort);  

    if ( unlikely(iqos_rem_L4port_hook_g == (iqos_rem_L4port_hook_t)NULL) )
        goto iqos_rem_L4port_exit;

    IQOS_LOCK_IRQSAVE();
    remIx = iqos_rem_L4port_hook_g( ipProto, destPort, ent ); 
    IQOS_UNLOCK_IRQRESTORE();

iqos_rem_L4port_exit:
    BCM_LOG_DEBUG( BCM_LOG_ID_IQ, "remIx<%d> ", remIx);  
    return remIx;
}
示例#10
0
/*
 *------------------------------------------------------------------------------
 * Add the Ingress QoS priority, and type of entry for L4 Dest port. 
 *------------------------------------------------------------------------------
 */
uint8_t iqos_add_L4port( iqos_ipproto_t ipProto, uint16_t destPort, 
        iqos_ent_t ent, iqos_prio_t prio )
{
    unsigned long flags;
    uint8_t addIx = IQOS_INVALID_NEXT_IX;

    BCM_LOG_DEBUG( BCM_LOG_ID_IQ, 
            "AddPort ent<%d> ipProto<%d> dport<%d> prio<%d> ", 
            ent, ipProto, destPort, prio );  

    if ( unlikely(iqos_add_L4port_hook_g == (iqos_add_L4port_hook_t)NULL) )
        goto iqos_add_L4port_exit;

    IQOS_LOCK_IRQSAVE();
    addIx = iqos_add_L4port_hook_g( ipProto, destPort, ent, prio ); 
    IQOS_UNLOCK_IRQRESTORE();

iqos_add_L4port_exit:
    BCM_LOG_DEBUG( BCM_LOG_ID_IQ, "addIx<%d>", addIx );  
    return addIx;
}
/* Transfers the given number of messages */
static int bcm63000_xfer(struct i2c_adapter *adap, 
                        struct i2c_msg *msgs, int num)
{
    struct i2c_msg *p, *q;
    int i, err = 0;
    /* Determine the FIFO length for Read and Write Transactions */
    int fifo_len = (reg_read((uint32 *)&I2C->CtlHiReg) 
                    & I2C_CTLHI_REG_DATA_REG_SIZE) ? 32 : 8;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);
    /* The 63000 supports read_then_write and write_then_read formats, 
       take advantage of these formats whenever possible */
    if (num == 2)
    {
     	p = &msgs[0]; q = &msgs[1];
        /* We may be able to use the read_then_write and write_then_read 
        formats only when the length of each message is less than fifo_len */
        if (p->len <= fifo_len && q->len <= fifo_len)
        {
            if ((p->flags == I2C_M_RD) && (!(q->flags & I2C_M_RD)))
            {
                err = i2c_read_then_write(msgs, fifo_len);
                return (err < 0) ? err : 2;
            }
            else if ((!(p->flags & I2C_M_RD)) && (q->flags == I2C_M_RD))
            {
                err = i2c_write_then_read(msgs, fifo_len);
                return (err < 0) ? err : 2;
            }
        }
    }
    
    /*TBD:See if we can use NO_STOP b/w multiple read and write transactions */
    for (i = 0; !err && i < num; i++)
    {
        p = &msgs[i];
        if (p->flags & I2C_M_RD)
            err = i2c_read(p, fifo_len);
        else
            err = i2c_write(p, fifo_len);
    }

    return (err < 0) ? err : i;
}
示例#12
0
ssize_t bcm3450_write(char *buf, size_t count)
{ 
    struct i2c_client *client = &pclient_data->client;
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(buf[0], DWORD_ALIGN))
        return -1;

    if(count > MAX_TRANSACTION_SIZE)
    {
    	BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "count > %d is not yet supported \n", 
                       MAX_TRANSACTION_SIZE);
        return -1;
    }

    /* BCM3450 requires the offset to be the register number */
    buf[0] = buf[0]/4;
    
    return i2c_master_send(client, buf, count);
}
示例#13
0
ssize_t bcm3450_read(char *buf, size_t count)
{
    struct i2c_msg msg[2];
    struct i2c_client *client = &pclient_data->client;
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(buf[0], DWORD_ALIGN))
        return -1;

    /* BCM3450 requires the offset to be the register number */
    buf[0] = buf[0]/4;

    if(count > MAX_TRANSACTION_SIZE)
    {
    	BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "count > %d is not yet supported \n", 
                       MAX_TRANSACTION_SIZE);
        return -1;
    }
 
    /* First write the offset  */
    msg[0].addr = msg[1].addr = client->addr;
    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;

    msg[0].len = 1;
    msg[0].buf = buf;

    /* Now read the data */
    msg[1].flags |= I2C_M_RD;
    msg[1].len = count;
    msg[1].buf = buf;

    /* On I2C bus, we receive LS byte first. So swap bytes as necessary */
    if(i2c_transfer(client->adapter, msg, 2) == 2)
    {
        return count;
    }

    return -1;
}
示例#14
0
/* Read Function of PROCFS attribute "/proc/b3450_reg" */
static ssize_t b3450_proc_read(char *page, char **start, off_t off, int count,
                               int *eof, void *data) 
{
    int ret_val;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "The offset is %d; the count is %d \n", 
                  (int)off, count);

    /* Only 4-Byte reads are supported */
    if (count != REGISTER_LENGTH) {
        BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "Only 4 Byte reads are supported \n");
        return -EINVAL;
    }

    /*   See comments in the proc_file_read for info on 3 different
    *    ways of returning data. We are following below method.
    *    Set *start = an address within the buffer.
    *    Put the data of the requested offset at *start.
    *    Return the number of bytes of data placed there.
    *    If this number is greater than zero and you
    *    didn't signal eof and the reader is prepared to
    *    take more data you will be called again with the
    *    requested offset advanced by the number of bytes
    *    absorbed. */
    ret_val = bcm3450_read_reg((u8)off);
#ifdef __LITTLE_ENDIAN
    *((int *)page) = ret_val;
#else
    *((int *)page) = swab32(ret_val);
#endif
    *start = page;
    *eof = 1;

    /* If ret_val is less than 0, return ret_val; else return number
       of bytes read which is 4 */
    return ((ret_val < 0) ? ret_val : REGISTER_LENGTH);
}
示例#15
0
int bcm3450_write_reg(u8 offset, int val)
{
    char buf[5];
    struct i2c_client *client = &pclient_data->client;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if(check_offset(offset, DWORD_ALIGN)) {
        return -EINVAL;
    }

    /* BCM3450 requires the offset to be the register number */
    buf[0] = offset/4;

    /* On the I2C bus, LS Byte should go first */
    val = swab32(val);

    memcpy(&buf[1], (char*)&val, 4);
    if (i2c_master_send(client, buf, 5) == 5)
	{
        return 0;
	}
    return -1;
}
/*  Keep polling until the bcm63000 completes the I2C transaction or timeout */
static inline int wait_xfer_done(void)
{
    int i, temp = 0;

    for (i = 0; i < xfer_timeout; i++) 
    {
        temp = reg_read((uint32 *)&I2C->IICEnable); 
        if (temp & I2C_IIC_NO_ACK)
        {
            BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "No Ack received \n");
            return -1;
        }
        /* The xfer is complete and successful when INTRP is set 
           and NOACK is not set */
        if ((temp & I2C_IIC_INTRP) && !(temp & I2C_IIC_NO_ACK))
        {
            return 0;
        }
        /* TBD: Call the schedule() */
        udelay(1);
    }

    return -ETIMEDOUT;
}
示例#17
0
/* This function is called by i2c_probe */
static int bcm3450_detect(struct i2c_adapter *adapter, int address, int kind)
{
    struct i2c_client *client;
    int err = 0;
#ifdef PROCFS_HOOKS
    struct proc_dir_entry *p;
#endif

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
        goto exit;

    if (!(pclient_data = kzalloc(sizeof(struct bcm3450_data), GFP_KERNEL))) 
    {
        err = -ENOMEM;
        goto exit;
    }

    /* Setup the i2c client data */
    client = &pclient_data->client;
    i2c_set_clientdata(client, pclient_data);
    client->addr = address;
    client->adapter = adapter;
    client->driver = &bcm3450_driver;
    client->flags = 0;
    strlcpy(client->name, "bcm3450", I2C_NAME_SIZE);

    /* Tell the I2C layer a new client has arrived */
    if ((err = i2c_attach_client(client)))
        goto exit_kfree;

#ifdef SYSFS_HOOKS
    /* Register sysfs hooks */
    err = sysfs_create_group(&client->dev.kobj, &bcm3450_attr_group);
    if (err)
        goto exit_detach;
#endif

#ifdef PROCFS_HOOKS
    p = create_proc_entry(PROC_ENTRY_NAME1, 0, 0);
    if (!p) {
        BCM_LOG_ERROR(BCM_LOG_ID_I2C, "bcmlog: unable to create /proc/%s!\n", 
                      PROC_ENTRY_NAME1);
        err = -EIO;
#ifdef SYSFS_HOOKS
        sysfs_remove_group(&client->dev.kobj, &bcm3450_attr_group);
#endif
        goto exit_detach;
    }
    p->read_proc = b3450_proc_read;
    p->write_proc = b3450_proc_write;
    p->data = (void *)pclient_data;
    
#ifdef MOCA_I2C_TEST
        p = create_proc_entry(PROC_ENTRY_NAME2, 0, 0);
        if (p) {
            p->proc_fops = &b3450Test_fops;
        }
#endif
#endif

    return 0;

#if defined(SYSFS_HOOKS) || defined(PROCFS_HOOKS)
exit_detach:
    i2c_detach_client(client);
#endif
exit_kfree:
    kfree(pclient_data);
exit:
    return err;
}
/* Write the given value to given bcm63000 register */
static inline void reg_write(uint32* offset, int val)
{
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "reg_write: offset = %lx; val = %x\n", 
                  (long int)offset, val);
    *offset = val;
}
示例#19
0
/* Calls the appropriate function based on user command */
static int exec_command(const char *buf, size_t count, int fs_type)
{
#define MAX_ARGS 2
#define MAX_ARG_SIZE 32
    int i, argc = 0, val = 0;
    char cmd;
    u8 offset;
    char arg[MAX_ARGS][MAX_ARG_SIZE];
#if 0
    char temp_buf[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
#endif
#ifdef PROCFS_HOOKS
#define LOG_WR_KBUF_SIZE 128
    char kbuf[LOG_WR_KBUF_SIZE];

    if(fs_type == PROC_FS)
    {
        if ((count > LOG_WR_KBUF_SIZE-1) || 
            (copy_from_user(kbuf, buf, count) != 0))
            return -EFAULT;
    	kbuf[count]=0;
        argc = sscanf(kbuf, "%c %s %s", &cmd, arg[0], arg[1]);
    }
#endif

#ifdef SYSFS_HOOKS
    if(fs_type == SYS_FS)
        argc = sscanf(buf, "%c %s %s", &cmd, arg[0], arg[1]);
#endif

    if (argc <= 1) {
        BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "Need at-least 2 arguments \n");
        return -EFAULT;
    }

    for (i=0; i<MAX_ARGS; ++i) {
        arg[i][MAX_ARG_SIZE-1] = '\0';
    }

    offset = (u8) simple_strtoul(arg[0], NULL, 0);
    if (argc == 3)
        val = (int) simple_strtoul(arg[1], NULL, 0);

    switch (cmd) {

#if 0
    case 'y':
        if (argc == 3) {
            if (val > 7) {
                BCM_LOG_INFO(BCM_LOG_ID_I2C, "Limiting byte count to 7 \n");
                val = 7;
            }
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Write Byte Stream: offset = %x, " 
   		 	              "count = %x \n", offset, val);
            for (i=0; i< val; i++) {
                BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "%x, ",temp_buf[i]);
            }
            temp_buf[0] = offset;
            bcm3450_write(temp_buf, val+1);
        }
        break;

    case 'z':
        if (argc == 3) {
            if (val > 8) {
                BCM_LOG_INFO(BCM_LOG_ID_I2C, "This test limits the byte stream" 
                             " count to 8 \n");
                val = 8;
            }
            for (i=0; i< val; i++) {
                BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "%x, ",temp_buf[i]);
            }
            temp_buf[0] = offset;
            bcm3450_read(temp_buf, val);
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Read Byte Stream: offset = %x, " 
   		 	              "count = %x \n", offset, val);
            for (i=0; i< val; i++) {
                BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "%x, ",temp_buf[i]);
            }
            BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "\n");
        }
        break;
#endif

    case 'b':
        if (argc == 3) {
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Write Byte: offset = %x, " 
   		 	              "val = %x \n", offset, val);
            bcm3450_write_byte(offset, (u8)val);
        }
        else {
            val = bcm3450_read_byte(offset);
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Read Byte: offset = %x, " 
   		 	              "val = %x \n", offset, val);
        }
        break;

    case 'w':
        if (argc == 3) {
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Write Word: offset = %x, " 
   		 	              "val = %x \n", offset, val);
            bcm3450_write_word(offset, (u16)val);
        }
        else {
            val = bcm3450_read_word(offset);
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Read Word: offset = %x, " 
   		 	              "val = %x \n", offset, val);
        }
        break;

    case 'd':	
        if (argc == 3) {
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Write Register: offset = %x, " 
   		 	              "val = %x \n", offset, val);
            bcm3450_write_reg(offset, val);
        }
        else {
            val = bcm3450_read_reg(offset);
   		 	BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Read Register: offset = %x, "
   		 	              "val = %x \n", offset, val);
        }
        break;

    default:
        BCM_LOG_NOTICE(BCM_LOG_ID_I2C, "Invalid command. \n Valid commands: \n" 
                       "  Write Reg:   d offset val \n" 
                       "  Read Reg:    d offset \n" 
                       "  Write Word:  w offset val \n" 
                       "  Read Word:   w offset \n" 
                       "  Write Byte:  b offset val \n" 
                       "  Read Byte:   b offset \n" 
#if 0
                       "  Write Bytes: y offset count \n" 
                       "  Read Bytes:  z offset count \n"
#endif
                       );
        break;
    }
    return count;
}
示例#20
0
static int bcm3450_attach_adapter(struct i2c_adapter *adapter)
{
    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);
    return i2c_probe(adapter, &addr_data, bcm3450_detect);
}
/* write followed by read without a stop in between */
static int i2c_write_then_read(struct i2c_msg *msgs, int fifo_len)
{
    int j, ret = 0;
    u16 xfer_cnt;
    struct i2c_msg *p = &msgs[0], *q = &msgs[1];
    uint32 flags;

    spin_lock_irqsave(&bcm_i2c_lock, flags);

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);
    /* Make sure IIC_Enable bit is zero before start of a new transaction. 
       Note that a 0-1 transition of IIC_Enable is required to initiate 
       an I2C bus transaction */
    reg_write((uint32 *)&I2C->IICEnable, 0);

    /* Set the transfer counts for both the transactions */
    xfer_cnt = (q->len << I2C_CNT_REG2_SHIFT) | p->len;

    /* Set the address, transfer count, and data transfer format */
    i2c_rd_wr_common((u8)p->addr, xfer_cnt, I2C_CTL_REG_DTF_WRITE_AND_READ);

    /* Write the data */
    if (fifo_len == 8)
    {
        for (j = 0; j < (p->len); j++) 
            reg_write((uint32 *)&I2C->DataIn0 + j, p->buf[j]);
    }
    else
    {
        int num_dwords = ((p->len) + 3)/4;
        for (j = 0; j < num_dwords; j++) 
        {
#ifdef __LITTLE_ENDIAN
            reg_write((uint32 *)&I2C->DataIn0 + j, 
                      *((int *)&p->buf[j*4]));
#else
            reg_write((uint32 *)&I2C->DataIn0 + j, 
                      swab32(*((int *)&p->buf[j*4])));
#endif
        }
    }

    /* Start the I2C transaction */
    reg_write((uint32 *)&I2C->IICEnable, I2C_IIC_ENABLE);

    /* Wait for completion */
    if (wait_xfer_done())
    {
        ret = -EIO;
        goto end;
    }

    /* Read the data */
    if (fifo_len == 8)
    {
        for (j = 0; j < (q->len); j++) 
            q->buf[j] = (u8)reg_read((uint32 *)&I2C->DataOut0 + j);
    }
    else
    {
        int num_dwords = ((q->len) + 3)/4;
        for (j = 0; j < num_dwords; j++) 
        {
#ifdef __LITTLE_ENDIAN
            *((int *)&q->buf[j*4]) = 
                reg_read((uint32 *)&I2C->DataOut0 + j);
#else
            *((int *)&q->buf[j*4]) = 
                swab32(reg_read((uint32 *)&I2C->DataOut0 + j));
#endif
        }
    }

end:
    /* I2C bus transaction is complete, so set the IIC_Enable to zero */
    reg_write((uint32 *)&I2C->IICEnable, 0);
    spin_unlock_irqrestore(&bcm_i2c_lock, flags);
    return ret;
}
/* Write data of given length to the slave. Note that 2 or more transactions
   would be required on the bus if the length is more than the fifo_len */
static int i2c_write(struct i2c_msg *p, int fifo_len)
{
    int i, j, ret = 0;
    u16 xfer_cnt;
    unsigned int len = p->len;
    unsigned char *buf = p->buf;
    unsigned char addr = p->addr;
    int loops = (len + (fifo_len - 1))/fifo_len;
    uint32 flags;

    BCM_LOG_DEBUG(BCM_LOG_ID_I2C, "Entering the function %s \n", __FUNCTION__);

    spin_lock_irqsave(&bcm_i2c_lock, flags);
    /* Make sure IIC_Enable bit is zero before start of a new transaction. 
       Note that a 0-1 transition of IIC_Enable is required to initiate 
       an I2C bus transaction */
    reg_write((uint32 *)&I2C->IICEnable, 0);

    for (i = 0; i < loops; i++)
    {
        /* Transfer size for the last iteration will be the remaining size */
        xfer_cnt = (i==loops-1) ? (len - (i * fifo_len)) : fifo_len;

        /* Set the address, transfer count, and data transfer format */
        i2c_rd_wr_common(addr, xfer_cnt, I2C_CTL_REG_DTF_WRITE);

        /* Write the data */
        if (fifo_len == 8) 
        {
            for (j = 0; j < xfer_cnt; j++) 
                reg_write((uint32 *)&I2C->DataIn0 + j, buf[i * fifo_len + j]);
        }
        else 
        {
            int num_dwords = (xfer_cnt + 3)/4;
            for (j = 0; j < num_dwords; j++) 
            {
#ifdef __LITTLE_ENDIAN
                reg_write((uint32 *)&I2C->DataIn0 + j, 
                          *((int *)&buf[i * fifo_len + j*4]));
#else
                reg_write((uint32 *)&I2C->DataIn0 + j, 
                          swab32(*((int *)&buf[i * fifo_len + j*4])));
#endif
            }
        }

        /* Start the I2C transaction */
        reg_write((uint32 *)&I2C->IICEnable, I2C_IIC_ENABLE);

        /* Wait for completion */
        if (wait_xfer_done())
        {
            ret = -EIO;
            goto end;
        }
    }

end:
    /* I2C bus transaction is complete, so set the IIC_Enable to zero */
    reg_write((uint32 *)&I2C->IICEnable, 0);
    spin_unlock_irqrestore(&bcm_i2c_lock, flags);
    return ret;
}