#define RT2860REG(addr) (*(volatile u32 *)(addr))
static void gpio_i2c_set_bit(int id, int onoff)
{
int tmp;
if(id<=21&&id>=0)
{
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
tmp |= (1<<(id));
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
tmp = (tmp&~(1<<(id)))|(onoff<<(id));
*(volatile u32 *)(RALINK_REG_PIODATA) = tmp;
}
else if(id>=22&&id<=27)
{
}
else
{
printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
}
}
static int gpio_i2c_get_bit(int id)
{
int tmp;
if(id<=21&&id>=0)
{
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
tmp &= ~(1<<(id));
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
return (tmp>>id&0x01);
}
else if(id>=22&&id<=27)
{
}
else
{
printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
}
}
static void i2c_clk(int onoff)
{
gpio_i2c_set_bit(2,onoff);
}
static void i2c_dat(int onoff)
{
gpio_i2c_set_bit(1,onoff);
}
static unsigned char i2c_data_read(void)
{
return gpio_i2c_get_bit(1);
}
/*
* sends a start bit via I2C rountine.
*
*/
static void i2c_start_bit(void)
{
DELAY(1);
i2c_clk(1);
i2c_dat(1);
DELAY(3);
i2c_dat(0);
DELAY(1);
}
/*
* sends a stop bit via I2C rountine.
*
*/
static void i2c_stop_bit(void)
{
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
i2c_dat(1);
}
/*
* sends an acknowledge over I2C rountine.
*
*/
static void i2c_send_ack(void)
{
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
static void i2c_send_nack(void)
{
i2c_clk(0);
i2c_dat(1);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
/*
* sends a character over I2C rountine.
*
* @param c: character to send
*
*/
static void i2c_send_byte(unsigned char c)
{
int i;
//local_irq_disable();
//i2c_clk(1);
for (i=0; i<8; i++)
{
i2c_clk(0);
if (c & (1<<(7-i)))
i2c_dat(1);
else
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
// i2c_dat(1);
//local_irq_enable();
}
/* receives a character from I2C rountine.
*
* @return value: character received
*
*/
static unsigned char i2c_receive_byte_ack(void)
{
int j=0;
int i;
unsigned char regvalue;
//local_irq_disable();
//i2c_data_read();
for (i=0; i<8; i++)
{
i2c_clk(0);
DELAY(1);
i2c_clk(1);
set_gpio_direction(SDA,INP);
if (i2c_data_read())
j+=(1<<(7-i));
DELAY(1);
}
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
//local_irq_enable();
// i2c_dat(0);
// DELAY(1);
return j;
}
static unsigned char i2c_receive_byte_noack(void)
{
int j=0;
int i;
unsigned char regvalue;
//local_irq_disable();
i2c_data_read();
for (i=0; i<8; i++)
{
i2c_clk(0);
DELAY(1);
i2c_clk(1);
i2c_data_read();
if (i2c_data_read())
j+=(1<<(7-i));
DELAY(1);
}
i2c_clk(0);
i2c_dat(1);
DELAY(1);
i2c_clk(1);
DELAY(1);
//local_irq_enable();
// i2c_dat(0);
// DELAY(1);
return j;
}
/* receives an acknowledge from I2C rountine.
*
* @return value: 0--Ack received; 1--Nack received
*
*/
static int i2c_receive_ack(void)
{
int nack;
i2c_data_read();
i2c_clk(0);
DELAY(1);
i2c_clk(1);
//i2c_data_read();
nack = i2c_data_read();
DELAY(1);
i2c_dat(1);
return nack;
}
/*
* read data from the I2C bus by GPIO simulated of a device rountine.
*
* @param devaddress: address of the device
* @param address: address of register within device
*
* @return value: data from the device readed
*
*/
int gpio_i2c_read(unsigned char devaddress, unsigned char address,unsigned char *buff, int ByteNo)
{
unsigned long flags;
int rxdata=-1;
int i;
i2c_start_bit();
i2c_send_byte((unsigned char)((devaddress<<1)|0));
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_send_byte(address);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_clk(0);
i2c_start_bit();
i2c_send_byte((unsigned char)(0xC1));
if(i2c_receive_ack())
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
//rxdata = i2c_receive_byte();
for(i=0;i<ByteNo;i++)
{
if(i<ByteNo-1)
{
buff[i] = i2c_receive_byte_ack();
}
else
{
buff[i] = i2c_receive_byte_noack();
}
}
i2c_stop_bit();
rxdata = 0;
EXIT:
return rxdata;
}
EXPORT_SYMBOL(gpio_i2c_read);
/*
* writes data to a device on the I2C bus rountine.
*
* @param devaddress: address of the device
* @param address: address of register within device
* @param data: data for write to device
*
*/
int gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char *data, int len)
{
int ret = -1;
unsigned long flags;
int i;
//spin_lock_irqsave(&i2c_lock,flags);
spin_lock(&i2c_lock);
i2c_start_bit();
i2c_send_byte((unsigned char)((devaddress<<1)|0));
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_send_byte(address);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
for(i=0 ; i<len;i++)
{
i2c_send_byte(data[i]);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
}
i2c_stop_bit();
ret=0;
EXIT:
//spin_unlock_irqrestore(&i2c_lock,flags);
spin_unlock(&i2c_lock);
return ret;
}
EXPORT_SYMBOL(gpio_i2c_write);
static void gpio_i2c_set_bit(int id, int onoff)
{
int tmp;
if(id<=21&&id>=0)
{
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
tmp |= (1<<(id));
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
tmp = (tmp&~(1<<(id)))|(onoff<<(id));
*(volatile u32 *)(RALINK_REG_PIODATA) = tmp;
}
else if(id>=22&&id<=27)
{
}
else
{
printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
}
}
static int gpio_i2c_get_bit(int id)
{
int tmp;
if(id<=21&&id>=0)
{
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
tmp &= ~(1<<(id));
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
return (tmp>>id&0x01);
}
else if(id>=22&&id<=27)
{
}
else
{
printk("####HU#### %s id %d invalid \r\n",__FUNCTION__,id);
}
}
static void i2c_clk(int onoff)
{
gpio_i2c_set_bit(2,onoff);
}
static void i2c_dat(int onoff)
{
gpio_i2c_set_bit(1,onoff);
}
static unsigned char i2c_data_read(void)
{
return gpio_i2c_get_bit(1);
}
/*
* sends a start bit via I2C rountine.
*
*/
static void i2c_start_bit(void)
{
DELAY(1);
i2c_clk(1);
i2c_dat(1);
DELAY(3);
i2c_dat(0);
DELAY(1);
}
/*
* sends a stop bit via I2C rountine.
*
*/
static void i2c_stop_bit(void)
{
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
i2c_dat(1);
}
/*
* sends an acknowledge over I2C rountine.
*
*/
static void i2c_send_ack(void)
{
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
static void i2c_send_nack(void)
{
i2c_clk(0);
i2c_dat(1);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
/*
* sends a character over I2C rountine.
*
* @param c: character to send
*
*/
static void i2c_send_byte(unsigned char c)
{
int i;
//local_irq_disable();
//i2c_clk(1);
for (i=0; i<8; i++)
{
i2c_clk(0);
if (c & (1<<(7-i)))
i2c_dat(1);
else
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
}
// i2c_dat(1);
//local_irq_enable();
}
/* receives a character from I2C rountine.
*
* @return value: character received
*
*/
static unsigned char i2c_receive_byte_ack(void)
{
int j=0;
int i;
unsigned char regvalue;
//local_irq_disable();
//i2c_data_read();
for (i=0; i<8; i++)
{
i2c_clk(0);
DELAY(1);
i2c_clk(1);
set_gpio_direction(SDA,INP);
if (i2c_data_read())
j+=(1<<(7-i));
DELAY(1);
}
i2c_clk(0);
i2c_dat(0);
DELAY(1);
i2c_clk(1);
DELAY(1);
//local_irq_enable();
// i2c_dat(0);
// DELAY(1);
return j;
}
static unsigned char i2c_receive_byte_noack(void)
{
int j=0;
int i;
unsigned char regvalue;
//local_irq_disable();
i2c_data_read();
for (i=0; i<8; i++)
{
i2c_clk(0);
DELAY(1);
i2c_clk(1);
i2c_data_read();
if (i2c_data_read())
j+=(1<<(7-i));
DELAY(1);
}
i2c_clk(0);
i2c_dat(1);
DELAY(1);
i2c_clk(1);
DELAY(1);
//local_irq_enable();
// i2c_dat(0);
// DELAY(1);
return j;
}
/* receives an acknowledge from I2C rountine.
*
* @return value: 0--Ack received; 1--Nack received
*
*/
static int i2c_receive_ack(void)
{
int nack;
i2c_data_read();
i2c_clk(0);
DELAY(1);
i2c_clk(1);
//i2c_data_read();
nack = i2c_data_read();
DELAY(1);
i2c_dat(1);
return nack;
}
/*
* read data from the I2C bus by GPIO simulated of a device rountine.
*
* @param devaddress: address of the device
* @param address: address of register within device
*
* @return value: data from the device readed
*
*/
int gpio_i2c_read(unsigned char devaddress, unsigned char address,unsigned char *buff, int ByteNo)
{
unsigned long flags;
int rxdata=-1;
int i;
i2c_start_bit();
i2c_send_byte((unsigned char)((devaddress<<1)|0));
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_send_byte(address);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_clk(0);
i2c_start_bit();
i2c_send_byte((unsigned char)(0xC1));
if(i2c_receive_ack())
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
//rxdata = i2c_receive_byte();
for(i=0;i<ByteNo;i++)
{
if(i<ByteNo-1)
{
buff[i] = i2c_receive_byte_ack();
}
else
{
buff[i] = i2c_receive_byte_noack();
}
}
i2c_stop_bit();
rxdata = 0;
EXIT:
return rxdata;
}
EXPORT_SYMBOL(gpio_i2c_read);
/*
* writes data to a device on the I2C bus rountine.
*
* @param devaddress: address of the device
* @param address: address of register within device
* @param data: data for write to device
*
*/
int gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char *data, int len)
{
int ret = -1;
unsigned long flags;
int i;
//spin_lock_irqsave(&i2c_lock,flags);
spin_lock(&i2c_lock);
i2c_start_bit();
i2c_send_byte((unsigned char)((devaddress<<1)|0));
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
i2c_send_byte(address);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
for(i=0 ; i<len;i++)
{
i2c_send_byte(data[i]);
if(i2c_receive_ack()==1)
{
printk("error in %s,%d !!!",__FILE__,__LINE__);
goto EXIT;
}
}
i2c_stop_bit();
ret=0;
EXIT:
//spin_unlock_irqrestore(&i2c_lock,flags);
spin_unlock(&i2c_lock);
return ret;
}
EXPORT_SYMBOL(gpio_i2c_write);