Documentation/driver-api/phy/phy.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

PHY Subsystem

Generic PHY provider·consumer API, 호출 순서, PM runtime과 mapping을 다루는 전문 번역입니다.

Source pathDocumentation/driver-api/phy/phy.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

phy.rst:1-223

Generic PHY Framework는 external PHY provider와 consumer의 생성·reference·전원·파괴 수명을 공통화합니다. Managed API는 devres와 결합하고 optional get의 `NULL`은 유효한 NOP PHY이며, PM runtime 요청은 child PHY device에서 parent provider로 전파됩니다.

문서 구성
원문 줄내용
1-27External PHY와 framework 목적
28-96Provider 등록과 PHY 생성
97-159Reference 획득, optional PHY와 호출 순서
160-186Reference 해제와 instance 파괴
187-202PM runtime 연동
203-223Non-DT lookup과 DT binding

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =============
2 PHY subsystem
3 =============
4
5 :Author: Kishon Vijay Abraham I <[email protected]>
6
7 This document explains the Generic PHY Framework along with the APIs provided,
8 and how-to-use.
9
10 Introduction
11 ============
12
13 *PHY* is the abbreviation for physical layer. It is used to connect a device
14 to the physical medium e.g., the USB controller has a PHY to provide functions
15 such as serialization, de-serialization, encoding, decoding and is responsible
16 for obtaining the required data transmission rate. Note that some USB
17 controllers have PHY functionality embedded into it and others use an external
18 PHY. Other peripherals that use PHY include Wireless LAN, Ethernet,
19 SATA etc.
20
21 The intention of creating this framework is to bring the PHY drivers spread
22 all over the Linux kernel to drivers/phy to increase code re-use and for
23 better code maintainability.
24
25 This framework will be of use only to devices that use external PHY (PHY
26 functionality is not embedded within the controller).
27
28 Registering/Unregistering the PHY provider
29 ==========================================
30
31 PHY provider refers to an entity that implements one or more PHY instances.
32 For the simple case where the PHY provider implements only a single instance of
33 the PHY, the framework provides its own implementation of of_xlate in
34 of_phy_simple_xlate. If the PHY provider implements multiple instances, it
35 should provide its own implementation of of_xlate. of_xlate is used only for
36 dt boot case.
37
38 ::
39
40 #define of_phy_provider_register(dev, xlate) \
41 __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
42
43 #define devm_of_phy_provider_register(dev, xlate) \
44 __devm_of_phy_provider_register((dev), NULL, THIS_MODULE,
45 (xlate))
46
47 of_phy_provider_register and devm_of_phy_provider_register macros can be used to
48 register the phy_provider and it takes device and of_xlate as
49 arguments. For the dt boot case, all PHY providers should use one of the above
50 2 macros to register the PHY provider.
51
52 Often the device tree nodes associated with a PHY provider will contain a set
53 of children that each represent a single PHY. Some bindings may nest the child
54 nodes within extra levels for context and extensibility, in which case the low
55 level of_phy_provider_register_full() and devm_of_phy_provider_register_full()
56 macros can be used to override the node containing the children.
57
58 ::
59
60 #define of_phy_provider_register_full(dev, children, xlate) \
61 __of_phy_provider_register(dev, children, THIS_MODULE, xlate)
62
63 #define devm_of_phy_provider_register_full(dev, children, xlate) \
64 __devm_of_phy_provider_register_full(dev, children,
65 THIS_MODULE, xlate)
66
67 void devm_of_phy_provider_unregister(struct device *dev,
68 struct phy_provider *phy_provider);
69 void of_phy_provider_unregister(struct phy_provider *phy_provider);
70
71 devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to
72 unregister the PHY.
73
74 Creating the PHY
75 ================
76
77 The PHY driver should create the PHY in order for other peripheral controllers
78 to make use of it. The PHY framework provides 2 APIs to create the PHY.
79
80 ::
81
82 struct phy *phy_create(struct device *dev, struct device_node *node,
83 const struct phy_ops *ops);
84 struct phy *devm_phy_create(struct device *dev,
85 struct device_node *node,
86 const struct phy_ops *ops);
87
88 The PHY drivers can use one of the above 2 APIs to create the PHY by passing
89 the device pointer and phy ops.
90 phy_ops is a set of function pointers for performing PHY operations such as
91 init, exit, power_on and power_off.
92
93 Inorder to dereference the private data (in phy_ops), the phy provider driver
94 can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
95 phy_ops to get back the private data.
96
97 Getting a reference to the PHY
98 ==============================
99
100 Before the controller can make use of the PHY, it has to get a reference to
101 it. This framework provides the following APIs to get a reference to the PHY.
102
103 ::
104
105 struct phy *phy_get(struct device *dev, const char *string);
106 struct phy *devm_phy_get(struct device *dev, const char *string);
107 struct phy *devm_phy_optional_get(struct device *dev,
108 const char *string);
109 struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
110 const char *con_id);
111 struct phy *devm_of_phy_optional_get(struct device *dev,
112 struct device_node *np,
113 const char *con_id);
114 struct phy *devm_of_phy_get_by_index(struct device *dev,
115 struct device_node *np,
116 int index);
117
118 phy_get, devm_phy_get and devm_phy_optional_get can be used to get the PHY.
119 In the case of dt boot, the string arguments
120 should contain the phy name as given in the dt data and in the case of
121 non-dt boot, it should contain the label of the PHY. The two
122 devm_phy_get associates the device with the PHY using devres on
123 successful PHY get. On driver detach, release function is invoked on
124 the devres data and devres data is freed.
125 The _optional_get variants should be used when the phy is optional. These
126 functions will never return -ENODEV, but instead return NULL when
127 the phy cannot be found.
128 Some generic drivers, such as ehci, may use multiple phys. In this case,
129 devm_of_phy_get or devm_of_phy_get_by_index can be used to get a phy
130 reference based on name or index.
131
132 It should be noted that NULL is a valid phy reference. All phy
133 consumer calls on the NULL phy become NOPs. That is the release calls,
134 the phy_init() and phy_exit() calls, and phy_power_on() and
135 phy_power_off() calls are all NOP when applied to a NULL phy. The NULL
136 phy is useful in devices for handling optional phy devices.
137
138 Order of API calls
139 ==================
140
141 The general order of calls should be::
142
143 [devm_][of_]phy_get()
144 phy_init()
145 phy_power_on()
146 [phy_set_mode[_ext]()]
147 ...
148 phy_power_off()
149 phy_exit()
150 [[of_]phy_put()]
151
152 Some PHY drivers may not implement :c:func:`phy_init` or :c:func:`phy_power_on`,
153 but controllers should always call these functions to be compatible with other
154 PHYs. Some PHYs may require :c:func:`phy_set_mode <phy_set_mode_ext>`, while
155 others may use a default mode (typically configured via devicetree or other
156 firmware). For compatibility, you should always call this function if you know
157 what mode you will be using. Generally, this function should be called after
158 :c:func:`phy_power_on`, although some PHY drivers may allow it at any time.
159
160 Releasing a reference to the PHY
161 ================================
162
163 When the controller no longer needs the PHY, it has to release the reference
164 to the PHY it has obtained using the APIs mentioned in the above section. The
165 PHY framework provides 2 APIs to release a reference to the PHY.
166
167 ::
168
169 void phy_put(struct phy *phy);
170 void devm_phy_put(struct device *dev, struct phy *phy);
171
172 Both these APIs are used to release a reference to the PHY and devm_phy_put
173 destroys the devres associated with this PHY.
174
175 Destroying the PHY
176 ==================
177
178 When the driver that created the PHY is unloaded, it should destroy the PHY it
179 created using one of the following 2 APIs::
180
181 void phy_destroy(struct phy *phy);
182 void devm_phy_destroy(struct device *dev, struct phy *phy);
183
184 Both these APIs destroy the PHY and devm_phy_destroy destroys the devres
185 associated with this PHY.
186
187 PM Runtime
188 ==========
189
190 This subsystem is pm runtime enabled. So while creating the PHY,
191 pm_runtime_enable of the phy device created by this subsystem is called and
192 while destroying the PHY, pm_runtime_disable is called. Note that the phy
193 device created by this subsystem will be a child of the device that calls
194 phy_create (PHY provider device).
195
196 So pm_runtime_get_sync of the phy_device created by this subsystem will invoke
197 pm_runtime_get_sync of PHY provider device because of parent-child relationship.
198 It should also be noted that phy_power_on and phy_power_off performs
199 phy_pm_runtime_get_sync and phy_pm_runtime_put respectively.
200 There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
201 phy_pm_runtime_put and phy_pm_runtime_put_sync for performing PM operations.
202
203 PHY Mappings
204 ============
205
206 In order to get reference to a PHY without help from DeviceTree, the framework
207 offers lookups which can be compared to clkdev that allow clk structures to be
208 bound to devices. A lookup can be made during runtime when a handle to the
209 struct phy already exists.
210
211 The framework offers the following API for registering and unregistering the
212 lookups::
213
214 int phy_create_lookup(struct phy *phy, const char *con_id,
215 const char *dev_id);
216 void phy_remove_lookup(struct phy *phy, const char *con_id,
217 const char *dev_id);
218
219 DeviceTree Binding
220 ==================
221
222 The documentation for PHY dt binding can be found @
223 Documentation/devicetree/bindings/phy/phy-bindings.txt
224

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

