I2C总线(二)注册控制器

一、i2c适配器

i2c适配器在硬件层面其实就是i2c控制器,因为跟芯片相关,一般内核会带对应厂商的芯片驱动,实现在i2c/busses中找好了。

我们直接看代码,以imx6为例。

1、平台总线匹配

imx6中是做了,驱动和设备树分离,以平台总线实现,
我们主要关注点是:

1、设备树中,找到有设备,节点为i2c1,
在这里插入图片描述
2、平台驱动中有定义驱动,并且我们看到 compatible 可以匹配上,
那么将,执行 i2c_imx_probe 。。。
在这里插入图片描述
在这里插入图片描述

2、执行probe(i2c_imx_probe),构建适配器

下面给这段代码做注释

static int i2c_imx_probe(struct platform_device *pdev)
{const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,&pdev->dev);struct imx_i2c_struct *i2c_imx;struct resource *res;struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);void __iomem *base;int irq, ret;u32 bitrate;dev_dbg(&pdev->dev, "<%s>\n", __func__);// 设备树定义了中断,获取中断irq = platform_get_irq(pdev, 0);if (irq < 0) {dev_err(&pdev->dev, "can't get irq number\n");return irq;}// 获取寄存器地址,并且映射成虚拟地址res = platform_get_resource(pdev, IORESOURCE_MEM, 0);base = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(base))return PTR_ERR(base);// 分配内存,imx_i2c_struct,是imx6自定义数据结构,// 但是注意,内部有一个 i2c_adapter,是属于i2c核心的数据结构// i2c_adapter 将会被注册到核心i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct),GFP_KERNEL);if (!i2c_imx) {dev_err(&pdev->dev, "can't allocate interface\n");return -ENOMEM;}// if (of_id)i2c_imx->hwdata = of_id->data;elsei2c_imx->hwdata = (struct imx_i2c_hwdata *)platform_get_device_id(pdev)->driver_data;// 下面是对重要结构体 i2c_adapter 初始化// // 1、这里将平台设备的名称,给 i2c_adapter 赋值了,所以他们的名字将一样/* Setup i2c_imx driver structure */strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));// 2、i2c_imx->adapter.owner		= THIS_MODULE;// 3、给适配器初始化了一个算法,// 通过这个回调,i2c核心将可以对控制器做硬件操作(收发数据)i2c_imx->adapter.algo		= &i2c_imx_algo;// 4、i2c_imx->adapter.dev.parent	= &pdev->dev;// 5、设备树定义的编号(i2c1的1),给到对应的适配器i2c_imx->adapter.nr 		= pdev->id;// 6、设备树节点获取到了i2c_imx->adapter.dev.of_node	= pdev->dev.of_node;// 7、imx6自己保存的,寄存器的基地址(虚拟地址)i2c_imx->base			= base;// 获取时钟(设备树定义的)/* Get I2C clock */i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);if (IS_ERR(i2c_imx->clk)) {dev_err(&pdev->dev, "can't get I2C clock\n");return PTR_ERR(i2c_imx->clk);}// 使能时钟(硬件操作)ret = clk_prepare_enable(i2c_imx->clk);if (ret) {dev_err(&pdev->dev, "can't enable I2C clock\n");return ret;}// 请求中断/* Request IRQ */ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,pdev->name, i2c_imx);if (ret) {dev_err(&pdev->dev, "can't claim irq %d\n", irq);return ret;}// 初始化队列/* Init queue */init_waitqueue_head(&i2c_imx->queue);// 这里注意,把imx6自定义数据给了 i2c_adapter 的私有数据。。/* Set up adapter data */i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);// 设置时钟的频率(硬件操作)/* Set up clock divider */bitrate = IMX_I2C_BIT_RATE;ret = of_property_read_u32(pdev->dev.of_node,"clock-frequency", &bitrate);if (ret < 0 && pdata && pdata->bitrate)bitrate = pdata->bitrate;i2c_imx_set_clk(i2c_imx, bitrate);///* Set up chip registers to defaults */imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,i2c_imx, IMX_I2C_I2CR);imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);// 重中之重,,,i2c_adapter 被注册,// 调用的是 i2c_add_numbered_adapter,是在i2c 核心定义的接口。。// 如果要了解该接口,移步 i2c 核心章节。。/* Add I2C adapter */ret = i2c_add_numbered_adapter(&i2c_imx->adapter);if (ret < 0) {dev_err(&pdev->dev, "registration failed\n");return ret;}// imx6自定义的数据结构体,也成了平台设备的私有数据了/* Set up platform driver data */platform_set_drvdata(pdev, i2c_imx);clk_disable_unprepare(i2c_imx->clk);dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",res->start, res->end);dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",resource_size(res), res->start);dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",i2c_imx->adapter.name);dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");return 0;   /* Return OK */
}

前面提到了,imx6自定义的数据结构 imx_i2c_struct ,里面包含了 i2c_adapter,截图记录。。
在这里插入图片描述

