i2c_add_adapter

这篇博客详细介绍了在Linux驱动中,如何通过i2c_add_adapter和i2c_add_numbered_adapter函数动态和静态地添加I2C适配器。这两个函数主要负责将I2C适配器注册到系统并创建相应的/sys/class/i2c-adapter目录。动态添加的适配器编号是动态申请的,而静态添加的编号在添加前已预先分配。注册过程包括将适配器添加到管理链表、创建设备表示以及扫描并附加客户端设备。

drivers/i2c/algos/i2c-algo-bit.c 中有两个函数都是用来添加adapter的,

一个是动态添加i2c_add_adapter(),

一个是静态添加i2c_add_numbered_adapter(),   numbered就是已经定好了adapter id号了的意思。

int i2c_bit_add_bus(struct i2c_adapter *adap)
{
        int err;

        err = i2c_bit_prepare_bus(adap);
        if (err)
                return err;

        return i2c_add_adapter(adap);
}
EXPORT_SYMBOL(i2c_bit_add_bus);

int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
{
        int err;

        err = i2c_bit_prepare_bus(adap);
        if (err)
                return err;

        return i2c_add_numbered_adapter(adap);
}
EXPORT_SYMBOL(i2c_bit_add_numbered_bus);

i2c_add_adapter() 的工作就是向系统,向/sys 注册i2c_adapter,以备后面的i2c操作。

/**
 * i2c_add_adapter - declare i2c adapter, use dynamic bus number
 * @adapter: the adapter to add
 *
 * This routine is used to declare an I2C adapter when its bus number
 * doesn't matter.  Examples: for I2C adapters dynamically added by
 * USB links or PCI plugin cards.
 *
 * When this returns zero, a new bus number was allocated and stored
 * in adap->nr, and the specified adapter became available for clients.
 * Otherwise, a negative errno value is returned.
 */
int i2c_add_adapter(struct i2c_adapter *adapter)
{
        int     id, res = 0;

retry:
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
                return -ENOMEM;

        mutex_lock(&core_lists);
        /* "above" here means "above or equal to", sigh */
        res = idr_get_new_above(&i2c_adapter_idr, adapter,
                                __i2c_first_dynamic_bus_num, &id);
        mutex_unlock(&core_lists);

        if (res < 0) {
                if (res == -EAGAIN)
                        goto retry;
                return res;
        }

        adapter->nr = id;
        return i2c_register_adapter(adapter);
}
EXPORT_SYMBOL(i2c_add_adapter);
idr 机制是linux系统中的一种数据结构,一种方便检索的机制,idr的要完成的任务是给要管理的对象分配一个数字,可以通过这个数字找到要管理的对象。

网上一堆介绍idr的。

i2c_add_numbered_adapter() 也差不多,不过他的adapter->nr 不是动态申请的,是原先就静态分配好的。

/**
 * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
 * @adap: the adapter to register (with adap->nr initialized)
 *
 * This routine is used to declare an I2C adapter when its bus number
 * matters.  Example: for I2C adapters from system-on-chip CPUs, or
 * otherwise built in to the system's mainboard, and where i2c_board_info
 * is used to properly configure I2C devices.
 *
 * If no devices have pre-been declared for this bus, then be sure to
 * register the adapter before any dynamically allocated ones.  Otherwise
 * the required bus ID may not be available.
 *
 * When this returns zero, the specified adapter became available for
 * clients using the bus number provided in adap->nr.  Also, the table
 * of I2C devices pre-declared using i2c_register_board_info() is scanned,
 * and the appropriate driver model device nodes are created.  Otherwise, a
 * negative errno value is returned.
 */
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
        int     id;
        int     status;

        if (adap->nr & ~MAX_ID_MASK)
                return -EINVAL;

retry:
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
                return 
