【Linux 驱动基础】pinctrl与gpio子系统

发布于:2024-04-16 ⋅ 阅读:(21) ⋅ 点赞:(0)

# 前置知识

Pinctrl子系统

功能

    (1)管理系统中所有的可以控制的pin,在系统初始化的时候,枚举所有可以控制的pin,并标识这些pin。

    (2)管理这些pin的复用(Multiplexing)。对于SOC而言,其引脚除了配置成普通的GPIO之外,若干个引脚还可以组成一个pin group,行程特定的功能。pin control subsystem要管理所有的pin group。

    (3)配置这些pin的特性。例如使能或关闭引脚上的pull-up、pull-down电阻,配置引脚的driver strength。

文档

== Introduction ==

Hardware modules that control pin multiplexing or configuration parameters
such as pull-up/down, tri-state, drive-strength etc are designated as pin
controllers. Each pin controller must be represented as a node in device tree,
just like any other hardware module.

Hardware modules whose signals are affected by pin configuration are
designated client devices. Again, each client device must be represented as a
node in device tree, just like any other hardware module.

For a client device to operate correctly, certain pin controllers must
set up certain specific pin configurations. Some client devices need a
single static pin configuration, e.g. set up during initialization. Others
need to reconfigure pins at run-time, for example to tri-state pins when the
device is inactive. Hence, each client device can define a set of named
states. The number and names of those states is defined by the client device's
own binding.

The common pinctrl bindings defined in this file provide an infrastructure
for client device device tree nodes to map those state names to the pin
configuration used by those states.

Note that pin controllers themselves may also be client devices of themselves.
For example, a pin controller may set up its own "active" state when the
driver loads. This would allow representing a board's static pin configuration
in a single place, rather than splitting it across multiple client device
nodes. The decision to do this or not somewhat rests with the author of
individual board device tree files, and any requirements imposed by the
bindings for the individual client devices in use by that board, i.e. whether
they require certain specific named states for dynamic pin configuration.

== Pinctrl client devices ==

For each client device individually, every pin state is assigned an integer
ID. These numbers start at 0, and are contiguous. For each state ID, a unique
property exists to define the pin configuration. Each state may also be
assigned a name. When names are used, another property exists to map from
those names to the integer IDs.

Each client device's own binding determines the set of states that must be
defined in its device tree node, and whether to define the set of state
IDs that must be provided, or whether to define the set of state names that
must be provided.

Required properties:
pinctrl-0:	List of phandles, each pointing at a pin configuration
		node. These referenced pin configuration nodes must be child
		nodes of the pin controller that they configure. Multiple
		entries may exist in this list so that multiple pin
		controllers may be configured, or so that a state may be built
		from multiple nodes for a single pin controller, each
		contributing part of the overall configuration. See the next
		section of this document for details of the format of these
		pin configuration nodes.

		In some cases, it may be useful to define a state, but for it
		to be empty. This may be required when a common IP block is
		used in an SoC either without a pin controller, or where the
		pin controller does not affect the HW module in question. If
		the binding for that IP block requires certain pin states to
		exist, they must still be defined, but may be left empty.

Optional properties:
pinctrl-1:	List of phandles, each pointing at a pin configuration
		node within a pin controller.
...
pinctrl-n:	List of phandles, each pointing at a pin configuration
		node within a pin controller.
pinctrl-names:	The list of names to assign states. List entry 0 defines the
		name for integer state ID 0, list entry 1 for state ID 1, and
		so on.

pinctrl-assert-gpios:
		List of phandles, each pointing at a GPIO which is used by some
		board design to steer pins between two peripherals on the board.
		It plays like a board level pin multiplexer to choose different
		functions for given pins by pulling up/down the GPIOs.  See
		bindings/gpio/gpio.txt for details of how to specify GPIO.

