diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/components/phy/device/phyar8031/fsl_phyar8031.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/components/phy/device/phyar8031/fsl_phyar8031.c | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/components/phy/device/phyar8031/fsl_phyar8031.c b/lib/chibios-contrib/ext/mcux-sdk/components/phy/device/phyar8031/fsl_phyar8031.c new file mode 100644 index 000000000..8fd5d09ce --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/components/phy/device/phyar8031/fsl_phyar8031.c | |||
@@ -0,0 +1,566 @@ | |||
1 | /* | ||
2 | * Copyright 2020 NXP | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * SPDX-License-Identifier: BSD-3-Clause | ||
6 | */ | ||
7 | |||
8 | #include "fsl_phyar8031.h" | ||
9 | |||
10 | /******************************************************************************* | ||
11 | * Definitions | ||
12 | ******************************************************************************/ | ||
13 | |||
14 | /*! @brief Defines the PHY AR8031 vendor defined registers. */ | ||
15 | #define PHY_SPECIFIC_STATUS_REG 0x11U /*!< The PHY specific status register. */ | ||
16 | #define PHY_COPPERFIBER_STATUS_REG 0x1BU /*!< The PHY copper/fiber status register. */ | ||
17 | #define PHY_DEBUGPORT_ADDR_REG 0x1DU /*!< The PHY Debug port address register.*/ | ||
18 | #define PHY_DEBUGPORT_DATA_REG 0x1EU /*!< The PHY Debug port data register.*/ | ||
19 | #define PHY_CHIP_CFG_REG 0x1FU /*!< The PHY chip configure register. */ | ||
20 | |||
21 | /*! @brief Defines the Debug register offset. */ | ||
22 | #define PHY_DEBUG_HIBECTL_REG_OFFSET 0x0BU /*!< The PHY Debug register offset 0xB.*/ | ||
23 | #define PHY_DEBUG_EXTLOOP_REG_OFFSET 0x11U /*!< The PHY Debug register offset 0x11.*/ | ||
24 | |||
25 | /*! @brief Defines the PHY AR8031 ID number. */ | ||
26 | #define PHY_CONTROL_ID1 0x004DU /*!< The PHY ID1 is 0x004D. */ | ||
27 | |||
28 | /*!@brief Defines the mask flag of operation mode in control two register*/ | ||
29 | #define PHY_CTL2_REMOTELOOP_MASK 0x0004U /*!< The PHY remote loopback mask. */ | ||
30 | #define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */ | ||
31 | #define PHY_CTL1_10HALFDUPLEX_MASK 0x0001U /*!< The PHY 10M half duplex mask. */ | ||
32 | #define PHY_CTL1_100HALFDUPLEX_MASK 0x0002U /*!< The PHY 100M half duplex mask. */ | ||
33 | #define PHY_CTL1_10FULLDUPLEX_MASK 0x0005U /*!< The PHY 10M full duplex mask. */ | ||
34 | #define PHY_CTL1_100FULLDUPLEX_MASK 0x0006U /*!< The PHY 100M full duplex mask. */ | ||
35 | |||
36 | /*! @brief Defines the mask flag in specific status register. */ | ||
37 | #define PHY_SSTATUS_LINKSTATUS_MASK 0x0400U /*!< The PHY link status mask. */ | ||
38 | #define PHY_SSTATUS_LINKSPEED_MASK 0xC000U /*!< The PHY link speed mask. */ | ||
39 | #define PHY_SSTATUS_LINKDUPLEX_MASK 0x2000U /*!< The PHY link duplex mask. */ | ||
40 | #define PHY_SSTATUS_LINKSPEED_SHIFT 14U /*!< The link speed shift */ | ||
41 | |||
42 | /*! @brief Defines the mask flag in PHY debug register- hibernate control register. */ | ||
43 | #define PHY_DEBUG_HIBERNATECTL_REG 0x8000U /*!< The power hibernate control mask. */ | ||
44 | |||
45 | /*! @brief Defines the PHY MMD access. */ | ||
46 | #define PHY_MMD_DEVICEID3 3U /*!< The PHY device id 3. */ | ||
47 | #define PHY_MMD_REMOTEPHY_LOOP_OFFSET 0x805A /*!< The PHY MMD phy register */ | ||
48 | #define PHY_MMD_SMARTEEE_CTL_OFFSET 0x805D /*!< The PHY MMD smartEEE register */ | ||
49 | #define PHY_MMD_SMARTEEE_LPI_EN_SHIFT 8U /*!< The SmartEEE enable/disable bit shift */ | ||
50 | /*! @brief Defines the chip configure register. */ | ||
51 | #define PHY_MODE_CFG_MASK 0xFU /*!< The PHY mode configure mask. */ | ||
52 | |||
53 | /*! @brief MDIO MMD Devices .*/ | ||
54 | #define PHY_MDIO_MMD_PCS 3U | ||
55 | #define PHY_MDIO_MMD_AN 7U | ||
56 | |||
57 | /*! @brief MDIO MMD Physical Coding layer device registers .*/ | ||
58 | #define PHY_MDIO_PCS_EEE_CAP 0x14U /* EEE capability */ | ||
59 | |||
60 | /*! @brief MDIO MMD AutoNegotiation device registers .*/ | ||
61 | #define PHY_MDIO_AN_EEE_ADV 0x3CU /* EEE advertisement */ | ||
62 | |||
63 | /*! @brief MDIO MMD EEE mask flags. (common for adv and cap) */ | ||
64 | #define PHY_MDIO_EEE_100TX 0x2U | ||
65 | #define PHY_MDIO_EEE_1000T 0x4U | ||
66 | |||
67 | /*! @brief Defines the timeout macro. */ | ||
68 | #define PHY_READID_TIMEOUT_COUNT 1000U | ||
69 | |||
70 | /******************************************************************************* | ||
71 | * Prototypes | ||
72 | ******************************************************************************/ | ||
73 | |||
74 | static status_t PHY_AR8031_MMD_SetDevice(phy_handle_t *handle, | ||
75 | uint8_t device, | ||
76 | uint16_t addr, | ||
77 | phy_mmd_access_mode_t mode); | ||
78 | static inline status_t PHY_AR8031_MMD_ReadData(phy_handle_t *handle, uint32_t *data); | ||
79 | static inline status_t PHY_AR8031_MMD_WriteData(phy_handle_t *handle, uint32_t data); | ||
80 | static status_t PHY_AR8031_MMD_Read(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t *data); | ||
81 | static status_t PHY_AR8031_MMD_Write(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t data); | ||
82 | |||
83 | /******************************************************************************* | ||
84 | * Variables | ||
85 | ******************************************************************************/ | ||
86 | const phy_operations_t phyar8031_ops = {.phyInit = PHY_AR8031_Init, | ||
87 | .phyWrite = PHY_AR8031_Write, | ||
88 | .phyRead = PHY_AR8031_Read, | ||
89 | .getAutoNegoStatus = PHY_AR8031_GetAutoNegotiationStatus, | ||
90 | .getLinkStatus = PHY_AR8031_GetLinkStatus, | ||
91 | .getLinkSpeedDuplex = PHY_AR8031_GetLinkSpeedDuplex, | ||
92 | .setLinkSpeedDuplex = PHY_AR8031_SetLinkSpeedDuplex, | ||
93 | .enableLoopback = PHY_AR8031_EnableLoopback}; | ||
94 | |||
95 | /******************************************************************************* | ||
96 | * Code | ||
97 | ******************************************************************************/ | ||
98 | |||
99 | status_t PHY_AR8031_Init(phy_handle_t *handle, const phy_config_t *config) | ||
100 | { | ||
101 | uint32_t counter = PHY_READID_TIMEOUT_COUNT; | ||
102 | status_t result = kStatus_Success; | ||
103 | uint32_t regValue = 0; | ||
104 | |||
105 | /* Init MDIO interface. */ | ||
106 | MDIO_Init(handle->mdioHandle); | ||
107 | |||
108 | /* Assign phy address. */ | ||
109 | handle->phyAddr = config->phyAddr; | ||
110 | |||
111 | /* Check PHY ID. */ | ||
112 | do | ||
113 | { | ||
114 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_ID1_REG, ®Value); | ||
115 | if (result != kStatus_Success) | ||
116 | { | ||
117 | return result; | ||
118 | } | ||
119 | counter--; | ||
120 | } while ((regValue != PHY_CONTROL_ID1) && (counter != 0U)); | ||
121 | |||
122 | if (counter == 0U) | ||
123 | { | ||
124 | return kStatus_Fail; | ||
125 | } | ||
126 | |||
127 | /* Configure RMII voltage 1.8V */ | ||
128 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, 0x1F); | ||
129 | if (result != kStatus_Success) | ||
130 | { | ||
131 | return result; | ||
132 | } | ||
133 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, 0x8); | ||
134 | if (result != kStatus_Success) | ||
135 | { | ||
136 | return result; | ||
137 | } | ||
138 | |||
139 | /* Reset PHY. */ | ||
140 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); | ||
141 | if (result == kStatus_Success) | ||
142 | { | ||
143 | /* Close smartEEE. */ | ||
144 | result = PHY_AR8031_MMD_SetDevice(handle, PHY_MMD_DEVICEID3, PHY_MMD_SMARTEEE_CTL_OFFSET, | ||
145 | kPHY_MMDAccessNoPostIncrement); | ||
146 | if (result == kStatus_Success) | ||
147 | { | ||
148 | result = PHY_AR8031_MMD_ReadData(handle, ®Value); | ||
149 | if (result == kStatus_Success) | ||
150 | { | ||
151 | result = PHY_AR8031_MMD_WriteData(handle, (regValue & ~((uint32_t)1 << PHY_MMD_SMARTEEE_LPI_EN_SHIFT))); | ||
152 | } | ||
153 | } | ||
154 | if (result != kStatus_Success) | ||
155 | { | ||
156 | return result; | ||
157 | } | ||
158 | |||
159 | /* Enable Tx clock delay */ | ||
160 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, 0x5); | ||
161 | if (result != kStatus_Success) | ||
162 | { | ||
163 | return result; | ||
164 | } | ||
165 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, ®Value); | ||
166 | if (result != kStatus_Success) | ||
167 | { | ||
168 | return result; | ||
169 | } | ||
170 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, (regValue | 0x0100U)); | ||
171 | if (result != kStatus_Success) | ||
172 | { | ||
173 | return result; | ||
174 | } | ||
175 | |||
176 | /* Enable Rx clock delay */ | ||
177 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, 0x0); | ||
178 | if (result != kStatus_Success) | ||
179 | { | ||
180 | return result; | ||
181 | } | ||
182 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, ®Value); | ||
183 | if (result != kStatus_Success) | ||
184 | { | ||
185 | return result; | ||
186 | } | ||
187 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, (regValue | 0x8000U)); | ||
188 | if (result != kStatus_Success) | ||
189 | { | ||
190 | return result; | ||
191 | } | ||
192 | |||
193 | /* Energy Efficient Ethernet config */ | ||
194 | if (config->enableEEE) | ||
195 | { | ||
196 | /* Get capabilities */ | ||
197 | result = PHY_AR8031_MMD_Read(handle, PHY_MDIO_MMD_PCS, PHY_MDIO_PCS_EEE_CAP, ®Value); | ||
198 | if (result == kStatus_Success) | ||
199 | { | ||
200 | /* Enable EEE for 100TX and 1000T */ | ||
201 | result = PHY_AR8031_MMD_Write(handle, PHY_MDIO_MMD_AN, PHY_MDIO_AN_EEE_ADV, | ||
202 | regValue & (PHY_MDIO_EEE_1000T | PHY_MDIO_EEE_100TX)); | ||
203 | } | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | result = PHY_AR8031_MMD_Write(handle, PHY_MDIO_MMD_AN, PHY_MDIO_AN_EEE_ADV, 0); | ||
208 | } | ||
209 | if (result != kStatus_Success) | ||
210 | { | ||
211 | return result; | ||
212 | } | ||
213 | |||
214 | if (config->autoNeg) | ||
215 | { | ||
216 | /* Set the negotiation. */ | ||
217 | result = | ||
218 | MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_AUTONEG_ADVERTISE_REG, | ||
219 | (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK | | ||
220 | PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | PHY_IEEE802_3_SELECTOR_MASK)); | ||
221 | if (result == kStatus_Success) | ||
222 | { | ||
223 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_1000BASET_CONTROL_REG, | ||
224 | PHY_1000BASET_FULLDUPLEX_MASK | PHY_1000BASET_HALFDUPLEX_MASK); | ||
225 | if (result == kStatus_Success) | ||
226 | { | ||
227 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value); | ||
228 | if (result != kStatus_Success) | ||
229 | { | ||
230 | return result; | ||
231 | } | ||
232 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, | ||
233 | (regValue | PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK)); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | else | ||
238 | { | ||
239 | /* Disable isolate mode */ | ||
240 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value); | ||
241 | if (result != kStatus_Success) | ||
242 | { | ||
243 | return result; | ||
244 | } | ||
245 | regValue &= ~PHY_BCTL_ISOLATE_MASK; | ||
246 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue); | ||
247 | if (result != kStatus_Success) | ||
248 | { | ||
249 | return result; | ||
250 | } | ||
251 | |||
252 | /* Disable the auto-negotiation and set user-defined speed/duplex configuration. */ | ||
253 | result = PHY_AR8031_SetLinkSpeedDuplex(handle, config->speed, config->duplex); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | return result; | ||
258 | } | ||
259 | |||
260 | status_t PHY_AR8031_Write(phy_handle_t *handle, uint32_t phyReg, uint32_t data) | ||
261 | { | ||
262 | return MDIO_Write(handle->mdioHandle, handle->phyAddr, phyReg, data); | ||
263 | } | ||
264 | |||
265 | status_t PHY_AR8031_Read(phy_handle_t *handle, uint32_t phyReg, uint32_t *dataPtr) | ||
266 | { | ||
267 | return MDIO_Read(handle->mdioHandle, handle->phyAddr, phyReg, dataPtr); | ||
268 | } | ||
269 | |||
270 | status_t PHY_AR8031_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status) | ||
271 | { | ||
272 | assert(status); | ||
273 | |||
274 | status_t result; | ||
275 | uint32_t regValue; | ||
276 | |||
277 | *status = false; | ||
278 | |||
279 | /* Check auto negotiation complete. */ | ||
280 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICSTATUS_REG, ®Value); | ||
281 | if (result == kStatus_Success) | ||
282 | { | ||
283 | if ((regValue & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0U) | ||
284 | { | ||
285 | *status = true; | ||
286 | } | ||
287 | } | ||
288 | return result; | ||
289 | } | ||
290 | |||
291 | status_t PHY_AR8031_GetLinkStatus(phy_handle_t *handle, bool *status) | ||
292 | { | ||
293 | assert(status); | ||
294 | |||
295 | status_t result = kStatus_Success; | ||
296 | uint32_t regValue; | ||
297 | |||
298 | /* Read the basic status register. */ | ||
299 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_SPECIFIC_STATUS_REG, ®Value); | ||
300 | if (result == kStatus_Success) | ||
301 | { | ||
302 | if ((PHY_SSTATUS_LINKSTATUS_MASK & regValue) != 0U) | ||
303 | { | ||
304 | /* Link up. */ | ||
305 | *status = true; | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | /* Link down. */ | ||
310 | *status = false; | ||
311 | } | ||
312 | } | ||
313 | return result; | ||
314 | } | ||
315 | |||
316 | status_t PHY_AR8031_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex) | ||
317 | { | ||
318 | assert(!((speed == NULL) && (duplex == NULL))); | ||
319 | |||
320 | status_t result; | ||
321 | uint32_t regValue; | ||
322 | |||
323 | /* Read the specfic status register. */ | ||
324 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_SPECIFIC_STATUS_REG, ®Value); | ||
325 | if (result == kStatus_Success) | ||
326 | { | ||
327 | if (speed != NULL) | ||
328 | { | ||
329 | switch ((regValue & PHY_SSTATUS_LINKSPEED_MASK) >> PHY_SSTATUS_LINKSPEED_SHIFT) | ||
330 | { | ||
331 | case (uint32_t)kPHY_Speed10M: | ||
332 | *speed = kPHY_Speed10M; | ||
333 | break; | ||
334 | case (uint32_t)kPHY_Speed100M: | ||
335 | *speed = kPHY_Speed100M; | ||
336 | break; | ||
337 | case (uint32_t)kPHY_Speed1000M: | ||
338 | *speed = kPHY_Speed1000M; | ||
339 | break; | ||
340 | default: | ||
341 | *speed = kPHY_Speed10M; | ||
342 | break; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | if (duplex != NULL) | ||
347 | { | ||
348 | if ((regValue & PHY_SSTATUS_LINKDUPLEX_MASK) != 0U) | ||
349 | { | ||
350 | *duplex = kPHY_FullDuplex; | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | *duplex = kPHY_HalfDuplex; | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | |||
359 | return result; | ||
360 | } | ||
361 | |||
362 | status_t PHY_AR8031_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex) | ||
363 | { | ||
364 | status_t result; | ||
365 | uint32_t regValue; | ||
366 | |||
367 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value); | ||
368 | if (result == kStatus_Success) | ||
369 | { | ||
370 | /* Disable the auto-negotiation and set according to user-defined configuration. */ | ||
371 | regValue &= ~PHY_BCTL_AUTONEG_MASK; | ||
372 | if (speed == kPHY_Speed1000M) | ||
373 | { | ||
374 | regValue &= PHY_BCTL_SPEED0_MASK; | ||
375 | regValue |= PHY_BCTL_SPEED1_MASK; | ||
376 | } | ||
377 | else if (speed == kPHY_Speed100M) | ||
378 | { | ||
379 | regValue |= PHY_BCTL_SPEED0_MASK; | ||
380 | regValue &= ~PHY_BCTL_SPEED1_MASK; | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | regValue &= ~PHY_BCTL_SPEED0_MASK; | ||
385 | regValue &= ~PHY_BCTL_SPEED1_MASK; | ||
386 | } | ||
387 | if (duplex == kPHY_FullDuplex) | ||
388 | { | ||
389 | regValue |= PHY_BCTL_DUPLEX_MASK; | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | regValue &= ~PHY_BCTL_DUPLEX_MASK; | ||
394 | } | ||
395 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue); | ||
396 | } | ||
397 | return result; | ||
398 | } | ||
399 | |||
400 | status_t PHY_AR8031_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable) | ||
401 | { | ||
402 | status_t result; | ||
403 | uint32_t regValue; | ||
404 | |||
405 | /* Set the loop mode. */ | ||
406 | if (enable) | ||
407 | { | ||
408 | if (mode == kPHY_LocalLoop) | ||
409 | { | ||
410 | if (speed == kPHY_Speed1000M) | ||
411 | { | ||
412 | regValue = PHY_BCTL_SPEED1_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; | ||
413 | } | ||
414 | else if (speed == kPHY_Speed100M) | ||
415 | { | ||
416 | regValue = PHY_BCTL_SPEED0_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | regValue = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; | ||
421 | } | ||
422 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue); | ||
423 | } | ||
424 | else if (mode == kPHY_RemoteLoop) | ||
425 | { | ||
426 | result = PHY_AR8031_MMD_Write(handle, PHY_MMD_DEVICEID3, PHY_MMD_REMOTEPHY_LOOP_OFFSET, 1); | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | result = | ||
431 | MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, PHY_DEBUG_HIBECTL_REG_OFFSET); | ||
432 | if (result == kStatus_Success) | ||
433 | { | ||
434 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, 0); | ||
435 | if (result == kStatus_Success) | ||
436 | { | ||
437 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, | ||
438 | PHY_DEBUG_EXTLOOP_REG_OFFSET); | ||
439 | if (result == kStatus_Success) | ||
440 | { | ||
441 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, 1); | ||
442 | if (result == kStatus_Success) | ||
443 | { | ||
444 | if (speed == kPHY_Speed1000M) | ||
445 | { | ||
446 | regValue = PHY_BCTL_SPEED1_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_RESET_MASK; | ||
447 | } | ||
448 | else if (speed == kPHY_Speed100M) | ||
449 | { | ||
450 | regValue = PHY_BCTL_SPEED0_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_RESET_MASK; | ||
451 | } | ||
452 | else | ||
453 | { | ||
454 | regValue = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_RESET_MASK; | ||
455 | } | ||
456 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue); | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | else | ||
464 | { | ||
465 | /* Disable the loop mode. */ | ||
466 | if (mode == kPHY_LocalLoop) | ||
467 | { | ||
468 | /* First read the current status in control register. */ | ||
469 | result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value); | ||
470 | if (result == kStatus_Success) | ||
471 | { | ||
472 | regValue &= ~PHY_BCTL_LOOP_MASK; | ||
473 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, | ||
474 | (regValue | PHY_BCTL_RESTART_AUTONEG_MASK)); | ||
475 | } | ||
476 | } | ||
477 | else if (mode == kPHY_RemoteLoop) | ||
478 | { | ||
479 | result = PHY_AR8031_MMD_Write(handle, PHY_MMD_DEVICEID3, PHY_MMD_REMOTEPHY_LOOP_OFFSET, 0); | ||
480 | } | ||
481 | else | ||
482 | { | ||
483 | result = | ||
484 | MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, PHY_DEBUG_HIBECTL_REG_OFFSET); | ||
485 | if (result == kStatus_Success) | ||
486 | { | ||
487 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, 0); | ||
488 | if (result == kStatus_Success) | ||
489 | { | ||
490 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_ADDR_REG, | ||
491 | PHY_DEBUG_EXTLOOP_REG_OFFSET); | ||
492 | if (result == kStatus_Success) | ||
493 | { | ||
494 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_DEBUGPORT_DATA_REG, 0); | ||
495 | if (result == kStatus_Success) | ||
496 | { | ||
497 | regValue = PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESET_MASK; | ||
498 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue); | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | return result; | ||
506 | } | ||
507 | |||
508 | static status_t PHY_AR8031_MMD_SetDevice(phy_handle_t *handle, | ||
509 | uint8_t device, | ||
510 | uint16_t addr, | ||
511 | phy_mmd_access_mode_t mode) | ||
512 | { | ||
513 | status_t result = kStatus_Success; | ||
514 | |||
515 | /* Set Function mode of address access(b00) and device address. */ | ||
516 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_CONTROL_REG, device); | ||
517 | if (result != kStatus_Success) | ||
518 | { | ||
519 | return result; | ||
520 | } | ||
521 | |||
522 | /* Set register address. */ | ||
523 | result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, addr); | ||
524 | if (result != kStatus_Success) | ||
525 | { | ||
526 | return result; | ||
527 | } | ||
528 | |||
529 | /* Set Function mode of data access(b01~11) and device address. */ | ||
530 | result = | ||
531 | MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_CONTROL_REG, (uint32_t)mode | (uint32_t)device); | ||
532 | return result; | ||
533 | } | ||
534 | |||
535 | static inline status_t PHY_AR8031_MMD_ReadData(phy_handle_t *handle, uint32_t *data) | ||
536 | { | ||
537 | return MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, data); | ||
538 | } | ||
539 | |||
540 | static inline status_t PHY_AR8031_MMD_WriteData(phy_handle_t *handle, uint32_t data) | ||
541 | { | ||
542 | return MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, data); | ||
543 | } | ||
544 | |||
545 | static status_t PHY_AR8031_MMD_Read(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t *data) | ||
546 | { | ||
547 | status_t result = kStatus_Success; | ||
548 | result = PHY_AR8031_MMD_SetDevice(handle, device, addr, kPHY_MMDAccessNoPostIncrement); | ||
549 | if (result == kStatus_Success) | ||
550 | { | ||
551 | result = PHY_AR8031_MMD_ReadData(handle, data); | ||
552 | } | ||
553 | return result; | ||
554 | } | ||
555 | |||
556 | static status_t PHY_AR8031_MMD_Write(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t data) | ||
557 | { | ||
558 | status_t result = kStatus_Success; | ||
559 | |||
560 | result = PHY_AR8031_MMD_SetDevice(handle, device, addr, kPHY_MMDAccessNoPostIncrement); | ||
561 | if (result == kStatus_Success) | ||
562 | { | ||
563 | result = PHY_AR8031_MMD_WriteData(handle, data); | ||
564 | } | ||
565 | return result; | ||
566 | } | ||