当前位置: 首页 > news >正文

linux内核没有dts配置I2C硬件信息的情况下,要怎么去适配I2C设备和对应的驱动匹配然后驱动正常跑进probe

在没有dts配置I2C硬件信息的情况下,要怎么去适配I2C设备和对应的驱动匹配,让驱动探测到设备,并且让probe函数跑起来

硬件信息:

CPU:海光平台Hygon3490

I2C芯片:at24c eep芯片, 从设备地址:0x57【可以跳电阻改地址】

I2C总线:I2C1

在内核没有设备树(DTS)的情况下,要加载 `at24` 驱动并指定硬件资源,主要有两种标准方法。根据硬件信息的情况(硬件连接在 `I2C1`,设备地址 `0x57`),我推荐使用 方法一。

首先不能忘记把对应驱动编译进内核或者模块:

#以下宏定义二选一即可,在对应defconfig文件配置 #eep驱动编译进内核 CONFIG_EEPROM_AT24=y #或者编译成模块,即ko CONFIG_EEPROM_AT24=m

方法一:使用 `i2c_board_info` (推荐)

这是在没有设备树的传统内核中最标准的方法。其核心思想是在板级初始化代码中,通过 `i2c_board_info` 结构体静态描述设备信息。

1. 定义 `i2c_board_info` 结构体

你需要在板级初始化文件(通常是 `arch/xxx/mach-xxx/board-xxx.c` 或类似文件)中添加如下代码。这个结构体告诉内核:“在名为 `24c256` 的设备,其从设备地址是 `0x57`”。

#include <linux/i2c.h> #include <linux/platform_data/at24.h> /* 如果驱动需要额外的平台数据,可以在这里定义 */ static struct at24_platform_data eeprom_pdata = { .byte_len = 256 * 1024 / 8, /* 根据你的 EEPROM 型号设置,例如 24c256 */ .page_size = 64, /* 根据你的 EEPROM 型号设置 */ .flags = AT24_FLAG_ADDR16, /* 根据你的 EEPROM 型号设置,例如 16-bit 地址 */ }; static struct i2c_board_info __initdata my_i2c_board_info[] = { { I2C_BOARD_INFO("24c256", 0x57), /* 驱动名称与设备地址 */ .platform_data = &eeprom_pdata, /* 可选,如果需要 */ }, };

2. 注册设备到 I2C 总线

在同一个文件的板级初始化函数中(例如 `xxx_init(void)`),调用 `i2c_register_board_info()` 函数,将上述设备信息注册到特定的 I2C 总线(这里是 `I2C1`)上。

/* * 第一个参数是总线号,对于 I2C1,通常是 1。 * 具体编号需参考你的硬件手册或内核中 I2C 控制器的注册顺序。 */ i2c_register_board_info(1, my_i2c_board_info, ARRAY_SIZE(my_i2c_board_info));

3. 重新编译内核并烧写

完成上述修改后,需要重新编译内核,并将新生成的内核镜像烧写或者更新到海光平台上。重启后,当 `at24` 驱动加载时,它应该就能正确匹配到这个设备并执行 `probe` 函数了。

或者如果没有板级配置文件或者不知道使用哪个板级配置文件也可以直接改到驱动里面去,参考如下:

.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; static struct i2c_client *at24_device_client; static int __init at24_init(void) { - if (!at24_io_limit) { - pr_err("at24: at24_io_limit must not be 0!\n"); - return -EINVAL; - } + struct i2c_adapter *adap; + struct i2c_board_info info = { + .type = "24c64", /* 匹配 at24_ids[] 中的 name */ + .addr = 0x57, /* 根据实际硬件修改:24c64 常见 0x50~0x57 */ + .flags = 0, + }; + int ret; + at24_io_limit = rounddown_pow_of_two(at24_io_limit); - return i2c_add_driver(&at24_driver); + /* 1. 注册驱动 */ + ret = i2c_add_driver(&at24_driver); + if (ret) { + pr_err("at24: driver registration failed (%d)\n", ret); + return ret; + } + /* 2. 获取 I2C adapter(总线号 1,用 i2cdetect -l 确认你的总线号) */ + adap = i2c_get_adapter(1); + if (!adap) { + pr_err("at24: i2c adapter 1 not found\n"); + i2c_del_driver(&at24_driver); + return -ENODEV; + } + /* 3. 强行在总线上创建设备 */ + at24_device_client = i2c_new_client_device(adap, &info); + i2c_put_adapter(adap); + + if (IS_ERR(at24_device_client)) { + ret = PTR_ERR(at24_device_client); + pr_err("at24: failed to create i2c client (%d)\n", ret); + at24_device_client = NULL; + i2c_del_driver(&at24_driver); + return ret; + } + pr_info("at24: go to probe 24c64 at 0x%02x on i2c-%d\n",info.addr, adap->nr); + return 0; } module_init(at24_init); static void __exit at24_exit(void) { + if (at24_device_client) { + i2c_unregister_device(at24_device_client); + at24_device_client = NULL; + } i2c_del_driver(&at24_driver); } module_exit(at24_exit);

方法二:通过 `/sys` 文件系统动态创建 (调试/临时)

此方法适用于调试或临时测试,不需要修改和编译内核。

1. 加载驱动

首先,确保 `at24` 驱动模块已加载。

insmod at24.ko # 或者如果已经编译进内核,则此步可跳过


2. 动态创建设备

使用 `echo` 命令向 `/sys/bus/i2c/devices/i2c-1/new_device` 文件写入设备信息,格式为 `设备名称 设备地址`。

