0001
0002
0003
0004
0005
0006 #include <linux/netdevice.h>
0007 #include <linux/bitfield.h>
0008 #include <linux/of_mdio.h>
0009
0010 #include "spl2sw_register.h"
0011 #include "spl2sw_define.h"
0012 #include "spl2sw_phy.h"
0013
0014 static void spl2sw_mii_link_change(struct net_device *ndev)
0015 {
0016 struct spl2sw_mac *mac = netdev_priv(ndev);
0017 struct phy_device *phydev = ndev->phydev;
0018 struct spl2sw_common *comm = mac->comm;
0019 u32 reg;
0020
0021 reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
0022
0023 if (phydev->link) {
0024 reg |= FIELD_PREP(MAC_FORCE_RMII_LINK, mac->lan_port);
0025
0026 if (phydev->speed == 100) {
0027 reg |= FIELD_PREP(MAC_FORCE_RMII_SPD, mac->lan_port);
0028 } else {
0029 reg &= FIELD_PREP(MAC_FORCE_RMII_SPD, ~mac->lan_port) |
0030 ~MAC_FORCE_RMII_SPD;
0031 }
0032
0033 if (phydev->duplex) {
0034 reg |= FIELD_PREP(MAC_FORCE_RMII_DPX, mac->lan_port);
0035 } else {
0036 reg &= FIELD_PREP(MAC_FORCE_RMII_DPX, ~mac->lan_port) |
0037 ~MAC_FORCE_RMII_DPX;
0038 }
0039
0040 if (phydev->pause) {
0041 reg |= FIELD_PREP(MAC_FORCE_RMII_FC, mac->lan_port);
0042 } else {
0043 reg &= FIELD_PREP(MAC_FORCE_RMII_FC, ~mac->lan_port) |
0044 ~MAC_FORCE_RMII_FC;
0045 }
0046 } else {
0047 reg &= FIELD_PREP(MAC_FORCE_RMII_LINK, ~mac->lan_port) |
0048 ~MAC_FORCE_RMII_LINK;
0049 }
0050
0051 writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
0052
0053 phy_print_status(phydev);
0054 }
0055
0056 int spl2sw_phy_connect(struct spl2sw_common *comm)
0057 {
0058 struct phy_device *phydev;
0059 struct net_device *ndev;
0060 struct spl2sw_mac *mac;
0061 int i;
0062
0063 for (i = 0; i < MAX_NETDEV_NUM; i++)
0064 if (comm->ndev[i]) {
0065 ndev = comm->ndev[i];
0066 mac = netdev_priv(ndev);
0067 phydev = of_phy_connect(ndev, mac->phy_node, spl2sw_mii_link_change,
0068 0, mac->phy_mode);
0069 if (!phydev)
0070 return -ENODEV;
0071
0072 phy_support_asym_pause(phydev);
0073 phy_attached_info(phydev);
0074 }
0075
0076 return 0;
0077 }
0078
0079 void spl2sw_phy_remove(struct spl2sw_common *comm)
0080 {
0081 struct net_device *ndev;
0082 int i;
0083
0084 for (i = 0; i < MAX_NETDEV_NUM; i++)
0085 if (comm->ndev[i]) {
0086 ndev = comm->ndev[i];
0087 if (ndev) {
0088 phy_disconnect(ndev->phydev);
0089 ndev->phydev = NULL;
0090 }
0091 }
0092 }