Nach der Entwicklung und dem Bau eines kundenspezifischen Carrier-Boards, das auf einem Variscite i.MX System on Module / Computer on Module basiert, besteht eine der ersten Aufgaben Ihres Software-Teams darin, eine neue Gerätebaum-Datei für den Linux-Kernel zu erstellen. Der Gerätebaum ist dafür verantwortlich, dem Kernel die Hardwarekonfiguration zu beschreiben, einschließlich der Funktion und der Einstellungen eines jeden Pins. Die meisten i.MX SoC-Pins sind gemultiplext und bieten bis zu 8 alternative Pin-Funktionen. Darüber hinaus verfügen die meisten Pins über konfigurierbare Einstellungen wie interne Pull-Ups, Pull-Downs usw. In dieser Anleitung erfahren Sie, wie Sie eine Pin-Funktion und ihre Einstellungen für Geräte im Linux-Gerätebaum für Variscite i.MX System on Modules konfigurieren.
Einrichten des Pinmux für ein Gerät
Wenn Sie einen Geräteknoten hinzufügen, der die physische Kontrolle über einen Pin erfordert, wie z. B. I2C, PWM, UART usw., müssen Sie die Funktion und die Einstellungen für jeden Pin festlegen. Dabei sind zwei Schritte zu beachten:
- Fügen Sie dem iomuxc-Knoten einen Pin-Gruppenknoten hinzu, der die Pin-Funktion und die Einstellungen definiert;
- Verweisen Sie auf diesen Pin-Gruppen-Knoten in dem Knoten des neuen Geräts, das Sie hinzufügen.
Um diesen Prozess zu veranschaulichen, lassen Sie uns die Pinmux-Konfiguration für UART3 auf dem VAR-SOM-MX8X SoM überprüfen:
Schritt 1: Fügen Sie dem iomuxc-Knoten einen Pin-Gruppenknoten hinzu
Für VAR-SOM-MX8X ist der UART3-Pin-Gruppenknoten in imx8qxp-var-som.dtsi definiert:
&iomuxc {
…
pinctrl_lpuart3: lpuart3grp {
fsl,pins = <
IMX8QXP_SCU_GPIO0_00_ADMA_UART3_RX 0x06000020
IMX8QXP_SCU_GPIO0_01_ADMA_UART3_TX 0x06000020
>;
};
};
iomuxc ist ein Geräteknoten für den imx8qxp pinctrl-Treiber. Er ist in imx8qxp.dtsi definiert. Die Dokumentation für diesen Knoten finden Sie im Linux-Kernel-Quellbaum unter:
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
pinctrl_lpuart3 ist ein Label, das als Name für die UART3-Pin-Gruppe verwendet wird. Wir werden dieses Label im nächsten Schritt verwenden.
„fsl,pins“ ist eine Liste der an UART3 verwendeten Pins und ihrer Konfiguration. Jeder Eintrag besteht aus einem Makro für die Pin-Funktion (pinmux) und einer Ganzzahl für die Pad-Einstellung (interne Pull-Ups, Pull-Downs usw.).
Pin-Funktion:
Jeder Pin hat bis zu 8 Funktionen, die gemultiplext sind. Um die Auswahl der Pin-Funktion zu vereinfachen, stellt NXP für jedes SoC Makros mit dem folgenden Namensformat zur Verfügung:
<SOC>_<PIN NAME>_<PIN FUNCTION>
In diesem Beispiel hat „fsl,pins“ zwei Pin-Einträge: Pin SCU_GPIO0_00 ist für die Funktion ADMA_UART3_RX und Pin SCU_GPIO0_01 ist für die Funktion ADMA_UART3_TX konfiguriert.
Warnung: Um Pinmux-Konflikte zu vermeiden, sollte jeder Pin auf nur eine Funktion eingestellt und jede Funktion nur einem Pin zugewiesen werden.
Jeder i.MX SoC verfügt über eine Pin-Konfigurationsdatei mit Definitionen von Pin-Funktionsmakros sowie über eine Dokumentation im Verzeichnis der Gerätebaumbindungen. Weitere Informationen zu den Werten der Pin-Funktionsmakros finden Sie in der Dokumentation des jeweiligen SoCs.
Für i.MX8X und i.MX8QM befinden sich die Pin-Header-Dateien unter „include/dt-bindings/pinctrl/“ und wie bereits erwähnt, befindet sich die Dokumentation unter „Documentation/devicetree/bindings/arm/freescale/“.
Header file | Documentation |
pads-imx8qxp.h | fsl,scu.txt |
pads-imx8qm.h | fsl,scu.txt |
Für die i.MX8M-Familie befinden sich die pinfunc-Dateien unter „arch/arm64/boot/dts/freescale/“ und die Dokumentation unter „Documentation/devicetree/bindings/pinctrl/“
Header file | Documentation |
imx8mp-pinfunc.h | fsl,imx8mp-pinctrl.txt |
imx8mq-pinfunc.h | fsl,imx8mq-pinctrl.txt |
imx8mm-pinfunc.h | fsl,imx8mm-pinctrl.txt |
imx8mn-pinfunc.h | fsl,imx8mn-pinctrl.txt |
Für die Familien i.MX6/i.MX6UL/i.MX7 befinden sich die pinfunc-Dateien unter „arch/arm/boot/dts/“ und die Dokumentation unter „Documentation/devicetree/bindings/pinctrl/“
Header file | Documentation |
imx6dl-pinfunc.h | fsl,imx6dl-pinctrl.txt |
imx6q-pinfunc.h | fsl,imx6q-pinctrl.txt |
imx6ul-pinfunc.h | fsl,imx6ul-pinctrl.txt |
imx6ull-pinfunc.h | fsl,imx6ul-pinctrl.txt |
imx7d-pinfunc.h | fsl,imx7d-pinctrl.txt |
Pad-Einstellung:
Zusätzlich zum Pin-Funktionsmakro benötigt jeder „fsl,pins“-Eintrag einen Wert für die Pad-Einstellungen. In diesem Fall ist 0x06000020 der Pad-Einstellungswert, der den Pin-Pull-up, die Stärke der Ansteuerung usw. konfiguriert. Die Konfigurationsoptionen für jeden Pin sind im i.MX8QXP-Referenzhandbuch beschrieben.
Nachfolgend finden Sie das Pad-/Mux-Steuerregister für den UART3_RX-Pin, aus dem i.MX8QXP-Referenzhandbuch Rev. 0, 05/2020, Seite 957:
Abbildung 1: Pad-/Mux-Steuerregister für SCU_GPIO0_00
Field | Function |
31 update_mux_mode |
update lock for mux control write 1 to allow programming to mux control [29:19] |
30 update_pad_ctl |
update lock for pad control write 1 to allow programming to pad control [14-1:0] |
29-27 mux_mode |
mux_mode 000b – SCU_GPIO0_IO00 001b – SCU_UART0_RX 010b – M40_UART0_RX 011b – ADMA_UART3_RX 100b – LSIO_GPIO2_IO03 |
26-25 sw_config |
output and input configuration 00b – DEFAULT 01b – OPEN_DRAIN 10b – OPEN_DRAIN_INPUT 11b – INOUT |
24-23 lp_config |
lower power configuration 00b – PASS 01b – EARLY_ISO 10b – LATE_ISO 11b – LATCH |
22 ENABLE_WAKEUP_CHANGE |
Enable WAKEUP change Allows modification of the WAKEUP_CTRL field without having to read or modify the other bits |
21-19 WAKEUP_CTRL |
wakeup control 000b – OFF 001b – RESAMPLE (The wakeup field is not modified (it retains its old value) but because a write is done, the flag is cleared) 100b – LOW 101b – FALL 110b – RISE 111b – HIGH |
18-17 | Reserved |
6-5 PULL |
Pull Down Pull Up 00b – Bus-Keeper 01b – pull up 10b – pull down 11b – No Pull |
4-3 | Reserved |
2-0 DSE |
Drive 000b – Drive select 1mA 001b – Drive select 2mA 010b – Drive select 4mA 011b – Drive select 6mA 100b – Drive select 8mA 101b – Drive select 10mA 110b – Drive select 12mA 111b – High Speed |
Da dieses Register in diesem Beispiel den Wert 0x06000020 (Bits 5, 25, 26 aktiviert) hat, ist dies die Liste aller Konfigurationen und ihrer Werte:
update_mux_mode: value 0
update_pad_ctl: value 0
mux_mode: value 0 (Konfiguriert durch die Pin-Funktion Makro)
sw_config: value 0b11
lp_config: value 0
enable_wakeup_change: value 0
wakeup_ctrl: value 0
pull: value 0b01: Interner Pull-Up-Widerstand ausgewählt.
DSE: value 0b000: Ansteuerungsstärke von 1 mA gewählt.
Um mehr über alle möglichen Konfigurationen zu erfahren, lesen Sie bitte das i.MX8QXP-Referenzhandbuch.
Schritt 2: Verweisen Sie im Geräteknoten auf diesen Pin-Gruppenknoten
Nachdem Sie den Pin-Gruppenknoten (lpuart3grp) zu iomuxc hinzugefügt haben, besteht der nächste Schritt darin, einen Verweis auf den Geräteknoten anzugeben, der diese Pins verwenden wird. In diesem Beispiel ist dies lpuart3, das in imx8-ss-dma.dtsi definiert und von Variscite in imx8qxp-var-som-symphony.dtsi konfiguriert wird:
/* Console */
&lpuart3 {
pinctrl-names = „default“;
pinctrl-0 = <&pinctrl_lpuart3>;
…
};
Während der Initialisierung von lpuart3 ruft der Linux-Gerätekern pinctrl_bind_pins auf, bevor die Probe-Funktion in der lpuart3-Treiber aufgerufen wird. Der pinctrl-Treiber schreibt dann in die i.MX-spezifischen Register, um den Standard-Pin-Status für jeden Eintrag in pinctrl_lpuart3 zu konfigurieren.
Pin-Zustände
Einige Geräte unterstützen mehrere Pin-Zustände.
Zum Beispiel ein MMC-Gerät:
&usdhc1 {
pinctrl-names = „default“, „state_100mhz“, „state_200mhz“;
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
…
};
In diesem Beispiel hat usdhc1 drei pinctrl-Zustände: Standard, 100 MHz und 200 MHz. Der Linux-Gerätekern initialisiert den Standardstatus, bevor er die Probefunktion des Plattformtreibers aufruft. Der Treiber hat jedoch auch die Möglichkeit, die Pin-Einstellungen je nach MMC-Modus zu ändern.
Weitere Informationen zu diesem Thema finden Sie in der folgenden Dokumentationsdatei im Kernel-Quellbaum: „Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt“
Zusammenfassung
Zusammenfassend lässt sich sagen, dass Geräteknoten, die eine Pin-Konfiguration benötigen, einen Verweis auf einen in iomuxc definierten Pin-Gruppenknoten benötigen. Der Pin-Gruppenknoten definiert die Pin-Funktion und die Einstellungen für jeden relevanten Pin. Wenn Sie mehr über die Details für jeden SoC erfahren möchten, finden Sie die Dokumentation im Kernel-Quellbaum unter „Documentation/devicetree/bindings/pinctrl/“.