подсистема pinctrl

Что такое подсистема pinctrl?

Подсистема pinctrl (управление контактами) — это подсистема в ядре Linux, которая управляет контактами в системе и предоставляет общий API управления контактами для драйверов устройств. Эта подсистема позволяет драйверам устройств настраивать и контролировать нужные им выводы, не заботясь о конкретной реализации базового оборудования.
Фреймворк для подсистемы pinctrl

Каркас подсистемы pinctrl в основном состоит из следующих частей:

пинктрл ядро

Ядро pinctrl — это основная часть подсистемы pinctrl, которая обеспечивает следующие функции:

管理和维护系统上的引脚和 pinctrl 配置;
提供通用的 pinctrl 接口供设备驱动程序使用;
管理设备驱动程序之间的引脚冲突和资源共享。

пинктрл драйвер

  1. Драйвер pinctrl — это драйвер ядра Linux для управления выводами чипа. Он регистрируется в ядре pinctrl, реализуя интерфейс, предоставляемый ядром pinctrl, и обеспечивает функции настройки и управления выводами микросхемы.
    сопоставитель pinctrl*

  2. Преобразователь pinctrl — это модуль, который сопоставляет конфигурации pinctrl с конкретными выводами микросхемы. Он отвечает за синтаксический анализ конфигурации pinctrl, сопоставление с определенным выводом и передачу результата сопоставления драйверу pinctrl. Преобразователь pinctrl можно настроить для различных архитектур чипов и расположения выводов чипа.
    основной API pinctrl

  3. API ядра pinctrl — это общий интерфейс, предоставляемый подсистемой pinctrl драйверам устройств, который включает следующие основные функции:

    pinctrl_register_mappings(): используется для регистрации преобразователя pinctrl в подсистеме pinctrl;
    pinctrl_register(): используется для регистрации драйвера pinctrl в подсистеме pinctrl;
    pinctrl_lookup_state(): используется для поиска и возврата состояния конфигурации pinctrl с указанным именем;
    pinctrl_select_state (): используется для выбора указанного состояния конфигурации pinctrl;
    pinctrl_force_sleep_state(): используется для перевода указанного контакта в спящий режим;
    pinctrl_request(): используется для запроса права на использование одного или нескольких контактов;
    pinctrl_free(): используется для освобождения права использовать один или несколько контактов.

Применение подсистемы pinctrl

Подсистема pinctrl широко используется во встроенных устройствах и встроенных системах, таких как:

  1. Во встроенных системах подсистема pinctrl часто используется для настройки выводов для различных периферийных устройств, таких как GPIO, SPI, I2C и т. д.
    Например, в Raspberry Pi подсистема pinctrl используется для настройки контактов, используемых для управления различными периферийными устройствами, такими как I2C, SPI, UART и GPIO.

  2. На макетной плате также широко используется подсистема pinctrl. Например, многие поставщики SoC предоставляют драйверы pinctrl и преобразователи для своих микросхем для использования разработчиками. Это позволяет разработчикам легко настраивать контакты и управлять ими для различных приложений.

  3. При разработке ядра подсистема pinctrl также является очень важной подсистемой. Многим драйверам устройств требуется интерфейс pinctrl для настройки и управления выводами. Поэтому разработчикам ядра очень полезно понять принцип и использование подсистемы pinctrl.

Подведем итог

Подсистема pinctrl — это подсистема ядра Linux, которая управляет выводами в системе. Это позволяет драйверам устройств быть независимыми от конкретной реализации базового оборудования, предоставляя общий API управления контактами. Подсистема pinctrl состоит из ядра pinctrl, драйвера pinctrl, преобразователя pinctrl и API-интерфейса ядра pinctrl. Подсистема pinctrl широко используется во встроенных устройствах и встроенных системах и играет важную роль в разработке ядра.

рутина

Ниже приведен простой драйвер pinctrl для настройки выводов GPIO. В функции probe() сначала получите устройство pinctrl, затем найдите и примените состояние конфигурации GPIO. Наконец, подайте заявку на контакты GPIO и примените конфигурацию pinctrl. В функции remove() освободите контакт GPIO.

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/gpio.h>

