Friday, April 26, 2024

pinctrl in device tree

An example where we configure imx8mp GPIO1_IO15 (B5) to use as a PWM output.

Can configure it in several ways in the device-tree.

option 1

&pwm4 {
    status = "okay";
};


&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&..>, <&pinctrl_pwm4>; /* pinctrl_pwm4 and others */
    pinctrl_pwm4: pwm4grp {
        fsl,pins = <
            MX8MP_IOMUXC_GPIO1_IO15__PWM4_OUT          0x00000006
        >;
    };
};


option 2

&pwm4 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm4>;
    status = "okay";
};


&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&..>;          /* other pinctrls but no pinctrl_pwm4 */
    pinctrl_pwm4: pwm4grp {
        fsl,pins = <
            MX8MP_IOMUXC_GPIO1_IO15__PWM4_OUT          0x00000006
        >;
    };
};


Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml tells us how to interpret the pinmux settings we are seeing in the device-tree

fsl,pins:
description:
  each entry consists of 6 integers and represents the mux and config
  setting for one pin. The first 5 integers <mux_reg conf_reg input_reg
  mux_val input_val> are specified using a PIN_FUNC_ID macro, which can
  be found in <arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h>. The last
  integer CONFIG is the pad setting value like pull-up on this pin. Please
  refer to i.MX8M Plus Reference Manual for detailed CONFIG settings.
$ref: /schemas/types.yaml#/definitions/uint32-matrix
items:
  items:
    - description: |
        "mux_reg" indicates the offset of mux register.
    - description: |
        "conf_reg" indicates the offset of pad configuration register.
    - description: |
        "input_reg" indicates the offset of select input register.
    - description: |
        "mux_val" indicates the mux value to be applied.
    - description: |
        "input_val" indicates the select input value to be applied.
    - description: |
        "pad_setting" indicates the pad configuration value to be applied..


From arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h


                      pad/pin     functionality we want to
                      in imx8mp   assign to the pad
                     |--------|  |---------|
#define MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15    0x050 0x2B0 0x000 0x0 0x0
#define MX8MP_IOMUXC_GPIO1_IO15__USB2_OC       0x050 0x2B0 0x000 0x1 0x0
#define MX8MP_IOMUXC_GPIO1_IO15__USDHC3_WP     0x050 0x2B0 0x634 0x4 0x0
#define MX8MP_IOMUXC_GPIO1_IO15__PWM4_OUT      0x050 0x2B0 0x000 0x5 0x0
#define MX8MP_IOMUXC_GPIO1_IO15__CCM_CLKO2     0x050 0x2B0 0x000 0x6 0x0


pin-mux from the imx8mp reference manual


instance    port            pad             mode

CCM         CCM_CLKO2       GPIO1_IO15      ALT6
GPIO1       GPIO1_IO15      GPIO1_IO15      ALT0
PWM4        PWM4_OUT        GPIO1_IO15      ALT5
USB2        USB2_OC         GPIO1_IO15      ALT1
USDHC3      USDHC3_WP       GPIO1_IO15      ALT4


From the imx8mp reference manual, we see mux_reg and conf_reg registers of iomuxc are


32-bit MUX Control Register IOMUXC_SW_MUX_CTL_PAD_x to configure ALT mode (MUX MODE)
32-bit PAD Control Register IOMUXC_SW_PAD_CTL_PAD_x to configure pad settings


For our GPIO1_IO15


SW_MUX_CTL_PAD_GPIO1_IO15 SW MUX Control Register
(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO15)
Address: 3033_0000h base + 50h offset = 3033_0050h


31 .... 5   4       3      2   1  0
[reserved][SION][reserved][mux mode]


mux_val: IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO15[2:0] = 101 -  ALT5_PWM4_OUT


SW_PAD_CTL_PAD_GPIO1_IO15 SW PAD Control Register
(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO15)
Address: 3033_0000h base + 2B0h offset = 3033_02B0h


31 .... 9  8    7    6    5    4      3      2..1    0
[reserved][PE][HYS][PUE][ODE][FSEL][reserved][DSE][reserved]


pad_setting = 0x00000006 : sets the drive strength

where

PE  : pull resistors enable/disable
HYS : cmos/schmitt
PUE : pull up/down config
ODE : open drain enable/disable
FSEL: slew rate slow/fast
DSE : drive strength


Other than linux kernel documentation, some good documentation on pin setting can be found in 

AN5078: Influence of Pin Setting on System Function and Performance


No comments: