龙芯1B i2c结构
ls1x_i2c结构
/*
void __iomem *base:一个指向I2C控制器寄存器基地址的指针。
u32 interrupt:表示I2C控制器的中断号。
wait_queue_head_t queue:用于I2C传输的等待队列头。
struct i2c_adapter adap:一个i2c_adapter结构体,用于表示I2C适配器的属性和方法。
int irq:表示I2C控制器的IRQ号。
u32 flags:用于存储一些I2C相关的标志。
*/
struct ls1x_i2c {
void __iomem *base;
u32 interrupt;
wait_queue_head_t queue;
struct i2c_adapter adap;
int irq;
u32 flags;
};
*
void __iomem *base:一个指向I2C控制器寄存器基地址的指针;该地址获取的方式举例
在i2c probe中通过platform_get_resource函数来获取平台platform_device的num_resources成员来获取
龙芯1B I2C读取单字节实现
static unsigned char i2c_readb (struct ls1x_i2c *i2c, unsigned char reg)
{
unsigned char data;
//读取寄存器中的数据
data = (*(volatile unsigned char *)(i2c->base + reg));
return data;
}
龙芯1B I2C写入单字节实现
static char i2c_writeb(struct ls1x_i2c *i2c, unsigned int reg, unsigned char data)
{
//给寄存器赋值
(*(volatile unsigned char *)(i2c->base + reg)) = data;
}
龙芯1B读取多字节实现
static int ls1x_xfer_read(struct ls1x_i2c *i2c, unsigned char *buf, int len)
{
int x;
for(x=0; x<len; x++) {
//send ACK last not send ACK
if(x != (len -1))
i2c_writeb(i2c, REG_I2C_CR, I2C_C_READ); //控制寄存器产生读信号
else
i2c_writeb(i2c, REG_I2C_CR, I2C_C_WACK |I2C_C_READ);//否则发产生ACK并且产生读信号
while(i2c_readb(i2c, REG_I2C_SR) & I2C_S_RUN);//等待数据传输完毕
buf[x] = i2c_readb(i2c,REG_I2C_TXR);//读取发送寄存器的内容
}
i2c_writeb(i2c,REG_I2C_CR, I2C_C_STOP);//控制寄存器发送停止信号
return 0;
}
龙芯1B写多字节实现
static int ls1x_xfer_write(struct ls1x_i2c *i2c, unsigned char *buf, int len)
{
int j;
for(j=0; j< len; j++) {
i2c_writeb(i2c, REG_I2C_TXR, buf[j]);//给寄存器赋值
i2c_writeb(i2c, REG_I2C_CR, I2C_C_WRITE);//控制寄存器产生写信号
while(i2c_readb(i2c, REG_I2C_SR) & I2C_S_RUN);//等待数据传输完毕
//收到应答位
if(i2c_readb(i2c, REG_I2C_SR) & I2C_S_RNOACK) {
i2c_writeb(i2c, REG_I2C_CR, I2C_C_STOP);//产生停止信号
return len;
}
}
i2c_writeb(i2c, REG_I2C_CR, I2C_C_STOP);//产生停止信号
return 0;
}
执行I2c总线的读写操作函数实现
static int ls1x_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
{
int i, ret;
struct ls1x_i2c *i2c = adap->algo_data;//从适配器的数据结构配i2c信息
dev_dbg(&adap->dev, "ls1x_xfer: processing %d messages:\n", num);
/*set slave addr*/
for(i=0;i<num;i++) {
char flags;
while(i2c_readb(i2c, REG_I2C_SR) & I2C_S_BUSY);//等待i2c总线空闲
flags = (pmsg->flags & I2C_M_RD)?1:0;//msg 的flasgs为读取消息标志时
i2c_writeb(i2c, REG_I2C_TXR, ((pmsg->addr << 1 ) | flags));//接收寄存器读取slave的地址信息
i2c_writeb(i2c, REG_I2C_CR, (I2C_C_WRITE | I2C_C_START | I2C_C_WACK));//控制寄存器产生start信号,写信号,应答信号
while(i2c_readb(i2c, REG_I2C_SR) & I2C_S_RUN);//等待传输完毕
//读取状态寄存器接收ACK
if (i2c_readb(i2c, REG_I2C_SR) & I2C_S_RNOACK) {
printk(" slave addr no ack !!\n");
i2c_writeb(i2c, REG_I2C_CR, I2C_C_STOP); //控制器产生停止信号
return 0;
}
if(flags )
ret = ls1x_xfer_read(i2c, pmsg->buf, pmsg->len);//读取寄存器中的数据
else
ret = ls1x_xfer_write(i2c, pmsg->buf, pmsg->len);//给寄存器赋值
++pmsg;
}
return num;
}