Skip to main content
added 601 characters in body
Source Link
nx4n
  • 109
  • 2

UPD: I did it, I recompiled new module. There was several easy changes, one function with another return type and one struct with one another name of field that takes this function pointer (return VOID, instead INT 0). I have new i2c-mv64xxx.ko file and other files within directory with this module. I did depmode and then modprobe i2c-mv64xxx, no errors, nothing is going on. lsmod | grep i2c : empty, dmesg | grep mv64 : empty, dmesg | grep i2c : i2c_dev: i2c /dev entries driver, BUT, it was already before I recompiled module. May be old module dont give me load new module? :(

UPD: I did it, I recompiled new module. There was several easy changes, one function with another return type and one struct with one another name of field that takes this function pointer (return VOID, instead INT 0). I have new i2c-mv64xxx.ko file and other files within directory with this module. I did depmode and then modprobe i2c-mv64xxx, no errors, nothing is going on. lsmod | grep i2c : empty, dmesg | grep mv64 : empty, dmesg | grep i2c : i2c_dev: i2c /dev entries driver, BUT, it was already before I recompiled module. May be old module dont give me load new module? :(

Source Link
nx4n
  • 109
  • 2

i2c driver linux, where is .ko file, recompile single driver and enable

I have SBC: mango pi mq-pro

Processor: Allwinner D1

Distribution: Linux Ubuntu 5.17.0-1003-allwinner riscv64

Link at distro: https://wiki.sipeed.com/hardware/en/lichee/RV/ubuntu.html

I need to enable the i2c interface on the board. There are specific legs to which the SDA and SCL functions are attached (i2c function in general). Activation and binding of legs are done through the Device Tree. After reboot i2c is activated:

$ 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

That is, everything is correctly indicated in the settings for enabling and linking pins.

Next, the command for the presence of i2c:

$ i2cdetect -l
i2c-0 i2c mv64xxx_i2c adapter I2C adapter
i2c-1 i2c DesignWare  HDMI    I2C adapter

The i2cdetect -y 1 command shows device addresses, something like:

    0  1  2  3...                      ...f
00:                     -- -- -- --
10: -- -- -- -- --...
...
30: 30 -- -- -- --...
...
70: -- -- -- -- --...

But this is not the chip that I need, I need 0, which is associated with the mv64xxx driver, because it is he who appears when i2c is activated in the device tree.

Command i2cdetect -y 0 output:

[время] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0

I found the source code for fixing this driver in kernel version 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;
}

It seems to me that this is precisely the point.

Questions (apologies, but there are several):

  • I can't figure out where the mv64xxx.ko file is located. The /lib/modules/.../kernel/drivers/i2c/busses directory contains all the other drivers, but the mv64xxx.ko file is missing. I do not understand how it is loaded into the kernel or how it is activated. It cannot be added or removed in modprobe, it is not in lsmod either, but it is activated, because error messages come from this file. Where does this file come from?

  • I want to replace my current mv64xxx driver on linux 5.17 with the mv64xxx driver from linux >= 6.4. I read about make inside /usr/src/kernel/, you can install a separate driver, but I can not fully understand how to do it. make oldconfig already done. If my theory is correct, then that driver-specific .ko file (from question 1) is linked to the kernel and removed, and the rest of the .ko files are there to do it with if needed. How can I recompile this file and include it in the kernel?

  • Well, the third question. How exactly can this problem be solved? Maybe someone else has come across this.

Thank you for your attention. I tried to describe the problem in detail.