Part 1
요약·해설
단일 참조부터 metadata가 있는 resource group, #*-cells와 C API까지 연결해 설명합니다.
Node 하나
참조 배열
참조 + metadata
#*-cells
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
4823D5B466ECC4B275583CFA6EDAC0A3FEA8983E39EB1931B8D310BE16572E98
.. _dt-phandles:
Phandles
########
The devicetree concept of a *phandle* is very similar to pointers in
C. You can use phandles to refer to nodes in devicetree similarly to the way
you can use pointers to refer to structures in C.
.. contents:: Contents
:local:
Getting phandles
****************
The usual way to get a phandle for a devicetree node is from one of its node
labels. For example, with this devicetree:
.. code-block:: DTS
/ {
lbl_a: node-1 {};
lbl_b: lbl_c: node-2 {};
};
You can write the phandle for:
- ``/node-1`` as ``&lbl_a``
- ``/node-2`` as either ``&lbl_b`` or ``&lbl_c``
Notice how the ``&nodelabel`` devicetree syntax is similar to the "address of"
C syntax.
Using phandles
**************
.. note::
"Type" in this section refers to one of the type names documented in
:ref:`dt-bindings-properties` in the devicetree bindings documentation.
Here are the main ways you will use phandles.
One node: phandle type
======================
You can use phandles to refer to ``node-b`` from ``node-a``, where ``node-b``
is related to ``node-a`` in some way.
One common example is when ``node-a`` represents some hardware that
generates an interrupt, and ``node-b`` represents the interrupt
controller that receives the asserted interrupt. In this case, you could
write:
.. code-block:: DTS
node_b: node-b {
interrupt-controller;
};
node-a {
interrupt-parent = <&node_b>;
};
This uses the standard ``interrupt-parent`` property defined in the
devicetree specification to capture the relationship between the two nodes.
These properties have type ``phandle``.
Zero or more nodes: phandles type
=================================
You can use phandles to make an array of references to other nodes.
One common example occurs in :ref:`pin control <pinctrl-guide>`. Pin control
properties like ``pinctrl-0``, ``pinctrl-1`` etc. may contain multiple
phandles, each of which "points" to a node containing information related to
pin configuration for that hardware peripheral. Here's an example of six
phandles in a single property:
.. code-block:: DTS
pinctrl-0 = <&quadspi_clk_pe10 &quadspi_ncs_pe11
&quadspi_bk1_io0_pe12 &quadspi_bk1_io1_pe13
&quadspi_bk1_io2_pe14 &quadspi_bk1_io3_pe15>;
These properties have type ``phandles``.
Zero or more nodes with metadata: phandle-array type
====================================================
You can use phandles to refer to and configure one or more resources that are
"owned" by some other node.
This is the most complex case. There are examples and more details in the
next section.
These properties have type ``phandle-array``.
.. _dt-phandle-arrays:
phandle-array properties
************************
These properties are commonly used to specify a resource that is owned by
another node along with additional metadata about the resource.
High level description
======================
Usually, properties with this type are written like ``phandle-array-prop`` in
this example:
.. code-block:: dts
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>, <&baz 4 5>;
};
That is, the property's value is written as a comma-separated sequence of
"groups", where each "group" is written inside of angle brackets (``< ... >``).
Each "group" starts with a phandle (``&foo``, ``&bar``, ``&baz``). The values
that follow the phandle in each "group" are called *specifiers*. There are
three specifiers in the above example:
#. ``1 2``
#. ``3``
#. ``4 5``
The phandle in each "group" is used to "point" to the hardware that controls
the resource you are interested in. The specifier describes the resource
itself, along with any additional necessary metadata.
The rest of this section describes a common example. Subsequent sections
document more rules about how to use phandle-array properties in practice.
Example phandle-arrays: GPIOs
=============================
Perhaps the most common use case for phandle-array properties is specifying one
or more GPIOs on your SoC that another chip on your board connects to. For that
reason, we'll focus on that use case here. However, there are **many other use
cases** that are handled in devicetree with phandle-array properties.
For example, consider an external chip with an interrupt pin that is connected
to a GPIO on your SoC. You will typically need to provide that GPIO's
information (GPIO controller and pin number) to the :ref:`device driver
<device_model_api>` for that chip. You usually also need to provide other
metadata about the GPIO, like whether it is active low or high, what kind of
internal pull resistor within the SoC should be enabled in order to communicate
with the device, etc., to the driver.
In the devicetree, there will be a node that represents the GPIO controller
that controls a group of pins. This reflects the way GPIO IP blocks are usually
developed in hardware. Therefore, there is no single node in the devicetree
that represents a GPIO pin, and you can't use a single phandle to represent it.
Instead, you would use a phandle-array property, like this:
.. code-block::
my-external-ic {
irq-gpios = <&gpioX pin flags>;
};
In this example, ``irq-gpios`` is a phandle-array property with just one
"group" in its value. ``&gpioX`` is the phandle for the GPIO controller node
that controls the pin. ``pin`` is the pin number (0, 1, 2, ...). ``flags`` is a
bit mask describing pin metadata (for example ``(GPIO_ACTIVE_LOW |
GPIO_PULL_UP)``); see :zephyr_file:`include/zephyr/dt-bindings/gpio/gpio.h` for
more details.
The device driver handling the ``my-external-ic`` node can then use the
``irq-gpios`` property's value to set up interrupt handling for the chip as it
is used on your board. This lets you configure the device driver in devicetree,
without changing the driver's source code.
Such properties can contain multiple values as well:
.. code-block::
my-other-external-ic {
handshake-gpios = <&gpioX pinX flagsX>, <&gpioY pinY flagsY>;
};
The above example specifies two pins:
- ``pinX`` on the GPIO controller with phandle ``&gpioX``, flags ``flagsX``
- ``pinY`` on ``&gpioY``, flags ``flagsY``
You may be wondering how the "pin and flags" convention is established and
enforced. To answer this question, we'll need to introduce a concept called
specifier spaces before moving on to some information about devicetree
bindings.
.. _dt-specifier-spaces:
Specifier spaces
****************
*Specifier spaces* are a way to allow nodes to describe how you should
use them in phandle-array properties.
We'll start with an abstract, high level description of how specifier spaces
work in DTS files, before moving on to a concrete example and providing
references to further reading for how this all works in practice using DTS
files and bindings files.
High level description
======================
As described above, a phandle-array property is a sequence of "groups" of
phandles followed by some number of cells:
.. code-block:: dts
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>;
};
The cells that follow each phandle are called a *specifier*. In this example,
there are two specifiers:
#. ``1 2``: two cells
#. ``3``: one cell
Every phandle-array property has an associated *specifier space*. This sounds
complex, but it's really just a way to assign a meaning to the cells that
follow each phandle in a hardware specific way. Every specifier space has a
unique name. There are a few "standard" names for commonly used hardware, but
you can create your own as well.
Devicetree nodes encode the number of cells that must appear in a specifier, by
name, using the ``#SPACE_NAME-cells`` property. For example, let's assume that
``phandle-array-prop``\ 's specifier space is named ``baz``. Then we would need
the ``foo`` and ``bar`` nodes to have the following ``#baz-cells`` properties:
.. code-block:: DTS
foo: node@1000 {
#baz-cells = <2>;
};
bar: node@2000 {
#baz-cells = <1>;
};
Without the ``#baz-cells`` property, the devicetree tooling would not be able
to validate the number of cells in each specifier in ``phandle-array-prop``.
This flexibility allows you to write down an array of hardware resources in a
single devicetree property, even though the amount of metadata you need to
describe each resource might be different for different nodes.
A single node can also have different numbers of cells in different specifier
spaces. For example, we might have:
.. code-block:: DTS
foo: node@1000 {
#baz-cells = <2>;
#bob-cells = <1>;
};
With that, if ``phandle-array-prop-2`` has specifier space ``bob``, we could
write:
.. code-block:: DTS
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>;
phandle-array-prop-2 = <&foo 4>;
};
This flexibility allows you to have a node that manages multiple different
kinds of resources at the same time. The node describes the amount of metadata
needed to describe each kind of resource (how many cells are needed in each
case) using different ``#SPACE_NAME-cells`` properties.
Example specifier space: gpio
=============================
From the above example, you're already familiar with how one specifier space
works: in the "gpio" space, specifiers almost always have two cells:
#. a pin number
#. a bit mask of flags related to the pin
Therefore, almost all GPIO controller nodes you will see in practice will look
like this:
.. code-block:: DTS
gpioX: gpio-controller@deadbeef {
gpio-controller;
#gpio-cells = <2>;
};
Associating properties with specifier spaces
********************************************
Above, we have described that:
- each phandle-array property has an associated specifier space
- specifier spaces are identified by name
- devicetree nodes use ``#SPECIFIER_NAME-cells`` properties to
configure the number of cells which must appear in a specifier
In this section, we explain how phandle-array properties get their specifier
spaces.
High level description
======================
In general, a ``phandle-array`` property named ``foos`` implicitly has
specifier space ``foo``. For example:
.. code-block:: YAML
properties:
dmas:
type: phandle-array
pwms:
type: phandle-array
The ``dmas`` property's specifier space is "dma". The ``pwm`` property's
specifier space is ``pwm``.
Special case: GPIO
==================
``*-gpios`` properties are special-cased so that e.g. ``foo-gpios`` resolves to
``#gpio-cells`` rather than ``#foo-gpio-cells``.
Manually specifying a space
===========================
You can manually specify the specifier space for any ``phandle-array``
property. See :ref:`dt-bindings-specifier-space`.
Naming the cells in a specifier
*******************************
You should name the cells in each specifier space your hardware supports when
writing bindings. For details on how to do this, see :ref:`dt-bindings-cells`.
This allows C code to query information about and retrieve the values of cells
in a specifier by name using devicetree APIs like these:
- :c:macro:`DT_PHA_BY_IDX`
- :c:macro:`DT_PHA_BY_NAME`
This feature and these macros are used internally by numerous hardware-specific
APIs. Here are a few examples:
- :c:macro:`DT_GPIO_PIN_BY_IDX`
- :c:macro:`DT_PWMS_CHANNEL_BY_IDX`
- :c:macro:`DT_DMAS_CELL_BY_NAME`
- :c:macro:`DT_IO_CHANNELS_INPUT_BY_IDX`
- :c:macro:`DT_CLOCKS_CELL_BY_NAME`
See also
********
- :ref:`dt-writing-property-values`: how to write phandles in devicetree
properties
- :ref:`dt-bindings-properties`: how to write bindings for properties with
phandle types (``phandle``, ``phandles``, ``phandle-array``)
- :ref:`dt-bindings-specifier-space`: how to manually specify a phandle-array
property's specifier space
Part 3
한국어 전문 번역
Phandle이란 무엇인가
Devicetree의 phandle은 C의 pointer와 매우 비슷합니다. C pointer가 structure를 가리키듯이 phandle은 devicetree 안의 다른 node를 가리킵니다.
Phandle 얻기
보통 node label에서 phandle을 얻습니다. 다음 tree를 보겠습니다.
/ {
lbl_a: node-1 {};
lbl_b: lbl_c: node-2 {};
};/node-1의 phandle은&lbl_a/node-2의 phandle은&lbl_b또는&lbl_c
&nodelabel 문법은 C의 address-of 연산자와 닮았습니다.
Phandle 사용 유형
Node 하나: phandle
node-a와 관계가 있는 node-b 하나를 참조할 때 사용합니다. 대표적으로 interrupt를 만드는 hardware와 그 interrupt를 받는 controller의 관계가 있습니다.
node_b: node-b {
interrupt-controller;
};
node-a {
interrupt-parent = <&node_b>;
};표준 interrupt-parent property가 두 node의 관계를 기록하며 이런 property의 type은 phandle입니다.
Node 0개 이상: phandles
다른 node에 대한 참조 배열입니다. Pin control의 pinctrl-0, pinctrl-1 같은 property는 peripheral pin 설정 정보를 가진 node 여러 개를 가리킬 수 있습니다.
pinctrl-0 = <&quadspi_clk_pe10 &quadspi_ncs_pe11
&quadspi_bk1_io0_pe12 &quadspi_bk1_io1_pe13
&quadspi_bk1_io2_pe14 &quadspi_bk1_io3_pe15>;이 예제는 property 하나에 phandle 여섯 개를 담으며 type은 phandles입니다.
Metadata를 동반한 node 0개 이상: phandle-array
다른 node가 소유한 resource 하나 이상을 참조하면서 각 resource를 설정할 metadata도 함께 전달합니다. 세 유형 중 가장 복잡하고 GPIO, DMA, PWM, clock 등에서 널리 사용합니다.
phandle-array property
다음처럼 comma로 구분한 group의 sequence로 씁니다. 각 group은 angle bracket 안에 있고 phandle로 시작합니다.
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>, <&baz 4 5>;
};각 phandle 뒤의 값은 specifier입니다. 위 예제에는 1 2, 3, 4 5 세 specifier가 있습니다. Phandle은 resource를 제어하는 hardware를 가리키고, specifier는 resource 자체와 필요한 metadata를 설명합니다.
GPIO phandle-array 예제
가장 흔한 사례는 board의 외부 chip이 SoC GPIO에 연결된 경우입니다. Driver에는 GPIO controller와 pin 번호뿐 아니라 active-low/high, internal pull resistor 같은 정보도 필요합니다. GPIO pin마다 별도 node가 있는 것이 아니라 controller node가 pin 묶음을 관리하므로 phandle 하나만으로는 pin을 완전히 표현할 수 없습니다.
my-external-ic {
irq-gpios = <&gpioX pin flags>;
};irq-gpios에는 group 하나가 있습니다. &gpioX는 controller node, pin은 pin 번호, flags는 GPIO_ACTIVE_LOW | GPIO_PULL_UP처럼 pin metadata를 담는 bit mask입니다. 이 정보로 driver는 source code를 바꾸지 않고 board 연결 방식에 맞춰 interrupt를 설정할 수 있습니다.
Property에는 여러 group도 넣을 수 있습니다.
my-other-external-ic {
handshake-gpios = <&gpioX pinX flagsX>, <&gpioY pinY flagsY>;
};&gpioXcontroller의pinX와flagsX&gpioYcontroller의pinY와flagsY
Specifier space
Specifier space는 phandle-array에서 어떤 cell을 몇 개 쓰고 각각이 무엇을 뜻하는지 node가 설명하게 하는 규칙입니다. 먼저 추상적인 예제를 보겠습니다.
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>;
};두 specifier는 cell 두 개인 1 2와 cell 하나인 3입니다. 모든 phandle-array property에는 고유 이름의 specifier space가 연결됩니다. 표준 hardware용 이름도 있고 binding 작성자가 새 이름을 정의할 수도 있습니다.
Node는 #SPACE_NAME-cells property로 해당 space에서 필요한 cell 수를 선언합니다. Space 이름이 baz라면 다음과 같습니다.
foo: node@1000 {
#baz-cells = <2>;
};
bar: node@2000 {
#baz-cells = <1>;
};#baz-cells가 없으면 도구는 각 group의 specifier cell 수를 검증할 수 없습니다. Node별로 resource metadata 양이 달라도 같은 property 배열에 함께 표현할 수 있는 이유가 이 규칙입니다.
Node 하나가 resource 종류에 따라 서로 다른 cell 수를 선언할 수도 있습니다.
foo: node@1000 {
#baz-cells = <2>;
#bob-cells = <1>;
};phandle-array-prop-2의 space가 bob이라면 다음처럼 같은 foo node가 두 resource 유형에 각각 다른 metadata 크기를 제공합니다.
node {
phandle-array-prop = <&foo 1 2>, <&bar 3>;
phandle-array-prop-2 = <&foo 4>;
};GPIO specifier space
gpio space의 specifier는 거의 항상 pin 번호와 pin flag bit mask 두 cell입니다. 그래서 일반적인 GPIO controller node는 다음 형태입니다.
gpioX: gpio-controller@deadbeef {
gpio-controller;
#gpio-cells = <2>;
};Property와 specifier space 연결
- 각 phandle-array property에는 specifier space가 하나 연결됩니다.
- Specifier space는 이름으로 식별합니다.
- 참조되는 node는
#SPECIFIER_NAME-cells로 필요한 cell 수를 선언합니다.
일반적으로 이름이 foos인 phandle-array property의 space는 단수형 foo로 추론합니다.
properties:
dmas:
type: phandle-array
pwms:
type: phandle-arraydmas의 space는 dma, pwms의 space는 pwm입니다. 단, *-gpios는 특별 규칙을 사용해 foo-gpios도 #foo-gpio-cells가 아니라 #gpio-cells에 연결됩니다. Binding에서 원하는 space를 명시적으로 지정할 수도 있습니다.
Specifier cell 이름과 C API
Binding을 작성할 때 hardware가 지원하는 각 specifier cell에 이름을 붙여야 합니다. 그러면 C code가 DT_PHA_BY_IDX, DT_PHA_BY_NAME으로 이름에 따라 값을 조회할 수 있습니다.
DT_GPIO_PIN_BY_IDXDT_PWMS_CHANNEL_BY_IDXDT_DMAS_CELL_BY_NAMEDT_IO_CHANNELS_INPUT_BY_IDXDT_CLOCKS_CELL_BY_NAME
함께 볼 문서
- Devicetree property에서 phandle 값을 쓰는 방법
phandle·phandles·phandle-arraybinding 작성법- phandle-array property의 specifier space를 수동 지정하는 방법
Source
출처
원문 파일의 단락, directive, 표, 코드, symbol, 경로는 영어 원문 영역에 그대로 보존했습니다.