mii.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * File : mii.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) chinesebear
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2017-08-24 chinesebear first version
  23. */
  24. #include "mii.h"
  25. static inline unsigned int mii_nway_result (unsigned int negotiated)
  26. {
  27. unsigned int ret;
  28. if (negotiated & LPA_100FULL)
  29. ret = LPA_100FULL;
  30. else if (negotiated & LPA_100BASE4)
  31. ret = LPA_100BASE4;
  32. else if (negotiated & LPA_100HALF)
  33. ret = LPA_100HALF;
  34. else if (negotiated & LPA_10FULL)
  35. ret = LPA_10FULL;
  36. else
  37. ret = LPA_10HALF;
  38. return ret;
  39. }
  40. static int mii_check_gmii_support(struct mii_if_info *mii)
  41. {
  42. int reg;
  43. reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
  44. if (reg & BMSR_ESTATEN) {
  45. reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
  46. if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
  47. return 1;
  48. }
  49. return 0;
  50. }
  51. static int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
  52. {
  53. struct synopGMACNetworkAdapter * dev = mii->dev;
  54. u32 advert, bmcr, lpa, nego;
  55. u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
  56. ecmd->supported =
  57. (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
  58. SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
  59. SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
  60. if (mii->supports_gmii)
  61. ecmd->supported |= SUPPORTED_1000baseT_Half |
  62. SUPPORTED_1000baseT_Full;
  63. /* only supports twisted-pair */
  64. ecmd->port = PORT_MII;
  65. /* only supports internal transceiver */
  66. ecmd->transceiver = XCVR_INTERNAL;
  67. /* this isn't fully supported at higher layers */
  68. ecmd->phy_address = mii->phy_id;
  69. ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
  70. advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
  71. if (mii->supports_gmii)
  72. advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
  73. if (advert & ADVERTISE_10HALF)
  74. ecmd->advertising |= ADVERTISED_10baseT_Half;
  75. if (advert & ADVERTISE_10FULL)
  76. ecmd->advertising |= ADVERTISED_10baseT_Full;
  77. if (advert & ADVERTISE_100HALF)
  78. ecmd->advertising |= ADVERTISED_100baseT_Half;
  79. if (advert & ADVERTISE_100FULL)
  80. ecmd->advertising |= ADVERTISED_100baseT_Full;
  81. if (advert2 & ADVERTISE_1000HALF)
  82. ecmd->advertising |= ADVERTISED_1000baseT_Half;
  83. if (advert2 & ADVERTISE_1000FULL)
  84. ecmd->advertising |= ADVERTISED_1000baseT_Full;
  85. bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
  86. lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
  87. if (mii->supports_gmii) {
  88. bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
  89. lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
  90. }
  91. if (bmcr & BMCR_ANENABLE) {
  92. ecmd->advertising |= ADVERTISED_Autoneg;
  93. ecmd->autoneg = AUTONEG_ENABLE;
  94. nego = mii_nway_result(advert & lpa);
  95. if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
  96. (lpa2 >> 2))
  97. ecmd->speed = SPEED_1000;
  98. else if (nego == LPA_100FULL || nego == LPA_100HALF)
  99. ecmd->speed = SPEED_100;
  100. else
  101. ecmd->speed = SPEED_10;
  102. if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
  103. nego == LPA_10FULL) {
  104. ecmd->duplex = DUPLEX_FULL;
  105. mii->full_duplex = 1;
  106. } else {
  107. ecmd->duplex = DUPLEX_HALF;
  108. mii->full_duplex = 0;
  109. }
  110. } else {
  111. ecmd->autoneg = AUTONEG_DISABLE;
  112. ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
  113. (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
  114. (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
  115. ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
  116. }
  117. /* ignore maxtxpkt, maxrxpkt for now */
  118. return 0;
  119. }
  120. static int mii_link_ok (struct mii_if_info *mii)
  121. {
  122. /* first, a dummy read, needed to latch some MII phys */
  123. mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
  124. if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
  125. return 1;
  126. return 0;
  127. }