总结:对于每款芯片而言,每个i2c控制器都将会抽象成一个适配器(i2c_adapter)注册成i2c总线设备。

3、注册 i2c_adapter

调用 i2c_add_numbered_adapter 接口,注册 i2c_adapter,,,
移步 I2C总线(一)核心

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC(生成式AI)试用 15 -- 小结

断断续续的尝试在实际的工作使用中理解和测试AIGC&#xff0c;运用会越来越多、越来越广范&#xff0c;但也是时候做个小结了。 没有太用热火的ChatGPT&#xff0c;只是拿了日常最容易用到的CSDN创作助手&#xff08;每周写文章总是看到&#xff09;和文心一言&#xff08;…

检测头篇 | RT-DETR 添加 小目标检测头 (P2,P3,P4,P5)

往期推荐 百度 RT-DETR 算法原理解析 | 超越YOLO的目标检测新高度? 手把手教你使用云服务器训练 RT-DETR (Pytorch版) RT-DETR 项目【训练】【验证】【推理】脚本 | 最新更新🍀 直接打印 FPS,mAP50,mAP75,mAP95🍀 RT-DETR Bug 及解决方案汇总 【训练 & 断点续训】 …

YOLOv3-YOLOv8的一些总结

0 写在前面 这个文档主要总结YOLO系列的创新点&#xff0c;以YOLOv3为baseline。参考(抄)了不少博客&#xff0c;就自己看看吧。有些模型的trick不感兴趣就没写进来&#xff0c;核心的都写了。 YOLO系列的网络都由四个部分组成&#xff1a;Input、Backbone、Neck、Prediction…

数据分析为何要学统计学(4)——何为置信区间?它有什么作用?

置信区间是统计学中的一个重要工具&#xff0c;是用样本参数()估计出来的总体均值在某置信水平下的范围。通俗一点讲&#xff0c;如果置信度为95%&#xff08;等价于显著水平a0.05&#xff09;&#xff0c;置信区间为[a,b]&#xff0c;这就意味着总体均值落入该区间的概率为95%…

Kubernetes (k8s) 快速认知

应用部署方式 传统部署时代 早期的时候&#xff0c;各个组织是在物理服务器上运行应用程序。缺点 资源分配问题&#xff1a; 无法限制在物理服务器中运行的应用程序资源使用 维护成本问题&#xff1a; 部署多个物理机&#xff0c;维护许多物理服务器的成本很高 虚拟化部署时…

c++11--左值,右值,移动语义,引用折叠,模板类型推断,完美转发

1.移动语义 移动构造和移动赋值均属于移动语义范畴。 移动语义的实现依赖于右值概念&#xff0c;右值引用。 1.1.一个移动构造的实例 #include <iostream> using namespace std; class HasPtrMem{ public:HasPtrMem():d(new int(3)){cout << "Construct: &qu…

Redis Set类型

集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中 1&#xff09;元素之间是无序的 2&#xff09;元素不允许重复 一个集合中最多可以存储2的32次方个元素。Redis 除了支持集合内的增删查改操作&#xff0c;同时还支持多个集合取交…

链表之带头双向循环链表(C语言版)

我们之前已经介绍过链表的知识了&#xff0c;这里我们直接开始实现带头双向循环链表 数据结构之单链表&#xff08;不带头单向非循环链表&#xff09;-CSDN博客 第一步&#xff1a;定义结构体 //定义结构体 typedef int SLTDateType; typedef struct Listnode {SLTDateType d…

【消息中间件】Rabbitmq的基本要素、生产和消费、发布和订阅

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、消息队列的基本要素1.队列:queue2.交换机:exchange3.事件:routing_key4.任务:task 二、生产消费模式1.安装pika2.模拟生产者进程3.模…

Web前端-HTML(常用标签)

文章目录 1. HTML常用标签1.1 排版标签1&#xff09;标题标签h (熟记)2&#xff09;段落标签p ( 熟记)3&#xff09;水平线标签hr(认识)4&#xff09;换行标签br (熟记)5&#xff09;div 和 span标签(重点)6&#xff09;排版标签总结 1.2 标签属性1.3 图像标签img (重点)1.4 链…

shell子进程管理

简介 在我们平时写代码过程中&#xff0c;可能经常会遇到串行执行速度慢 &#xff0c;串行无法执行多个任务&#xff0c;这时便需要使用子进程同时执行。使用父进程创建子进程时&#xff0c;子进程会复制父进程的内存、文件描述符和其他相关信息。当然&#xff0c;子进程可以独…

Web前端-JavaScript(js表达式)

文章目录 JavaScript基础第01天1.编程语言概述1.1 编程1.2 计算机语言1.2.1 机器语言1.2.2 汇编语言1.2.3 高级语言 1.4 翻译器 2.计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 3.初始JavaScript3.1 JavaScript 是什么3.2 JavaScript的作用3.3 HTML/CSS/…