fsl_phy.c 11 KB

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