[Conceptos básicos de Linux] - El sistema GPIO en el kernel de Linux (2): subsistema de control de pines

1. Diagrama del marco de software del subsistema de control de pines

1. Resumen de funciones e interfaces

En términos generales, aprender componentes de software complejos o módulos de software es un proceso doloroso. Podemos considerar el bloque de software que queremos aprender como una caja negra, por muy complicado que sea, el primer paso es siempre comprender sus funciones y características de la interfaz externa. Si lo desea, puede ignorar su implementación interna, primero piense en su lógica interna y formule una serie de preguntas, y luego tome estas preguntas para ver el código, que a menudo es más efectivo.

1), especificaciones funcionales

Las principales funciones del subsistema de control de pines incluyen:

a. Todos los pines que se pueden controlar en el sistema de gestión. Cuando se inicializa el sistema, se enumeran todos los pines que se pueden controlar y se identifican estos pines.

b) Gestionar la multiplexación de estos pines (Multiplexación). Para SOC, además de configurar sus pines como GPIO ordinario, varios pines también pueden formar un grupo de pines para formar una función específica. Por ejemplo, el número de pin es {0, 8, 16, 24} La combinación de estos cuatro pines forma un grupo de pines, que proporciona la función de SPI. El subsistema de control de pines debe administrar todos los grupos de pines.

c) Configure las características de estos pines. Por ejemplo, configure la resistencia pull-up / down en este pin, configure la fuerza de la unidad y así sucesivamente.

2), especificaciones de la interfaz

Un determinado componente de software del kernel de Linux debe volver a colocarse en el sistema Linux para explorar fácilmente su interfaz y su posición en el sistema. Por lo tanto, en la segunda sección de este capítulo, la descripción de cada subsistema de control de pines y otros módulos del kernel es basado en la interfaz del bloque del sistema.

3), lógica interna

Para estudiar el Roger interno de un subsistema, primero debe abrir la caja negra, subdividir los módulos y luego realizar el análisis funcional, el análisis de la interfaz externa y el análisis lógico interno para cada módulo. Si el módulo aún es relativamente grande y difícil de dominar, continúe subdividiendo, dividiendo en submódulos y repita el proceso de análisis anterior. En la tercera sección de este capítulo, abrimos la caja negra del subsistema de control de pines para un análisis más detallado.

2. La relación de la interfaz entre el subsistema de control de pines y otros módulos del kernel de Linux se muestra en la siguiente figura:

El subsistema de control de pines proporcionará interfaces a otros controladores en el sistema para establecer la configuración de pines y el mux de pines del controlador.Las interfaces de esta parte se describen en el Capítulo 4. El estado ideal es que el controlador de control GPIO solo interactúe con el subsistema de control de pines como controladores como UART y SPI. Sin embargo, de hecho, debido a varias razones (detalladas más adelante), el subsistema de control de pines y el subsistema GPIO deben interactuar. de la interfaz se describe en el Capítulo 5. El Capítulo 6 describe la interfaz entre el modelo de controlador y el subsistema de control de pines, y el Capítulo 7 describe la interfaz entre el árbol de dispositivos y el controlador de la máquina que proporciona soporte de base de datos para el subsistema de control de pines.

3 subs subsistema de control de pines 内部 diagrama de bloques

De hecho, después de comprender parte del contenido de la interfaz, es muy sencillo leer y analizar la lógica interna del subsistema de control de pines, por lo que este artículo no lo analizará.

2. Interfaz proporcionada por el subsistema de control de pines a otros controladores

Cuando se está preparando para escribir un controlador Linxu normal (como un controlador de puerto serie), ¿cómo espera que se vea la interfaz proporcionada por el subsistema de control de pines? Simple, por supuesto, lo mejor es simple, lo mejor es sin interfaz, por supuesto que esto es posible, consulte el sexto capítulo de la interfaz.

1. Información general

Los principales objetivos del subsistema de control de pin de llamada de controlador ordinario son:

1) Configure la función reutilización del dispositivo. Para configurar la reutilización de funciones del dispositivo, debe comprender dos conceptos, uno es función y el otro es grupo de pines. La función es una abstracción funcional, correspondiente a un bloque lógico HW, como SPI0. Aunque se proporciona un nombre de función específico, no estamos seguros de los pines utilizados. Por ejemplo: para flexibilidad de diseño, la función de SPI0 dentro del chip puede derivarse al grupo de clavijas {A8, A7, A6, A5}, o puede derivarse a otro grupo de clavijas {G4, G3, G2, G1}, pero hay No hay duda de que, estos dos grupos de pines no pueden estar activos al mismo tiempo, después de todo, solo puede haber un punto lógico de SPI0 dentro del chip. Por lo tanto, solo el selector de función (el llamado selector es un ID o índice) y el selector de grupo de pines de la función se pueden usar para configurar la función mux.

2) Establecer las características eléctricas de los pines correspondientes al dispositivo.

Además, debido a los requisitos de administración de energía, un dispositivo puede estar en un cierto estado de administración de energía, como inactivo o inactivo. En este momento, todos los pines que pertenecen al dispositivo deben estar en otro estado. Basándonos en los requisitos anteriores, hemos definido el concepto de estado de control de pines, lo que significa que el dispositivo puede estar en uno de muchos estados, y el controlador del dispositivo puede cambiar el estado del dispositivo. Para facilitar la gestión del estado de control de pines, hemos propuesto un concepto de titular de estado de control de pines para gestionar todos los estados de control de pines de un dispositivo. Por lo tanto, la interfaz del controlador ordinario para llamar al subsistema de control de pines lógicamente será principalmente:

(1) Obtenga el mango del titular de estado de control de pin

(2) Establecer estado de control de pines