For example:

	/* For a client device requiring named states */
	device {
		pinctrl-names = "active", "idle";
		pinctrl-0 = <&state_0_node_a>;
		pinctrl-1 = <&state_1_node_a &state_1_node_b>;
	};

	/* For the same device if using state IDs */
	device {
		pinctrl-0 = <&state_0_node_a>;
		pinctrl-1 = <&state_1_node_a &state_1_node_b>;
	};

	/*
	 * For an IP block whose binding supports pin configuration,
	 * but in use on an SoC that doesn't have any pin control hardware
	 */
	device {
		pinctrl-names = "active", "idle";
		pinctrl-0 = <>;
		pinctrl-1 = <>;
	};

== Pin controller devices ==

Pin controller devices should contain the pin configuration nodes that client
devices reference.

For example:

	pincontroller {
		... /* Standard DT properties for the device itself elided */

		state_0_node_a {
			...
		};
		state_1_node_a {
			...
		};
		state_1_node_b {
			...
		};
	}

The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
exists no common standard for this content.

The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
whether there is any interaction between the child and intermediate parent
nodes, is again defined entirely by the binding for the individual pin
controller device.

== Generic pin multiplexing node content ==

pin multiplexing nodes:

function		- the mux function to select
groups			- the list of groups to select with this function
			  (either this or "pins" must be specified)
pins			- the list of pins to select with this function (either
			  this or "groups" must be specified)

Example:

state_0_node_a {
	uart0 {
		function = "uart0";
		groups = "u0rxtx", "u0rtscts";
	};
};
state_1_node_a {
	spi0 {
		function = "spi0";
		groups = "spi0pins";
	};
};
state_2_node_a {
	function = "i2c0";
	pins = "mfio29", "mfio30";
};

== Generic pin configuration node content ==

Many data items that are represented in a pin configuration node are common
and generic. Pin control bindings should use the properties defined below
where they are applicable; not all of these properties are relevant or useful
for all hardware or binding structures. Each individual binding document
should state which of these generic properties, if any, are used, and the
structure of the DT nodes that contain these properties.

Supported generic properties are:

pins			- the list of pins that properties in the node
			  apply to (either this or "group" has to be
			  specified)
group			- the group to apply the properties to, if the driver
			  supports configuration of whole groups rather than
			  individual pins (either this or "pins" has to be
			  specified)
bias-disable		- disable any pin bias
bias-high-impedance	- high impedance mode ("third-state", "floating")
bias-bus-hold		- latch weakly
bias-pull-up		- pull up the pin
bias-pull-down		- pull down the pin
bias-pull-pin-default	- use pin-default pull state
drive-push-pull		- drive actively high and low
drive-open-drain	- drive with open drain
drive-open-source	- drive with open source
drive-strength		- sink or source at most X mA
input-enable		- enable input on pin (no effect on output)
input-disable		- disable input on pin (no effect on output)
input-schmitt-enable	- enable schmitt-trigger mode
input-schmitt-disable	- disable schmitt-trigger mode
input-debounce		- debounce mode with debound time X
power-source		- select between different power supplies
low-power-enable	- enable low power mode
low-power-disable	- disable low power mode
output-low		- set the pin to output mode with low level
output-high		- set the pin to output mode with high level
slew-rate		- set the slew rate

For example:

state_0_node_a {
	cts_rxd {
		pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
		bias-pull-up;
	};
};
state_1_node_a {
	rts_txd {
		pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
		output-high;
	};
};
state_2_node_a {
	foo {
		group = "foo-group";
		bias-pull-up;
	};
};

Some of the generic properties take arguments. For those that do, the
arguments are described below.

- pins takes a list of pin names or IDs as a required argument. The specific
  binding for the hardware defines:
  - Whether the entries are integers or strings, and their meaning.

- bias-pull-up, -down and -pin-default take as optional argument on hardware
  supporting it the pull strength in Ohm. bias-disable will disable the pull.

- drive-strength takes as argument the target strength in mA.

- input-debounce takes the debounce time in usec as argument
  or 0 to disable debouncing

More in-depth documentation on these parameters can be found in
<include/linux/pinctrl/pinconf-generic.h>

简要说明

pin controller devices 与 client device devices :

pin controller devices :

        pin controller devices 主要应该包含客户端的引脚配置,电气属性等,可以认为等于IMX芯片的 IOMUX功能──用来复用引脚,还可以配置引脚(比如上下拉电阻等)

        如下,pinctrl_gpio_keys中包含了GPIO的引脚复用和电气属性

client device devices:

        client device devices 就是 pin controller devices 的使用者,它在设备树里会被定义为一个节点,在节点里声明要用哪些引脚。
 

下图中,左边是 pin controller 节点,右边是 client device 节点:

pin state:

pinctrl-names:

        各个状态的名字,入口名称的ID为0,下一个为1,依次递增

pinctrl-n <n为数字>:

        对应 pinctrl-names 状态所需要的引脚

 

For example:

        第0种状态引脚在pinctrl-0中定义,它是state_0_node_a,位于 pincontroller 节点中。

        第1种状态引脚在pinctrl-1中定义,它是state_1_node_a,state_1_node_b ,位于 pincontroller 节点中。

device {
		pinctrl-names = "active", "idle";
		pinctrl-0 = <&state_0_node_a>;
		pinctrl-1 = <&state_1_node_a &state_1_node_b>;
	};


pincontroller {
		... /* Standard DT properties for the device itself elided */

		state_0_node_a {
			...
		};
		state_1_node_a {
			...
		};
		state_1_node_b {
			...
		};
	}

 function:

        功能描述,如下,这个节点的功能为 uart0

state_0_node_a {
	uart0 {
		function = "uart0";
		groups = "u0rxtx", "u0rtscts";
	};
};

 groups:

        一个设备会用到一个或多个引脚,这些引脚就可以归为一组(group),如下,u0rxtx 和 u0rtscts 这两个引脚组成一个groups ,这个 groups 复用为 uart0 这个功能

state_0_node_a {
	uart0 {
		function = "uart0";
		groups = "u0rxtx", "u0rtscts";
	};
};

其他属性: 

bias-disable		- disable any pin bias
bias-high-impedance	- high impedance mode ("third-state", "floating")
bias-bus-hold		- latch weakly
bias-pull-up		- pull up the pin
bias-pull-down		- pull down the pin
bias-pull-pin-default	- use pin-default pull state
drive-push-pull		- drive actively high and low
drive-open-drain	- drive with open drain
drive-open-source	- drive with open source
drive-strength		- sink or source at most X mA
input-enable		- enable input on pin (no effect on output)
input-disable		- disable input on pin (no effect on output)
input-schmitt-enable	- enable schmitt-trigger mode
input-schmitt-disable	- disable schmitt-trigger mode
input-debounce		- debounce mode with debound time X
power-source		- select between different power supplies
low-power-enable	- enable low power mode
low-power-disable	- disable low power mode
output-low		- set the pin to output mode with low level
output-high		- set the pin to output mode with high level
slew-rate		- set the slew rate

GPIO子系统

功能:

    (1)管理系统中所有的可以控制的pin,在系统初始化的时候,枚举所有可以控制的pin,并标识这些pin。

    (2)管理这些pin的复用(Multiplexing)。对于SOC而言,其引脚除了配置成普通的GPIO之外,若干个引脚还可以组成一个pin group,行程特定的功能。pin control subsystem要管理所有的pin group。

文档:

Specifying GPIO information for devices
============================================

1) gpios property
-----------------

Nodes that makes use of GPIOs should specify them using one or more
properties, each containing a 'gpio-list':

	gpio-list ::= <single-gpio> [gpio-list]
	single-gpio ::= <gpio-phandle> <gpio-specifier>
	gpio-phandle : phandle to gpio controller node
	gpio-specifier : Array of #gpio-cells specifying specific gpio
			 (controller specific)

GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
of this GPIO for the device. While a non-existent <name> is considered valid
for compatibility reasons (resolving to the "gpios" property), it is not allowed
for new bindings.

GPIO properties can contain one or more GPIO phandles, but only in exceptional
cases should they contain more than one. If your device uses several GPIOs with
distinct functions, reference each of them under its own property, giving it a
meaningful name. The only case where an array of GPIOs is accepted is when
several GPIOs serve the same function (e.g. a parallel data line).

The exact purpose of each gpios property must be documented in the device tree
binding of the device.

