fsl_phy.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2017 NXP
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * o Redistributions of source code must retain the above copyright notice, this list
  9. * of conditions and the following disclaimer.
  10. *
  11. * o Redistributions in binary form must reproduce the above copyright notice, this
  12. * list of conditions and the following disclaimer in the documentation and/or
  13. * other materials provided with the distribution.
  14. *
  15. * o Neither the name of the copyright holder nor the names of its
  16. * contributors may be used to endorse or promote products derived from this
  17. * software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "fsl_phy.h"
  31. /*******************************************************************************
  32. * Definitions
  33. ******************************************************************************/
  34. /*! @brief Defines the timeout macro. */
  35. #define PHY_TIMEOUT_COUNT 0xFFFFU
  36. /*******************************************************************************
  37. * Prototypes
  38. ******************************************************************************/
  39. /*!
  40. * @brief Get the ENET instance from peripheral base address.
  41. *
  42. * @param base ENET peripheral base address.
  43. * @return ENET instance.
  44. */
  45. extern uint32_t ENET_GetInstance(ENET_Type *base);
  46. /*******************************************************************************
  47. * Variables
  48. ******************************************************************************/
  49. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  50. /*! @brief Pointers to enet clocks for each instance. */
  51. #if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
  52. extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
  53. #elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
  54. extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_LPC_ENET_COUNT];
  55. #endif
  56. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  57. /*******************************************************************************
  58. * Code
  59. ******************************************************************************/
  60. status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
  61. {
  62. uint32_t reg;
  63. uint32_t idReg = 0;
  64. uint32_t delay = PHY_TIMEOUT_COUNT;
  65. uint32_t instance = ENET_GetInstance(base);
  66. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  67. /* Set SMI first. */
  68. CLOCK_EnableClock(s_enetClock[instance]);
  69. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  70. #if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
  71. ENET_SetSMI(base, srcClock_Hz, false);
  72. #elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
  73. ENET_SetSMI(base);
  74. #endif
  75. /* Initialization after PHY stars to work. */
  76. while ((idReg != PHY_CONTROL_ID1) && (delay != 0))
  77. {
  78. PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg);
  79. delay --;
  80. }
  81. if (!delay)
  82. {
  83. return kStatus_Fail;
  84. }
  85. delay = PHY_TIMEOUT_COUNT;
  86. /* Reset PHY and wait until completion. */
  87. PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
  88. do
  89. {
  90. PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &reg);
  91. } while (delay-- && reg & PHY_BCTL_RESET_MASK);
  92. if (!delay)
  93. {
  94. return kStatus_Fail;
  95. }
  96. /* Set the ability. */
  97. PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG, (PHY_ALL_CAPABLE_MASK | 0x1U));
  98. /* Start Auto negotiation and wait until auto negotiation completion */
  99. PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
  100. delay = PHY_TIMEOUT_COUNT;
  101. do
  102. {
  103. PHY_Read(base, phyAddr, PHY_SEPCIAL_CONTROL_REG, &reg);
  104. delay --;
  105. } while (delay && ((reg & PHY_SPECIALCTL_AUTONEGDONE_MASK) == 0));
  106. if (!delay)
  107. {
  108. return kStatus_Fail;
  109. }
  110. return kStatus_Success;
  111. }
  112. status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
  113. {
  114. #if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
  115. uint32_t counter;
  116. /* Clear the SMI interrupt event. */
  117. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  118. /* Starts a SMI write command. */
  119. ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data);
  120. /* Wait for SMI complete. */
  121. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  122. {
  123. if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
  124. {
  125. break;
  126. }
  127. }
  128. /* Check for timeout. */
  129. if (!counter)
  130. {
  131. return kStatus_PHY_SMIVisitTimeout;
  132. }
  133. /* Clear MII interrupt event. */
  134. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  135. #elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
  136. ENET_StartSMIWrite(base, phyAddr, phyReg, data);
  137. while (ENET_IsSMIBusy(base))
  138. ;
  139. #endif
  140. return kStatus_Success;
  141. }
  142. status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
  143. {
  144. #if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
  145. assert(dataPtr);
  146. uint32_t counter;
  147. /* Clear the MII interrupt event. */
  148. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  149. /* Starts a SMI read command operation. */
  150. ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame);
  151. /* Wait for MII complete. */
  152. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  153. {
  154. if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
  155. {
  156. break;
  157. }
  158. }
  159. /* Check for timeout. */
  160. if (!counter)
  161. {
  162. return kStatus_PHY_SMIVisitTimeout;
  163. }
  164. /* Get data from MII register. */
  165. *dataPtr = ENET_ReadSMIData(base);
  166. /* Clear MII interrupt event. */
  167. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  168. #elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
  169. ENET_StartSMIRead(base, phyAddr, phyReg);
  170. while (ENET_IsSMIBusy(base))
  171. ;
  172. *dataPtr = ENET_ReadSMIData(base);
  173. #endif
  174. return kStatus_Success;
  175. }
  176. status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status)
  177. {
  178. uint32_t reg;
  179. status_t result = kStatus_Success;
  180. /* Read the basic status register. */
  181. result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &reg);
  182. if (result == kStatus_Success)
  183. {
  184. if (reg & PHY_BSTATUS_LINKSTATUS_MASK)
  185. {
  186. /* link up. */
  187. *status = true;
  188. }
  189. else
  190. {
  191. *status = false;
  192. }
  193. }
  194. return result;
  195. }
  196. status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex)
  197. {
  198. assert(duplex);
  199. assert(speed);
  200. uint32_t reg;
  201. status_t result = kStatus_Success;
  202. /* Read the control two register. */
  203. result = PHY_Read(base, phyAddr, PHY_SEPCIAL_CONTROL_REG, &reg);
  204. if (result == kStatus_Success)
  205. {
  206. if (reg & PHY_SPECIALCTL_DUPLEX_MASK)
  207. {
  208. /* Full duplex. */
  209. *duplex = kPHY_FullDuplex;
  210. }
  211. else
  212. {
  213. /* Half duplex. */
  214. *duplex = kPHY_HalfDuplex;
  215. }
  216. if (reg & PHY_SPECIALCTL_100SPEED_MASK)
  217. {
  218. /* 100M speed. */
  219. *speed = kPHY_Speed100M;
  220. }
  221. else
  222. { /* 10M speed. */
  223. *speed = kPHY_Speed10M;
  224. }
  225. }
  226. return result;
  227. }