1.. _pinctrl-guide: 2 3Pin Control 4########### 5 6This is a high-level guide to pin control. See :ref:`pinctrl_api` for API 7reference material. 8 9Introduction 10************ 11 12The hardware blocks that control pin multiplexing and pin configuration 13parameters such as pin direction, pull-up/down resistors, etc. are named **pin 14controllers**. The pin controller's main users are SoC hardware peripherals, 15since the controller enables exposing peripheral signals, like for example, 16map ``I2C0`` ``SDA`` signal to pin ``PX0``. Not only that, but it usually allows 17configuring certain pin settings that are necessary for the correct functioning 18of a peripheral, for example, the slew-rate depending on the operating 19frequency. The available configuration options are vendor/SoC dependent and can 20range from simple pull-up/down options to more advanced settings such as 21debouncing, low-power modes, etc. 22 23The way pin control is implemented in hardware is vendor/SoC specific. It is 24common to find a *centralized* approach, that is, all pin configuration 25parameters are controlled by a single hardware block (typically named pinmux), 26including signal mapping. The figure below illustrates this 27approach. ``PX0`` can be mapped to ``UART0_TX``, ``I2C0_SCK`` or ``SPI0_MOSI`` 28depending on the ``AF`` control bits. Other configuration parameters such as 29pull-up/down are controlled in the same block via ``CONFIG`` bits. This model is 30used by several SoC families, such as many from NXP and STM32. 31 32.. figure:: images/hw-cent-control.svg 33 34 Example of pin control centralized into a single per-pin block 35 36Other vendors/SoCs use a *distributed* approach. In such case, the pin mapping 37and configuration are controlled by multiple hardware blocks. 38The figure below illustrates a distributed approach where pin 39mapping is controlled by peripherals, such as in Nordic nRF SoCs. 40 41.. figure:: images/hw-dist-control.svg 42 43 Example pin control distributed between peripheral registers and per-pin block 44 45From a user perspective, there is no difference in pin controller usage 46regardless of the hardware implementation: a user will always apply a state. 47The only difference lies in the driver implementation. In general, implementing 48a pin controller driver for a hardware that uses a distributed approach requires 49more effort, since the driver needs to gather knowledge of peripheral dependent 50registers. 51 52Pin control vs. GPIO 53==================== 54 55Some functionality covered by a pin controller driver overlaps with GPIO 56drivers. For example, pull-up/down resistors can usually be enabled by both the 57pin control driver and the GPIO driver. In Zephyr context, the pin control 58driver purpose is to perform peripheral signal multiplexing and configuration of 59other pin parameters required for the correct operation of that peripheral. 60Therefore, the main users of the pin control driver are SoC peripherals. In 61contrast, GPIO drivers are for general purpose control of a pin, that is, when 62its logic level is read or controlled manually. 63 64State model 65*********** 66 67For a device driver to operate correctly, a certain pin configuration needs to 68be applied. Some device drivers require a static configuration, usually set up 69at initialization time. Others need to change the configuration at runtime 70depending on the operating conditions, for example, to enable a low-power mode 71when suspending the device. Such requirements are modeled using **states**, a 72concept that has been adapted from the one in the Linux kernel. Each device 73driver owns a set of states. Each state has a unique name and contains a full 74pin configuration set (see the figure below). This effectively 75means that states are independent of each other, so they do not need to be 76applied in any specific order. Another advantage of the state model is that it 77isolates device drivers from pin configuration. 78 79.. table:: Example pin configuration encoded using the states model 80 :align: center 81 82 +----+------------------+----+------------------+ 83 | ``UART0`` peripheral | 84 +====+==================+====+==================+ 85 | ``default`` state | ``sleep`` state | 86 +----+------------------+----+------------------+ 87 | TX | - Pin: PA0 | TX | - Pin: PA0 | 88 | | - Pull: NONE | | - Pull: NONE | 89 | | - Low Power: NO | | - Low Power: YES | 90 +----+------------------+----+------------------+ 91 | RX | - Pin: PA1 | RX | - Pin: PA1 | 92 | | - Pull: UP | | - Pull: NONE | 93 | | - Low Power: NO | | - Low Power: YES | 94 +----+------------------+----+------------------+ 95 96Standard states 97=============== 98 99The name assigned to pin control states or the number of them is up to the 100device driver requirements. In many cases a single state applied at 101initialization time will be sufficient, but in some other cases more will be 102required. In order to make things consistent, a naming convention has been 103established for the most common use cases. The figure below 104details the standardized states and its purpose. 105 106.. table:: Standardized state names 107 :align: center 108 109 +-------------+----------------------------------+-------------------------+ 110 | State | Identifier | Purpose | 111 +-------------+----------------------------------+-------------------------+ 112 | ``default`` | :c:macro:`PINCTRL_STATE_DEFAULT` | State of the pins when | 113 | | | the device is in | 114 | | | operational state | 115 +-------------+----------------------------------+-------------------------+ 116 | ``sleep`` | :c:macro:`PINCTRL_STATE_SLEEP` | State of the pins when | 117 | | | the device is in low | 118 | | | power or sleep modes | 119 +-------------+----------------------------------+-------------------------+ 120 121Note that other standard states could be introduced in the future. 122 123Custom states 124============= 125 126Some device drivers may require using custom states beyond the standard ones. To 127achieve that, the device driver needs to have in its scope definitions for the 128custom state identifiers named as ``PINCTRL_STATE_{STATE_NAME}``, where 129``{STATE_NAME}`` is the capitalized state name. For example, if ``mystate`` has 130to be supported, a definition named ``PINCTRL_STATE_MYSTATE`` needs to be 131in the driver's scope. 132 133.. note:: 134 It is important that custom state identifiers start from 135 :c:macro:`PINCTRL_STATE_PRIV_START` 136 137If custom states need to be accessed from outside the driver, for example to 138perform dynamic pin control, custom identifiers should be placed in a header 139that is publicly accessible. 140 141Skipping states 142=============== 143 144In most situations, the states defined in Devicetree will be the ones used in 145the compiled firmware. However, there are some cases where certain states will 146be conditionally used depending on a compilation flag. A typical case is the 147``sleep`` state. This state is only used in practice if 148:kconfig:option:`CONFIG_PM` or :kconfig:option:`CONFIG_PM_DEVICE` is enabled. 149If a firmware variant without these power management configurations is needed, 150one should in theory remove the ``sleep`` state from Devicetree to not waste ROM 151space storing such unused state. 152 153States can be skipped by the ``pinctrl`` Devicetree macros if a definition named 154``PINCTRL_SKIP_{STATE_NAME}`` expanding to ``1`` is present when pin control 155configuration is defined. In case of the ``sleep`` state, the ``pinctrl`` API 156already provides such definition conditional to the availability of device power 157management: 158 159.. code-block:: c 160 161 #if !defined(CONFIG_PM) && !defined(CONFIG_PM_DEVICE) 162 /** Out of power management configurations, ignore "sleep" state. */ 163 #define PINCTRL_SKIP_SLEEP 1 164 #endif 165 166Dynamic pin control 167******************* 168 169Dynamic pin control refers to the capability of changing pin configuration 170at runtime. This feature can be useful in situations where the same firmware 171needs to run onto slightly different boards, each having a peripheral routed at 172a different set of pins. This feature can be enabled by setting 173:kconfig:option:`CONFIG_PINCTRL_DYNAMIC`. 174 175.. note:: 176 177 Dynamic pin control should only be used on devices that have not been 178 initialized. Changing pin configurations while a device is operating may 179 lead to unexpected behavior. Since Zephyr does not support device 180 de-initialization yet, this functionality should only be used during early 181 boot stages. 182 183One of the effects of enabling dynamic pin control is that 184:c:struct:`pinctrl_dev_config` will be stored in RAM instead of ROM (not states 185or pin configurations, though). The user can then use 186:c:func:`pinctrl_update_states` to update the states stored in 187:c:struct:`pinctrl_dev_config` with a new set. This effectively means that the 188device driver will apply the pin configurations stored in the updated states 189when it applies a state. 190 191Devicetree representation 192************************* 193 194Because Devicetree is meant to describe hardware, it is the natural choice when 195it comes to storing pin control configuration. In the following sections you 196will find an overview on how states and pin configurations are represented in 197Devicetree. 198 199States 200====== 201 202Given a device, each of its pin control state is represented in Devicetree by 203``pinctrl-N`` properties, being ``N`` the state index starting from zero. The 204``pinctrl-names`` property is then used to assign a unique identifier for each 205state property by index, for example, ``pinctrl-names`` list entry 0 is the name 206for ``pinctrl-0``. 207 208.. code-block:: devicetree 209 210 periph0: periph@0 { 211 ... 212 /* state 0 ("default") */ 213 pinctrl-0 = <...>; 214 ... 215 /* state N ("mystate") */ 216 pinctrl-N = <...>; 217 /* names for state 0 up to state N */ 218 pinctrl-names = "default", ..., "mystate"; 219 ... 220 }; 221 222Pin configuration 223================= 224 225There are multiple ways to represent the pin configurations in Devicetree. 226However, all end up encoding the same information: the pin multiplexing and the 227pin configuration parameters. For example, ``UART_RX`` is mapped to ``PX0`` and 228pull-up is enabled. The representation choice largely depends on each 229vendor/SoC, so the Devicetree binding files for the pin control drivers are the 230best place to look for details. 231 232A popular and versatile option is shown in the example below. One of the 233advantages of this choice is the grouping capability based on shared pin 234configuration. This allows to reduce the verbosity of the pin control 235definitions. Another advantage is that the pin configuration parameters for a 236particular state are enclosed in a single Devicetree node. 237 238.. code-block:: devicetree 239 240 /* board.dts */ 241 #include "board-pinctrl.dtsi" 242 243 &periph0 { 244 pinctrl-0 = <&periph0_default>; 245 pinctrl-names = "default"; 246 }; 247 248.. code-block:: c 249 250 /* vnd-soc-pkgxx.h 251 * File with valid mappings for a specific package (may be autogenerated). 252 * This file is optional, but recommended. 253 */ 254 ... 255 #define PERIPH0_SIGA_PX0 VNDSOC_PIN(X, 0, MUX0) 256 #define PERIPH0_SIGB_PY7 VNDSOC_PIN(Y, 7, MUX4) 257 #define PERIPH0_SIGC_PZ1 VNDSOC_PIN(Z, 1, MUX2) 258 ... 259 260.. code-block:: devicetree 261 262 /* board-pinctrl.dtsi */ 263 #include <vnd-soc-pkgxx.h> 264 265 &pinctrl { 266 /* Node with pin configuration for default state */ 267 periph0_default: periph0_default { 268 group1 { 269 /* Mappings: PERIPH0_SIGA -> PX0, PERIPH0_SIGC -> PZ1 */ 270 pinmux = <PERIPH0_SIGA_PX0>, <PERIPH0_SIGC_PZ1>; 271 /* Pins PX0 and PZ1 have pull-up enabled */ 272 bias-pull-up; 273 }; 274 ... 275 groupN { 276 /* Mappings: PERIPH0_SIGB -> PY7 */ 277 pinmux = <PERIPH0_SIGB_PY7>; 278 }; 279 }; 280 }; 281 282Another popular model is based on having a node for each pin configuration and 283state. While this model may lead to shorter board pin control files, it also 284requires to have one node for each pin mapping and state, since in general, 285nodes can not be re-used for multiple states. This method is discouraged if 286autogeneration is not an option. 287 288.. note:: 289 290 Because all Devicetree information is parsed into a C header, it is important 291 to make sure its size is kept to a minimum. For this reason it is important 292 to prefix pre-generated nodes with ``/omit-if-no-ref/``. This prefix makes 293 sure that the node is discarded when not used. 294 295.. code-block:: devicetree 296 297 /* board.dts */ 298 #include "board-pinctrl.dtsi" 299 300 &periph0 { 301 pinctrl-0 = <&periph0_siga_px0_default &periph0_sigb_py7_default 302 &periph0_sigc_pz1_default>; 303 pinctrl-names = "default"; 304 }; 305 306.. code-block:: devicetree 307 308 /* vnd-soc-pkgxx.dtsi 309 * File with valid nodes for a specific package (may be autogenerated). 310 * This file is optional, but recommended. 311 */ 312 313 &pinctrl { 314 /* Mapping for PERIPH0_SIGA -> PX0, to be used for default state */ 315 /omit-if-no-ref/ periph0_siga_px0_default: periph0_siga_px0_default { 316 pinmux = <VNDSOC_PIN(X, 0, MUX0)>; 317 }; 318 319 /* Mapping for PERIPH0_SIGB -> PY7, to be used for default state */ 320 /omit-if-no-ref/ periph0_sigb_py7_default: periph0_sigb_py7_default { 321 pinmux = <VNDSOC_PIN(Y, 7, MUX4)>; 322 }; 323 324 /* Mapping for PERIPH0_SIGC -> PZ1, to be used for default state */ 325 /omit-if-no-ref/ periph0_sigc_pz1_default: periph0_sigc_pz1_default { 326 pinmux = <VNDSOC_PIN(Z, 1, MUX2)>; 327 }; 328 }; 329 330.. code-block:: devicetree 331 332 /* board-pinctrl.dts */ 333 #include <vnd-soc-pkgxx.dtsi> 334 335 /* Enable pull-up for PX0 (default state) */ 336 &periph0_siga_px0_default { 337 bias-pull-up; 338 }; 339 340 /* Enable pull-up for PZ1 (default state) */ 341 &periph0_sigc_pz1_default { 342 bias-pull-up; 343 }; 344 345.. note:: 346 347 It is discouraged to add pin configuration defaults in pre-defined nodes. 348 In general, pin configurations depend on the board design or on the 349 peripheral working conditions, so the decision should be made by the board. 350 For example, enabling a pull-up by default may not always be desired because 351 the board already has one or because its value depends on the operating bus 352 speed. Another downside of defaults is that user may not be aware of them, 353 for example: 354 355 .. code-block:: devicetree 356 357 /* not evident that "periph0_siga_px0_default" also implies "bias-pull-up" */ 358 /omit-if-no-ref/ periph0_siga_px0_default: periph0_siga_px0_default { 359 pinmux = <VNDSOC_PIN(X, 0, MUX0)>; 360 bias-pull-up; 361 }; 362 363Implementation guidelines 364************************* 365 366Pin control drivers 367=================== 368 369Pin control drivers need to implement a single function: 370:c:func:`pinctrl_configure_pins`. This function receives an array of pin 371configurations that need to be applied. Furthermore, if 372:kconfig:option:`CONFIG_PINCTRL_STORE_REG` is set, it also receives the associated 373device register address for the given pins. This information may be required by 374some drivers to perform device specific actions. 375 376The pin configuration is stored in an opaque type that is vendor/SoC dependent: 377``pinctrl_soc_pin_t``. This type needs to be defined in a header named 378``pinctrl_soc.h`` file that is in the Zephyr's include path. It can range from 379a simple integer value to a struct with multiple fields. ``pinctrl_soc.h`` also 380needs to define a macro named ``Z_PINCTRL_STATE_PINS_INIT`` that accepts two 381arguments: a node identifier and a property name (``pinctrl-N``). With this 382information the macro needs to define an initializer for all pin configurations 383contained within the ``pinctrl-N`` property of the given node. 384 385Regarding Devicetree pin configuration representation, vendors can decide which 386option is better for their devices. However, the following guidelines should be 387followed: 388 389- Use ``pinctrl-N`` (N=0, 1, ...) and ``pinctrl-names`` properties to define pin 390 control states. These properties are defined in 391 :file:`dts/bindings/pinctrl/pinctrl-device.yaml`. 392- Use standard pin configuration properties as defined in 393 :file:`dts/bindings/pinctrl/pincfg-node.yaml`. 394 395Representations not following these guidelines may be accepted if they are 396already used by the same vendor in other operating systems, e.g. Linux. 397 398Device drivers 399============== 400 401In this section you will find some tips on how a device driver should use the 402``pinctrl`` API to successfully configure the pins it needs. 403 404The device compatible needs to be modified in the corresponding binding so that 405the ``pinctrl-device.yaml`` is included. For example: 406 407.. code-block:: yaml 408 409 include: [base.yaml, pinctrl-device.yaml] 410 411This file is needed to add ``pinctrl-N`` and ``pinctrl-names`` properties to the 412device. 413 414From a device driver perspective there are two steps that need to be performed 415to be able to use the ``pinctrl`` API. First, the pin control configuration 416needs to be defined. This includes all states and pins. 417:c:macro:`PINCTRL_DT_DEFINE` or :c:macro:`PINCTRL_DT_INST_DEFINE` macros 418should be used for this purpose. Second, a reference to 419the device instance :c:struct:`pinctrl_dev_config` needs to be stored, since it 420is required to later use the API. This can be achieved using the 421:c:macro:`PINCTRL_DT_DEV_CONFIG_GET` and 422:c:macro:`PINCTRL_DT_INST_DEV_CONFIG_GET` macros. 423 424It is worth to note that the only relationship between a device and its 425associated pin control configuration is based on variable naming conventions. 426The way an instance of :c:struct:`pinctrl_dev_config` is named for a 427corresponding device instance allows to later obtain a reference to it given the 428device's Devicetree node identifier. This allows to minimize ROM usage, since 429only devices requiring pin control will own a reference to a pin control 430configuration. 431 432Once the driver has defined the pin control configuration and kept a reference 433to it, it is ready to use the API. The most common way to apply a state is by 434using :c:func:`pinctrl_apply_state`. It is also possible to use the lower level 435function :c:func:`pinctrl_apply_state_direct` to skip state lookup if it is 436cached in advance (e.g. at init time). Since state lookup time is expected to be 437fast, it is recommended to use :c:func:`pinctrl_apply_state`. 438 439The example below contains a complete example of a device driver that uses the 440``pinctrl`` API. 441 442.. code-block:: c 443 444 /* A driver for the "mydev" compatible device */ 445 #define DT_DRV_COMPAT mydev 446 447 ... 448 #include <zephyr/drivers/pinctrl.h> 449 ... 450 451 struct mydev_config { 452 ... 453 /* Reference to mydev pinctrl configuration */ 454 const struct pinctrl_dev_config *pcfg; 455 ... 456 }; 457 458 ... 459 460 static int mydev_init(const struct device *dev) 461 { 462 const struct mydev_config *config = dev->config; 463 int ret; 464 ... 465 /* Select "default" state at initialization time */ 466 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); 467 if (ret < 0) { 468 return ret; 469 } 470 ... 471 } 472 473 #define MYDEV_DEFINE(i) \ 474 /* Define all pinctrl configuration for instance "i" */ \ 475 PINCTRL_DT_INST_DEFINE(i); \ 476 ... \ 477 static const struct mydev_config mydev_config_##i = { \ 478 ... \ 479 /* Keep a ref. to the pinctrl configuration for instance "i" */ \ 480 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(i), \ 481 ... \ 482 }; \ 483 ... \ 484 \ 485 DEVICE_DT_INST_DEFINE(i, mydev_init, NULL, &mydev_data##i, \ 486 &mydev_config##i, ...); 487 488 DT_INST_FOREACH_STATUS_OKAY(MYDEV_DEFINE) 489 490.. _pinctrl_api: 491 492Pin Control API 493**************** 494 495.. doxygengroup:: pinctrl_interface 496 497Dynamic pin control 498==================== 499 500.. doxygengroup:: pinctrl_interface_dynamic 501 502 503Other reference material 504************************ 505 506- `Introduction to pin muxing and GPIO control under Linux <https://elinux.org/images/a/a7/ELC-2021_Introduction_to_pin_muxing_and_GPIO_control_under_Linux.pdf>`_ 507