app_phy.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <stdio.h>
  2. #include "app_phy.h"
  3. #define PHY_BASE_ADDR 0x7
  4. #define PHY_REG_CONTROL 0x0
  5. #define PHY_REG_STATUS 0x1
  6. #define PHY_REG_ANE 0x6
  7. #define PHY_REG_SPEC_STATUS 0x11
  8. #define PHY_REG_EXTEND_STATUS 0x1B
  9. #define PHY_BIT_CONTROL_RESET 0x8000 /*!< Control reg : reset */
  10. #define PHY_BIT_CONTROL_ANEN 0x1000 /*!< Control reg : auto-negotiation enable */
  11. #define PHY_BIT_CONTROL_RSAN 0x0200 /*!< Control reg : auto-negotiation restart */
  12. #define PHY_BIT_STATUS_ANC 0x0020 /*!< Status reg : auto-negotiation complete */
  13. #define PHY_BIT_STATUS_LINK 0x0004 /*!< Status reg : link is up */
  14. #define PHY_BIT_ANE_LPAN 0x0001 /*!< ANE reg : link partner can auto-neg */
  15. #define PHY_BIT_SPEED 0xC000 /*!< specific status reg : speed */
  16. #define PHY_BIT_DUPLEX 0x2000 /*!< specific status reg : duplex */
  17. #define PHY_BIT_AUTO_MEDIA_DISABLE 0x8000 /*!< extended status reg : auto media select disable */
  18. #define PHY_BIT_AUTO_MEDIA_REG_DISABLE 0x0200 /*!< extended status reg : auto media register select disable */
  19. void phy_Reset() {
  20. ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, PHY_BIT_CONTROL_RESET);
  21. while (1) {
  22. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
  23. if ((ret & PHY_BIT_CONTROL_RESET) == 0) {
  24. break;
  25. }
  26. }
  27. }
  28. void phy_AutoMediaSelect() {
  29. uint32_t data;
  30. // auto media and auto media register selection
  31. data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS);
  32. data &= ~PHY_BIT_AUTO_MEDIA_DISABLE;
  33. data &= ~PHY_BIT_AUTO_MEDIA_REG_DISABLE;
  34. ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS, data);
  35. }
  36. void phy_AutoNeg()
  37. {
  38. uint32_t data;
  39. data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
  40. data |= (PHY_BIT_CONTROL_ANEN | PHY_BIT_CONTROL_RSAN);
  41. ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, data);
  42. while (1)
  43. {
  44. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
  45. if ((ret & PHY_BIT_STATUS_ANC) == PHY_BIT_STATUS_ANC)
  46. {
  47. break;
  48. }
  49. rt_thread_delay(1);
  50. }
  51. }
  52. BOOL phy_IsLink() {
  53. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
  54. return (ret & PHY_BIT_STATUS_LINK) ? TRUE : FALSE;
  55. }
  56. BOOL phy_PartnerCanAutoNeg() {
  57. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_ANE);
  58. return (ret & PHY_BIT_ANE_LPAN) ? TRUE : FALSE;
  59. }
  60. uint32_t phy_GetSpeed() {
  61. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
  62. return ((ret & PHY_BIT_SPEED) >> 14);
  63. }
  64. uint32_t phy_GetDuplex() {
  65. uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
  66. return ((ret & PHY_BIT_DUPLEX) >> 13);
  67. }
  68. BOOL phy_Init() {
  69. phy_AutoMediaSelect();
  70. phy_AutoNeg();
  71. if (!phy_PartnerCanAutoNeg()) {
  72. printf("Warning:: PHY's partner can't do auto-negotiation\n");
  73. }
  74. if (!phy_IsLink()) {
  75. printf("link is down\n");
  76. return FALSE;
  77. }
  78. {
  79. uint32_t speed = phy_GetSpeed();
  80. if (speed == PHY_SPEED_10) {
  81. speed = 10;
  82. } else if (speed == PHY_SPEED_100) {
  83. speed = 100;
  84. } else if (speed == PHY_SPEED_1000) {
  85. speed = 1000;
  86. }
  87. printf("PHY runs in %dM speed %s duplex\n",
  88. speed, (phy_GetDuplex() == PHY_DUPLEX_HALF) ? "half" : "full");
  89. }
  90. // After auto-negcioation, Mawell PHY need some
  91. // time to initial itself.
  92. // So we have to delay some time since different
  93. // connection way, such as direct wire, hub, switch.
  94. // If not to delay, the first several sent frame
  95. // may be lost.
  96. // Please according to actual environment to tune
  97. // this delay.
  98. udelay(200000);
  99. return TRUE;
  100. }