i2c драйвер linux, где .ko файл, рекомпиляция одного драйвера

Рейтинг: 0Ответов: 2Опубликовано: 17.08.2023

Доброго времени суток всем :)

Устройство: mango pi mq-pro

Процессор: allwinner D1

Дистрибутив: Linux Ubuntu 5.17.0-1003-allwinner riscv64

Ссылка на дистрибутив: https://wiki.sipeed.com/hardware/en/lichee/RV/ubuntu.html

Нужно активировать i2c интерфейс на плате. Есть конкретные ножки к которым привязываются функции SDA и SCL (i2c функция в общем). Активация и привязка ножек делаются через Device Tree. После перезагрузки 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) // Эта строка добавлена в обновлении
            ndelay(100);      // И эта

        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;
}

Мне кажется дело именно в этом и есть.

Вопросы (прошу прощения, но их тут несколько):

  1. Я не могу понять где находится файл mv64xxx.ko конкретно. В директории /lib/modules/.../kernel/drivers/i2c/busses есть все прочие драйвера, но нет именно mv64xxx.ko файла. Не понимаю как он грузится в ядро или как активируется. В modprobe его не добавить и не удалить, в lsmod его тоже нет, но он активирован, ибо сообщения об ошибке идут из этого файла. Откуда он берется?

  2. Я хочу заменить мой текущий драйвер mv64xxx при линуксе 5.17 на драйвер mv64xxx из линукса >= 6.4. Я читал про make внутри /usr/src/ядро/, там можно отдельный драйвер установить, но не могу до конца понять как именно это сделать. make oldconfig уже сделал. Если моя теория верна, то этот файл .ko конкретного драйвера (из 1 вопроса) линкуется с ядром и удаляется, а остальные .ko файлы есть чтоб сделать это с ними при необходимости. Как мне скомпилировать заново этот файл и включить в ядро?

  3. Ну и третий вопрос. Как вообще эту проблему можно решить точно? Может уже кто сталкивался с таким.

Спасибо за внимание. Я старался подробно описать проблему, возможно я не по адресу, но все же. Если кто-то знает лучше сайт для подобных вопросов, то будьте добры подсказать :)

Ответы

▲ 0

У модуля нет .ko файла потому что он интегрирован в ядро при сбрке.

Для того чтоб перенести драйвер нужно

  1. скачать исходники вашего ядра (5.17).

  2. заменить строчки в файле драйвера.

  3. собрать модуль как внешний (kbuild)

Овеотом на 3ий вопрос может быть стоит обновить ядро полностью?

▲ 0

modinfo имя_модуля - может показать где находиться модуль, иногда модуль может быть собран монолитно с ядром, тогда его в ФС не будет, иногда модуль может иметь несколько имён, и в ФС одно. rmmod имя_модуля - можно попытаться выгрузить модуль ядра, если он не занят. По сборке ядра и командам, есть краткий man https://www.kernel.org/doc/makehelp.txt