The following example could be used to describe GPIO pins used as device enable
and bit-banged data signals:

	gpio1: gpio1 {
		gpio-controller
		 #gpio-cells = <2>;
	};
	gpio2: gpio2 {
		gpio-controller
		 #gpio-cells = <1>;
	};
	[...]

	enable-gpios = <&gpio2 2>;
	data-gpios = <&gpio1 12 0>,
		     <&gpio1 13 0>,
		     <&gpio1 14 0>,
		     <&gpio1 15 0>;

Note that gpio-specifier length is controller dependent.  In the
above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
only uses one.

gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted.
Exact meaning of each specifier cell is controller specific, and must
be documented in the device tree binding for the device. Use the macros
defined in include/dt-bindings/gpio/gpio.h whenever possible:

Example of a node using GPIOs:

	node {
		enable-gpios = <&qe_pio_e 18 GPIO_ACTIVE_HIGH>;
	};

GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.

1.1) GPIO specifier best practices
----------------------------------

A gpio-specifier should contain a flag indicating the GPIO polarity; active-
high or active-low. If it does, the following best practices should be
followed:

The gpio-specifier's polarity flag should represent the physical level at the
GPIO controller that achieves (or represents, for inputs) a logically asserted
value at the device. The exact definition of logically asserted should be
defined by the binding for the device. If the board inverts the signal between
the GPIO controller and the device, then the gpio-specifier will represent the
opposite physical level than the signal at the device's pin.

When the device's signal polarity is configurable, the binding for the
device must either:

a) Define a single static polarity for the signal, with the expectation that
any software using that binding would statically program the device to use
that signal polarity.

The static choice of polarity may be either:

a1) (Preferred) Dictated by a binding-specific DT property.

or:

a2) Defined statically by the DT binding itself.

In particular, the polarity cannot be derived from the gpio-specifier, since
that would prevent the DT from separately representing the two orthogonal
concepts of configurable signal polarity in the device, and possible board-
level signal inversion.

or:

b) Pick a single option for device signal polarity, and document this choice
in the binding. The gpio-specifier should represent the polarity of the signal
(at the GPIO controller) assuming that the device is configured for this
particular signal polarity choice. If software chooses to program the device
to generate or receive a signal of the opposite polarity, software will be
responsible for correctly interpreting (inverting) the GPIO signal at the GPIO
controller.

2) gpio-controller nodes
------------------------

Every GPIO controller node must contain both an empty "gpio-controller"
property, and a #gpio-cells integer property, which indicates the number of
cells in a gpio-specifier.

The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
providing automatic GPIO request and configuration as part of the
gpio-controller's driver probe function.

Each GPIO hog definition is represented as a child node of the GPIO controller.
Required properties:
- gpio-hog:   A property specifying that this child node represent a GPIO hog.
- gpios:      Store the GPIO information (id, flags, ...). Shall contain the
	      number of cells specified in its parent node (GPIO controller
	      node).
Only one of the following properties scanned in the order shown below.
This means that when multiple properties are present they will be searched
in the order presented below and the first match is taken as the intended
configuration.
- input:      A property specifying to set the GPIO direction as input.
- output-low  A property specifying to set the GPIO direction as output with
	      the value low.
- output-high A property specifying to set the GPIO direction as output with
	      the value high.

Optional properties:
- line-name:  The GPIO label name. If not present the node name is used.

Example of two SOC GPIO banks defined as gpio-controller nodes:

	qe_pio_a: gpio-controller@1400 {
		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
		reg = <0x1400 0x18>;
		gpio-controller;
		#gpio-cells = <2>;

		line_b {
			gpio-hog;
			gpios = <6 0>;
			output-low;
			line-name = "foo-bar-gpio";
		};
	};

	qe_pio_e: gpio-controller@1460 {
		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
		reg = <0x1460 0x18>;
		gpio-controller;
		#gpio-cells = <2>;
	};

2.1) gpio- and pin-controller interaction
-----------------------------------------

Some or all of the GPIOs provided by a GPIO controller may be routed to pins
on the package via a pin controller. This allows muxing those pins between
GPIO and other functions.

