Разработка встраиваемых систем Linux | подсистема pinctrl

Обзор

Как мы все знаем, каждая SoC имеет много контактов.Помимо контактов со специальными функциями, такими как питание, заземление и т. д., другие контакты обычно «играют несколько ролей». Например, контакт можно использовать в качестве GPIO. , также может использоваться как TX UART или MOSI SPI; более того, эти контакты часто имеют разные возможности, такие как подтягивание, понижение, различные возможности управления и т. д.

Подсистема pinctrl предназначена для выполнения вышеперечисленных функций.Pinctrl управляет всеми выводами SoC вниз и предоставляет интерфейсы для настройки всех контактов SoC вверх. Обычно при портировании системы Linux на новую SoC одной из задач является регистрация всех пинов в подсистеме pinctrl и предоставление соответствующих интерфейсов для настройки этих пинов.

Расположение подсистемы pinctrl в ядре Linux . В этой статье в основном представлены базовые настройки и использование pinctrl. Если вы хотите узнать больше о pinctrl, обратитесь к наиболее авторитетной документации ядра, в которой рассказывается о подсистеме pinctrl в ядре 5.18. Введение . Вы можете обратиться к статьям, которые я написал ранее .

эффект

Подсистема pinctrl, являющаяся важной частью встроенного Linux, обычно выполняет следующие функции:

  1. Перечислите и назовите все контакты SoC;
  2. Функция управления группой контактов; для некоторых интерфейсов, таких как spi или i2c, обычно требуется совместное использование нескольких контактов, а для одного и того же периферийного контроллера может быть несколько групп контактов. Например, комбинация контактов контроллера i2c0 может быть {21, 22} или {31, 32}. Подсистема pinctrl должна иметь возможность управлять этими группами контактов.
  3. Обеспечить конфигурацию мультиплексирования контактов;
  4. Предоставляет интерфейсы для настройки специальных возможностей выводов, таких как подтягивание, понижение, двухтактный выход, выход с открытым стоком, настройка возможностей управления нагрузкой и т. д.

Pinctrl будет управлять всеми контактами с точки зрения глобальной системы и предоставлять услуги взаимоисключающего доступа к контактам.То есть каждый контакт может использоваться только одним потребителем одновременно и может быть настроен только для одной функции.

При разработке драйверов он может быть размером с чип сетевой карты с более чем десятью линиями управляющего сигнала или всего лишь с одним светодиодом или кнопкой GPIO. Помните, что первое, что нужно сделать, это настроить функцию мультиплексирования и функцию контакты, используемые периферийными устройствами.Характеристики ввода-вывода. Например, если мы используем вывод для управления светодиодом, нам потребуется следующая конфигурация:

  1. Вывод мультиплексирован как GPIO.
  2. IO — режим вывода.
  3. На основе фактической аппаратной схемы определите, включены ли подтягивание и понижение напряжения, а также необходимые возможности управления.

Архитектура

Вставьте сюда описание изображения
Диаграмма архитектуры подсистемы pinctrl показывает, что она предоставляет два набора интерфейсов:

  1. Далее он обеспечивает интерфейс определения контактов и регистрации методов управления для различных аппаратных платформ.
  2. С другой стороны, он предоставляет интерфейсы для различных драйверов для управления выводами, такие как базовый интерфейс управления GPIO, подсистема GPIO и интерфейс взаимодействия подсистемы pinctrl.

интерфейс верхнего уровня

  • Определите аппаратное обеспечение pinctrl . Фактически аппаратное обеспечение pinctrl представляет собой регистр памяти. Эти регистры могут настраивать контакты для выполнения таких задач, как мультиплексирование (мультиплексирование), настройка повышения/понижения (смещение), нагрузочная способность (грузоподъемность), возможности привода и т. д. .
  • Определите все контакты , подушечки, пальцы и шарики SoC, чтобы они имели одинаковое значение, указывая на определенный вывод. Контакты, управляемые каждым аппаратным обеспечением pinctrl, принадлежат к одному и тому же пространству имен, а диапазон составляет 0 ~ maxpins. Те, которые будут пропущены, будут пропущены. штыря не существует, поэтому это пространство может быть прерывистым.

Когда каждое оборудование pinctrl инициализируется, оно регистрирует дескрипторы всех выводов, задействованных в структуре pinctrl. Вот пример SoC в корпусе PGA (Pin Grid Array).Все контакты SoC расположены следующим образом:

		A   B   C   D   E   F   G   H

   8    o   o   o   o   o   o   o   o

   7    o   o   o   o   o   o   o   o

   6    o   o   o   o   o   o   o   o

   5    o   o   o   o   o   o   o   o

   4    o   o   o   o   o   o   o   o

   3    o   o   o   o   o   o   o   o

   2    o   o   o   o   o   o   o   o

   1    o   o   o   o   o   o   o   o

