ax88796c_ioctl.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2010 ASIX Electronics Corporation
  4. * Copyright (c) 2020 Samsung Electronics Co., Ltd.
  5. *
  6. * ASIX AX88796C SPI Fast Ethernet Linux driver
  7. */
  8. #define pr_fmt(fmt) "ax88796c: " fmt
  9. #include <linux/bitmap.h>
  10. #include <linux/iopoll.h>
  11. #include <linux/phy.h>
  12. #include <linux/netdevice.h>
  13. #include "ax88796c_main.h"
  14. #include "ax88796c_ioctl.h"
  15. static const char ax88796c_priv_flag_names[][ETH_GSTRING_LEN] = {
  16. "SPICompression",
  17. };
  18. static void
  19. ax88796c_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
  20. {
  21. /* Inherit standard device info */
  22. strncpy(info->driver, DRV_NAME, sizeof(info->driver));
  23. }
  24. static u32 ax88796c_get_msglevel(struct net_device *ndev)
  25. {
  26. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  27. return ax_local->msg_enable;
  28. }
  29. static void ax88796c_set_msglevel(struct net_device *ndev, u32 level)
  30. {
  31. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  32. ax_local->msg_enable = level;
  33. }
  34. static void
  35. ax88796c_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
  36. {
  37. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  38. pause->tx_pause = !!(ax_local->flowctrl & AX_FC_TX);
  39. pause->rx_pause = !!(ax_local->flowctrl & AX_FC_RX);
  40. pause->autoneg = (ax_local->flowctrl & AX_FC_ANEG) ?
  41. AUTONEG_ENABLE :
  42. AUTONEG_DISABLE;
  43. }
  44. static int
  45. ax88796c_set_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
  46. {
  47. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  48. int fc;
  49. /* The following logic comes from phylink_ethtool_set_pauseparam() */
  50. fc = pause->tx_pause ? AX_FC_TX : 0;
  51. fc |= pause->rx_pause ? AX_FC_RX : 0;
  52. fc |= pause->autoneg ? AX_FC_ANEG : 0;
  53. ax_local->flowctrl = fc;
  54. if (pause->autoneg) {
  55. phy_set_asym_pause(ax_local->phydev, pause->tx_pause,
  56. pause->rx_pause);
  57. } else {
  58. int maccr = 0;
  59. phy_set_asym_pause(ax_local->phydev, 0, 0);
  60. maccr |= (ax_local->flowctrl & AX_FC_RX) ? MACCR_RXFC_ENABLE : 0;
  61. maccr |= (ax_local->flowctrl & AX_FC_TX) ? MACCR_TXFC_ENABLE : 0;
  62. mutex_lock(&ax_local->spi_lock);
  63. maccr |= AX_READ(&ax_local->ax_spi, P0_MACCR) &
  64. ~(MACCR_TXFC_ENABLE | MACCR_RXFC_ENABLE);
  65. AX_WRITE(&ax_local->ax_spi, maccr, P0_MACCR);
  66. mutex_unlock(&ax_local->spi_lock);
  67. }
  68. return 0;
  69. }
  70. static int ax88796c_get_regs_len(struct net_device *ndev)
  71. {
  72. return AX88796C_REGDUMP_LEN + AX88796C_PHY_REGDUMP_LEN;
  73. }
  74. static void
  75. ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p)
  76. {
  77. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  78. int offset, i;
  79. u16 *p = _p;
  80. memset(p, 0, ax88796c_get_regs_len(ndev));
  81. mutex_lock(&ax_local->spi_lock);
  82. for (offset = 0; offset < AX88796C_REGDUMP_LEN; offset += 2) {
  83. if (!test_bit(offset / 2, ax88796c_no_regs_mask))
  84. *p = AX_READ(&ax_local->ax_spi, offset);
  85. p++;
  86. }
  87. mutex_unlock(&ax_local->spi_lock);
  88. for (i = 0; i < AX88796C_PHY_REGDUMP_LEN / 2; i++) {
  89. *p = phy_read(ax_local->phydev, i);
  90. p++;
  91. }
  92. }
  93. static void
  94. ax88796c_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
  95. {
  96. switch (stringset) {
  97. case ETH_SS_PRIV_FLAGS:
  98. memcpy(data, ax88796c_priv_flag_names,
  99. sizeof(ax88796c_priv_flag_names));
  100. break;
  101. }
  102. }
  103. static int
  104. ax88796c_get_sset_count(struct net_device *ndev, int stringset)
  105. {
  106. int ret = 0;
  107. switch (stringset) {
  108. case ETH_SS_PRIV_FLAGS:
  109. ret = ARRAY_SIZE(ax88796c_priv_flag_names);
  110. break;
  111. default:
  112. ret = -EOPNOTSUPP;
  113. }
  114. return ret;
  115. }
  116. static int ax88796c_set_priv_flags(struct net_device *ndev, u32 flags)
  117. {
  118. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  119. if (flags & ~AX_PRIV_FLAGS_MASK)
  120. return -EOPNOTSUPP;
  121. if ((ax_local->priv_flags ^ flags) & AX_CAP_COMP)
  122. if (netif_running(ndev))
  123. return -EBUSY;
  124. ax_local->priv_flags = flags;
  125. return 0;
  126. }
  127. static u32 ax88796c_get_priv_flags(struct net_device *ndev)
  128. {
  129. struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
  130. return ax_local->priv_flags;
  131. }
  132. int ax88796c_mdio_read(struct mii_bus *mdiobus, int phy_id, int loc)
  133. {
  134. struct ax88796c_device *ax_local = mdiobus->priv;
  135. int ret;
  136. mutex_lock(&ax_local->spi_lock);
  137. AX_WRITE(&ax_local->ax_spi, MDIOCR_RADDR(loc)
  138. | MDIOCR_FADDR(phy_id) | MDIOCR_READ, P2_MDIOCR);
  139. ret = read_poll_timeout(AX_READ, ret,
  140. (ret != 0),
  141. 0, jiffies_to_usecs(HZ / 100), false,
  142. &ax_local->ax_spi, P2_MDIOCR);
  143. if (!ret)
  144. ret = AX_READ(&ax_local->ax_spi, P2_MDIODR);
  145. mutex_unlock(&ax_local->spi_lock);
  146. return ret;
  147. }
  148. int
  149. ax88796c_mdio_write(struct mii_bus *mdiobus, int phy_id, int loc, u16 val)
  150. {
  151. struct ax88796c_device *ax_local = mdiobus->priv;
  152. int ret;
  153. mutex_lock(&ax_local->spi_lock);
  154. AX_WRITE(&ax_local->ax_spi, val, P2_MDIODR);
  155. AX_WRITE(&ax_local->ax_spi,
  156. MDIOCR_RADDR(loc) | MDIOCR_FADDR(phy_id)
  157. | MDIOCR_WRITE, P2_MDIOCR);
  158. ret = read_poll_timeout(AX_READ, ret,
  159. ((ret & MDIOCR_VALID) != 0), 0,
  160. jiffies_to_usecs(HZ / 100), false,
  161. &ax_local->ax_spi, P2_MDIOCR);
  162. mutex_unlock(&ax_local->spi_lock);
  163. return ret;
  164. }
  165. const struct ethtool_ops ax88796c_ethtool_ops = {
  166. .get_drvinfo = ax88796c_get_drvinfo,
  167. .get_link = ethtool_op_get_link,
  168. .get_msglevel = ax88796c_get_msglevel,
  169. .set_msglevel = ax88796c_set_msglevel,
  170. .get_link_ksettings = phy_ethtool_get_link_ksettings,
  171. .set_link_ksettings = phy_ethtool_set_link_ksettings,
  172. .nway_reset = phy_ethtool_nway_reset,
  173. .get_pauseparam = ax88796c_get_pauseparam,
  174. .set_pauseparam = ax88796c_set_pauseparam,
  175. .get_regs_len = ax88796c_get_regs_len,
  176. .get_regs = ax88796c_get_regs,
  177. .get_strings = ax88796c_get_strings,
  178. .get_sset_count = ax88796c_get_sset_count,
  179. .get_priv_flags = ax88796c_get_priv_flags,
  180. .set_priv_flags = ax88796c_set_priv_flags,
  181. };
  182. int ax88796c_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
  183. {
  184. int ret;
  185. ret = phy_mii_ioctl(ndev->phydev, ifr, cmd);
  186. return ret;
  187. }