A, pinctrl device tree configuration subsystem
With pinctrl subsystem after the drive can operate pinctrl subsystem interface function complete I / O operations, and without the need to configure themselves. General pinctrl subsystem is driven by the BSP engineers to achieve good chip original. Drive engineers to use pinctrl subsystem configured device tree. Some I / O port has a different status (state), such that when a working group of I / O port is configured to uart interface configured to sleep when the output is high and the GPIO interface. pinctrl subsystem configured device tree also comply with service and client structure.
For example: where the node device to become a client subsystem pinctrl device, since it uses a pinctrl subsystem which provides interfaces out. pinctrl is the abbreviation of pincontroller.
// Client Node Device { pinctrl -names = " default " , " SLEEP " ; // use pinctrl-names to indicate the status (state) of the device, there are two, respectively, the default state and a sleep state. pinctrl- 0 = <& state_0_node_a>; // 0 states correspond to the "default" state, the corresponding pin is defined inside pinctrl-0. pinctrl- 0 = <& state_1_node_a>; // first state corresponds to a "sleep" state, the corresponding pin is defined inside pinctrl-1. }; // -Service node pincontroller { state_0_node_a { function = " UART0 " ; u0rxtx", "u0rtscts"; }; state_1_node_a { function = "gpio"; groups = "u0rxtx", "u0rtscts"; }; };
The above is a set of pins multiplexed, multiplexed in different states uart gpio pin or pins, known as "Generic pin multiplexing node" ( multiplex nodes ). Another configuration is called "Generic pin configuration node" ( configuration node ) is arranged on the pins, the different states (default, idle, sleep ...) arranged different functions.
An example of a configuration of the nodes as follows:
// Client Node Device { pinctrl -names = " default " , " SLEEP " ; // use pinctrl-names to indicate the status (state) of the device, there are two, respectively, the default state and a sleep state. pinctrl- 0 = <& state_0_node_a>; // 0 states correspond to the "default" state, the corresponding pin is defined inside pinctrl-0. pinctrl- 0 = <& state_1_node_a>; // first state corresponds to a "sleep" state, the corresponding pin is defined inside pinctrl-1. }; // -Service node, controller to provide services pincontroller { state_0_node_a { // multiplex node function = " UART0 "Groups = " u0rxtx " , " u0rtscts " ; }; state_1_node_a { // Configure Node Groups = " u0rxtx " , " u0rtscts " ; Output -high; // output high }; };
Whether multiplex configuration node or nodes, are to operate these pins. It can be specified for a plurality of client state (state), corresponding to a child node can be specified in each of the states to describe its state. In the service-side child node controller implemented, it may be a child node can also be a complex configuration node (corresponding to the pin is configured as a state) with a node (the pin is multiplexed with corresponding to a function).
For the client node, which is written in the device tree format is essentially the same, uniform. But for writing controller node on the service side of the five law eight, and some simply do not function and the group, the format can say is no.
A few examples of practical use:
1.imx6ull of
// Client side: @ {UART1 pinctrl -names = " default " ; pinctrl - 0 = <& pinctrl_uart1> ; Status = " Okay " ; }; // pincontroller server pinctrl_uart1: uartlgrp { fsl.pins = <MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX, // named UART1_TX pins are multiplexed into UART1_DCE_TX function. MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX>; // write here are two macros, so do not add "&" };
2.rk3288 platform
// Client terminal @ UART0 { pinctrl -names = " default " ; pinctrl - 0 = <& uart0_xfer & uart0_cts & uart0_rts>; // it uses three nodes to represent three pins. = Status " Okay " ; }; // pincontroller server gpio4_uart0 { uart0_xfer: UART0 - XFER { rockchip, pins = <UART0BT_SIN>, <UART0BT_SOUT>; // use rockchip, pins used to specify which pins, it is equivalent to Groups Rockchip, pull = <VALUE_PULL_DISABLE>; // these two fields to configure the parameters of these pins rockchip, drive = <; }; Uart0_cts: UART0 - CTS { Rockchip, pins = <UART0BT_CTSN>; // write here are two macro, there is no increase, "&", designated here actually two pins. Rockchip, pull = <VALUE_PULL_DISABLE> ; Rockchip, Drive = <VALUE_DRV_DEFAULT> ; }; uart0_rts: UART0 - RTS { Rockchip, pins = <UART0BT_RTSN> ; Rockchip, pull = <VALUE_PULL_DISABLE> ; Rockchip, Drive = <VALUE_DRV_DEFAULT> ; }; uart0_rts_gpio: UART0 -rts- GPIO { Rockchip, pins= <FUNC_TO_GPIO(UART0BT_RTSN)>; rockchip,drive = <VALUE_DRV_DEFAULT>; }; };
Although pincontroller server is no uniform format, but the notion that there is still the same, what to use pins that can be classified as a group of a group, these pins are multiplexed into a single function.
Second, how to use the drive subsystem pinctrl
For how to use the driver code pinctrl subsystem, which is transparent to the driver engineers, we do not control the basic driving, when the device switches state (state pinctrl-names of the corresponding device tree), will be a corresponding pinctrl transfer.
1. Before the drive on the first probe to obtain a variety of state pinctl
really_probe // Drivers / Base / dd.c / * the If the using pinctrl, now before the bind pins Probing * / // first pin configuration acquisition pinctrl RET = pinctrl_bind_pins (dev); // Drivers / Base / pinctrl.c // . 1 save "default" state of pin configuration the dev-> pins-> default_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_DEFAULT); // 2. save "init" state of pin configuration dev-> pins-> init_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_INIT); IF (IS_ERR (the dev-> pins-> init_state)) { // if the init state is present on the choice of "init" state, otherwise choose "default" state = pinctrl_select_state RET (the dev-> pins-> P, the dev-> pins-> default_state); } the else { RET = pinctrl_select_state (the dev-> pins-> P, the dev-> pins-> init_state); } // . 3. saving "sleep" state of pin configuration the dev-> pins-> sleep_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_SLEEP); // 4. save "idle" state of pin configuration dev-> pins-> idle_state = pinctrl_lookup_state (dev-> pins-> the p-, PINCTRL_STATE_IDLE); // then probe our drive drv-> probe (dev);
2. If have to call their own, but also function
struct pinctrl * __must_check devm_pinctrl_get_select_default ( struct Device * dev) // Get pinctrl "default" state is disposed struct pinctrl * __must_check devm_pinctrl_get_select ( struct Device dev *, const char * name); // Get the name specified configuration pinctrl void devm_pinctrl_put ( struct * the p-pinctrl); // release pinctrl allocation of resources, we usually do not need to call.