Я работаю над тем, чтобы заставить работать более современный Linux на одноплатном компьютере, где первоначальная компания обанкротилась, но оборудование хорошо поддерживается сообществом разработчиков открытого исходного кода. Я добился очень хорошего прогресса, но столкнулся с проблемой, когда для определенного устройства загружается неправильный модуль драйвера.
Платформа — Allwinner R8 (такая же, как Allwinner A13), а устройство — резистивный сенсорный экран. Дистрибутив — Slackware-current для ARM, что означает отсутствие systemd, но использование eudev. Я скомпилировал ядро 5.2.0-rc6 из исходников, поскольку хотел попробовать драйвер Mali lima и нуждался в некоторых модулях, которые в любом случае не включены в сборку дистрибутива. Соответствующие разделы из дерева устройств приведены ниже.
u-boot/arch/arm/dts/sun5i.dtsi:
587 rtp: rtp@1c25000 {
588 compatible = "allwinner,sun5i-a13-ts";
589 reg = <0x01c25000 0x100>;
590 interrupts = <29>;
591 #thermal-sensor-cells = <0>;
592 };
оверлей (который скопирован с оверлея производителя для модифицированного ядра 4.4, включенного в патчи из дерева для некоторых устройств)
76 /* Enable the touchscreen */
77 fragment@4 {
78 target = <&rtp>;
79 __overlay__ {
80 touchscreen-inverted-x;
81 touchscreen-inverted-y;
82 allwinner,ts-attached;
83 };
84 };
Проблема в том, чтоsun4i-gpadcмодуль загружен для этого устройства, когда мне нужноsun4i-ts. Первый — это драйвер АЦП общего назначения, а второй — драйвер сенсорного экрана, который мне нужен.
root@pocketslack:/etc# udevadm info -a /sys/devices/platform/soc\@1c00000/1c25000.rtp
looking at device '/devices/platform/soc@1c00000/1c25000.rtp':
KERNEL=="1c25000.rtp"
SUBSYSTEM=="platform"
DRIVER=="sun4i-gpadc"
ATTR{driver_override}=="(null)"
Если я использую modprobe для удаления sun4i_gpadc и sun4i_ts, а затем использую его для их загрузки, начиная с sun4i-ts, он захватывает устройство и работает правильно.
root@pocketslack:/etc# modprobe -r sun4i_gpadc
root@pocketslack:/etc# modprobe -r sun4i_ts
root@pocketslack:/etc# modprobe sun4i_ts
root@pocketslack:/etc# modprobe sun4i_gpadc
root@pocketslack:/etc# udevadm info -a /sys/devices/platform/soc\@1c00000/1c25000.rtp
looking at device '/devices/platform/soc@1c00000/1c25000.rtp':
KERNEL=="1c25000.rtp"
SUBSYSTEM=="platform"
DRIVER=="sun4i-ts"
ATTR{driver_override}=="(null)"
У меня есть правило udev, которое я также взял из старого репозитория компании, и которое, как я думал, должно было с этим справиться, но устройство по-прежнему занято драйвером gpadc.
root@pocketslack:/etc# cat /etc/udev/rules.d/10-sun4i-ts.rules
ACTION=="add", SUBSYSTEM=="input", DRIVERS=="sun4i-ts", SYMLINK+="input/sun4i-ts-%k"
Я признаю, что я совсем новичок в udev, поэтому я не уверен, что именно это правило говорит ему делать. По моим догадкам, оно просто говорит ему загрузить этот модуль и как назвать любое устройство, к которому он подключается. Я также не уверен, что мне вообще нужен драйвер sun4i-gpadc, но я понял из документации ядра, что он, похоже, нужен для работы термодатчиков SoC. Это устройство также имеет открытые контакты для проектов, поэтому я подумал, что это также может быть полезно, если кто-то действительно захочет использовать включенный АЦП таким образом. Также кажется, что должен быть какой-то механизм для указания правильного драйвера, когда можно применить несколько, и я решил, что мне следует просто узнать, как это сделать, а не просто не собирать или вносить в черный список модуль gpadc.
решение1
Похоже, в этом конкретном случае я действительно хочу отключитьsun4i_gpadcмодуль. Я заметилATTRS{driver_override}часть в udevadm info
выводе выше, которую я раньше не замечал и погуглил, что привело к выяснению немного больше о том, как записи дерева устройств определяют модуль через атрибут «совместимый». Это привело меня к открытию того, modinfo
что оба этих модуля ищут одни и те же совместимые строки, и после повторного просмотра конфигурации ядра я вижу, что драйверы несовместимы, и поэтому мне действительно следует либо не собирать, либо внести в черный список драйвер gpadc в этом случае, поскольку это зависит от!TOUCHSCREEN_SUN4I.
Symbol: MFD_SUN4I_GPADC [=m] │
│ Type : tristate │
│ Prompt: Allwinner sunxi platforms' GPADC MFD driver │
│ Location: │
│ -> Device Drivers │
│ (2) -> Multifunction device drivers │
│ Defined at drivers/mfd/Kconfig:54 │
│ Depends on: HAS_IOMEM [=y] && (ARCH_SUNXI [=y] || COMPILE_TEST [=n]) && !TOUCHSCREEN_SUN4I [=m] │
│ Selects: MFD_CORE [=y] && REGMAP_MMIO [=y] && REGMAP_IRQ [=y]
Извините, что не совсем правильно изложил свои мысли :)