Следующий код перечисляет все контакты в приведенном выше SoC. Макрос PINCTRL_PIN используется для определения номера и имени каждого контакта. Номер уникален для системы.
Примечание. Если взять приведенный выше SoC в качестве примера, порядок определения контактов здесь от 0 до 63. Этот порядок не уникален. Это зависит от нескольких аспектов: 1) расположение аппаратного регистра pingctrl; 2) простота ли он для сопоставления с номером GPIO;

#include <linux/pinctrl/pinctrl.h>

	const struct pinctrl_pin_desc foo_pins[] = {
    
    
		PINCTRL_PIN(0, "A8"),
		PINCTRL_PIN(1, "B8"),
		PINCTRL_PIN(2, "C8"),
		...
		PINCTRL_PIN(61, "F1"),
		PINCTRL_PIN(62, "G1"),
		PINCTRL_PIN(63, "H1"),
	};

	static struct pinctrl_desc foo_desc = {
    
    
		.name = "foo",
		.pins = foo_pins,
		.npins = ARRAY_SIZE(foo_pins),
		.owner = THIS_MODULE,
	};

	int __init foo_probe(void)
	{
    
    
		int error;

		struct pinctrl_dev *pctl;

		error = pinctrl_register_and_init(&foo_desc, <PARENT>,
						  NULL, &pctl);
		if (error)
			return error;

		return pinctrl_enable(pctl);
	}

Связь между подсистемой GPIO и подсистемой pinctrl

Подсистема GPIO управляет работой оборудования, что в конечном итоге реализуется через pinctrl. Однако обе системы имеют свои собственные пространства имен. Например, подсистема GPIO делит выводы по блокам, аналогично блоку A, блоку B и т. д., тогда как подсистема pinctrl определяется последовательно в соответствии с серийным номером выводов SoC. индексы двух системных выводов не соответствуют один к одному, что требует карты для сопоставления. Например, следующий код:

	struct gpio_chip chip_a;
	struct gpio_chip chip_b;

	static struct pinctrl_gpio_range gpio_range_a = {
    
    
		.name = "chip a",
		.id = 0,
		.base = 32,
		.pin_base = 32,
		.npins = 16,
		.gc = &chip_a;
	};

	static struct pinctrl_gpio_range gpio_range_b = {
    
    
		.name = "chip b",
		.id = 0,
		.base = 48,
		.pin_base = 64,
		.npins = 8,
		.gc = &chip_b;
	};

	{
    
    
		struct pinctrl_dev *pctl;
		...
		pinctrl_add_gpio_range(pctl, &gpio_range_a);
		pinctrl_add_gpio_range(pctl, &gpio_range_b);
	}
  • чип_а и чип_b — два блока подсистемы GPIO;
  • Структура pinctrl_gpio_range используется для определения отношений отображения между двумя выводами подсистемы;
  • base представляет собой начальный серийный номер контакта в определенном блоке, pin_base представляет его начальный серийный номер в подсистеме pinctrl, а bpins представляет количество контактов в блоке;

Ниже приводится взаимосвязь сопоставления выводов между двумя подсистемами:

chip a:
 - GPIO range : [32 .. 47]
 - pin range  : [32 .. 47]
chip b:
 - GPIO range : [48 .. 55]
 - pin range  : [64 .. 71]

Обратите внимание , что в приведенном выше представлении контакты в двух подсистемах отображаются линейно. Что, если это нелинейно или случайно? Пожалуйста, посмотрите на код ниже:

static const unsigned range_pins[] = {
    
     14, 1, 22, 17, 10, 8, 6, 2 };

	static struct pinctrl_gpio_range gpio_range = {
    
    
		.name = "chip",
		.id = 0,
		.base = 32,
		.pins = &range_pins,
		.npins = ARRAY_SIZE(range_pins),
		.gc = &chip;
	};

Обратите внимание , что для линейного сопоставления вместо pin_base используются выводы, а выводы в range_pins являются случайными.

**Вывод:** Будь то линейное или случайное сопоставление, обратите внимание, что для одного и того же вывода номер в двух системах, скорее всего, будет разным!

Когда подсистема GPIO управляет определенным контактом, она преобразует его в номер контакта в pinctrl посредством сопоставления между двумя системными контактами, тем самым управляя аппаратным обеспечением.

Конфигурация DTS

Пример

Guess you like

Origin blog.csdn.net/linux_embedded/article/details/124830867