整理总结简化下述内容:I2C 是很常用的一个串行通信接口, 用于连接各种外设、 传感器等。 I2C 总线仅仅 使用 SCL、 SDA 这两根信号线就实现了设备之间的数据交互, 极大地简化了对硬件 资源和 PCB 板布线空间的占用。 在本章中主 要来看一下在 Linux 内核中如何使用 I2C 的驱动框架。 Linux I2C 驱动框架简介 在 Linux 内核中 I2C 的体系结构分为 3 个部分:  I2C 核心: I2C 核心提供了 I2C 总线驱动和设备驱动的注册、 注销方法等。  I2C 总线驱动: I2C 总线驱动是对 I2C 硬件体系结构中适配器端的实现, 适配器 可由 CPU 控制, 甚至可以直接集成在 CPU 内部。  I2C 设备驱动: I2C 设备驱动是对 I2C 硬件体系结构中设备端的实现, 设备一般 挂接在受 CPU 控制的 I2C 适配器上, 通过 I2C 适配器与 CPU 交换数据。 Linux 的驱动分离与分层的思想,因此 Linu x 内核也将 I2C 驱动分为两部分 ①、 I2C 总线驱动, I2C 总线驱动就是 SOC 的 I2C 控制器驱动,也叫做 I2C 适配 器驱动。 ②、 I2C 设备驱动, I2C 设备驱动就是针对具体的 I2C 设备而编写的驱动。I2C 总线驱动 首先来看一下 I2C 总线,在讲 platform 的时候就说过, platform 是虚拟出来的一条 总线,目的是为了实现总线、设备、驱动框架。对于 I2C 而言,不需要虚拟出一条总 线,直接使用 I2 C 总线即可。 I2C 总线驱动重点是 I2C 适配器(也就是 SOC 的 I2C 接口控制器)驱动,这里要用到两个重要的数据结构: i2c_adapteri2c_algorithm, Linux 内核将 SOC 的 I2C 适配器(控制器)抽象成 i2c_adapteri2c_adapter 结构体 定义在 include/linux/i2c.h 文件中,结构体内容如下: 498 struct i2c adapter { 499struct module *owner; 500 501 502 unsigned int class;/*classes to allow probing for */const struct i2c algorithm *algo;/* 总线访问算法 */void *algo data; 503 504 505 506 507 508 509 /* data fields that are valid for all devices */struct rt mutexbus lock; int timeout;/* in jiffies */int retries;/*the adapter device */struct device dev; 510 511 512 513 int nr; char name[48]; struct completion dev released; 514 515 5潆匽銎夺多挚端盟6 struct mutexuserspace clients lock;struct list head userspace clients; 517 518struct i2c bus recovery info *bus recovery info;const struct i2c adapter quirks *quirks; 519 520 }; i2c_algorithm 类型的指针变量 algo,对于一个 12C 适配器,肯定要对第 501行,外提供读写 AP!函数,设备驱动程序可以使用这些API函数来完成读写操作。i2c_algorithm 就是12C 适配器与 I℃ 设备进行通信的方法。 i2c_algorithm 结构体定义在 include/linux/i2c.h 文件中,内容如下 391 struct i2c algorithm { .::.: 398int(*master xfer)(struct i2c adapter *adap, struct i2c msg *msgs, 399 int num); 400int(*smbus xfer)(struct i2c adapter *adap, ul6 addr, 401 unsigned short flags,char read write, 402 u8 command,int size,union i2c smbus data *data); 403 404/* To determine what the adapter supports */405u32(*functionality)(struct i2c adapter*); 。” 411 };第 398 行, master_xfer 就是 I2C 适配器的传输函数,可以通过此函数来完成与 IIC 设备之间的通信。 第 400 行, smbus_xfer 就是 SMBUS 总线的传输函数。 综上所述, I2C 总线驱动,或者说 I2C 适配器驱动的主要工作就是初始化 i2c_adapter 结构体变量,然后设置 i2c_algorithm 中的 master_xfer 函数。完成以后 通过 i2c_add_numbered_adapt er 或 i2c_add_adapter 这两个函数向系统注册设置好 的 i2c_adapter,这两个函数的原型如下 int i2c_add_adapter(struct i2c_adapter *adapter) int i2c_add_numbered_adapter(struct i2c_adapter *adap) 这两个函数的区别在于 i2c_add_adapter 使用动态的总线号,而 i2c_add_numbered_adapter 使用静态总线号。函数参数和返回值含义如下: adapter 或 adap:要添加到 Linux 内核中的 i2c_adapter,也就是 I2C 适配器。返 回值: 0,成功;负值,失败。 如果要删除 I2C 适配器的话使用 i2c_del_adapter 函数即可,函数原型如下: void i2c_del_adapter(struct i2c_adapter * adap) 函数参数和返回值含义如下: adap:要删除的 I2C 适配器。返回值: 无。 关于 I2C 的总线(控制器或适配器)驱动就讲解到这里,一般 SOC 的 I2C 总线驱动都 是由半导体厂商编写的,比如 I.MX6U 的 I2C 适配器驱动 NXP 已经编写好了,这个 不需要用户去编写。因此 I2C 总线驱动对我们这些 SOC 使用者来说是被屏蔽掉的, 我们只要专注于 I2C 设备驱动即可。除非你是在半导体公司上班,工作内容就是写 I2C 适配器驱动。
11-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值