spl2sw_phy.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright Sunplus Technology Co., Ltd.
  3. * All rights reserved.
  4. */
  5. #include <linux/netdevice.h>
  6. #include <linux/bitfield.h>
  7. #include <linux/of_mdio.h>
  8. #include "spl2sw_register.h"
  9. #include "spl2sw_define.h"
  10. #include "spl2sw_phy.h"
  11. static void spl2sw_mii_link_change(struct net_device *ndev)
  12. {
  13. struct spl2sw_mac *mac = netdev_priv(ndev);
  14. struct phy_device *phydev = ndev->phydev;
  15. struct spl2sw_common *comm = mac->comm;
  16. u32 reg;
  17. reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
  18. if (phydev->link) {
  19. reg |= FIELD_PREP(MAC_FORCE_RMII_LINK, mac->lan_port);
  20. if (phydev->speed == 100) {
  21. reg |= FIELD_PREP(MAC_FORCE_RMII_SPD, mac->lan_port);
  22. } else {
  23. reg &= FIELD_PREP(MAC_FORCE_RMII_SPD, ~mac->lan_port) |
  24. ~MAC_FORCE_RMII_SPD;
  25. }
  26. if (phydev->duplex) {
  27. reg |= FIELD_PREP(MAC_FORCE_RMII_DPX, mac->lan_port);
  28. } else {
  29. reg &= FIELD_PREP(MAC_FORCE_RMII_DPX, ~mac->lan_port) |
  30. ~MAC_FORCE_RMII_DPX;
  31. }
  32. if (phydev->pause) {
  33. reg |= FIELD_PREP(MAC_FORCE_RMII_FC, mac->lan_port);
  34. } else {
  35. reg &= FIELD_PREP(MAC_FORCE_RMII_FC, ~mac->lan_port) |
  36. ~MAC_FORCE_RMII_FC;
  37. }
  38. } else {
  39. reg &= FIELD_PREP(MAC_FORCE_RMII_LINK, ~mac->lan_port) |
  40. ~MAC_FORCE_RMII_LINK;
  41. }
  42. writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
  43. phy_print_status(phydev);
  44. }
  45. int spl2sw_phy_connect(struct spl2sw_common *comm)
  46. {
  47. struct phy_device *phydev;
  48. struct net_device *ndev;
  49. struct spl2sw_mac *mac;
  50. int i;
  51. for (i = 0; i < MAX_NETDEV_NUM; i++)
  52. if (comm->ndev[i]) {
  53. ndev = comm->ndev[i];
  54. mac = netdev_priv(ndev);
  55. phydev = of_phy_connect(ndev, mac->phy_node, spl2sw_mii_link_change,
  56. 0, mac->phy_mode);
  57. if (!phydev)
  58. return -ENODEV;
  59. phy_support_asym_pause(phydev);
  60. phy_attached_info(phydev);
  61. }
  62. return 0;
  63. }
  64. void spl2sw_phy_remove(struct spl2sw_common *comm)
  65. {
  66. struct net_device *ndev;
  67. int i;
  68. for (i = 0; i < MAX_NETDEV_NUM; i++)
  69. if (comm->ndev[i]) {
  70. ndev = comm->ndev[i];
  71. if (ndev)
  72. phy_disconnect(ndev->phydev);
  73. }
  74. }