PHY subsystem의 목적과 적용 범위

1-27

Kishon Vijay Abraham I가 작성한 이 문서는 Generic PHY Framework가 제공하는 API와 사용 방법을 설명합니다. PHY는 physical layer의 약자로, device를 실제 전송 medium에 연결합니다.

예를 들어 USB controller의 PHY는 serialization, de-serialization, encoding, decoding을 수행하고 필요한 data transmission rate를 확보합니다. 어떤 USB controller는 PHY 기능을 내부에 포함하고, 다른 controller는 external PHY를 사용합니다. Wireless LAN, Ethernet, SATA도 PHY를 사용하는 대표적인 peripheral입니다.

이 framework의 목적은 커널 곳곳에 흩어진 PHY driver를 `drivers/phy`로 모아 code reuse와 유지보수성을 높이는 것입니다. Controller 안에 PHY 기능이 내장된 장치가 아니라 external PHY를 사용하는 장치에만 적용됩니다.

External PHY의 위치
Peripheral controllerGeneric PHY consumer APIExternal PHYPhysical medium
PHY provider driver`drivers/phy`Serialization / encoding / link rate

Generic PHY Framework는 controller와 physical medium 사이의 외부 PHY를 공통 API로 관리합니다.

=============
PHY subsystem
=============

:Author: Kishon Vijay Abraham I <[email protected]>

