i2c适配器驱动源码分析(i2c总线驱动)

本文深入分析了i2c适配器驱动源码,以i2c-sunxi.c为例,探讨了I2C总线驱动如何加载及适配器注册过程。重点讲解了probe函数的作用,以及在设备与驱动绑定时的执行情况。此外,文章还详细阐述了i2c_transfer函数如何调用adapter的sunxi_i2c_xfer函数完成与i2c设备的通讯,并强调了在调试时理解调用流程的重要性。
摘要由CSDN通过智能技术生成

i2c适配器源码位置在driver/i2c/buss下这里以i2c-sunxi.c为例,i2c适配器设备和驱动的加载绑定过程也可以看做是i2c总线驱动的加载过程,I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。
下面以源码进行分析:
函数的入口:

subsys_initcall(sunxi_i2c_adap_init);  //和一般的驱动函数一样存在入口函数

static int __init sunxi_i2c_adap_init(void)//入口函数
{
    I2C_DBG("Sunxi I2C adapt init\n");

    return platform_driver_register(&sunxi_i2c_driver);//向platform总线注册这个驱动
}

定义适配器驱动:

static struct platform_driver sunxi_i2c_driver = {
    .probe      = sunxi_i2c_probe,//定义probe函数,设备和驱动绑定后
                                     第一个执行的函数
    .remove     = sunxi_i2c_remove,
    .driver     = {
        .name   = SUNXI_TWI_DEV_NAME, //该驱动的名称
        .owner  = THIS_MODULE,
        .pm     = SUNXI_I2C_DEV_PM_OPS,
        .of_match_table = sunxi_i2c_match, //定义匹配函数,这个函数
                                             很重要,内核会依据这个
                                             函数中compatible的值
                                             是否相等来决定是否绑定
    },
};
static const struct of_device_id sunxi_i2c_match[] = {
    { .compatible = "allwinner,sun8i-twi", },
    { .compatible = "allwinner,sun50i-twi", },
    { .compatible = "allwinner,sun3i-twi", },
    {},//内核会自动将这里的值和设备树中的compatible的值进行匹配,匹配成功则将设备和驱动绑定并执行probe函数
};

probe函数:
主要完成adapter的注册和向i2c总线添加adapter工作

static int sunxi_i2c_probe(struct platform_device *pdev)
{
    struct device_node *np = pdev->dev.of_node; 
    struct sunxi_i2c *i2c = NULL;
    struct resource *mem_res = NULL;
    struct sunxi_i2c_platform_data *pdata = NULL;
    int ret, irq;
    unsigned long int_flag = IRQF_DISABLED;

    if (np == NULL) {
        I2C_ERR("I2C failed to get of node\n");//获取设备的节点
        return -ENODEV;
    }

    i2c = kzalloc(sizeof(struct sunxi_i2c), GFP_KERNEL);
    if (!i2c) {
        return -ENOMEM;
    }

    pdata = kzalloc(sizeof(struct sunxi_i2c_platform_data), GFP_KERNEL);
    if (pdata == NULL) {
        kfree(i2c);
        return -ENOMEM;
    }
    pdev->dev.platform_data = pdata;

    pdev->id = of_alias_get_id(np, "twi");
    if (pdev->id < 0) {
        I2C_ERR("I2C failed to get alias id\n");
        ret = -EINVAL;
        goto emem;
    }
    pdata->bus_num  = pdev
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值