Line data Source code
1 1 : /**
2 : * @file
3 : *
4 : * @brief Public APIs for Ethernet PHY drivers.
5 : */
6 :
7 : /*
8 : * Copyright (c) 2021 IP-Logix Inc.
9 : * Copyright 2022 NXP
10 : * Copyright (c) 2025 Aerlync Labs Inc.
11 : *
12 : * SPDX-License-Identifier: Apache-2.0
13 : */
14 : #ifndef ZEPHYR_INCLUDE_DRIVERS_PHY_H_
15 : #define ZEPHYR_INCLUDE_DRIVERS_PHY_H_
16 :
17 : /**
18 : * @brief Ethernet PHY Interface
19 : * @defgroup ethernet_phy Ethernet PHY Interface
20 : * @since 2.7
21 : * @version 0.8.0
22 : * @ingroup networking
23 : * @{
24 : */
25 : #include <zephyr/types.h>
26 : #include <zephyr/device.h>
27 : #include <zephyr/sys/util_macro.h>
28 : #include <errno.h>
29 :
30 : #ifdef __cplusplus
31 : extern "C" {
32 : #endif
33 :
34 : /** @brief Ethernet link speeds. */
35 1 : enum phy_link_speed {
36 : /** 10Base Half-Duplex */
37 : LINK_HALF_10BASE = BIT(0),
38 : /** 10Base Full-Duplex */
39 : LINK_FULL_10BASE = BIT(1),
40 : /** 100Base Half-Duplex */
41 : LINK_HALF_100BASE = BIT(2),
42 : /** 100Base Full-Duplex */
43 : LINK_FULL_100BASE = BIT(3),
44 : /** 1000Base Half-Duplex */
45 : LINK_HALF_1000BASE = BIT(4),
46 : /** 1000Base Full-Duplex */
47 : LINK_FULL_1000BASE = BIT(5),
48 : /** 2.5GBase Full-Duplex */
49 : LINK_FULL_2500BASE = BIT(6),
50 : /** 5GBase Full-Duplex */
51 : LINK_FULL_5000BASE = BIT(7),
52 : };
53 :
54 : /**
55 : * @brief Check if phy link is full duplex.
56 : *
57 : * @param x Link capabilities
58 : *
59 : * @return True if link is full duplex, false if not.
60 : */
61 1 : #define PHY_LINK_IS_FULL_DUPLEX(x) \
62 : (x & (LINK_FULL_10BASE | LINK_FULL_100BASE | LINK_FULL_1000BASE | LINK_FULL_2500BASE | \
63 : LINK_FULL_5000BASE))
64 :
65 : /**
66 : * @brief Check if phy link speed is 1 Gbit/sec.
67 : *
68 : * @param x Link capabilities
69 : *
70 : * @return True if link is 1 Gbit/sec, false if not.
71 : */
72 1 : #define PHY_LINK_IS_SPEED_1000M(x) (x & (LINK_HALF_1000BASE | LINK_FULL_1000BASE))
73 :
74 : /**
75 : * @brief Check if phy link speed is 100 Mbit/sec.
76 : *
77 : * @param x Link capabilities
78 : *
79 : * @return True if link is 100 Mbit/sec, false if not.
80 : */
81 1 : #define PHY_LINK_IS_SPEED_100M(x) (x & (LINK_HALF_100BASE | LINK_FULL_100BASE))
82 :
83 : /**
84 : * @brief Check if phy link speed is 10 Mbit/sec.
85 : *
86 : * @param x Link capabilities
87 : *
88 : * @return True if link is 10 Mbit/sec, false if not.
89 : */
90 1 : #define PHY_LINK_IS_SPEED_10M(x) (x & (LINK_HALF_10BASE | LINK_FULL_10BASE))
91 :
92 : /** @brief Link state */
93 1 : struct phy_link_state {
94 : /** Link speed */
95 1 : enum phy_link_speed speed;
96 : /** When true the link is active and connected */
97 1 : bool is_up;
98 : };
99 :
100 : /** @brief Ethernet configure link flags. */
101 1 : enum phy_cfg_link_flag {
102 : /** Auto-negotiation disable */
103 : PHY_FLAG_AUTO_NEGOTIATION_DISABLED = BIT(0),
104 : };
105 :
106 : /** @brief PLCA (Physical Layer Collision Avoidance) Reconciliation Sublayer configurations */
107 1 : struct phy_plca_cfg {
108 : /** PLCA register map version */
109 1 : uint8_t version;
110 : /** PLCA configured mode (enable/disable) */
111 1 : bool enable;
112 : /** PLCA local node identifier */
113 1 : uint8_t node_id;
114 : /** PLCA node count */
115 1 : uint8_t node_count;
116 : /** Additional frames a node is allowed to send in single transmit opportunity (TO) */
117 1 : uint8_t burst_count;
118 : /** Wait time for the MAC to send a new frame before interrupting the burst */
119 1 : uint8_t burst_timer;
120 : /** PLCA to_timer in bit-times, which determines the PLCA transmit opportunity */
121 1 : uint8_t to_timer;
122 : };
123 :
124 : /**
125 : * @brief Write PHY PLCA configuration
126 : *
127 : * This routine provides a generic interface to configure PHY PLCA settings.
128 : *
129 : * @param[in] dev PHY device structure
130 : * @param[in] plca_cfg Pointer to plca configuration structure
131 : *
132 : * @retval 0 If successful.
133 : * @retval -EIO If communication with PHY failed.
134 : */
135 1 : int genphy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg);
136 :
137 : /**
138 : * @brief Read PHY PLCA configuration
139 : *
140 : * This routine provides a generic interface to get PHY PLCA settings.
141 : *
142 : * @param[in] dev PHY device structure
143 : * @param plca_cfg Pointer to plca configuration structure
144 : *
145 : * @retval 0 If successful.
146 : * @retval -EIO If communication with PHY failed.
147 : */
148 1 : int genphy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg);
149 :
150 : /**
151 : * @brief Read PHY PLCA status
152 : *
153 : * This routine provides a generic interface to get PHY PLCA status.
154 : *
155 : * @param[in] dev PHY device structure
156 : * @param plca_status Pointer to plca status
157 : *
158 : * @retval 0 If successful.
159 : * @retval -EIO If communication with PHY failed.
160 : */
161 1 : int genphy_get_plca_sts(const struct device *dev, bool *plca_status);
162 :
163 : /**
164 : * @typedef phy_callback_t
165 : * @brief Define the callback function signature for
166 : * `phy_link_callback_set()` function.
167 : *
168 : * @param dev PHY device structure
169 : * @param state Pointer to link_state structure.
170 : * @param user_data Pointer to data specified by user
171 : */
172 1 : typedef void (*phy_callback_t)(const struct device *dev, struct phy_link_state *state,
173 : void *user_data);
174 :
175 : /**
176 : * @cond INTERNAL_HIDDEN
177 : *
178 : * These are for internal use only, so skip these in
179 : * public documentation.
180 : */
181 : __subsystem struct ethphy_driver_api {
182 : /** Get link state */
183 : int (*get_link)(const struct device *dev, struct phy_link_state *state);
184 :
185 : /** Configure link */
186 : int (*cfg_link)(const struct device *dev, enum phy_link_speed adv_speeds,
187 : enum phy_cfg_link_flag flags);
188 :
189 : /** Set callback to be invoked when link state changes. Driver has to invoke
190 : * callback once after setting it, even if link state has not changed.
191 : */
192 : int (*link_cb_set)(const struct device *dev, phy_callback_t cb, void *user_data);
193 :
194 : /** Read PHY register */
195 : int (*read)(const struct device *dev, uint16_t reg_addr, uint32_t *data);
196 :
197 : /** Write PHY register */
198 : int (*write)(const struct device *dev, uint16_t reg_addr, uint32_t data);
199 :
200 : /** Read PHY C45 register */
201 : int (*read_c45)(const struct device *dev, uint8_t devad, uint16_t regad, uint16_t *data);
202 :
203 : /** Write PHY C45 register */
204 : int (*write_c45)(const struct device *dev, uint8_t devad, uint16_t regad, uint16_t data);
205 :
206 : /* Set PLCA settings */
207 : int (*set_plca_cfg)(const struct device *dev, struct phy_plca_cfg *plca_cfg);
208 :
209 : /* Get PLCA settings */
210 : int (*get_plca_cfg)(const struct device *dev, struct phy_plca_cfg *plca_cfg);
211 :
212 : /* Get PLCA status */
213 : int (*get_plca_sts)(const struct device *dev, bool *plca_sts);
214 : };
215 : /**
216 : * @endcond
217 : */
218 :
219 : /**
220 : * @brief Configure PHY link
221 : *
222 : * This route configures the advertised link speeds.
223 : *
224 : * @param[in] dev PHY device structure
225 : * @param speeds OR'd link speeds to be advertised by the PHY
226 : * @param flags OR'd flags to control the link configuration or 0.
227 : *
228 : * @retval 0 If successful.
229 : * @retval -EIO If communication with PHY failed.
230 : * @retval -ENOTSUP If not supported.
231 : * @retval -EALREADY If already configured with the same speeds and flags.
232 : */
233 1 : static inline int phy_configure_link(const struct device *dev, enum phy_link_speed speeds,
234 : enum phy_cfg_link_flag flags)
235 : {
236 : if (DEVICE_API_GET(ethphy, dev)->cfg_link == NULL) {
237 : return -ENOSYS;
238 : }
239 :
240 : /* Check if only one speed is set, when auto-negotiation is disabled */
241 : if ((flags & PHY_FLAG_AUTO_NEGOTIATION_DISABLED) && !IS_POWER_OF_TWO(speeds)) {
242 : return -EINVAL;
243 : }
244 :
245 : return DEVICE_API_GET(ethphy, dev)->cfg_link(dev, speeds, flags);
246 : }
247 :
248 : /**
249 : * @brief Get PHY link state
250 : *
251 : * Returns the current state of the PHY link. This can be used by
252 : * to determine when a link is up and the negotiated link speed.
253 : *
254 : *
255 : * @param[in] dev PHY device structure
256 : * @param state Pointer to receive PHY state
257 : *
258 : * @retval 0 If successful.
259 : * @retval -EIO If communication with PHY failed.
260 : */
261 1 : static inline int phy_get_link_state(const struct device *dev, struct phy_link_state *state)
262 : {
263 : if (DEVICE_API_GET(ethphy, dev)->get_link == NULL) {
264 : return -ENOSYS;
265 : }
266 :
267 : return DEVICE_API_GET(ethphy, dev)->get_link(dev, state);
268 : }
269 :
270 : /**
271 : * @brief Set link state change callback
272 : *
273 : * Sets a callback that is invoked when link state changes. This is the
274 : * preferred method for ethernet drivers to be notified of the PHY link
275 : * state change. The callback will be invoked once after setting it,
276 : * even if link state has not changed. There can only one callback
277 : * function set and active at a time. This function is mainly used
278 : * by ethernet drivers to register a callback to be notified of
279 : * link state changes and should therefore not be used by applications.
280 : *
281 : * @param[in] dev PHY device structure
282 : * @param callback Callback handler
283 : * @param user_data Pointer to data specified by user.
284 : *
285 : * @retval 0 If successful.
286 : * @retval -ENOTSUP If not supported.
287 : */
288 1 : static inline int phy_link_callback_set(const struct device *dev, phy_callback_t callback,
289 : void *user_data)
290 : {
291 : if (DEVICE_API_GET(ethphy, dev)->link_cb_set == NULL) {
292 : return -ENOSYS;
293 : }
294 :
295 : return DEVICE_API_GET(ethphy, dev)->link_cb_set(dev, callback, user_data);
296 : }
297 :
298 : /**
299 : * @brief Read PHY registers
300 : *
301 : * This routine provides a generic interface to read from a PHY register.
302 : *
303 : * @param[in] dev PHY device structure
304 : * @param[in] reg_addr Register address
305 : * @param value Pointer to receive read value
306 : *
307 : * @retval 0 If successful.
308 : * @retval -EIO If communication with PHY failed.
309 : */
310 1 : static inline int phy_read(const struct device *dev, uint16_t reg_addr, uint32_t *value)
311 : {
312 : if (DEVICE_API_GET(ethphy, dev)->read == NULL) {
313 : return -ENOSYS;
314 : }
315 :
316 : return DEVICE_API_GET(ethphy, dev)->read(dev, reg_addr, value);
317 : }
318 :
319 : /**
320 : * @brief Write PHY register
321 : *
322 : * This routine provides a generic interface to write to a PHY register.
323 : *
324 : * @param[in] dev PHY device structure
325 : * @param[in] reg_addr Register address
326 : * @param[in] value Value to write
327 : *
328 : * @retval 0 If successful.
329 : * @retval -EIO If communication with PHY failed.
330 : */
331 1 : static inline int phy_write(const struct device *dev, uint16_t reg_addr, uint32_t value)
332 : {
333 : if (DEVICE_API_GET(ethphy, dev)->write == NULL) {
334 : return -ENOSYS;
335 : }
336 :
337 : return DEVICE_API_GET(ethphy, dev)->write(dev, reg_addr, value);
338 : }
339 :
340 : /**
341 : * @brief Read PHY C45 register
342 : *
343 : * This routine provides a generic interface to read to a PHY C45 register.
344 : *
345 : * @param[in] dev PHY device structure
346 : * @param[in] devad Device address
347 : * @param[in] regad Register address
348 : * @param data Pointer to receive read data
349 : *
350 : * @retval 0 If successful.
351 : * @retval -EIO If communication with PHY failed.
352 : */
353 1 : static inline int phy_read_c45(const struct device *dev, uint8_t devad, uint16_t regad,
354 : uint16_t *data)
355 : {
356 : if (DEVICE_API_GET(ethphy, dev)->read_c45 == NULL) {
357 : return -ENOSYS;
358 : }
359 :
360 : return DEVICE_API_GET(ethphy, dev)->read_c45(dev, devad, regad, data);
361 : }
362 :
363 : /**
364 : * @brief Write PHY C45 register
365 : *
366 : * This routine provides a generic interface to write to a PHY C45 register.
367 : *
368 : * @param[in] dev PHY device structure
369 : * @param[in] devad Device address
370 : * @param[in] regad Register address
371 : * @param[in] data Data to write
372 : *
373 : * @retval 0 If successful.
374 : * @retval -EIO If communication with PHY failed.
375 : */
376 1 : static inline int phy_write_c45(const struct device *dev, uint8_t devad, uint16_t regad,
377 : uint16_t data)
378 : {
379 : if (DEVICE_API_GET(ethphy, dev)->write_c45 == NULL) {
380 : return -ENOSYS;
381 : }
382 :
383 : return DEVICE_API_GET(ethphy, dev)->write_c45(dev, devad, regad, data);
384 : }
385 :
386 : /**
387 : * @brief Write PHY PLCA configuration
388 : *
389 : * This routine provides a generic interface to configure PHY PLCA settings.
390 : *
391 : * @param[in] dev PHY device structure
392 : * @param[in] plca_cfg Pointer to plca configuration structure
393 : *
394 : * @retval 0 If successful.
395 : * @retval -EIO If communication with PHY failed.
396 : */
397 1 : static inline int phy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
398 : {
399 : if (DEVICE_API_GET(ethphy, dev)->set_plca_cfg == NULL) {
400 : return -ENOSYS;
401 : }
402 :
403 : return DEVICE_API_GET(ethphy, dev)->set_plca_cfg(dev, plca_cfg);
404 : }
405 :
406 : /**
407 : * @brief Read PHY PLCA configuration
408 : *
409 : * This routine provides a generic interface to get PHY PLCA settings.
410 : *
411 : * @param[in] dev PHY device structure
412 : * @param plca_cfg Pointer to plca configuration structure
413 : *
414 : * @retval 0 If successful.
415 : * @retval -EIO If communication with PHY failed.
416 : */
417 1 : static inline int phy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
418 : {
419 : if (DEVICE_API_GET(ethphy, dev)->get_plca_cfg == NULL) {
420 : return -ENOSYS;
421 : }
422 :
423 : return DEVICE_API_GET(ethphy, dev)->get_plca_cfg(dev, plca_cfg);
424 : }
425 :
426 : /**
427 : * @brief Read PHY PLCA status
428 : *
429 : * This routine provides a generic interface to get PHY PLCA status.
430 : *
431 : * @param[in] dev PHY device structure
432 : * @param plca_status Pointer to plca status
433 : *
434 : * @retval 0 If successful.
435 : * @retval -EIO If communication with PHY failed.
436 : */
437 1 : static inline int phy_get_plca_sts(const struct device *dev, bool *plca_status)
438 : {
439 : if (DEVICE_API_GET(ethphy, dev)->get_plca_sts == NULL) {
440 : return -ENOSYS;
441 : }
442 :
443 : return DEVICE_API_GET(ethphy, dev)->get_plca_sts(dev, plca_status);
444 : }
445 :
446 : #ifdef __cplusplus
447 : }
448 : #endif
449 :
450 : /**
451 : * @}
452 : */
453 :
454 : #endif /* ZEPHYR_INCLUDE_DRIVERS_PHY_H_ */
|