This document explains the Generic PHY Framework along with the APIs provided,
and how-to-use.

Introduction
============

*PHY* is the abbreviation for physical layer. It is used to connect a device
to the physical medium e.g., the USB controller has a PHY to provide functions
such as serialization, de-serialization, encoding, decoding and is responsible
for obtaining the required data transmission rate. Note that some USB
controllers have PHY functionality embedded into it and others use an external
PHY. Other peripherals that use PHY include Wireless LAN, Ethernet,
SATA etc.

The intention of creating this framework is to bring the PHY drivers spread
all over the Linux kernel to drivers/phy to increase code re-use and for
better code maintainability.

This framework will be of use only to devices that use external PHY (PHY
functionality is not embedded within the controller).

PHY provider 등록과 해제

28-73

PHY provider는 하나 이상의 PHY instance를 구현하는 entity입니다. 단일 PHY provider에는 framework가 `of_phy_simple_xlate`라는 `of_xlate` 구현을 제공합니다. 여러 instance를 제공하면 provider가 자체 `of_xlate`를 구현해야 합니다. `of_xlate`는 DT boot에서만 사용됩니다.

`of_phy_provider_register(dev, xlate)`와 `devm_of_phy_provider_register(dev, xlate)` macro는 device와 `of_xlate`를 받아 각각 `__of_phy_provider_register()`와 `__devm_of_phy_provider_register()`를 호출합니다. DT boot의 모든 provider는 이 둘 중 하나로 등록해야 합니다.

