Explicación detallada del marco del controlador del subsistema pinctrl del kernel de Linux

Tabla de contenido

1. Introducción

2 pinctrl en el árbol de dispositivos

2.1 nodo iomuxc

2.2 Cómo usar el controlador pinctrl en otros nodos

Flujo de código del controlador de 3 pines y estructuras de datos relacionadas

Proceso de código de cliente de 4 dispositivos y estructuras de datos relacionadas

5 preguntas relacionadas al leer el código fuente del kernel

6 Método de aprendizaje de Feynman: así que grabé un video que explica el subsistema pinctrl


1. Introducción

Independientemente de STM32 o IMX6ULL, si queremos usar un determinado pin para controlar el encendido y apagado de la luz LED, entonces, en términos generales, necesitamos configurar el pin como se muestra en la figura anterior. La función y las propiedades eléctricas del pin son configurado en el kernel de Linux: esto lo realiza el subsistema pinctrl. El subsistema pinctrl tiene tres funciones principales:

  • Función 1: Enumeración y denominación de pines.
  • Función 2: Multiplexación de pines (Multiplexación)
  • Función 3: Establecer propiedades eléctricas (Configuración)

Además, los fabricantes de chips han implementado el código relacionado con el subsistema pinctrl en el kernel de Linux. Los usuarios no necesitan escribir código, solo necesitan modificar el archivo del árbol de dispositivos. 

2 pinctrl en el árbol de dispositivos

Diferentes fabricantes tienen diferentes formatos de árbol de dispositivos pinctrl. Aquí tomamos la plataforma imx6ull como ejemplo. La siguiente lectura de código se basa en el código fuente del kernel Linux4.9.88 proporcionado por imx6ull como ejemplo para lectura y explicación.

2.1 nodo iomuxc

Primer vistazo al nodo iomuxc

iomuxc: iomuxc@020e0000 {
    compatible = "fsl,imx6ul-iomuxc";
    reg = <0x020e0000 0x4000>;
    imx6ul-evk {
        pinctrl_hog_1: hoggrp-1 {
			fsl,pins = <
				MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
				MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */
				MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
			>;
		};
        
        pinctrl_csi1: csi1grp {
			fsl,pins = <
				MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
				MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
                               ...没写全...
				MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
				MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
			>;
		};

        pinctrl_i2c1: i2c1grp {
			fsl,pins = <
				MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
				MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
			>;
		};
                    
    }
};

La información en fsl y pines es la dirección de compensación y el valor del registro, que se utiliza para configurar las propiedades eléctricas y de multiplexación de un determinado pin. Por ejemplo, tome

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* CD SD1 */

Entre ellos, MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 es una definición de macro,

#definir MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x0090 0x031c 0x0000 5 0

Si reemplaza la definición de macro, entonces MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */ es

0x0090 0x031c 0x0000 5 0 0x17059

Estos seis valores son

mux_reg conf_reg input_reg mux_mode input_val conf_reg 

En base a estos 6 valores, puede configurar las propiedades eléctricas y de multiplexación de un pin.

2.2 Cómo usar el controlador pinctrl en otros nodos

como i2c1

&i2c1 {     frecuencia de reloj = <100000>;     pinctrl-names = "predeterminado";     pinctrl-0 = <&pinctrl_i2c1>;     estado = "bien";



};

De esta forma, el nodo i2c1 utiliza la configuración de pines proporcionada por pinctrl.

En este punto, podemos terminar de hablar sobre el subsistema pinctrl, porque se puede usar. La siguiente explicación es para comprenderlo y luego leo el código fuente del kernel de Linux.

Flujo de código del controlador de 3 pines y estructuras de datos relacionadas

Dibujé directamente un diagrama para explicar el flujo de código y las estructuras de datos relacionadas del controlador de pin.

 Primero, el nodo iomuxc en el árbol de dispositivos se convertirá en un dispositivo_plataforma, y ​​luego, cuando coincida de acuerdo con compatible = "fsl,imx6ul-iomuxc", se llamará a la función imx6ul_pinctrl_probe. En esta función, pinctrl_info = (struct imx_pinctrl_soc_info *) Primero se saca match->data; esto en realidad es una enumeración de pines, y luego se llama a la función imx_pinctrl_probe(pdev, pinctrl_info);. Se asigna una estructura pinctrl_desc en esta función.

    imx_pinctrl_desc->nombre = dev_name(&pdev->dev);

    imx_pinctrl_desc->pins = información->pins;

    imx_pinctrl_desc->npins = información->npins;

    imx_pinctrl_desc->pctlops = &imx_pctrl_ops;

    imx_pinctrl_desc->pmxops = &imx_pmx_ops;

    imx_pinctrl_desc->confops = &imx_pinconf_ops;

    imx_pinctrl_desc->propietario = ESTE_MODULE;

Luego, esta estructura contiene pines y algunas funciones de operación, y luego llama a imx_pinctrl_probe_dt(pdev, info); aquí se analiza el árbol de dispositivos para obtener esas direcciones de registro y valores de registro. Luego llame a la función ipctl->pctl = devm_pinctrl_register(&pdev->dev, imx_pinctrl_desc, ipctl);. Esta función construye una estructura struct pinctrl_dev *pctldev;. Esta estructura struct pinctrl_dev *pctldev; contiene pines y funciones de operación. , así como toda la información, como valores de registro y direcciones de registro.

Proceso de código de cliente de 4 dispositivos y estructuras de datos relacionadas

Primero, echemos un vistazo a la estructura de datos del dispositivo cliente y dibujé un diagrama para representarla.

Luego, echemos un vistazo al código fuente del kernel de Linux y veamos el proceso de construcción de las estructuras de datos anteriores. También hice un dibujo directamente.

 5 preguntas relacionadas al leer el código fuente del kernel

 ¡Hola! Su comprensión es correcta. En este código platform_set_drvdata(pdev, ipctl); se llama  platform_set_drvdata a una función  que estará  asociada ipctl al dispositivo de la plataforma  . pdevDe esta manera, cuando necesites acceder a los datos privados del dispositivo en el controlador del dispositivo, puedes usar  platform_get_drvdata la función para obtenerlos  ipctl.

ipctl Es un  imx_pinctrl puntero a una estructura que contiene información de registro de PIN analizada desde el árbol de dispositivos. Esta información se almacena en  ipctl->info->pin_regs una matriz y cada elemento es una  imx_pin_reg estructura que representa la información de registro de un pin.

Por lo tanto, en este código, la información del registro PIN analizada del árbol de dispositivos se guarda en formato  pdev->dev.driver_data . ¡Espero que esta información sea útil!

6 Método de aprendizaje de Feynman: así que grabé un video que explica el subsistema pinctrl

Una explicación de 15 minutos del subsistema pinctrl del kernel de Linux_bilibili_bilibili 

Supongo que te gusta

Origin blog.csdn.net/u013171226/article/details/132431972
Recomendado
Clasificación