Управляйте контактом USART RTS от драйвера на встроенной плате - PullRequest
2 голосов
/ 09 июля 2019

Я портирую модуль ядра lirc_serial для работы на нашей встроенной плате. Нам нужно только реализовать функцию ИК-передатчика.

Только для передатчика, пользовательский драйвер должен управлять только выводом RTS на /dev/ttyS0, изнутри модуля.

На стандартном оборудовании драйвер загружается:

00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A

НОВЫЙ ПОДХОД

Я не понял, как деактивировать текущий драйвер для последовательного порта, вместо того, чтобы создавать новый драйвер, как бы вы использовали текущий драйвер 8250-dw для изменения контакта RTS от имени моего модуля ядра? Как то так?

Driver stack

Использование линейных дисциплин в этой статье для драйвера скольжения выглядит многообещающе, просто возьмите slip.c и удалите сетевой код. Но для этого требуется программа пространства пользователя (slattach или dip), чтобы открыть / dev / ttyS0 и активировать дисциплину строки.

Возможно ли это (или хорошая идея) из модуля ядра?

From https://www.linux.it/~rubini/docs/serial/serial.html

В этом похожем вопросе Как мне открыть / записать / прочитать устройство uart из модуля ядра? , Ian Abbott предложил перенести serdev в ядро ​​4.9.

Это немного усложняется, и мы уже отстаем от графика. Есть ли более простой способ?

ОРИГИНАЛЬНЫЙ ВОПРОС

Однако встроенная плата (основанная на BayTrail Atom E3845 ) имеет контроллер последовательного порта в отображаемой памяти ввода-вывода:

80860F0A:00: ttyS0 at MMIO 0x90a0c000 (irq = 39, base_baud = 2764800) is a 16550A
80860F0A:01: ttyS1 at MMIO 0x90a0e000 (irq = 40, base_baud = 2764800) is a 16550A

Я новичок в разработке драйверов. Я думаю, 0x90a0c000 это физический адрес контроллера?

Чтобы проверить модуль, я сначала переназначил 0x90a0c000 на виртуальный адрес, используя ioremap_nocache, а затем попытался зарезервировать память, используя request_mem_region. Это не удалось.

ioVirtBase = ioremap_nocache(iommap, 8);

TQTRACE("ecp_serial_probe: devm_ioremap for MMIO 0x%X returned 0x%X\n", (uint32_t)iommap, (uint32_t)ioVirtBase);
if (ioVirtBase != NULL)
{
    tqDumpBuffer(ioVirtBase, 8);
}

tqRes = request_mem_region((uint32_t)ioVirtBase, 8, ECP_DRIVER_NAME);
TQTRACE("ecp_serial_probe: request_mem_region for 0x%X returned 0x%X\n", (uint32_t)ioVirtBase, (uint32_t)tqRes);
if (!tqRes)
{
    TQTRACE("ecp_serial_probe: Cannot request memory at 0x%X\n", (uint32_t)iommap);
    return -ENXIO;
}

Это правильный порядок функций?

Кроме того, кажется, что request_mem_region дает сбой, потому что устройство находится под контролем 80860F0A ?? В lsmod такой записи нет, но в /sys/devices.

Нужно ли выгружать этот драйвер для управления USART? Как?

# ls -l  /sys/devices/platform/80860F0A\:00
lrwxrwxrwx 1 root root    0 Jul  8 23:30 driver -> ../../../bus/platform/drivers/dw-apb-uart
-rw-r--r-- 1 root root 4096 Jul  9 17:02 driver_override
lrwxrwxrwx 1 root root    0 Jul  9 17:14 firmware_node -> ../../LNXSYSTM:00/LNXSYBUS:00/80860F0A:00
-r--r--r-- 1 root root 4096 Jul  9 17:02 modalias
drwxr-xr-x 2 root root    0 Jul  9 17:02 power
lrwxrwxrwx 1 root root    0 Jul  8 23:30 subsystem -> ../../../bus/platform
drwxr-xr-x 3 root root    0 Jul  8 23:30 tty
-rw-r--r-- 1 root root 4096 Jul  9 17:02 uevent
drwxr-xr-x 3 root root    0 Jul  8 23:30 VCOM0001:00

вывод dmesg ниже. Сброс данных по переназначенному виртуальному адресу не согласован. Иногда все 0xFF, иногда 00 00 00 00 41 02 1C 48. Я тоже этого не понимаю ...

MARK Tue Jul 9 17:45:35 SGT 2019
ecp_serial: ecp_serial_exit_module()
Spectre V2 : System may be vulnerable to spectre v2
ecp_serial: loading module not compiled with retpoline compiler.
ecp_serial: ecp_serial_init_module()
ecp_serial: ecp_serial_init()
ecp_serial: ecp_serial_probe() iommap=0x90A0C000
ecp_serial: ecp_serial_probe: devm_ioremap for MMIO 0x90A0C000 returned 0xE3296000
ecp_serial: Dump address 0xE3296000:
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
0000  FF FF FF FF FF FF FF FF 
ecp_serial: ecp_serial_probe: request_mem_region for 0xE3296000 returned 0x0
ecp_serial: ecp_serial_probe: Cannot request memory at 0x90A0C000
platform ecp_serial.0: lirc_dev: driver ecp_serial registered at minor = 0

MARK Tue Jul 9 17:46:08 SGT 2019
ecp_serial: ecp_serial_exit_module()
Spectre V2 : System may be vulnerable to spectre v2
ecp_serial: loading module not compiled with retpoline compiler.
ecp_serial: ecp_serial_init_module()
ecp_serial: ecp_serial_init()
ecp_serial: ecp_serial_probe() iommap=0x90A0C000
ecp_serial: ecp_serial_probe: devm_ioremap for MMIO 0x90A0C000 returned 0xE32A2000
ecp_serial: Dump address 0xE32A2000:
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
0000  00 00 00 00 41 02 1C 48 
ecp_serial: ecp_serial_probe: request_mem_region for 0xE32A2000 returned 0x0
ecp_serial: ecp_serial_probe: Cannot request memory at 0x90A0C000
platform ecp_serial.0: lirc_dev: driver ecp_serial registered at minor = 0

Что говорит proc / iomem

90a0c000-90a0cfff : 80860F0A:00
90a0e000-90a0efff : 80860F0A:01

Так что, действительно, память находится под контролем другого драйвера ... Но как выгрузить ее, если она не указана в lsmod?

# rmmod 80860F0A:00
ERROR: Module 80860F0A:00 does not exist in /proc/modules
# rmmod 80860F0A
ERROR: Module 80860F0A does not exist in /proc/modules

OS INFO

# uname -a
Linux ecp 4.4.127-1.el6.elrepo.i686 #1 SMP Sun Apr 8 09:44:43 EDT 2018 i686 i686 i386 GNU/Linux
# cat /etc/centos-release
CentOS release 6.6 (Final)
...