Provider의 Device Tree node 아래에는 보통 PHY 하나를 나타내는 child node들이 있습니다. Binding이 context나 extensibility를 위해 child를 더 깊게 중첩한다면 `of_phy_provider_register_full()` 또는 `devm_of_phy_provider_register_full()`로 실제 child container node를 지정할 수 있습니다.

등록 해제에는 `of_phy_provider_unregister()`를 사용합니다. Managed provider는 `devm_of_phy_provider_unregister()`로 해제할 수 있으며 device 수명과 devres 정리를 맞춰야 합니다.

Provider 등록 API
상황API수명·xlate
단일 PHY, 직접 관리`of_phy_provider_register()``of_phy_simple_xlate` 사용 가능
단일 PHY, devres`devm_of_phy_provider_register()`Device detach에서 관리
중첩 child node`of_phy_provider_register_full()``children` node 지정
중첩 child + devres`devm_of_phy_provider_register_full()`Managed full registration
직접 해제`of_phy_provider_unregister()`Provider reference 종료
Managed 해제`devm_of_phy_provider_unregister()`Associated devres 정리

Registering/Unregistering the PHY provider
==========================================

PHY provider refers to an entity that implements one or more PHY instances.
For the simple case where the PHY provider implements only a single instance of
the PHY, the framework provides its own implementation of of_xlate in
of_phy_simple_xlate. If the PHY provider implements multiple instances, it
should provide its own implementation of of_xlate. of_xlate is used only for
dt boot case.

::

        #define of_phy_provider_register(dev, xlate)    \
                __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))

        #define devm_of_phy_provider_register(dev, xlate)       \
                __devm_of_phy_provider_register((dev), NULL, THIS_MODULE,
                                                (xlate))

of_phy_provider_register and devm_of_phy_provider_register macros can be used to
register the phy_provider and it takes device and of_xlate as
arguments. For the dt boot case, all PHY providers should use one of the above
2 macros to register the PHY provider.

Often the device tree nodes associated with a PHY provider will contain a set
of children that each represent a single PHY. Some bindings may nest the child
nodes within extra levels for context and extensibility, in which case the low
level of_phy_provider_register_full() and devm_of_phy_provider_register_full()
macros can be used to override the node containing the children.

::

        #define of_phy_provider_register_full(dev, children, xlate) \
                __of_phy_provider_register(dev, children, THIS_MODULE, xlate)

        #define devm_of_phy_provider_register_full(dev, children, xlate) \
                __devm_of_phy_provider_register_full(dev, children,
                                                     THIS_MODULE, xlate)

        void devm_of_phy_provider_unregister(struct device *dev,
                struct phy_provider *phy_provider);
        void of_phy_provider_unregister(struct phy_provider *phy_provider);

devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to
unregister the PHY.

PHY instance 생성과 private data

74-96

다른 peripheral controller가 PHY를 사용하려면 PHY driver가 instance를 생성해야 합니다. 직접 관리 방식은 `phy_create(dev, node, ops)`, device-managed 방식은 `devm_phy_create(dev, node, ops)`입니다.

두 API 모두 provider device pointer, 해당 Device Tree node, `struct phy_ops`를 받습니다. `phy_ops`는 `init`, `exit`, `power_on`, `power_off` 같은 PHY operation을 수행하는 function pointer 집합입니다.

Provider의 private data는 PHY 생성 후 `phy_set_drvdata()`로 연결하고, `phy_ops` callback 안에서 `phy_get_drvdata()`로 다시 가져옵니다.

