6、i2c设备驱动

news2024/11/27 12:40:48

I2C设备驱动要使用i2c_driver和i2c_client数据结构并填充i2c_driver中的成员函数。 i2c_client一般被包

含在设备的私有信息结构体yyy_data中, 而i2c_driver则适合被定义为全局变量并初始化

static struct i2c_driver pca954x_driver = {

.driver                = {

.name        = "pca954x",

.pm        = &pca954x_pm,

.of_match_table = pca954x_of_match,

},

.probe                = pca954x_probe,

.remove                = pca954x_remove,

.id_table        = pca954x_id,

};

static const struct of_device_id pca954x_of_match[] = {

{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },

{ .compatible = "nxp,pca9542", .data = &chips[pca_9542] },

{ .compatible = "nxp,pca9543", .data = &chips[pca_9543] },

{ .compatible = "nxp,pca9544", .data = &chips[pca_9544] },

{ .compatible = "nxp,pca9545", .data = &chips[pca_9545] },

{ .compatible = "nxp,pca9546", .data = &chips[pca_9546] },

{ .compatible = "nxp,pca9547", .data = &chips[pca_9547] },

{ .compatible = "nxp,pca9548", .data = &chips[pca_9548] },

{ .compatible = "nxp,pca9846", .data = &chips[pca_9846] },

{ .compatible = "nxp,pca9847", .data = &chips[pca_9847] },

{ .compatible = "nxp,pca9848", .data = &chips[pca_9848] },

{ .compatible = "nxp,pca9849", .data = &chips[pca_9849] },

{}

};

static const struct i2c_device_id pca954x_id[] = {

{ "pca9540", pca_9540 },

{ "pca9542", pca_9542 },

{ "pca9543", pca_9543 },

{ "pca9544", pca_9544 },

{ "pca9545", pca_9545 },

{ "pca9546", pca_9546 },

{ "pca9547", pca_9547 },

{ "pca9548", pca_9548 },

{ "pca9846", pca_9846 },

{ "pca9847", pca_9847 },

{ "pca9848", pca_9848 },

{ "pca9849", pca_9849 },

{ }

};

I2C设备驱动的模块加载函数通过I2C核心的i2c_add_driver() API函数添加i2c_driver的工作

#define i2c_add_driver(driver) \

i2c_register_driver(THIS_MODULE, driver)


int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

{

int res;

/* Can't register until after driver model init */

if (WARN_ON(!is_registered))

return -EAGAIN;

/* add the driver to the list of i2c drivers in the driver core */

driver->driver.owner = owner;

driver->driver.bus = &i2c_bus_type;

INIT_LIST_HEAD(&driver->clients);

/* When registration returns, the driver core

 * will have called probe() for all matching-but-unbound devices.

 */

res = driver_register(&driver->driver);

if (res)

return res;

pr_debug("driver [%s] registered\n", driver->driver.name);

/* Walk the adapters that are already present */

i2c_for_each_dev(driver, __process_new_driver);

return 0;

}

模块卸载函数需要做相反的工作: 通过I2C核心的i2c_del_driver() 函数删除i2c_driver。

void i2c_del_driver(struct i2c_driver *driver)

{

i2c_for_each_dev(driver, __process_removed_driver);

driver_unregister(&driver->driver);

pr_debug("driver [%s] unregistered\n", driver->driver.name);

}

I2C设备驱动的数据传输

在I2C设备上读写数据的时序且数据通常通过i2c_msg数组进行组织, 最后通过i2c_transfer() 函数完成

i2c-core-acpi.c

read

static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,

u8 cmd, u8 *data, u8 data_len)

{

struct i2c_msg msgs[2];

int ret;

u8 *buffer;

buffer = kzalloc(data_len, GFP_KERNEL);

if (!buffer)

return AE_NO_MEMORY;

msgs[0].addr = client->addr;

msgs[0].flags = client->flags;

msgs[0].len = 1;

msgs[0].buf = &cmd;

msgs[1].addr = client->addr;

msgs[1].flags = client->flags | I2C_M_RD;

msgs[1].len = data_len;

msgs[1].buf = buffer;

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

if (ret < 0) {

/* Getting a NACK is unfortunately normal with some DSTDs */

if (ret == -EREMOTEIO)

dev_dbg(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",

data_len, client->addr, cmd, ret);

else

dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",

data_len, client->addr, cmd, ret);

/* 2 transfers must have completed successfully */

} else if (ret == 2) {

memcpy(data, buffer, data_len);

ret = 0;

} else {

ret = -EIO;

}

kfree(buffer);

return ret;

}

write

static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,

u8 cmd, u8 *data, u8 data_len)

{

struct i2c_msg msgs[1];

u8 *buffer;

int ret = AE_OK;

buffer = kzalloc(data_len + 1, GFP_KERNEL);

if (!buffer)

return AE_NO_MEMORY;

buffer[0] = cmd;

memcpy(buffer + 1, data, data_len);

msgs[0].addr = client->addr;

msgs[0].flags = client->flags;

msgs[0].len = data_len + 1;

msgs[0].buf = buffer;

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

kfree(buffer);

if (ret < 0) {

dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret);

return ret;

}