static struct pinctrl *pinctrl;
static struct pinctrl_state *pinctrl_state;

static int gpio_pin = 4;

static int pinctrl_gpio_probe(struct platform_device *pdev)
{
    
    
    int ret;

    // 获取 pinctrl 设备
    pinctrl = devm_pinctrl_get(&pdev->dev);
    if (IS_ERR(pinctrl)) {
    
    
        dev_err(&pdev->dev, "failed to get pinctrl\n");
        return PTR_ERR(pinctrl);
    }

    // 配置引脚用于控制 GPIO
    pinctrl_state = pinctrl_lookup_state(pinctrl, "gpio");
    if (IS_ERR(pinctrl_state)) {
    
    
        dev_err(&pdev->dev, "failed to lookup gpio state\n");
        return PTR_ERR(pinctrl_state);
    }

    // 配置 GPIO 引脚
    ret = gpio_request(gpio_pin, "example");
    if (ret < 0) {
    
    
        dev_err(&pdev->dev, "failed to request gpio pin\n");
        return ret;
    }

    // 应用 pinctrl 配置
    ret = pinctrl_select_state(pinctrl, pinctrl_state);
    if (ret < 0) {
    
    
        dev_err(&pdev->dev, "failed to select pinctrl state\n");
        return ret;
    }

    return 0;
}

static int pinctrl_gpio_remove(struct platform_device *pdev)
{
    
    
    // 释放 GPIO 引脚
    gpio_free(gpio_pin);

    return 0;
}

static const struct of_device_id pinctrl_gpio_match[] = {
    
    
    {
    
     .compatible = "example,pinctrl-gpio" },
    {
    
    },
};
MODULE_DEVICE_TABLE(of, pinctrl_gpio_match);

static struct platform_driver pinctrl_gpio_driver = {
    
    
    .probe = pinctrl_gpio_probe,
    .remove = pinctrl_gpio_remove,
    .driver = {
    
    
        .name = "pinctrl-gpio",
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr(pinctrl_gpio_match),
    },
};

module_platform_driver(pinctrl_gpio_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example");
MODULE_DESCRIPTION("Example pinctrl gpio driver");

Ниже приведен пример кода дерева устройств для подсистемы pinctrl:

pinctrl-gpio {
    
    
    compatible = "example,pinctrl-gpio";
    gpio = <&gpio4 0>;
    pinctrl-0 = <&gpio_pinmux>;
};

gpio_pinmux: gpio_pinmux {
    
    
    pinctrl-single,pins = <
        0x10 0x7   /* GPIO4_IO00 */
    >;
};

В дереве устройств узел pinctrl-gpio определяет подсистему pinctrl и указывает состояние конфигурации контактов GPIO (ссылка на атрибут pinctrl-0). Узел gpio_pinmux определяет сопоставление выводов (определено в атрибуте pinctrl-single, pins), здесь указан вывод GPIO4_IO00.

Обратите внимание, что состояние конфигурации pinctrl в дереве устройств и драйвер pinctrl должны совпадать. В этом примере имя состояния конфигурации, указанное в узле pinctrl-gpio, — «gpio», и состояние, которое просматривается и применяется в функции pinctrl_gpio_probe(), — также «gpio».

Ниже приведен пример Makefile для подсистемы pinctrl:

obj-m += pinctrl-gpio.o

KDIR ?= /lib/modules/$(shell uname -r)/build

all:
    make -C $(KDIR) M=$(PWD) modules

clean:
    make -C $(KDIR) M=$(PWD) clean

В Makefile мы определяем модуль ядра pinctrl-gpio.o для компиляции и определяем расположение исходного кода ядра. В цели all мы используем команду make для компиляции модулей. В чистой цели мы используем команду make для очистки скомпилированных файлов.

Guess you like

Origin blog.csdn.net/qq_31057589/article/details/130280666