PHY instance 생성
Provider device + DT node`phy_create()` / `devm_phy_create()``struct phy``phy_set_drvdata()`Provider private data
`struct phy_ops``init / exit / power_on / power_off``phy_get_drvdata()`

Provider state와 operation table을 PHY instance에 연결합니다.

Creating the PHY
================

The PHY driver should create the PHY in order for other peripheral controllers
to make use of it. The PHY framework provides 2 APIs to create the PHY.

::

        struct phy *phy_create(struct device *dev, struct device_node *node,
                               const struct phy_ops *ops);
        struct phy *devm_phy_create(struct device *dev,
                                    struct device_node *node,
                                    const struct phy_ops *ops);

The PHY drivers can use one of the above 2 APIs to create the PHY by passing
the device pointer and phy ops.
phy_ops is a set of function pointers for performing PHY operations such as
init, exit, power_on and power_off.

Inorder to dereference the private data (in phy_ops), the phy provider driver
can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
phy_ops to get back the private data.

Consumer의 PHY reference 획득과 optional PHY

97-137

Controller는 PHY를 사용하기 전에 reference를 얻어야 합니다. 기본 API는 `phy_get()`, `devm_phy_get()`, `devm_phy_optional_get()`입니다. DT boot에서는 string 인자가 DT data에 기록된 PHY name이고, non-DT boot에서는 PHY label입니다.

Managed get은 성공한 PHY reference를 consumer device와 devres로 연결합니다. Driver detach 때 release callback이 호출되고 devres data가 해제됩니다.

Optional PHY에는 `_optional_get` 변형을 사용합니다. `devm_phy_optional_get()`과 `devm_of_phy_optional_get()`은 PHY를 찾지 못해도 `-ENODEV`를 반환하지 않고 `NULL`을 반환합니다.

EHCI 같은 generic driver가 여러 PHY를 사용할 때는 `devm_of_phy_get()`으로 name 기반 reference를 얻거나 `devm_of_phy_get_by_index()`로 index 기반 reference를 얻을 수 있습니다.

`NULL`은 유효한 PHY reference입니다. `NULL`에 대한 release, `phy_init()`, `phy_exit()`, `phy_power_on()`, `phy_power_off()` consumer call은 모두 NOP가 됩니다. 이 규칙 덕분에 optional PHY를 위해 각 호출을 별도 조건문으로 감쌀 필요가 없습니다.

PHY reference 획득
API선택 기준없을 때관리
`phy_get()`DT name 또는 label오류직접 `phy_put()`
`devm_phy_get()`DT name 또는 label오류devres
`devm_phy_optional_get()`Optional name`NULL`devres
`devm_of_phy_get()`Node + connection ID오류devres
`devm_of_phy_optional_get()`Optional node + ID`NULL`devres
`devm_of_phy_get_by_index()`Node + index오류devres

Getting a reference to the PHY
==============================

Before the controller can make use of the PHY, it has to get a reference to
it. This framework provides the following APIs to get a reference to the PHY.

::

        struct phy *phy_get(struct device *dev, const char *string);
        struct phy *devm_phy_get(struct device *dev, const char *string);
        struct phy *devm_phy_optional_get(struct device *dev,
                                          const char *string);
        struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
                                    const char *con_id);
        struct phy *devm_of_phy_optional_get(struct device *dev,
                                             struct device_node *np,
                                             const char *con_id);
        struct phy *devm_of_phy_get_by_index(struct device *dev,
                                             struct device_node *np,
                                             int index);

phy_get, devm_phy_get and devm_phy_optional_get can be used to get the PHY.
In the case of dt boot, the string arguments
should contain the phy name as given in the dt data and in the case of
non-dt boot, it should contain the label of the PHY.  The two
devm_phy_get associates the device with the PHY using devres on
successful PHY get. On driver detach, release function is invoked on
the devres data and devres data is freed.
The _optional_get variants should be used when the phy is optional. These
functions will never return -ENODEV, but instead return NULL when
the phy cannot be found.
Some generic drivers, such as ehci, may use multiple phys. In this case,
devm_of_phy_get or devm_of_phy_get_by_index can be used to get a phy
reference based on name or index.

