[Linux Basics] - The GPIO system in the Linux kernel (2): pin control subsystem

1. Software framework diagram of pin control subsystem

1. Overview of functions and interfaces

Generally speaking, learning complex software components or software modules is a painful process. We can regard the software block we want to learn as a black box. No matter how complicated it is, the first step is always to understand its functions and external interface characteristics. If you want, you can ignore its internal implementation, first think about its internal logic, and form a number of questions, and then take these questions to look at the code, which is often twice the result with half the effort.

1), functional specifications

The main functions of pin control subsystem include:

a. All the pins that can be controlled in the management system. When the system is initialized, all the pins that can be controlled are enumerated and these pins are identified.

b. Manage the multiplexing of these pins (Multiplexing). For SOC, in addition to configuring its pins as ordinary GPIO, several pins can also form a pin group to form a specific function. For example, the pin number is {0, 8, 16, 24}. The combination of these four pins forms a pin group, which provides the function of SPI. The pin control subsystem must manage all pin groups.

c. Configure the characteristics of these pins. For example, configure the pull-up/down resistance on this pin, configure the drive strength and so on.

2), interface specifications

A certain software component of the Linux kernel must be put back into the Linux system to easily explore its interface and its position in the system. Therefore, in the second section of this chapter, the description of each pin control subsystem and other kernel modules is based on the system block. interface.

3), internal logic

To study the internal Roger of a subsystem, you must first open the black box, subdivide the modules, and then perform functional analysis, external interface analysis, and internal logic analysis for each module. If the module is still relatively large and difficult to master, then continue to subdivide, split into sub-modules, and repeat the above analysis process. In the third section of this chapter, we open the black box of pin control subsystem for further analysis.

2. The interface relationship between pin control subsystem and other linux kernel modules is shown in the figure below:

The pin control subsystem will provide interfaces to other drivers in the system to set the pin config and pin mux of the driver. The interfaces of this part are described in Chapter 4. The ideal state is that the GPIO control driver only interacts with the pin control subsystem like drivers such as UART and SPI. However, due to various reasons (detailed later), the pin control subsystem and the GPIO subsystem must interact. Part of the interface is described in Chapter 5. Chapter 6 describes the interface between Driver model and pin control subsystem, and Chapter 7 describes the interface between Device Tree and Machine driver that provides database support for Pin control subsystem.

3、pin control subsystem 内部 block diagram

In fact, after understanding part of the content of the interface, it is very simple to read and analyze the internal logic of the pin control subsystem, so this article will not analyze it.

2. Interface provided by pin control subsystem to other drivers

When you are preparing to write an ordinary Linxu driver (such as a serial port driver), what do you expect the interface provided by the pin control subsystem to look like? Simple, of course the best is simple, the best is no interface, of course this is possible, please refer to Chapter 6 interface for details.

1 Overview

The main goals of ordinary driver calling pin control subsystem are:

1). Set the function reuse of the device. To set the function reuse of the device, you need to understand two concepts, one is function, and the other is pin group. function is a functional abstraction, corresponding to a HW logic block, such as SPI0. Although a specific function name is given, we are not sure about the pins used. For example: For design flexibility, the function of SPI0 inside the chip may be derived to pin group {A8, A7, A6, A5}, or may be derived to another pin group {G4, G3, G2, G1}, but there is no doubt that, These two pin groups cannot be active at the same time, after all, there can only be one logic point of SPI0 inside the chip. Therefore, only the function selector (the so-called selector is an ID or index) and the pin group selector of the function can be used to set the function mux.

2) Set the electrical characteristics of the pins corresponding to the device.

In addition, due to the requirements of power management, a certain device may be in a certain power management state, such as idle or sleep. At this time, all pins belonging to the device need to be in another state. Based on the above requirements, we have defined the concept of pin control state, which means that the device may be in one of many states, and the device driver can switch the state of the device. In order to facilitate the management of pin control state, we have proposed a concept of pin control state holder to manage all pin control states of a device. Therefore, the interface of the ordinary driver to call the pin control subsystem will logically mainly be:

(1) Get the handle of the pin control state holder

(2) Set pin control status

(3) Release the handle of the pin control state holder

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
};

Every device in the system that needs to interact with the pin control subsystem needs to obtain this handle before setting it up. All the states belonging to the device are linked to a linked list. The head of the linked list is the states member of the pin control state holder. The definition of a state is as follows:

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

A pin state contains several settings, and all settings are hung in a linked list. The head of the linked list is the settings member in the pin state, which is defined as follows:

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;
};

When the driver sets a pin state, the pin control subsystem will traverse the state's settings linked list and set the settings one by one. There are various types of these settings, which are defined as follows:

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 的电气特性
};

There are pin mux related settings (PIN_MAP_TYPE_MUX_GROUP), defined as follows:

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

With the function selector and the group selector belonging to the functiong, the device and pin mux related settings can be made. The settings for setting electrical characteristics are defined as follows:

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

2. Specific interface

1)devm_pinctrl_get 和 pinctrl_get

devm_pinctrl_get is the resource managed version of pinctrl_get, the core is pinctrl_get function. Both of these interfaces are to obtain the pin control state holder (struct pinctrl) of the device (struct device in the device model). The pin control state holder is not statically defined, and is usually created dynamically when the function is called for the first time. Creating a pin control state holder is a big project, let’s analyze this code:



    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

Yes 1) The inverse function in the interface. Devm_pinctrl_get and pinctrl_get apply for a lot of resources when obtaining the handle, which can be released in devm_pinctrl_put and pinctrl_put. It should be noted that calling the get function multiple times will not repeatedly allocate support, only the reference count will be increased by one, and the reference count in the put will be decreased by one. When count==0, all the pin control state holders of the device are released. Resources.

3)pinctrl_lookup_state

Find the corresponding pin control state in the pin control state holder according to the state name. The specific state is defined by each device itself, but the pin control subsystem defines some standard pin control states, which are defined in the pinctrl-stat.h file:

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

4)pinctrl_select_state

Set a specific pin control stae interface.

Guess you like

Origin blog.csdn.net/u014674293/article/details/108869196