I2C总线协议相关的函数详解

本文详细介绍了I2C总线协议的相关函数,包括i2c_set_bit()和i2c_clr_bit(),以及write_i2c()函数的实现。文章通过分析驱动代码,展示了如何在Linux内核中处理I2C传输,如master_xfer()函数的作用,并解释了在不同驱动中如何实现I2C传输。同时,提到了V4L2子系统在I2C交互中的作用。
摘要由CSDN通过智能技术生成

源码位置: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; e

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值