我有 SBC:mango pi mq-pro
处理器:全志D1
发行版:Linux Ubuntu 5.17.0-1003-allwinner riscv64
发行版链接:https://wiki.sipeed.com/hardware/en/lichee/RV/ubuntu.html
我需要在板上启用 i2c 接口。有特定的支路,SDA 和 SCL 功能连接到这些支路(一般为 i2c 功能)。支路的激活和绑定是通过设备树完成的。重启后,i2c 被激活:
$ cat /sys/firmware/devicetree/base/soc/i2c@2502000/status
okay
$ cat /sys/kernel/debug/pinctrl/2000000.pinctrl/pinmux-pins | grep i2c
pin 144 (PE16): device 2502000.i2c function i2c3 group PE16
pin 145 (PE17): device 2502000.i2c function i2c3 group PE17
也就是说,在启用和链接引脚的设置中所有内容均已正确指示。
接下来是 i2c 存在的命令:
$ i2cdetect -l
i2c-0 i2c mv64xxx_i2c adapter I2C adapter
i2c-1 i2c DesignWare HDMI I2C adapter
该i2cdetect -y 1
命令显示设备地址,类似于:
0 1 2 3... ...f
00: -- -- -- --
10: -- -- -- -- --...
...
30: 30 -- -- -- --...
...
70: -- -- -- -- --...
但这不是我需要的芯片,我需要的是0,它和mv64xxx驱动有关联,因为在设备树中i2c激活的时候出现的就是他。
命令i2cdetect -y 0
输出:
[время] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
我在内核版本6.4中找到了修复此驱动程序的源代码:
static irqreturn_t
mv64xxx_i2c_intr(int irq, void *dev_id)
{
struct mv64xxx_i2c_data *drv_data = dev_id;
u32 status;
irqreturn_t rc = IRQ_NONE;
spin_lock(&drv_data->lock);
if (drv_data->offload_enabled)
rc = mv64xxx_i2c_intr_offload(drv_data);
while (readl(drv_data->reg_base + drv_data->reg_offsets.control) &
MV64XXX_I2C_REG_CONTROL_IFLG) {
/*
* It seems that sometime the controller updates the status
* register only after it asserts IFLG in control register.
* This may result in weird bugs when in atomic mode. A delay
* of 100 ns before reading the status register solves this
* issue. This bug does not seem to appear when using
* interrupts.
*/
if (drv_data->atomic) // The new in 6.4
ndelay(100); // And this
status = readl(drv_data->reg_base + drv_data->reg_offsets.status);
mv64xxx_i2c_fsm(drv_data, status);
mv64xxx_i2c_do_action(drv_data);
if (drv_data->irq_clear_inverted)
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_IFLG,
drv_data->reg_base + drv_data->reg_offsets.control);
rc = IRQ_HANDLED;
}
spin_unlock(&drv_data->lock);
return rc;
}
在我看来这正是关键所在。
问题(抱歉,但有几个):
我不知道 mv64xxx.ko 文件位于何处。/lib/modules/.../kernel/drivers/i2c/busses 目录包含所有其他驱动程序,但缺少 mv64xxx.ko 文件。我不明白它是如何加载到内核中的,或者它是如何被激活的。它无法在 modprobe 中添加或删除,它也不在 lsmod 中,但它被激活了,因为错误消息来自这个文件。这个文件来自哪里?
我想用 Linux >= 6.4 中的 mv64xxx 驱动程序替换 Linux 5.17 上当前的 mv64xxx 驱动程序。我读到 /usr/src/kernel/ 中的 make,您可以安装单独的驱动程序,但我无法完全理解如何操作。make oldconfig 已完成。如果我的理论是正确的,那么该驱动程序特定的 .ko 文件(来自问题 1)将链接到内核并被删除,其余的 .ko 文件将在需要时用来执行此操作。我如何重新编译此文件并将其包含在内核中?
好吧,第三个问题。这个问题到底该如何解决?也许其他人也遇到过这个问题。
感谢您的关注。我尝试详细描述该问题。
更新:
我做到了,我重新编译了新模块。有几个简单的更改,一个函数具有另一种返回类型,一个结构具有另一个接受此函数指针的字段名称(返回 VOID,而不是 INT 0)。我有新的 i2c-mv64xxx.ko 文件和目录中包含此模块的其他文件。我这样做了,depmode
然后modprobe i2c-mv64xxx
,没有错误,什么都没有发生。lsmod | grep i2c : empty
,,,但是,在我重新编译模块之前就已经dmesg | grep mv64 : empty
这样dmesg | grep i2c : i2c_dev: i2c /dev entries driver
了。可能是旧模块不让我加载新模块?:(
答案1
我不知道 mv64xxx.ko 文件位于何处。/lib/modules/.../kernel/drivers/i2c/busses 目录包含所有其他驱动程序,但缺少 mv64xxx.ko 文件。我不明白它是如何加载到内核中的,或者它是如何被激活的。它无法在 modprobe 中添加或删除,它也不在 lsmod 中,但它被激活了,因为错误消息来自这个文件。这个文件来自哪里?
在编译时,它被选择为内置– 它实际上是主vmlinuz
映像的一部分。(这通常用于需要在早期启动期间可用的驱动程序,以防构建器不想使用 initramfs 或者平台使 initramfs 的使用变得困难。)
这通常意味着驱动程序也不能通过加载模块来覆盖。您需要重建整个内核。