It should be noted that NULL is a valid phy reference. All phy
consumer calls on the NULL phy become NOPs. That is the release calls,
the phy_init() and phy_exit() calls, and phy_power_on() and
phy_power_off() calls are all NOP when applied to a NULL phy. The NULL
phy is useful in devices for handling optional phy devices.

Consumer API 호출 순서

138-159

일반 호출 순서는 `[devm_][of_]phy_get()`, `phy_init()`, `phy_power_on()`, 선택적인 `phy_set_mode[_ext]()`, 실제 사용, `phy_power_off()`, `phy_exit()`, 선택적인 `[[of_]phy_put()]`입니다.

일부 PHY driver가 `phy_init()` 또는 `phy_power_on()`을 구현하지 않더라도 controller는 다른 PHY와의 호환성을 위해 항상 호출해야 합니다.

어떤 PHY는 `phy_set_mode()` 또는 `phy_set_mode_ext()`가 필요하고, 다른 PHY는 Device Tree나 firmware의 default mode를 사용합니다. 사용할 mode를 알고 있다면 호환성을 위해 항상 설정해야 합니다. 일반적으로 `phy_power_on()` 뒤에 호출하지만, 일부 driver는 다른 시점도 허용합니다.

권장 PHY 수명 순서
`[devm_][of_]phy_get()``phy_init()``phy_power_on()``phy_set_mode[_ext]()`Use PHY`phy_power_off()``phy_exit()``[of_]phy_put()`

획득과 해제, init과 exit, power on과 off를 대칭으로 배치합니다.

Order of API calls
==================

The general order of calls should be::

    [devm_][of_]phy_get()
    phy_init()
    phy_power_on()
    [phy_set_mode[_ext]()]
    ...
    phy_power_off()
    phy_exit()
    [[of_]phy_put()]

Some PHY drivers may not implement :c:func:`phy_init` or :c:func:`phy_power_on`,
but controllers should always call these functions to be compatible with other
PHYs. Some PHYs may require :c:func:`phy_set_mode <phy_set_mode_ext>`, while
others may use a default mode (typically configured via devicetree or other
firmware). For compatibility, you should always call this function if you know
what mode you will be using. Generally, this function should be called after
:c:func:`phy_power_on`, although some PHY drivers may allow it at any time.

Reference 해제와 PHY 파괴

160-186

Controller가 PHY를 더 이상 사용하지 않으면 `phy_get()` 계열로 얻은 reference를 해제해야 합니다. `phy_put()`은 직접 reference를 반환하고, `devm_phy_put(dev, phy)`는 PHY와 연결된 devres도 파괴합니다.

PHY를 만든 provider driver가 unload될 때는 instance 자체를 파괴해야 합니다. 직접 생성한 PHY에는 `phy_destroy()`, managed PHY에는 `devm_phy_destroy()`를 사용합니다. 후자는 PHY를 파괴하면서 연결된 devres도 정리합니다.

Consumer reference 해제와 provider instance 파괴는 서로 다른 수명 단계입니다. 모든 consumer 사용이 끝난 뒤 provider의 등록·instance를 해제해야 합니다.

Reference와 instance 수명
소유자생성·획득종료Managed 효과
Consumer`phy_get()``phy_put()`없음
Consumer`devm_phy_get()``devm_phy_put()` 또는 detachdevres 파괴
Provider`phy_create()``phy_destroy()`없음
Provider`devm_phy_create()``devm_phy_destroy()` 또는 detachdevres 파괴

Releasing a reference to the PHY
================================

When the controller no longer needs the PHY, it has to release the reference
to the PHY it has obtained using the APIs mentioned in the above section. The
PHY framework provides 2 APIs to release a reference to the PHY.

::

        void phy_put(struct phy *phy);
        void devm_phy_put(struct device *dev, struct phy *phy);