It is useful to represent which GPIOs correspond to which pins on which pin
controllers. The gpio-ranges property described below represents this, and
contains information structures as follows:

	gpio-range-list ::= <single-gpio-range> [gpio-range-list]
	single-gpio-range ::= <numeric-gpio-range> | <named-gpio-range>
	numeric-gpio-range ::=
			<pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
	named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>'
	pinctrl-phandle : phandle to pin controller node
	gpio-base : Base GPIO ID in the GPIO controller
	pinctrl-base : Base pinctrl pin ID in the pin controller
	count : The number of GPIOs/pins in this range

The "pin controller node" mentioned above must conform to the bindings
described in ../pinctrl/pinctrl-bindings.txt.

In case named gpio ranges are used (ranges with both <pinctrl-base> and
<count> set to 0), the property gpio-ranges-group-names contains one string
for every single-gpio-range in gpio-ranges:
	gpiorange-names-list ::= <gpiorange-name> [gpiorange-names-list]
	gpiorange-name : Name of the pingroup associated to the GPIO range in
			the respective pin controller.

Elements of gpiorange-names-list corresponding to numeric ranges contain
the empty string. Elements of gpiorange-names-list corresponding to named
ranges contain the name of a pin group defined in the respective pin
controller. The number of pins/GPIOs in the range is the number of pins in
that pin group.

Previous versions of this binding required all pin controller nodes that
were referenced by any gpio-ranges property to contain a property named
#gpio-range-cells with value <3>. This requirement is now deprecated.
However, that property may still exist in older device trees for
compatibility reasons, and would still be required even in new device
trees that need to be compatible with older software.

Example 1:

	qe_pio_e: gpio-controller@1460 {
		#gpio-cells = <2>;
		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
		reg = <0x1460 0x18>;
		gpio-controller;
		gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
	};

Here, a single GPIO controller has GPIOs 0..9 routed to pin controller
pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's
pins 50..59.

Example 2:

	gpio_pio_i: gpio-controller@14B0 {
		#gpio-cells = <2>;
		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
		reg = <0x1480 0x18>;
		gpio-controller;
		gpio-ranges =			<&pinctrl1 0 20 10>,
						<&pinctrl2 10 0 0>,
						<&pinctrl1 15 0 10>,
						<&pinctrl2 25 0 0>;
		gpio-ranges-group-names =	"",
						"foo",
						"",
						"bar";
	};

Here, three GPIO ranges are defined wrt. two pin controllers. pinctrl1 GPIO
ranges are defined using pin numbers whereas the GPIO ranges wrt. pinctrl2
are named "foo" and "bar".

简要说明

gpio controller 与 gpio client:

        在几乎所有 ARM 芯片中, GPIO 都分为几组,每组中有若干个引脚。所以在使用 GPIO 子系统之前,就要先确定:它是哪组的?组里的哪一个?

        在设备树中,“ GPIO 组”就是一个 GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它名字,比如“ gpio1”,然后指定要用它里面的哪个引脚,比如<&gpio1 0>

如下图:key1使用的是 gpio1的第18个引脚,低电平有效

key1@1 {
		label = "USER-KEY1";
		linux,code = <114>;
		gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
		gpio-key,wakeup;
	};


gpio1: gpio@0209c000 {
	compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
	reg = <0x0209c000 0x4000>;
	interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
				<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
	gpio-controller;
	#gpio-cells = <2>;
	interrupt-controller;
	#interrupt-cells = <2>;
};

[<name>-]gpios: 

        name为GPIO名称,如下,该GPIO的名称为reset

reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;

 gpio-controller:

        表示节点是一个 GPIO Controller,它下面有很多引脚。

 #gpio-cells:

#gpio-cells = <2>”表示这个控制器下每一个引脚要用 2 个 32 位的数(cell)来描述

GPIO相关子函数

        GPIO 子系统有两套接口:基于描述符的(descriptor-based)、老的(legacy)。前者的函数都有前缀“ gpiod_”,它使用 gpio_desc 结构体来表示一个引脚;后者的函数都有前缀“ gpio_”,它使用一个整数来表示一个引脚。