1 /*
2 * Copyright 2020-2023 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #ifndef _FSL_PHY_H_
7 #define _FSL_PHY_H_
8
9 #include "fsl_common.h"
10
11 /*! @brief This abstract layer is to unify the PHY interface in SDK, let application
12 * use one set of PHY interfaces. The data structures are applicable to different
13 * PHYs.
14 */
15
16 /*******************************************************************************
17 * Definitions
18 ******************************************************************************/
19
20 /*! @note The following PHY registers are the IEEE802.3 standard definition, same register and bit field may
21 have different names in various PHYs, but the feature they represent should be same or very similar. */
22
23 /*! @brief Defines the IEEE802.3 standard PHY registers. */
24 #define PHY_BASICCONTROL_REG (0x00U) /*!< The PHY basic control register. */
25 #define PHY_BASICSTATUS_REG (0x01U) /*!< The PHY basic status register. */
26 #define PHY_ID1_REG (0x02U) /*!< The PHY ID one register. */
27 #define PHY_ID2_REG (0x03U) /*!< The PHY ID two register. */
28 #define PHY_AUTONEG_ADVERTISE_REG (0x04U) /*!< The PHY auto-negotiate advertise register. */
29 #define PHY_AUTONEG_LINKPARTNER_REG (0x05U) /*!< The PHY auto negotiation link partner ability register. */
30 #define PHY_AUTONEG_EXPANSION_REG (0x06U) /*!< The PHY auto negotiation expansion register. */
31 #define PHY_1000BASET_CONTROL_REG (0x09U) /*!< The PHY 1000BASE-T control register. */
32 #define PHY_MMD_ACCESS_CONTROL_REG (0x0DU) /*!< The PHY MMD access control register. */
33 #define PHY_MMD_ACCESS_DATA_REG (0x0EU) /*!< The PHY MMD access data register. */
34
35 /*! @brief Defines the mask flag in basic control register(Address 0x00). */
36 #define PHY_BCTL_SPEED1_MASK ((uint16_t)0x0040U) /*!< The PHY speed bit mask(MSB).*/
37 #define PHY_BCTL_ISOLATE_MASK ((uint16_t)0x0400U) /*!< The PHY isolate mask.*/
38 #define PHY_BCTL_DUPLEX_MASK ((uint16_t)0x0100U) /*!< The PHY duplex bit mask. */
39 #define PHY_BCTL_RESTART_AUTONEG_MASK ((uint16_t)0x0200U) /*!< The PHY restart auto negotiation mask. */
40 #define PHY_BCTL_AUTONEG_MASK ((uint16_t)0x1000U) /*!< The PHY auto negotiation bit mask. */
41 #define PHY_BCTL_SPEED0_MASK ((uint16_t)0x2000U) /*!< The PHY speed bit mask(LSB). */
42 #define PHY_BCTL_LOOP_MASK ((uint16_t)0x4000U) /*!< The PHY loop bit mask. */
43 #define PHY_BCTL_RESET_MASK ((uint16_t)0x8000U) /*!< The PHY reset bit mask. */
44
45 /*! @brief Defines the mask flag in basic status register(Address 0x01). */
46 #define PHY_BSTATUS_LINKSTATUS_MASK ((uint16_t)0x0004U) /*!< The PHY link status mask. */
47 #define PHY_BSTATUS_AUTONEGABLE_MASK ((uint16_t)0x0008U) /*!< The PHY auto-negotiation ability mask. */
48 #define PHY_BSTATUS_SPEEDUPLX_MASK ((uint16_t)0x001CU) /*!< The PHY speed and duplex mask. */
49 #define PHY_BSTATUS_AUTONEGCOMP_MASK ((uint16_t)0x0020U) /*!< The PHY auto-negotiation complete mask. */
50
51 /*! @brief Defines the mask flag in PHY auto-negotiation advertise register(Address 0x04). */
52 #define PHY_100BaseT4_ABILITY_MASK ((uint16_t)0x200U) /*!< The PHY have the T4 ability. */
53 #define PHY_100BASETX_FULLDUPLEX_MASK ((uint16_t)0x100U) /*!< The PHY has the 100M full duplex ability.*/
54 #define PHY_100BASETX_HALFDUPLEX_MASK ((uint16_t)0x080U) /*!< The PHY has the 100M full duplex ability.*/
55 #define PHY_10BASETX_FULLDUPLEX_MASK ((uint16_t)0x040U) /*!< The PHY has the 10M full duplex ability.*/
56 #define PHY_10BASETX_HALFDUPLEX_MASK ((uint16_t)0x020U) /*!< The PHY has the 10M full duplex ability.*/
57 #define PHY_IEEE802_3_SELECTOR_MASK ((uint16_t)0x001U) /*!< The message type being sent by Auto-Nego.*/
58
59 /*! @brief Defines the mask flag in the 1000BASE-T control register(Address 0x09). */
60 #define PHY_1000BASET_FULLDUPLEX_MASK ((uint16_t)0x200U) /*!< The PHY has the 1000M full duplex ability.*/
61 #define PHY_1000BASET_HALFDUPLEX_MASK ((uint16_t)0x100U) /*!< The PHY has the 1000M half duplex ability.*/
62
63 typedef struct _phy_handle phy_handle_t;
64 typedef struct _phy_config phy_config_t;
65
66 /*! @brief IEEE 802.3 Clause 22 MDIO write data. */
67 typedef status_t (*mdioWrite)(uint8_t phyAddr, uint8_t regAddr, uint16_t data);
68
69 /*! @brief IEEE 802.3 Clause 22 MDIO read data. */
70 typedef status_t (*mdioRead)(uint8_t phyAddr, uint8_t regAddr, uint16_t *pData);
71
72 /*! @brief IEEE 802.3 Clause 45 MDIO write data. */
73 typedef status_t (*mdioWriteExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t data);
74
75 /*! @brief IEEE 802.3 Clause 45 MDIO read data. */
76 typedef status_t (*mdioReadExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t *pData);
77
78 /*! @brief Defines the PHY link speed. */
79 typedef enum _phy_speed
80 {
81 kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */
82 kPHY_Speed100M, /*!< ENET PHY 100M speed. */
83 kPHY_Speed1000M /*!< ENET PHY 1000M speed. */
84 } phy_speed_t;
85
86 /*! @brief Defines the PHY link duplex. */
87 typedef enum _phy_duplex
88 {
89 kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */
90 kPHY_FullDuplex /*!< ENET PHY full duplex. */
91 } phy_duplex_t;
92
93 /*! @brief Defines the PHY loopback mode. */
94 typedef enum _phy_loop
95 {
96 kPHY_LocalLoop = 0U, /*!< ENET PHY local/digital loopback. */
97 kPHY_RemoteLoop, /*!< ENET PHY remote loopback. */
98 kPHY_ExternalLoop, /*!< ENET PHY external loopback. */
99 } phy_loop_t;
100
101 /*! @brief Defines the PHY MMD data access mode. */
102 typedef enum _phy_mmd_access_mode
103 {
104 kPHY_MMDAccessNoPostIncrement = (1U << 14), /*!< ENET PHY MMD access data with no address post increment. */
105 kPHY_MMDAccessRdWrPostIncrement =
106 (2U << 14), /*!< ENET PHY MMD access data with Read/Write address post increment. */
107 kPHY_MMDAccessWrPostIncrement = (3U << 14), /*!< ENET PHY MMD access data with Write address post increment. */
108 } phy_mmd_access_mode_t;
109
110 /*! @brief Defines the PHY interrupt type. */
111 typedef enum _phy_interrupt_type
112 {
113 kPHY_IntrDisable = 0U, /*!< ENET PHY interrupt disable. */
114 kPHY_IntrActiveLow, /*!< ENET PHY interrupt active low. */
115 kPHY_IntrActiveHigh, /*!< ENET PHY interrupt active high. */
116 } phy_interrupt_type_t;
117
118 /*! @brief PHY device operations. */
119 typedef struct _phy_operations
120 {
121 status_t (*phyInit)(phy_handle_t *handle, const phy_config_t *config);
122 status_t (*phyWrite)(phy_handle_t *handle, uint8_t phyReg, uint16_t data);
123 status_t (*phyRead)(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData);
124 status_t (*getAutoNegoStatus)(phy_handle_t *handle, bool *status);
125 status_t (*getLinkStatus)(phy_handle_t *handle, bool *status);
126 status_t (*getLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex);
127 status_t (*setLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex);
128 status_t (*enableLoopback)(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable);
129 status_t (*enableLinkInterrupt)(phy_handle_t *handle, phy_interrupt_type_t type);
130 status_t (*clearInterrupt)(phy_handle_t *handle);
131 } phy_operations_t;
132
133 /*! @brief Defines PHY configuration. */
134 struct _phy_config
135 {
136 uint8_t phyAddr; /*!< PHY address. */
137 void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
138 const phy_operations_t *ops; /*!< PHY operational method. */
139 phy_speed_t speed; /*!< PHY speed configuration. */
140 phy_duplex_t duplex; /*!< PHY duplex configuration. */
141 bool autoNeg; /*!< PHY auto-negotiation, true: enable, false: disable. */
142 bool enableEEE; /*!< PHY Energy Efficient Ethernet, true: enable, false: disable. */
143 phy_interrupt_type_t intrType; /*!< PHY interrupt configuration. */
144 };
145
146 /*! @brief PHY device handle. */
147 struct _phy_handle
148 {
149 uint8_t phyAddr; /*!< PHY address. */
150 void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
151 const phy_operations_t *ops; /*!< PHY operational method. */
152 };
153
154 /*******************************************************************************
155 * API
156 ******************************************************************************/
157
158 #if defined(__cplusplus)
159 extern "C" {
160 #endif
161
162 /*!
163 * @name PHY Driver
164 * @{
165 */
166
167 /*!
168 * @brief Initializes PHY.
169 * This function initializes PHY.
170 *
171 * @param handle PHY device handle.
172 * @param config PHY configuration.
173 * @retval kStatus_Success PHY initialization succeeds
174 * @retval kStatus_Fail PHY initialization fails
175 * @retval kStatus_Timeout PHY MDIO visit time out
176 */
PHY_Init(phy_handle_t * handle,const phy_config_t * config)177 static inline status_t PHY_Init(phy_handle_t *handle, const phy_config_t *config)
178 {
179 handle->ops = config->ops;
180 return handle->ops->phyInit(handle, config);
181 }
182 /*!
183 * @brief PHY Write function.
184 * This function writes data over the MDIO to the specified PHY register.
185 *
186 * @param handle PHY device handle.
187 * @param phyReg The PHY register.
188 * @param data The data written to the PHY register.
189 * @retval kStatus_Success PHY write success
190 * @retval kStatus_Timeout PHY MDIO visit time out
191 */
PHY_Write(phy_handle_t * handle,uint8_t phyReg,uint16_t data)192 static inline status_t PHY_Write(phy_handle_t *handle, uint8_t phyReg, uint16_t data)
193 {
194 return handle->ops->phyWrite(handle, phyReg, data);
195 }
196
197 /*!
198 * @brief PHY Read function.
199 * This interface reads data over the MDIO from the specified PHY register.
200 *
201 * @param handle PHY device handle.
202 * @param phyReg The PHY register address.
203 * @param pData The address to store the data read from the PHY register.
204 * @retval kStatus_Success PHY read success
205 * @retval kStatus_Timeout PHY MDIO visit time out
206 */
PHY_Read(phy_handle_t * handle,uint8_t phyReg,uint16_t * pData)207 static inline status_t PHY_Read(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData)
208 {
209 return handle->ops->phyRead(handle, phyReg, pData);
210 }
211
212 /*!
213 * @brief Gets the PHY auto-negotiation status.
214 *
215 * @param handle PHY device handle.
216 * @param status The auto-negotiation status of the PHY.
217 * - true the auto-negotiation is over.
218 * - false the auto-negotiation is on-going or not started.
219 * @retval kStatus_Success PHY gets status success
220 * @retval kStatus_Timeout PHY MDIO visit time out
221 */
PHY_GetAutoNegotiationStatus(phy_handle_t * handle,bool * status)222 static inline status_t PHY_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status)
223 {
224 return handle->ops->getAutoNegoStatus(handle, status);
225 }
226
227 /*!
228 * @brief Gets the PHY link status.
229 *
230 * @param handle PHY device handle.
231 * @param status The link up or down status of the PHY.
232 * - true the link is up.
233 * - false the link is down.
234 * @retval kStatus_Success PHY get link status success
235 * @retval kStatus_Timeout PHY MDIO visit time out
236 */
PHY_GetLinkStatus(phy_handle_t * handle,bool * status)237 static inline status_t PHY_GetLinkStatus(phy_handle_t *handle, bool *status)
238 {
239 return handle->ops->getLinkStatus(handle, status);
240 }
241
242 /*!
243 * @brief Gets the PHY link speed and duplex.
244 *
245 * @brief This function gets the speed and duplex mode of PHY. User can give one of speed
246 * and duplex address paramter and set the other as NULL if only wants to get one of them.
247 *
248 * @param handle PHY device handle.
249 * @param speed The address of PHY link speed.
250 * @param duplex The link duplex of PHY.
251 * @retval kStatus_Success PHY get link speed and duplex success
252 * @retval kStatus_Timeout PHY MDIO visit time out
253 */
PHY_GetLinkSpeedDuplex(phy_handle_t * handle,phy_speed_t * speed,phy_duplex_t * duplex)254 static inline status_t PHY_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex)
255 {
256 return handle->ops->getLinkSpeedDuplex(handle, speed, duplex);
257 }
258
259 /*!
260 * @brief Sets the PHY link speed and duplex.
261 *
262 * @param handle PHY device handle.
263 * @param speed Specified PHY link speed.
264 * @param duplex Specified PHY link duplex.
265 * @retval kStatus_Success PHY gets status success
266 * @retval kStatus_Timeout PHY MDIO visit time out
267 */
PHY_SetLinkSpeedDuplex(phy_handle_t * handle,phy_speed_t speed,phy_duplex_t duplex)268 static inline status_t PHY_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex)
269 {
270 return handle->ops->setLinkSpeedDuplex(handle, speed, duplex);
271 }
272
273 /*!
274 * @brief Enables/Disables PHY loopback mode.
275 *
276 * @param handle PHY device handle.
277 * @param mode The loopback mode to be enabled, please see "phy_loop_t".
278 * All loopback modes should not be set together, when one loopback mode is set
279 * another should be disabled.
280 * @param speed PHY speed for loopback mode.
281 * @param enable True to enable, false to disable.
282 * @retval kStatus_Success PHY get link speed and duplex success
283 * @retval kStatus_Timeout PHY MDIO visit time out
284 */
PHY_EnableLoopback(phy_handle_t * handle,phy_loop_t mode,phy_speed_t speed,bool enable)285 static inline status_t PHY_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable)
286 {
287 return handle->ops->enableLoopback(handle, mode, speed, enable);
288 }
289
290 /*!
291 * @brief Enables/Disables PHY link management interrupt.
292 *
293 * This function controls link status change interrupt. Application should get
294 * status through PHY_GetLinkStatus() and PHY_GetAutoNegotiationStatus() when
295 * interrupt triggers.
296 *
297 * @note Not all PHYs support link up, link down and auto auto-negotiation complete
298 * interrupt separately. Some PHY may combine link up/down or no link up or no
299 * auto-negotiation complete interrupt. The interrupt trigger situation depends
300 * on specific PHY.
301 *
302 * @param handle PHY device handle.
303 * @param type PHY interrupt type.
304 * @retval kStatus_Success PHY enables/disables interrupt success
305 * @retval kStatus_Timeout PHY MDIO visit time out
306 */
PHY_EnableLinkInterrupt(phy_handle_t * handle,phy_interrupt_type_t type)307 static inline status_t PHY_EnableLinkInterrupt(phy_handle_t *handle, phy_interrupt_type_t type)
308 {
309 return handle->ops->enableLinkInterrupt(handle, type);
310 }
311
312 /*!
313 * @brief Clears PHY interrupt status.
314 * @note Usually this API clears all interrupts of PHY because related register
315 * flags are read clear.
316 *
317 * @param handle PHY device handle.
318 * @retval kStatus_Success PHY read and clear interrupt success
319 * @retval kStatus_Timeout PHY MDIO visit time out
320 */
PHY_ClearInterrupt(phy_handle_t * handle)321 static inline status_t PHY_ClearInterrupt(phy_handle_t *handle)
322 {
323 return handle->ops->clearInterrupt(handle);
324 }
325
326 /* @} */
327
328 #if defined(__cplusplus)
329 }
330 #endif
331
332 /*! @}*/
333 #endif
334