/* 1 transfer must have completed successfully */

return (ret == 1) ? 0 : -EIO;

}

transfer

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

{

int ret;

if (!adap->algo->master_xfer) {

dev_dbg(&adap->dev, "I2C level transfers not supported\n");

return -EOPNOTSUPP;

}

/* REVISIT the fault reporting model here is weak:

 *

 *  - When we get an error after receiving N bytes from a slave,

 *    there is no way to report "N".

 *

 *  - When we get a NAK after transmitting N bytes to a slave,

 *    there is no way to report "N" ... or to let the master

 *    continue executing the rest of this combined message, if

 *    that's the appropriate response.

 *

 *  - When for example "num" is two and we successfully complete

 *    the first message but get an error part way through the

 *    second, it's unclear whether that should be reported as

 *    one (discarding status on the second message) or errno

 *    (discarding status on the first one).

 */

ret = __i2c_lock_bus_helper(adap);

if (ret)

return ret;

ret = __i2c_transfer(adap, msgs, num);

i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);

return ret;

}

int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

{

unsigned long orig_jiffies;

int ret, try;

if (WARN_ON(!msgs || num < 1))

return -EINVAL;

ret = __i2c_check_suspended(adap);

if (ret)

return ret;

if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))

return -EOPNOTSUPP;

/*

 * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets

 * enabled.  This is an efficient way of keeping the for-loop from

 * being executed when not needed.

 */

if (static_branch_unlikely(&i2c_trace_msg_key)) {

int i;

for (i = 0; i < num; i++)

if (msgs[i].flags & I2C_M_RD)

trace_i2c_read(adap, &msgs[i], i);

else

trace_i2c_write(adap, &msgs[i], i);

}

/* Retry automatically on arbitration loss */

orig_jiffies = jiffies;

for (ret = 0, try = 0; try <= adap->retries; try++) {

if (i2c_in_atomic_xfer_mode() && adap->algo->master_xfer_atomic)

ret = adap->algo->master_xfer_atomic(adap, msgs, num);

else

ret = adap->algo->master_xfer(adap, msgs, num);

if (ret != -EAGAIN)

break;

if (time_after(jiffies, orig_jiffies + adap->timeout))

break;

}

if (static_branch_unlikely(&i2c_trace_msg_key)) {

int i;

for (i = 0; i < ret; i++)

if (msgs[i].flags & I2C_M_RD)

trace_i2c_reply(adap, &msgs[i], i);

trace_i2c_result(adap, num, ret);

}

return ret;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

组件的插槽以及组件通信

组件的插槽以及组件通信 1. 插槽1.1. 单个插槽1.2. 多个插槽 2. 组件通信2.1. 属性绑定2.2. 事件绑定&#xff08;重点&#xff09;2.3. 获取组件实例 1. 插槽 在自定义组件的 wxml 结构中&#xff0c;可以提供一个 节点&#xff08;插槽&#xff09;&#xff0c;用于承载组件…

2023WAIC大会后记:我们距离AGI还有多远?

只有解决了算力问题&#xff0c;才能离大模型的商业化之路更进一步&#xff0c;等等问题&#xff0c;都在成为当下限制我们想象力的关键因素。继2023世界人工智能大会后&#xff0c;大模型还有多少想象力&#xff1f; 作者|思杭 编辑|皮爷 出品|产业家 1亿用户&#xff0…

当用AopContext.currentProxy()方式调用@Asyn注解的方法,发现不起作用了

1、前言 遇到到平常一些spring相关调用错误浅浅记录下 2、我们常常会用到在一个类的方法内部会去调用本类的别一个方法 我们常常会用到在一个类的方法内部会去调用本类的别一个方法&#xff0c;示例如下&#xff1a; public interface ITestAsy {String funttion1();String…

pycharm新建分支并提送至GitHub

文章目录 前言pycharm创建本地分支Push至远程分支 前言 当我们写的项目代码越来越多时&#xff0c;一个master分支无法满足需求了&#xff0c;这个时候就需要创建分支来管理代码。 创建分支可以快速的回滚到某个节点的版本&#xff0c;也可以多个开发者同时开发一个项目&#…

css:横向滚动布局

效果&#xff1a; 实现代码&#xff1a; <template><div class"index_div"><div class"container"><div class"flexBox"><div class"flex_item" v-for"item in topMenu" :key"item.id&quo…

五种不同自动化测试模型的基本介绍

随着移动互联网的发展&#xff0c;软件研发模型逐步完善&#xff0c;软件交付质量越来越受到软件公司的重视&#xff0c;软件测试技术特别是自动化测试技术开始在软件系统研发过程中发挥着越来越重要的作用。 与传统的手工测试技术相比&#xff0c;自动化测试具备了良好的可操…

模拟实现浏览器自带的 ctrl+f 搜索功能

主要利用的就是元素的innerHtml&#xff0c;通过replace方法&#xff0c;把文本替换为带标签的文本&#xff0c;然后就有样式了 下图贴出 主要代码及效果 <template><div class"search-page"><el-input style"width: 200px" v-model"…

