GPIO
В: Как настроить интерфейсы UART, I2C, SPI на определённые выводы модуля?
О: Сначала необходимо определить, какие функции доступны на нужных физических выводах SoM. Соответствие выводов модуля сигналам RK3568 приведено в pinout:
https://files.diasom.ru/ds-rk3568_v3_pinout.xlsx
У RK3568 большинство выводов являются мультиплексируемыми: один и тот же вывод может использоваться как GPIO либо как сигнал одного из периферийных интерфейсов. Одновременно на выводе может быть активна только одна функция.
Выбор функции выполняется через pinctrl в Device Tree. Для периферийного устройства задаётся нужная группа выводов через pinctrl-0.
Пример для I2C2:
&i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2m1_xfer>; status = "okay"; };
Группы вида i2c2m0_xfer, i2c2m1_xfer, uartXmY_xfer, spiXmY_* описывают конкретные варианты IOMUX одного контроллера. Суффиксы m0, m1, m2 означают разные группы физических выводов, на которые может быть выведена одна и та же периферия.
Для RK3568 стандартные pinctrl-группы уже определены в SoC Device Tree (rk3568-pinctrl.dtsi). На уровне платы обычно достаточно выбрать подходящую группу через pinctrl-0; создавать собственную pinctrl-группу требуется только если нужной конфигурации нет среди уже определённых.
При выборе группы необходимо учитывать не только IOMUX, но и напряжение соответствующего VCCIO-домена. На RK3568 разные GPIO-группы могут относиться к доменам 1.8 В, 3.3 В или к переключаемым 1.8/3.3 В доменам.
DTS-файл от отладочной платы DS-RK3568-EVB можно использовать как референс.
В: Как пересчитать bank/pin в Linux GPIO-номер?
О: Обозначение Rockchip состоит из номера GPIO-банка, группы A–D и номера вывода 0–7.
Смещения групп внутри одного GPIO-банка:
A0...A7 = 0...7 B0...B7 = 8...15 C0...C7 = 16...23 D0...D7 = 24...31
Например:
GPIO2_D1
имеет смещение внутри GPIO-банка:
24 + 1 = 25
Старая глобальная нумерация GPIO вычислялась как:
GPIO = bank * 32 + offset
Для GPIO2_D1:
2 * 32 + 25 = 89
То есть в legacy-схеме это был бы GPIO 89.
Эту глобальную нумерацию нельзя использовать как стабильный интерфейс современных Linux-систем. Номера /dev/gpiochipN назначаются ядром и не должны вычисляться из номера Rockchip-банка.
Для userspace следует использовать GPIO character-device API и libgpiod. Определить доступные контроллеры и линии можно командами:
gpiodetect gpioinfo
Работа с GPIO выполняется по GPIO-chip и offset линии, например offset 25 для GPIOx_D1 внутри соответствующего банка.
Устаревший интерфейс /sys/class/gpio и глобальные номера GPIO для новых разработок использовать не следует.
В Device Tree глобальный номер вообще не используется. GPIO задаётся через phandle соответствующего контроллера и номер линии:
reset-gpios = <&gpio2 RK_PD1 GPIO_ACTIVE_LOW>;
Здесь:
&gpio2— GPIO-банк 2;RK_PD1— линия D1 внутри банка;GPIO_ACTIVE_LOW— активный уровень сигнала.
В: Как переназначить функцию пинов через DTS? Например, CAN2 → I2C2
О: Необходимо отключить устройство, которое использует эти выводы, и выбрать pinctrl-группу нового интерфейса, соответствующую тем же физическим выводам.
Для RK3568 группа CAN2_M0 использует:
CAN2_RX_M0 -> GPIO4_B4 CAN2_TX_M0 -> GPIO4_B5
Группа I2C2_M1 использует те же выводы:
I2C2_SDA_M1 -> GPIO4_B4 I2C2_SCL_M1 -> GPIO4_B5
Поэтому для переназначения этой пары выводов с CAN2 на I2C2 используется:
&can2 { status = "disabled"; }; &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2m1_xfer>; status = "okay"; };
Одновременно использовать CAN2_M0 и I2C2_M1 нельзя, поскольку они физически используют одни и те же выводы.
Если используется другой вариант разводки (m0, m1 и т. д.), необходимо выбрать pinctrl-группу, соответствующую фактическим выводам платы. Названия маршрутов нельзя менять произвольно: они соответствуют вариантам IOMUX, реализованным аппаратно в RK3568.
Для UART, SPI, PWM и других интерфейсов принцип тот же:
определить физические выводы по pinout;
определить доступную для них IOMUX-функцию;
отключить конфликтующее устройство;
выбрать нужную pinctrl-группу в узле используем