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 /*! @brief Defines the IEEE802.3 standard MDIO Manageable Device addresses. */
64 #define PHY_MMD_PMAPMD (1U)
65 #define PHY_MMD_WIS (2U)
66 #define PHY_MMD_PCS (3U)
67 #define PHY_MMD_PHY_XS (4U)
68 #define PHY_MMD_DTE_XS (5U)
69 #define PHY_MMD_TC (6U)
70 #define PHY_MMD_AN (7U)
71 #define PHY_MMD_PMA1 (8U)
72 #define PHY_MMD_PMA2 (9U)
73 #define PHY_MMD_PMA3 (10U)
74 #define PHY_MMD_PMA4 (11U)
75 #define PHY_MMD_OFDM_PMAPMD (12U)
76 #define PHY_MMD_POWER_UNIT (13U)
77 #define PHY_MMD_C22EXT (29U)
78 #define PHY_MMD_VEND1 (30U)
79 #define PHY_MMD_VEND2 (31U)
80
81 typedef struct _phy_handle phy_handle_t;
82 typedef struct _phy_config phy_config_t;
83
84 /*! @brief IEEE 802.3 Clause 22 MDIO write data. */
85 typedef status_t (*mdioWrite)(uint8_t phyAddr, uint8_t regAddr, uint16_t data);
86
87 /*! @brief IEEE 802.3 Clause 22 MDIO read data. */
88 typedef status_t (*mdioRead)(uint8_t phyAddr, uint8_t regAddr, uint16_t *pData);
89
90 /*! @brief IEEE 802.3 Clause 45 MDIO write data. */
91 typedef status_t (*mdioWriteExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t data);
92
93 /*! @brief IEEE 802.3 Clause 45 MDIO read data. */
94 typedef status_t (*mdioReadExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t *pData);
95
96 /*! @brief Defines the PHY link speed. */
97 typedef enum _phy_speed
98 {
99 kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */
100 kPHY_Speed100M, /*!< ENET PHY 100M speed. */
101 kPHY_Speed1000M, /*!< ENET PHY 1000M speed. */
102 kPHY_Speed2500M, /*!< ENET PHY 2.5G speed. */
103 kPHY_Speed5G, /*!< ENET PHY 5G speed. */
104 kPHY_Speed10G /*!< ENET PHY 10G speed. */
105 } phy_speed_t;
106
107 /*! @brief Defines the PHY link duplex. */
108 typedef enum _phy_duplex
109 {
110 kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */
111 kPHY_FullDuplex /*!< ENET PHY full duplex. */
112 } phy_duplex_t;
113
114 /*! @brief Defines the PHY loopback mode. */
115 typedef enum _phy_loop
116 {
117 kPHY_LocalLoop = 0U, /*!< ENET PHY local/digital loopback. */
118 kPHY_RemoteLoop, /*!< ENET PHY remote loopback. */
119 kPHY_ExternalLoop, /*!< ENET PHY external loopback. */
120 } phy_loop_t;
121
122 /*! @brief Defines the PHY MMD data access mode. */
123 typedef enum _phy_mmd_access_mode
124 {
125 kPHY_MMDAccessNoPostIncrement = (1U << 14), /*!< ENET PHY MMD access data with no address post increment. */
126 kPHY_MMDAccessRdWrPostIncrement =
127 (2U << 14), /*!< ENET PHY MMD access data with Read/Write address post increment. */
128 kPHY_MMDAccessWrPostIncrement = (3U << 14), /*!< ENET PHY MMD access data with Write address post increment. */
129 } phy_mmd_access_mode_t;
130
131 /*! @brief Defines the PHY interrupt type. */
132 typedef enum _phy_interrupt_type
133 {
134 kPHY_IntrDisable = 0U, /*!< ENET PHY interrupt disable. */
135 kPHY_IntrActiveLow, /*!< ENET PHY interrupt active low. */
136 kPHY_IntrActiveHigh, /*!< ENET PHY interrupt active high. */
137 } phy_interrupt_type_t;
138
139 /*! @brief PHY device operations. */
140 typedef struct _phy_operations
141 {
142 status_t (*phyInit)(phy_handle_t *handle, const phy_config_t *config);
143 status_t (*phyWrite)(phy_handle_t *handle, uint8_t phyReg, uint16_t data);
144 status_t (*phyRead)(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData);
145 status_t (*phyWriteC45)(phy_handle_t *handle, uint8_t devAddr, uint16_t regAddr, uint16_t data);
146 status_t (*phyReadC45)(phy_handle_t *handle, uint8_t devAddr, uint16_t regAddr, uint16_t *pdata);
147 status_t (*getAutoNegoStatus)(phy_handle_t *handle, bool *status);
148 status_t (*getLinkStatus)(phy_handle_t *handle, bool *status);
149 status_t (*getLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex);
150 status_t (*setLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex);
151 status_t (*enableLoopback)(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable);
152 status_t (*enableLinkInterrupt)(phy_handle_t *handle, phy_interrupt_type_t type);
153 status_t (*clearInterrupt)(phy_handle_t *handle);
154 } phy_operations_t;
155
156 /*! @brief Defines PHY configuration. */
157 struct _phy_config
158 {
159 uint8_t phyAddr; /*!< PHY address. */
160 void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
161 const phy_operations_t *ops; /*!< PHY operational method. */
162 phy_speed_t speed; /*!< PHY speed configuration. */
163 phy_duplex_t duplex; /*!< PHY duplex configuration. */
164 bool autoNeg; /*!< PHY auto-negotiation, true: enable, false: disable. */
165 bool enableEEE; /*!< PHY Energy Efficient Ethernet, true: enable, false: disable. */
166 phy_interrupt_type_t intrType; /*!< PHY interrupt configuration. */
167 };
168
169 /*! @brief PHY device handle. */
170 struct _phy_handle
171 {
172 uint8_t phyAddr; /*!< PHY address. */
173 void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
174 const phy_operations_t *ops; /*!< PHY operational method. */
175 };
176
177 /*******************************************************************************
178 * API
179 ******************************************************************************/
180
181 #if defined(__cplusplus)
182 extern "C" {
183 #endif
184
185 /*!
186 * @name PHY Driver
187 * @{
188 */
189
190 /*!
191 * @brief Initializes PHY.
192 * This function initializes PHY.
193 *
194 * @param handle PHY device handle.
195 * @param config PHY configuration.
196 * @retval kStatus_Success PHY initialization succeeds
197 * @retval kStatus_Fail PHY initialization fails
198 * @retval kStatus_Timeout PHY MDIO visit time out
199 */
PHY_Init(phy_handle_t * handle,const phy_config_t * config)200 static inline status_t PHY_Init(phy_handle_t *handle, const phy_config_t *config)
201 {
202 handle->ops = config->ops;
203 return handle->ops->phyInit(handle, config);
204 }
205 /*!
206 * @brief PHY Write function.
207 * This function writes data over the MDIO to the specified PHY register.
208 *
209 * @param handle PHY device handle.
210 * @param phyReg The PHY register.
211 * @param data The data written to the PHY register.
212 * @retval kStatus_Success PHY write success
213 * @retval kStatus_Timeout PHY MDIO visit time out
214 */
PHY_Write(phy_handle_t * handle,uint8_t phyReg,uint16_t data)215 static inline status_t PHY_Write(phy_handle_t *handle, uint8_t phyReg, uint16_t data)
216 {
217 return handle->ops->phyWrite(handle, phyReg, data);
218 }
219
220 /*!
221 * @brief PHY Read function.
222 * This interface reads data over the MDIO from the specified PHY register.
223 *
224 * @param handle PHY device handle.
225 * @param phyReg The PHY register address.
226 * @param pData The address to store the data read from the PHY register.
227 * @retval kStatus_Success PHY read success
228 * @retval kStatus_Timeout PHY MDIO visit time out
229 */
PHY_Read(phy_handle_t * handle,uint8_t phyReg,uint16_t * pData)230 static inline status_t PHY_Read(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData)
231 {
232 return handle->ops->phyRead(handle, phyReg, pData);
233 }
234
235 /*!
236 * @brief PHY Write C45 function.
237 * This function writes data over the MDIO to the specified PHY register.
238 *
239 * @param handle PHY device handle.
240 * @param devAddr The device address.
241 * @param phyReg The PHY register.
242 * @param data The data written to the PHY register.
243 * @retval kStatus_Success PHY write success
244 * @retval kStatus_Timeout PHY MDIO visit time out
245 */
PHY_WriteC45(phy_handle_t * handle,uint8_t devAddr,uint8_t phyReg,uint16_t data)246 static inline status_t PHY_WriteC45(phy_handle_t *handle, uint8_t devAddr, uint8_t phyReg, uint16_t data)
247 {
248 return handle->ops->phyWriteC45(handle, devAddr, phyReg, data);
249 }
250
251 /*!
252 * @brief PHY Read C45 function.
253 * This interface reads data over the MDIO from the specified PHY register.
254 *
255 * @param handle PHY device handle.
256 * @param devAddr The device address.
257 * @param phyReg The PHY register address.
258 * @param pData The address to store the data read from the PHY register.
259 * @retval kStatus_Success PHY read success
260 * @retval kStatus_Timeout PHY MDIO visit time out
261 */
PHY_ReadC45(phy_handle_t * handle,uint8_t devAddr,uint8_t phyReg,uint16_t * pData)262 static inline status_t PHY_ReadC45(phy_handle_t *handle, uint8_t devAddr, uint8_t phyReg, uint16_t *pData)
263 {
264 return handle->ops->phyReadC45(handle, devAddr, phyReg, pData);
265 }
266
267 /*!
268 * @brief Gets the PHY auto-negotiation status.
269 *
270 * @param handle PHY device handle.
271 * @param status The auto-negotiation status of the PHY.
272 * - true the auto-negotiation is over.
273 * - false the auto-negotiation is on-going or not started.
274 * @retval kStatus_Success PHY gets status success
275 * @retval kStatus_Timeout PHY MDIO visit time out
276 */
PHY_GetAutoNegotiationStatus(phy_handle_t * handle,bool * status)277 static inline status_t PHY_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status)
278 {
279 return handle->ops->getAutoNegoStatus(handle, status);
280 }
281
282 /*!
283 * @brief Gets the PHY link status.
284 *
285 * @param handle PHY device handle.
286 * @param status The link up or down status of the PHY.
287 * - true the link is up.
288 * - false the link is down.
289 * @retval kStatus_Success PHY get link status success
290 * @retval kStatus_Timeout PHY MDIO visit time out
291 */
PHY_GetLinkStatus(phy_handle_t * handle,bool * status)292 static inline status_t PHY_GetLinkStatus(phy_handle_t *handle, bool *status)
293 {
294 return handle->ops->getLinkStatus(handle, status);
295 }
296
297 /*!
298 * @brief Gets the PHY link speed and duplex.
299 *
300 * @brief This function gets the speed and duplex mode of PHY. User can give one of speed
301 * and duplex address paramter and set the other as NULL if only wants to get one of them.
302 *
303 * @param handle PHY device handle.
304 * @param speed The address of PHY link speed.
305 * @param duplex The link duplex of PHY.
306 * @retval kStatus_Success PHY get link speed and duplex success
307 * @retval kStatus_Timeout PHY MDIO visit time out
308 */
PHY_GetLinkSpeedDuplex(phy_handle_t * handle,phy_speed_t * speed,phy_duplex_t * duplex)309 static inline status_t PHY_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex)
310 {
311 return handle->ops->getLinkSpeedDuplex(handle, speed, duplex);
312 }
313
314 /*!
315 * @brief Sets the PHY link speed and duplex.
316 *
317 * @param handle PHY device handle.
318 * @param speed Specified PHY link speed.
319 * @param duplex Specified PHY link duplex.
320 * @retval kStatus_Success PHY gets status success
321 * @retval kStatus_Timeout PHY MDIO visit time out
322 */
PHY_SetLinkSpeedDuplex(phy_handle_t * handle,phy_speed_t speed,phy_duplex_t duplex)323 static inline status_t PHY_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex)
324 {
325 return handle->ops->setLinkSpeedDuplex(handle, speed, duplex);
326 }
327
328 /*!
329 * @brief Enables/Disables PHY loopback mode.
330 *
331 * @param handle PHY device handle.
332 * @param mode The loopback mode to be enabled, please see "phy_loop_t".
333 * All loopback modes should not be set together, when one loopback mode is set
334 * another should be disabled.
335 * @param speed PHY speed for loopback mode.
336 * @param enable True to enable, false to disable.
337 * @retval kStatus_Success PHY get link speed and duplex success
338 * @retval kStatus_Timeout PHY MDIO visit time out
339 */
PHY_EnableLoopback(phy_handle_t * handle,phy_loop_t mode,phy_speed_t speed,bool enable)340 static inline status_t PHY_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable)
341 {
342 return handle->ops->enableLoopback(handle, mode, speed, enable);
343 }
344
345 /*!
346 * @brief Enables/Disables PHY link management interrupt.
347 *
348 * This function controls link status change interrupt. Application should get
349 * status through PHY_GetLinkStatus() and PHY_GetAutoNegotiationStatus() when
350 * interrupt triggers.
351 *
352 * @note Not all PHYs support link up, link down and auto auto-negotiation complete
353 * interrupt separately. Some PHY may combine link up/down or no link up or no
354 * auto-negotiation complete interrupt. The interrupt trigger situation depends
355 * on specific PHY.
356 *
357 * @param handle PHY device handle.
358 * @param type PHY interrupt type.
359 * @retval kStatus_Success PHY enables/disables interrupt success
360 * @retval kStatus_Timeout PHY MDIO visit time out
361 */
PHY_EnableLinkInterrupt(phy_handle_t * handle,phy_interrupt_type_t type)362 static inline status_t PHY_EnableLinkInterrupt(phy_handle_t *handle, phy_interrupt_type_t type)
363 {
364 return handle->ops->enableLinkInterrupt(handle, type);
365 }
366
367 /*!
368 * @brief Clears PHY interrupt status.
369 * @note Usually this API clears all interrupts of PHY because related register
370 * flags are read clear.
371 *
372 * @param handle PHY device handle.
373 * @retval kStatus_Success PHY read and clear interrupt success
374 * @retval kStatus_Timeout PHY MDIO visit time out
375 */
PHY_ClearInterrupt(phy_handle_t * handle)376 static inline status_t PHY_ClearInterrupt(phy_handle_t *handle)
377 {
378 return handle->ops->clearInterrupt(handle);
379 }
380
381 /* @} */
382
383 #if defined(__cplusplus)
384 }
385 #endif
386
387 /*! @}*/
388 #endif
389