fsl_phy.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright (c) 2015, 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 0xFFFFFU
  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. extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
  52. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  53. /*******************************************************************************
  54. * Code
  55. ******************************************************************************/
  56. status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
  57. {
  58. uint32_t bssReg;
  59. uint32_t counter = PHY_TIMEOUT_COUNT;
  60. uint32_t idReg = 0;
  61. status_t result = kStatus_Success;
  62. uint32_t instance = ENET_GetInstance(base);
  63. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  64. /* Set SMI first. */
  65. CLOCK_EnableClock(s_enetClock[instance]);
  66. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  67. ENET_SetSMI(base, srcClock_Hz, false);
  68. /* Initialization after PHY stars to work. */
  69. while ((idReg != PHY_CONTROL_ID1) && (counter != 0))
  70. {
  71. PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg);
  72. counter --;
  73. }
  74. if (!counter)
  75. {
  76. return kStatus_Fail;
  77. }
  78. /* Reset PHY. */
  79. counter = PHY_TIMEOUT_COUNT;
  80. result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
  81. if (result == kStatus_Success)
  82. {
  83. /* Set the negotiation. */
  84. result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
  85. (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
  86. PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U));
  87. if (result == kStatus_Success)
  88. {
  89. result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG,
  90. (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
  91. if (result == kStatus_Success)
  92. {
  93. /* Check auto negotiation complete. */
  94. while (counter --)
  95. {
  96. result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &bssReg);
  97. if ( result == kStatus_Success)
  98. {
  99. if ((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0)
  100. {
  101. break;
  102. }
  103. }
  104. if (!counter)
  105. {
  106. return kStatus_PHY_AutoNegotiateFail;
  107. }
  108. }
  109. }
  110. }
  111. }
  112. return result;
  113. }
  114. status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
  115. {
  116. uint32_t counter;
  117. /* Clear the SMI interrupt event. */
  118. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  119. /* Starts a SMI write command. */
  120. ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data);
  121. /* Wait for SMI complete. */
  122. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  123. {
  124. if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
  125. {
  126. break;
  127. }
  128. }
  129. /* Check for timeout. */
  130. if (!counter)
  131. {
  132. return kStatus_PHY_SMIVisitTimeout;
  133. }
  134. /* Clear MII interrupt event. */
  135. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  136. return kStatus_Success;
  137. }
  138. status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
  139. {
  140. assert(dataPtr);
  141. uint32_t counter;
  142. /* Clear the MII interrupt event. */
  143. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  144. /* Starts a SMI read command operation. */
  145. ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame);
  146. /* Wait for MII complete. */
  147. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  148. {
  149. if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
  150. {
  151. break;
  152. }
  153. }
  154. /* Check for timeout. */
  155. if (!counter)
  156. {
  157. return kStatus_PHY_SMIVisitTimeout;
  158. }
  159. /* Get data from MII register. */
  160. *dataPtr = ENET_ReadSMIData(base);
  161. /* Clear MII interrupt event. */
  162. ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
  163. return kStatus_Success;
  164. }
  165. status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, bool enable)
  166. {
  167. status_t result;
  168. uint32_t data = 0;
  169. /* Set the loop mode. */
  170. if (enable)
  171. {
  172. if (mode == kPHY_LocalLoop)
  173. {
  174. /* First read the current status in control register. */
  175. result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
  176. if (result == kStatus_Success)
  177. {
  178. return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_LOOP_MASK));
  179. }
  180. }
  181. else
  182. {
  183. /* First read the current status in control register. */
  184. result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data);
  185. if (result == kStatus_Success)
  186. {
  187. return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REMOTELOOP_MASK));
  188. }
  189. }
  190. }
  191. else
  192. {
  193. /* Disable the loop mode. */
  194. if (mode == kPHY_LocalLoop)
  195. {
  196. /* First read the current status in the basic control register. */
  197. result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
  198. if (result == kStatus_Success)
  199. {
  200. return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data & ~PHY_BCTL_LOOP_MASK));
  201. }
  202. }
  203. else
  204. {
  205. /* First read the current status in control one register. */
  206. result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data);
  207. if (result == kStatus_Success)
  208. {
  209. return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data & ~PHY_CTL2_REMOTELOOP_MASK));
  210. }
  211. }
  212. }
  213. return result;
  214. }
  215. status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status)
  216. {
  217. assert(status);
  218. status_t result = kStatus_Success;
  219. uint32_t data;
  220. /* Read the basic status register. */
  221. result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &data);
  222. if (result == kStatus_Success)
  223. {
  224. if (!(PHY_BSTATUS_LINKSTATUS_MASK & data))
  225. {
  226. /* link down. */
  227. *status = false;
  228. }
  229. else
  230. {
  231. /* link up. */
  232. *status = true;
  233. }
  234. }
  235. return result;
  236. }
  237. status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex)
  238. {
  239. assert(duplex);
  240. status_t result = kStatus_Success;
  241. uint32_t data, ctlReg;
  242. /* Read the control two register. */
  243. result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg);
  244. if (result == kStatus_Success)
  245. {
  246. data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
  247. if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
  248. {
  249. /* Full duplex. */
  250. *duplex = kPHY_FullDuplex;
  251. }
  252. else
  253. {
  254. /* Half duplex. */
  255. *duplex = kPHY_HalfDuplex;
  256. }
  257. data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
  258. if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
  259. {
  260. /* 100M speed. */
  261. *speed = kPHY_Speed100M;
  262. }
  263. else
  264. { /* 10M speed. */
  265. *speed = kPHY_Speed10M;
  266. }
  267. }
  268. return result;
  269. }