(3) Suelte la manija del soporte de estado de control de pin

struct pinctrl {
    struct list_head node; //系统中的所有 device 的 pin control state holder 被挂入到了一个全局链表中
    struct device *dev; //该 pin control state holder 对应的 device
    struct list_head states; //该设备的所有的状态被挂入到这个链表中
    struct pinctrl_state *state; //当前的 pin control state
    struct list_head dt_maps; // mapping table
    struct kref users; //reference count
};

Todos los dispositivos del sistema que necesitan interactuar con el subsistema de control de pines deben obtener este identificador antes de configurarlo. Todos los estados que pertenecen al dispositivo están vinculados a una lista vinculada. El encabezado de la lista vinculada son los estados miembros del titular del estado de control de pines. La definición de un estado es la siguiente:

struct pinctrl_state {
    struct list_head node; //挂入链表头的节点
    const char *name; //该 state 的名字
    struct list_head settings; //属于该状态的所有的 setting
};

Un estado de pin contiene varias configuraciones, y todas las configuraciones se cuelgan en una lista vinculada. El encabezado de la lista vinculada es el miembro de configuración en el estado de pin, que se define de la siguiente manera:

struct pinctrl_setting {
    struct list_head node;
    enum pinctrl_map_type type;
    struct pinctrl_dev *pctldev;
    const char *dev_name;
    union {
        struct pinctrl_setting_mux mux;
        struct pinctrl_setting_configs configs;
    }data;
};

Cuando el controlador establece un estado de pin, el subsistema de control de pin recorrerá la lista enlazada de configuraciones del estado y establecerá las configuraciones una por una. Hay varios tipos de estas configuraciones, que se definen de la siguiente manera:

enum pinctrl_map_type {
    PIN_MAP_TYPE_INVALID,
    PIN_MAP_TYPE_DUMMY_STATE,
    PIN_MAP_TYPE_MUX_GROUP, //功能复用的 setting
    PIN_MAP_TYPE_CONFIGS_PIN, //设定单一一个 pin 的电气特性
    PIN_MAP_TYPE_CONFIGS_GROUP, //设定单 pin group 的电气特性
};

Hay configuraciones relacionadas con pin mux (PIN_MAP_TYPE_MUX_GROUP), definidas de la siguiente manera:

struct pinctrl_setting_mux {
    unsigned group; //该 setting 所对应的group selector
    unsigned func; //该 setting 所对应的 function selector
};

Con el selector de función y el selector de grupo perteneciente a la función, se pueden realizar los ajustes relacionados con el dispositivo y el pin mux. Los ajustes para configurar las características eléctricas se definen de la siguiente manera:

struct pinctrl_map_configs {
    const char *group_or_pin; //该pin或者pin group 的名字
    unsigned long *configs; //要设定的值的列表。这个值用来写入 HW
    unsigned num_configs; //列表中值的个数
};

2. Interfaz específica

1) devm_pinctrl_get 和 pinctrl_get

devm_pinctrl_get es la versión administrada por recursos de pinctrl_get, el núcleo es la función pinctrl_get. Ambas interfaces son para obtener el titular de estado de control de pin (struct pinctrl) del dispositivo (dispositivo struct en el modelo del dispositivo). El titular del estado de control de pin no está definido estáticamente y, por lo general, se crea dinámicamente cuando se llama a la función por primera vez. Crear un titular de estado de control de pin es un gran proyecto, analicemos este código:



    static struct pinctrl *create_pinctrl(struct device *dev)
    {

       分配pin control state holder占用的内存并初始化
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        p->dev = dev;
        INIT_LIST_HEAD(&p->states);
        INIT_LIST_HEAD(&p->dt_maps);

    mapping table这个database的建立也是动态的,当第一次调用pin control state holder的get函数的时候,就会通过调用pinctrl_dt_to_map来建立该device需要的mapping entry。具体请参考第七章。

        ret = pinctrl_dt_to_map(p);

        devname = dev_name(dev);

        mutex_lock(&pinctrl_maps_mutex);
        for_each_maps(maps_node, i, map) {
            /* Map must be for this device */
            if (strcmp(map->dev_name, devname))
                continue;

            ret = add_setting(p, map);----分析一个mapping entry,把这个setting的代码加入到holder中

        }
        mutex_unlock(&pinctrl_maps_mutex);

        kref_init(&p->users);

        /* 把这个新增加的pin control state holder加入到全局链表中 */
        mutex_lock(&pinctrl_list_mutex);
        list_add_tail(&p->node, &pinctrl_list);
        mutex_unlock(&pinctrl_list_mutex);

        return p;
    }

2) devm_pinctrl_put 和 pinctrl_put

Sí 1) La función inversa en la interfaz. Devm_pinctrl_get y pinctrl_get solicitan muchos recursos al obtener el identificador, que se puede liberar en devm_pinctrl_put y pinctrl_put. Cabe señalar que varias llamadas a la función get no asignarán soporte repetidamente, solo el recuento de referencias se incrementará en uno, y el recuento de referencias se reducirá en uno en el lugar, y todos los titulares de estado de control de pines del dispositivo lo harán ser liberado cuando cuenta == 0. Recursos.

3) pinctrl_lookup_state

Busque el estado de control de pin correspondiente en el titular de estado de control de pin de acuerdo con el nombre del estado. El estado específico lo define cada dispositivo, pero el subsistema de control de pines define algunos estados de control de pines estándar, que se definen en el archivo pinctrl-stat.h:

#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_IDLE "idle"
#define PINCTRL_STATE_SLEEP "sleep"

4) pinctrl_select_state

Establezca una interfaz de estado de control de pines específica.

Supongo que te gusta

Origin blog.csdn.net/u014674293/article/details/108869196
Recomendado
Clasificación