static const struct i2c_algorithm s3c2440_i2c_algo = {
// .smbus_xfer = , //smbus是i2c传输的一个子集,支持的话可以在这里指定处理函数
.master_xfer = s3c2440_i2c_xfer, //传输函数
.functionality = s3c2440_i2c_func,
};
/* 1. 分配/设置i2c_adapter
*/
static struct i2c_adapter s3c2440_i2c_adapter = {
.name = "s3c2440_sheldon",
.algo = &s3c2440_i2c_algo, //算法函数
.owner = THIS_MODULE,
};
static int isLastMsg(void)
{
return (s3c2440_i2c_xfer_data.cur_msg == s3c2440_i2c_xfer_data.msn_num - 1);
}
static int isEndData(void)
{
return (s3c2440_i2c_xfer_data.cur_ptr >= s3c2440_i2c_xfer_data.msgs->len);
}
static int isLastData(void)
{
return (s3c2440_i2c_xfer_data.cur_ptr == s3c2440_i2c_xfer_data.msgs->len - 1);
}
static irqreturn_t s3c2440_i2c_xfer_irq(int irq, void *dev_id)
{
unsigned int iicSt;
iicSt = s3c2440_i2c_regs->iicstat; //读取i2c控制器的状态寄存器,判断是否读写成功
if(iicSt & 0x8){ printk("Bus arbitration failed\n\r"); }
switch (s3c2440_i2c_xfer_data.state)
{
case STATE_START : /* 发出S和设备地址后,产生中断 */
{
PRINTK("Start\n");
/* 如果没有ACK, 返回错误 */
if (iicSt & S3C2410_IICSTAT_LASTBIT)
{
s3c2440_i2c_stop(-ENODEV);
break;
}
if (isLastMsg() && isEndData())
{
s3c2440_i2c_stop(0);
break;
}
/* 进入下一个状态 */
if (s3c2440_i2c_xfer_data.msgs->flags & I2C_M_RD) /* 读 */
{
s3c2440_i2c_xfer_data.state = STATE_READ;
goto next_read;
}
else
{
s3c2440_i2c_xfer_data.state = STATE_WRITE;
}
}
case STATE_WRITE:
{
PRINTK("STATE_WRITE\n");
/* 如果没有ACK, 返回错误 */
if (iicSt & S3C2410_IICSTAT_LASTBIT)
{
s3c2440_i2c_stop(-ENODEV);
break;
}
if (!isEndData()) /* 如果当前msg还有数据要发送 */
{
s3c2440_i2c_regs->iicds = s3c2440_i2c_xfer_data.msgs->buf[s3c2440_i2c_xfer_data.cur_ptr];
s3c2440_i2c_xfer_data.cur_ptr++;
// 将数据写入IICDS后,需要一段时间才能出现在SDA线上
ndelay(50);
s3c2440_i2c_regs->iiccon = 0xaf; // 恢复I2C传输
break;
}
else if (!isLastMsg())
{
/* 开始处理下一个消息 */
s3c2440_i2c_xfer_data.msgs++;
s3c2440_i2c_xfer_data.cur_msg++;
s3c2440_i2c_xfer_data.cur_ptr = 0;
s3c2440_i2c_xfer_data.state = STATE_START;
/* 发出START信号和发出设备地址 */
s3c2440_i2c_start();
break;
}
else
{
/* 是最后一个消息的最后一个数据 */
s3c2440_i2c_stop(0);
break;
}
break;
}