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 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_PHY_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_PHY_H_
15
16 /**
17 * @brief Ethernet PHY Interface
18 * @defgroup ethernet_phy Ethernet PHY Interface
19 * @since 2.7
20 * @version 0.8.0
21 * @ingroup networking
22 * @{
23 */
24 #include <zephyr/types.h>
25 #include <zephyr/device.h>
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 /** @brief Ethernet link speeds. */
32 enum phy_link_speed {
33 /** 10Base-T Half-Duplex */
34 LINK_HALF_10BASE_T = BIT(0),
35 /** 10Base-T Full-Duplex */
36 LINK_FULL_10BASE_T = BIT(1),
37 /** 100Base-T Half-Duplex */
38 LINK_HALF_100BASE_T = BIT(2),
39 /** 100Base-T Full-Duplex */
40 LINK_FULL_100BASE_T = BIT(3),
41 /** 1000Base-T Half-Duplex */
42 LINK_HALF_1000BASE_T = BIT(4),
43 /** 1000Base-T Full-Duplex */
44 LINK_FULL_1000BASE_T = BIT(5),
45 };
46
47 /**
48 * @brief Check if phy link is full duplex.
49 *
50 * @param x Link capabilities
51 *
52 * @return True if link is full duplex, false if not.
53 */
54 #define PHY_LINK_IS_FULL_DUPLEX(x) (x & (BIT(1) | BIT(3) | BIT(5)))
55
56 /**
57 * @brief Check if phy link speed is 1 Gbit/sec.
58 *
59 * @param x Link capabilities
60 *
61 * @return True if link is 1 Gbit/sec, false if not.
62 */
63 #define PHY_LINK_IS_SPEED_1000M(x) (x & (BIT(4) | BIT(5)))
64
65 /**
66 * @brief Check if phy link speed is 100 Mbit/sec.
67 *
68 * @param x Link capabilities
69 *
70 * @return True if link is 1 Mbit/sec, false if not.
71 */
72 #define PHY_LINK_IS_SPEED_100M(x) (x & (BIT(2) | BIT(3)))
73
74 /** @brief Link state */
75 struct phy_link_state {
76 /** Link speed */
77 enum phy_link_speed speed;
78 /** When true the link is active and connected */
79 bool is_up;
80 };
81
82 /**
83 * @typedef phy_callback_t
84 * @brief Define the callback function signature for
85 * `phy_link_callback_set()` function.
86 *
87 * @param dev PHY device structure
88 * @param state Pointer to link_state structure.
89 * @param user_data Pointer to data specified by user
90 */
91 typedef void (*phy_callback_t)(const struct device *dev,
92 struct phy_link_state *state,
93 void *user_data);
94
95 /**
96 * @cond INTERNAL_HIDDEN
97 *
98 * These are for internal use only, so skip these in
99 * public documentation.
100 */
101 __subsystem struct ethphy_driver_api {
102 /** Get link state */
103 int (*get_link)(const struct device *dev,
104 struct phy_link_state *state);
105
106 /** Configure link */
107 int (*cfg_link)(const struct device *dev,
108 enum phy_link_speed adv_speeds);
109
110 /** Set callback to be invoked when link state changes. */
111 int (*link_cb_set)(const struct device *dev, phy_callback_t cb,
112 void *user_data);
113
114 /** Read PHY register */
115 int (*read)(const struct device *dev, uint16_t reg_addr,
116 uint32_t *data);
117
118 /** Write PHY register */
119 int (*write)(const struct device *dev, uint16_t reg_addr,
120 uint32_t data);
121 };
122 /**
123 * @endcond
124 */
125
126 /**
127 * @brief Configure PHY link
128 *
129 * This route configures the advertised link speeds.
130 *
131 * @param[in] dev PHY device structure
132 * @param speeds OR'd link speeds to be advertised by the PHY
133 *
134 * @retval 0 If successful.
135 * @retval -EIO If communication with PHY failed.
136 * @retval -ENOTSUP If not supported.
137 */
phy_configure_link(const struct device * dev,enum phy_link_speed speeds)138 static inline int phy_configure_link(const struct device *dev,
139 enum phy_link_speed speeds)
140 {
141 const struct ethphy_driver_api *api =
142 (const struct ethphy_driver_api *)dev->api;
143
144 return api->cfg_link(dev, speeds);
145 }
146
147 /**
148 * @brief Get PHY link state
149 *
150 * Returns the current state of the PHY link. This can be used by
151 * to determine when a link is up and the negotiated link speed.
152 *
153 *
154 * @param[in] dev PHY device structure
155 * @param state Pointer to receive PHY state
156 *
157 * @retval 0 If successful.
158 * @retval -EIO If communication with PHY failed.
159 */
phy_get_link_state(const struct device * dev,struct phy_link_state * state)160 static inline int phy_get_link_state(const struct device *dev,
161 struct phy_link_state *state)
162 {
163 const struct ethphy_driver_api *api =
164 (const struct ethphy_driver_api *)dev->api;
165
166 return api->get_link(dev, state);
167 }
168
169 /**
170 * @brief Set link state change callback
171 *
172 * Sets a callback that is invoked when link state changes. This is the
173 * preferred method for ethernet drivers to be notified of the PHY link
174 * state change.
175 *
176 * @param[in] dev PHY device structure
177 * @param callback Callback handler
178 * @param user_data Pointer to data specified by user.
179 *
180 * @retval 0 If successful.
181 * @retval -ENOTSUP If not supported.
182 */
phy_link_callback_set(const struct device * dev,phy_callback_t callback,void * user_data)183 static inline int phy_link_callback_set(const struct device *dev,
184 phy_callback_t callback,
185 void *user_data)
186 {
187 const struct ethphy_driver_api *api =
188 (const struct ethphy_driver_api *)dev->api;
189
190 return api->link_cb_set(dev, callback, user_data);
191 }
192
193 /**
194 * @brief Read PHY registers
195 *
196 * This routine provides a generic interface to read from a PHY register.
197 *
198 * @param[in] dev PHY device structure
199 * @param[in] reg_addr Register address
200 * @param value Pointer to receive read value
201 *
202 * @retval 0 If successful.
203 * @retval -EIO If communication with PHY failed.
204 */
phy_read(const struct device * dev,uint16_t reg_addr,uint32_t * value)205 static inline int phy_read(const struct device *dev, uint16_t reg_addr,
206 uint32_t *value)
207 {
208 const struct ethphy_driver_api *api =
209 (const struct ethphy_driver_api *)dev->api;
210
211 return api->read(dev, reg_addr, value);
212 }
213
214 /**
215 * @brief Write PHY register
216 *
217 * This routine provides a generic interface to write to a PHY register.
218 *
219 * @param[in] dev PHY device structure
220 * @param[in] reg_addr Register address
221 * @param[in] value Value to write
222 *
223 * @retval 0 If successful.
224 * @retval -EIO If communication with PHY failed.
225 */
phy_write(const struct device * dev,uint16_t reg_addr,uint32_t value)226 static inline int phy_write(const struct device *dev, uint16_t reg_addr,
227 uint32_t value)
228 {
229 const struct ethphy_driver_api *api =
230 (const struct ethphy_driver_api *)dev->api;
231
232 return api->write(dev, reg_addr, value);
233 }
234
235
236 #ifdef __cplusplus
237 }
238 #endif
239
240 /**
241 * @}
242 */
243
244 #endif /* ZEPHYR_INCLUDE_DRIVERS_PHY_H_ */
245