i2c 驱动程序 linux,.ko 文件在哪里,重新编译单个驱动程序并启用

i2c 驱动程序 linux,.ko 文件在哪里,重新编译单个驱动程序并启用

我有 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 的使用变得困难。)

这通常意味着驱动程序也不能通过加载模块来覆盖。您需要重建整个内核。

相关内容