1
0

drv_mdio.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-09-29 WangQiang the first version
  9. *
  10. */
  11. #include <rtthread.h>
  12. #ifdef BSP_USING_PHY
  13. #define LOG_TAG "drv.mdio"
  14. #include <drv_log.h>
  15. #include <rtdevice.h>
  16. #include "drv_mdio.h"
  17. /*! @brief Defines the timeout macro. */
  18. #define PHY_TIMEOUT_COUNT 0x3FFFFFFU
  19. /*!
  20. * @brief Get the ENET instance from peripheral base address.
  21. *
  22. * @param base ENET peripheral base address.
  23. * @return ENET instance.
  24. */
  25. extern uint32_t ENET_GetInstance(ENET_Type *base);
  26. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  27. /*! @brief Pointers to enet clocks for each instance. */
  28. extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
  29. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  30. static rt_bool_t rt_hw_mdio_init(void *bus, rt_uint32_t src_clock_hz)
  31. {
  32. struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus;
  33. uint32_t instance = ENET_GetInstance((ENET_Type *)(bus_obj->hw_obj));
  34. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  35. /* Set SMI first. */
  36. CLOCK_EnableClock(s_enetClock[instance]);
  37. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  38. ENET_SetSMI((ENET_Type *)(bus_obj->hw_obj), src_clock_hz, RT_FALSE);
  39. return RT_TRUE;
  40. }
  41. static rt_size_t rt_hw_mdio_read(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size)
  42. {
  43. RT_ASSERT(data);
  44. struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus;
  45. rt_uint32_t counter;
  46. rt_uint32_t *data_ptr = (rt_uint32_t *)data;
  47. if (4 != size)
  48. {
  49. return 0;
  50. }
  51. /* Clear the MII interrupt event. */
  52. ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK);
  53. /* Starts a SMI read command operation. */
  54. ENET_StartSMIRead((ENET_Type *)(bus_obj->hw_obj), addr, reg, kENET_MiiReadValidFrame);
  55. /* Wait for MII complete. */
  56. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  57. {
  58. if (ENET_GetInterruptStatus((ENET_Type *)(bus_obj->hw_obj)) & ENET_EIR_MII_MASK)
  59. {
  60. break;
  61. }
  62. }
  63. /* Check for timeout. */
  64. if (!counter)
  65. {
  66. // return kStatus_PHY_SMIVisitTimeout;
  67. return 0;
  68. }
  69. /* Get data from MII register. */
  70. *data_ptr = ENET_ReadSMIData((ENET_Type *)(bus_obj->hw_obj));
  71. /* Clear MII interrupt event. */
  72. ENET_ClearInterruptStatus((ENET_Type *)bus_obj->hw_obj, ENET_EIR_MII_MASK);
  73. return 4;
  74. }
  75. static rt_size_t rt_hw_mdio_write(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size)
  76. {
  77. struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus;
  78. uint32_t counter;
  79. rt_uint32_t *data_ptr = (rt_uint32_t *)data;
  80. if (4 != size)
  81. {
  82. return 0;
  83. }
  84. /* Clear the SMI interrupt event. */
  85. ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK);
  86. /* Starts a SMI write command. */
  87. ENET_StartSMIWrite((ENET_Type *)(bus_obj->hw_obj), addr, reg, kENET_MiiWriteValidFrame, *data_ptr);
  88. /* Wait for SMI complete. */
  89. for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
  90. {
  91. if (ENET_GetInterruptStatus((ENET_Type *)(bus_obj->hw_obj)) & ENET_EIR_MII_MASK)
  92. {
  93. break;
  94. }
  95. }
  96. /* Check for timeout. */
  97. if (!counter)
  98. {
  99. return 0;
  100. }
  101. /* Clear MII interrupt event. */
  102. ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK);
  103. return size;
  104. }
  105. static struct rt_mdio_bus_ops imxrt_mdio_ops =
  106. {
  107. .init = rt_hw_mdio_init,
  108. .read = rt_hw_mdio_read,
  109. .write = rt_hw_mdio_write,
  110. .uninit = RT_NULL,
  111. };
  112. static rt_mdio_t mdio_bus;
  113. rt_mdio_t *rt_hw_mdio_register(void *hw_obj, char *name)
  114. {
  115. mdio_bus.hw_obj = hw_obj;
  116. mdio_bus.name = name;
  117. mdio_bus.ops = &imxrt_mdio_ops;
  118. return &mdio_bus;
  119. }
  120. rt_mdio_t *rt_hw_mdio_get(void)
  121. {
  122. return &mdio_bus;
  123. }
  124. #endif