Both these APIs are used to release a reference to the PHY and devm_phy_put
destroys the devres associated with this PHY.

Destroying the PHY
==================

When the driver that created the PHY is unloaded, it should destroy the PHY it
created using one of the following 2 APIs::

        void phy_destroy(struct phy *phy);
        void devm_phy_destroy(struct device *dev, struct phy *phy);

Both these APIs destroy the PHY and devm_phy_destroy destroys the devres
associated with this PHY.

PHY의 PM runtime 연동

187-202

PHY subsystem은 PM runtime을 사용합니다. PHY를 생성할 때 subsystem이 만든 `phy_device`에 `pm_runtime_enable()`을 호출하고, PHY를 파괴할 때 `pm_runtime_disable()`을 호출합니다.

이 `phy_device`는 `phy_create()`를 호출한 PHY provider device의 child입니다. Parent-child 관계 때문에 `phy_device`의 `pm_runtime_get_sync()`는 provider device의 `pm_runtime_get_sync()`도 호출하게 됩니다.

`phy_power_on()`은 `phy_pm_runtime_get_sync()`를 수행하고 `phy_power_off()`는 `phy_pm_runtime_put()`을 수행합니다. 별도 PM operation에는 export된 `phy_pm_runtime_get()`, `phy_pm_runtime_get_sync()`, `phy_pm_runtime_put()`, `phy_pm_runtime_put_sync()`를 사용할 수 있습니다.

PHY PM runtime 전파
`phy_power_on()``phy_pm_runtime_get_sync()`Child `phy_device`Parent PHY provider device
`phy_power_off()``phy_pm_runtime_put()`Runtime suspend path

Child phy_device의 runtime PM 요청이 parent provider device로 전파됩니다.

PM Runtime
==========

This subsystem is pm runtime enabled. So while creating the PHY,
pm_runtime_enable of the phy device created by this subsystem is called and
while destroying the PHY, pm_runtime_disable is called. Note that the phy
device created by this subsystem will be a child of the device that calls
phy_create (PHY provider device).

So pm_runtime_get_sync of the phy_device created by this subsystem will invoke
pm_runtime_get_sync of PHY provider device because of parent-child relationship.
It should also be noted that phy_power_on and phy_power_off performs
phy_pm_runtime_get_sync and phy_pm_runtime_put respectively.
There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
phy_pm_runtime_put and phy_pm_runtime_put_sync for performing PM operations.

Non-DT PHY mapping과 DeviceTree binding

203-223

DeviceTree 도움 없이 PHY reference를 얻기 위해 framework는 `clkdev` lookup과 유사한 PHY mapping을 제공합니다. 이미 `struct phy` handle이 있는 runtime 시점에 device와 connection ID를 연결할 수 있습니다.

`phy_create_lookup(phy, con_id, dev_id)`는 lookup을 등록하고, `phy_remove_lookup(phy, con_id, dev_id)`는 같은 mapping을 해제합니다.

PHY DeviceTree binding 문서는 원문이 가리키는 `Documentation/devicetree/bindings/phy/phy-bindings.txt`에서 확인할 수 있습니다.

PHY lookup
작업API
등록`phy_create_lookup()``phy`, `con_id`, `dev_id`
해제`phy_remove_lookup()``phy`, `con_id`, `dev_id`
DT binding`Documentation/devicetree/bindings/phy/phy-bindings.txt`Firmware description

PHY Mappings
============

In order to get reference to a PHY without help from DeviceTree, the framework
offers lookups which can be compared to clkdev that allow clk structures to be
bound to devices. A lookup can be made during runtime when a handle to the
struct phy already exists.

The framework offers the following API for registering and unregistering the
lookups::

        int phy_create_lookup(struct phy *phy, const char *con_id,
                              const char *dev_id);
        void phy_remove_lookup(struct phy *phy, const char *con_id,
                               const char *dev_id);

DeviceTree Binding
==================

The documentation for PHY dt binding can be found @
Documentation/devicetree/bindings/phy/phy-bindings.txt