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