Что такое подсистема pinctrl?
Подсистема pinctrl (управление контактами) — это подсистема в ядре Linux, которая управляет контактами в системе и предоставляет общий API управления контактами для драйверов устройств. Эта подсистема позволяет драйверам устройств настраивать и контролировать нужные им выводы, не заботясь о конкретной реализации базового оборудования.
Фреймворк для подсистемы pinctrl
Каркас подсистемы pinctrl в основном состоит из следующих частей:
пинктрл ядро
Ядро pinctrl — это основная часть подсистемы pinctrl, которая обеспечивает следующие функции:
管理和维护系统上的引脚和 pinctrl 配置;
提供通用的 pinctrl 接口供设备驱动程序使用;
管理设备驱动程序之间的引脚冲突和资源共享。
пинктрл драйвер
-
Драйвер pinctrl — это драйвер ядра Linux для управления выводами чипа. Он регистрируется в ядре pinctrl, реализуя интерфейс, предоставляемый ядром pinctrl, и обеспечивает функции настройки и управления выводами микросхемы.
сопоставитель pinctrl* -
Преобразователь pinctrl — это модуль, который сопоставляет конфигурации pinctrl с конкретными выводами микросхемы. Он отвечает за синтаксический анализ конфигурации pinctrl, сопоставление с определенным выводом и передачу результата сопоставления драйверу pinctrl. Преобразователь pinctrl можно настроить для различных архитектур чипов и расположения выводов чипа.
основной API pinctrl -
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 широко используется во встроенных устройствах и встроенных системах, таких как:
-
Во встроенных системах подсистема pinctrl часто используется для настройки выводов для различных периферийных устройств, таких как GPIO, SPI, I2C и т. д.
Например, в Raspberry Pi подсистема pinctrl используется для настройки контактов, используемых для управления различными периферийными устройствами, такими как I2C, SPI, UART и GPIO. -
На макетной плате также широко используется подсистема pinctrl. Например, многие поставщики SoC предоставляют драйверы pinctrl и преобразователи для своих микросхем для использования разработчиками. Это позволяет разработчикам легко настраивать контакты и управлять ими для различных приложений.
-
При разработке ядра подсистема 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 для очистки скомпилированных файлов.