echo "24c256 0x57" > /sys/bus/i2c/devices/i2c-1/new_device



执行后,内核会尝试在 `I2C1` 总线上创建一个地址为 `0x57` 的 `24c256` 设备,并尝试与 `at24` 驱动进行匹配。

方法三:使用设备树覆盖层 (Device Tree Overlay)

如果你的海光平台使用设备树,但你想在不修改基础 DTS 的情况下添加设备,可以使用设备树覆盖层 (DT Overlay)。

创建一个 `.dts` 文件(例如 `eeprom-overlay.dts`),内容如下:```dts

/dts-v1/; /plugin/; / { fragment@1 { target = <&i2c1>; /* 假设 I2C1 在基础 DTS 中的标签是 &i2c1 */ __overlay__ { #address-cells = <1>; #size-cells = <0>; eeprom@57 { compatible = "atmel,24c256"; /* 需要与驱动匹配 */ reg = <0x57>; }; }; }; };

然后编译并加载这个 overlay:

dtc -@ -I dts -O dtb -o eeprom-overlay.dtbo eeprom-overlay.dts # 加载 overlay (具体命令可能因平台而异)

关于at24驱动加载函数

`at24_init` 函数使用 `i2c_add_driver(&at24_driver)` 来注册驱动。这个操作本身只是告诉内核:“我这里有 `at24` 这个驱动”。驱动与设备的匹配(即 `probe` 函数的调用)发生在内核遍历 I2C 设备列表时。因此,关键在于“如何将这个设备信息放入内核的 I2C 设备列表”中,这正是上面三种方法要解决的问题。

重要检查与注意事项

1. 确认 I2C 总线编号:务必确认 `I2C1` 在内核中对应的总线编号是 `1`。可以通过 `i2cdetect -l` 命令查看系统中所有 I2C 总线及其编号。
2. 确保驱动兼容:`at24` 驱动是一个通用驱动,它通过 `compatible` 或 `i2c_device_id` 来匹配设备。请确保 `I2C_BOARD_INFO` 中的名称(如 `"24c256"`)存在于 `at24` 驱动的 `i2c_device_id` 列表中。通常,`at24` 驱动支持 `"24c256"`、`"atmel,24c256"` 等多种名称。
3. 验证设备地址:`0x57` 是标准的 7 位 I2C 设备地址,不包含读写位。
4. 检查 `at24_io_limit`:你的 `at24_init` 函数中检查了 `at24_io_limit`,如果它为 0 则加载失败。请确保在加载驱动前,通过模块参数或其他方式正确设置了该值。

总结一下

最可靠的方法是修改板级文件,使用 `i2c_register_board_info` 进行静态注册。如果只是想快速验证,可以使用 `/sys` 文件系统接口。选择哪种方法,取决于你的需求是永久性的解决方案还是临时性的调试。

http://www.jsqmd.com/news/1210749/

相关文章:

  • ChatGPT数据可视化Prompt工程实战手册:80条防幻觉可交付指令
  • FPGA国产化进程:从Xilinx到复旦微电子的技术突破
  • Capstone项目重构:从学术模型秀到工业级数据工程实战
  • Android照片恢复原理与实战技巧
  • 2026年7月广州电梯/广州电梯安装经销商帮我推荐几家_广州市永恒电梯有限公司 - 品牌宣传支持者
  • 深圳江诗丹顿回收价格查询与靠谱平台实测排行(2026年7月最新数据) - 天价名表回收平台
  • 【Cursor智能编码×AB测试双引擎】:2024最新版AB分流逻辑验证框架,支持动态权重+埋点自动注入
  • Sqribble文档自动化流水线:非AI驱动的PDF生成方案
  • 2026年短视频特效素材网站评测:透明通道、动态图形与模板工作流
  • 亨得利官方名表服务中心|最新热线电话与地址权威信息公示(2026年7月更新) - 亨得利官方
  • 林伽一 · AI科技日报 | OpenAI Sol 自主删库,AI Agent 安全范式亟待重构
  • 2026年佛山代运营服务商深度剖析与制造业企业推荐
  • n8n自动化工作流构建科技新闻处理系统
  • 生产级机器学习系统设计:从模型正确性到系统韧性
  • 怎么用手机工具把多张截图拼接成完整长图 - 软件工具教程方法
  • 劳力士中国官方售后服务中心|官方地址及售后服务热线权威信息声明(2026年7月更新) - 劳力士服务中心
  • 发现一款免费的批量打印工具,分享给大家
  • ES6数组操作指南:从基础到高阶实践
  • Tiva TM4C123通用定时器(GPTM)配置与应用实战指南
  • AI技术Newsletter如何构建学习者协作操作系统
  • 武汉万国回收价格查询及靠谱回收平台实测排行(2026年7月最新) - 诚收名表回收平台
  • 业绩一好就膨胀加人,然后赔惨了——用血泪换来的教训
  • AI工程化落地:Jira-Slack-GitHub三角集成实践
  • 数据科学家真正在用的统计工具包:从p值到业务决策
  • Streamlit+Plotly构建联合国难民数据交互地图看板
  • Kotlin 与 Java 互操作:混合工程里的平台类型与 API 边界
  • Unreal Engine多人游戏网络同步实战:从核心原理到工程避坑
  • PHP面试核心知识点与实战技巧解析
  • 学生作业高效完成指南:类型分析与应对策略
  • COUNT() 函数深度解析:NULL处理、性能优化与跨数据库差异