源码位置:drivers/i2c/busses/i2c-nomadik.c
通过 掩码“mask”设置寄存器某个几个位的值为1。 掩码中1对应的位置置为1。
static inline void i2c_set_bit(void __iomem *reg, u32 mask)
{
writel(readl(reg) | mask, reg);
}
通过 掩码“mask”设置寄存器某个几个位的值为0。掩码中1对应的位置置为0。
static inline void i2c_clr_bit(void __iomem *reg, u32 mask)
{
writel(readl(reg) & ~mask, reg);
}
i2c_clr_bit()的实现中对mask进行了取反。也就是说如果对同一位进行操作, i2c_clr_bit()和 i2c_set_bit()所使用的掩码是一样的。
static int write_i2c(struct nmk_i2c_dev *dev)
u32 status = 0;
u32 mcr;
u32 irq_mask = 0;
int timeout;
mcr = load_i2c_mcr_reg(dev);
writel(mcr, dev->virtbase + I2C_MCR);
/* load the current CR value */
writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
dev->virtbase + I2C_CR);
/* enable the controller */
i2c_set_bit(dev->virtbase + I2C_CR , I2C_CR_PE);
init_completion(&dev->xfer_complete);
/* enable interrupts by settings the masks */
irq_mask = (I2C_IT_TXFNE | I2C_IT_TXFOVR |
I2C_IT_MAL | I2C_IT_BERR);
/*
* check if we want to transfer a single or multiple bytes, if so
* set the MTDWS bit (Master Transaction Done Without Stop)
* to start repeated start operation
*/
if (dev->stop)
irq_mask |= I2C_IT_MTD;
else
irq_mask |= I2C_IT_MTDWS;
irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
dev->virtbase + I2C_IMSCR);
timeout = wait_for_completion_interruptible_timeout(
&dev->xfer_complete, msecs_to_jiffies(I2C_TIMEOUT_MS));
if (timeout < 0) {
dev_err(&dev->pdev->dev,
"wait_for_completion_interruptible_timeout"
"returned %d waiting for event\n", timeout);
status = timeout;
}
if (timeout == 0) {
/* controler has timedout, re-init the h/w */
dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
(void) init_hw(dev);
status = -ETIMEDOUT;
}
return status;
}
注意:其他的驱动也有实现自己的 write_i2c()函数。其过程可能是不一样的。
drivers/i2c/i2c-core.c
/* ----------------------------------------------------
* the functional interface to the i2c busses. 到I2C总线的函数接口
* ----------------------------------------------------
*/
/**
* i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
* terminate the operation; each message begins with a START.
* @num: Number of messages to be executed.
*
* Returns negative errno, else the number of
I2C总线协议:函数详解与驱动实现

本文详细介绍了I2C总线协议的相关函数,包括i2c_set_bit()和i2c_clr_bit(),以及write_i2c()函数的实现。文章通过分析驱动代码,展示了如何在Linux内核中处理I2C传输,如master_xfer()函数的作用,并解释了在不同驱动中如何实现I2C传输。同时,提到了V4L2子系统在I2C交互中的作用。
最低0.47元/天 解锁文章
1791

被折叠的 条评论
为什么被折叠?