2023年信号处理与机器学习国际研讨会(WSPML 2023)| SPIE独立出版 快速稳定

会议简介 Brief Introduction 2023年信号处理与机器学习国际研讨会(WSPML 2023) 会议时间&#xff1a;2023年9月22 -24日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;www.wspml.org 2023年信号处理与机器学习国际研讨会(WSPML 2023) 由西安交通大学、重庆大学光电技术及…

【学术小白如何写好论文】研究结论:结论vs结论

文章目录 一、引言二、研究结论的重要性三、研究结论的切入口&#xff08;1&#xff09;这个结论与前人研究的对话&#xff08;2&#xff09;这个研究结果本身的意义所在 四、注意事项&#xff08;1&#xff09;清楚区别&#xff08;2&#xff09;对结论的深入解析&#xff08;…

Lua脚本本地调试

这里主要使用日志的方式进行debug 环境依赖 项目对openresty包的依赖比较高&#xff0c;所以环境基础都在openresty下进行 openresty的使用 openresty下载地址 下载完成后解压&#xff0c;具体使用方式和nginx没有什么区别&#xff0c;主要依赖文件是一下几个 nginx.exe …

qt开发技巧之嵌入式linux点击触发两次

1.问题 移植qt5.12.9到嵌入式linux系统&#xff0c;tslib作为触摸输入&#xff0c;开发平台是imx6ull&#xff0c;点击pushbutton按钮会出现触发两次点击的情况。 2.解决 vi /etc/profile&#xff0c;在 /etc/profile里添加环境变量&#xff0c;禁止QT自带输入检测&#xff0…

数据结构---手撕图解堆的实现和TopK的应用

文章目录 重要的概念树的存储方式顺序存储链式存储 堆的概念堆的实现向上调整算法一些实现过程中的技巧实现搭建堆实现出堆的操作向下调整算法 堆排序TopK 重要的概念 要讲到堆&#xff0c;先要说两个关于二叉树的概念 满二叉树&#xff1a;一个二叉树如果每一层的节点数都是最…

ylb_学习笔记02

1.随机4位数&#xff1a; String random RandomStringUtils.randomNumeric(4);System.out.println("注册验证码的随机数 random"random);2.使用http时判断响应的状态为ture&#xff08;200&#xff09;&#xff1a; response.getStatusLine().getStatusCode() Htt…

在阿里云linux上安装MySql数据库

我们先远程连接服务器 然后输入 sudo yum update重新运行一下 然后 sudo yum install mysql-server安装 mysql 服务 其中有两次 y n 选择 都选y就好了 然后 运行 sudo service mysqld start启动MySql 然后 我们查看一下MySql sudo service mysqld status

谷歌浏览器,网站多账号登陆的方法

在测试系统某些功能的时候&#xff0c;不同的模块&#xff0c;需要不同的权限&#xff0c;所以需要登陆不同的账号&#xff0c;以下有两种办法&#xff0c;可以快速切换账号方便进行测试。 1&#xff0c;使用SessionBox插件 SessionBox是一款可以方便地切换网站的session&…

Android开发笔记

一、知识点 1、Notification 通知的创建流程 1&#xff09;创建一个NotificationManager&#xff0c;获取系统服务&#xff0c;getSystemService()方法&#xff1b; 2&#xff09;使用Builder构造器来创建Notification对象&#xff0c;设置通知的各种属性&#xff1b; 3&#…

postgresql还原bak

1、第一步肯定是要新建自己还原的目标数据库&#xff0c;例如&#xff1a; 2、进入postgresql的安装目录下的bin目录下 然后地址栏输入cmd进入命令 输入以下 psql -h localhost -U postgres -p 5432 -d SamsinoYardStandard_karamay -f "D:\desktop\zk\20230628.bak&quo…

CEO对今天的CIO们真正的要求是什么?

在当今数字化和信息时代&#xff0c;企业的首席信息官&#xff08;CIO&#xff09;的角色变得至关重要。CIO不仅需要具备深厚的技术知识&#xff0c;还需要在商业战略、创新和领导力方面展现出卓越的能力。作为企业的首席执行官&#xff08;CEO&#xff09;&#xff0c;他们对C…

【Distributed】分布式Ceph存储系统

文章目录 一、存储基础1. 单机存储设备1.1 DAS1.2 NAS1.3 SAN1.4 单机存储的问题1.5 商业存储解决方案 2. 分布式存储&#xff08;软件定义的存储 SDS &#xff09;分布式存储的类型 3. Ceph 简介4. Ceph 优势5. Ceph 架构6. Ceph 核心组件7. OSD 存储后端7.1 Filestore7.2 Blu…

单轴机器人的结构与特点

单轴机器人是由马达驱动的移动平台&#xff0c;由滚珠螺杆和 U型线性滑轨导引构成&#xff0c;其滑座同时为滚珠螺杆的驱动螺帽及线性滑轨的导引滑块&#xff0c;可用半导体、光电、交通运输业、环保节能产业、精密工具机、机械产业、智慧自动化、生技医疗上。 相对于传统的模组…