i2c драйвер linux, где .ko файл, рекомпиляция одного драйвера
Доброго времени суток всем :)
Устройство: 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;
}
Мне кажется дело именно в этом и есть.
Вопросы (прошу прощения, но их тут несколько):
Я не могу понять где находится файл mv64xxx.ko конкретно. В директории /lib/modules/.../kernel/drivers/i2c/busses есть все прочие драйвера, но нет именно mv64xxx.ko файла. Не понимаю как он грузится в ядро или как активируется. В modprobe его не добавить и не удалить, в lsmod его тоже нет, но он активирован, ибо сообщения об ошибке идут из этого файла. Откуда он берется?
Я хочу заменить мой текущий драйвер mv64xxx при линуксе 5.17 на драйвер mv64xxx из линукса >= 6.4. Я читал про make внутри /usr/src/ядро/, там можно отдельный драйвер установить, но не могу до конца понять как именно это сделать. make oldconfig уже сделал. Если моя теория верна, то этот файл .ko конкретного драйвера (из 1 вопроса) линкуется с ядром и удаляется, а остальные .ko файлы есть чтоб сделать это с ними при необходимости. Как мне скомпилировать заново этот файл и включить в ядро?
Ну и третий вопрос. Как вообще эту проблему можно решить точно? Может уже кто сталкивался с таким.
Спасибо за внимание. Я старался подробно описать проблему, возможно я не по адресу, но все же. Если кто-то знает лучше сайт для подобных вопросов, то будьте добры подсказать :)