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