1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright (c) 2016-2017 Hisilicon Limited. 3 4 #include <linux/etherdevice.h> 5 #include <linux/kernel.h> 6 7 #include "hclge_cmd.h" 8 #include "hclge_main.h" 9 #include "hclge_mdio.h" 10 11 #define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \ 12 SUPPORTED_TP | \ 13 SUPPORTED_Pause | \ 14 SUPPORTED_Asym_Pause | \ 15 PHY_10BT_FEATURES | \ 16 PHY_100BT_FEATURES | \ 17 PHY_1000BT_FEATURES) 18 19 enum hclge_mdio_c22_op_seq { 20 HCLGE_MDIO_C22_WRITE = 1, 21 HCLGE_MDIO_C22_READ = 2 22 }; 23 24 #define HCLGE_MDIO_CTRL_START_B 0 25 #define HCLGE_MDIO_CTRL_ST_S 1 26 #define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S) 27 #define HCLGE_MDIO_CTRL_OP_S 3 28 #define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S) 29 30 #define HCLGE_MDIO_PHYID_S 0 31 #define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S) 32 33 #define HCLGE_MDIO_PHYREG_S 0 34 #define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S) 35 36 #define HCLGE_MDIO_STA_B 0 37 38 struct hclge_mdio_cfg_cmd { 39 u8 ctrl_bit; 40 u8 phyid; 41 u8 phyad; 42 u8 rsvd; 43 __le16 reserve; 44 __le16 data_wr; 45 __le16 data_rd; 46 __le16 sta; 47 }; 48 49 static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum, 50 u16 data) 51 { 52 struct hclge_mdio_cfg_cmd *mdio_cmd; 53 struct hclge_dev *hdev = bus->priv; 54 struct hclge_desc desc; 55 int ret; 56 57 if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) 58 return 0; 59 60 hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false); 61 62 mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data; 63 64 hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M, 65 HCLGE_MDIO_PHYID_S, phyid); 66 hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M, 67 HCLGE_MDIO_PHYREG_S, regnum); 68 69 hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1); 70 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M, 71 HCLGE_MDIO_CTRL_ST_S, 1); 72 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M, 73 HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE); 74 75 mdio_cmd->data_wr = cpu_to_le16(data); 76 77 ret = hclge_cmd_send(&hdev->hw, &desc, 1); 78 if (ret) { 79 dev_err(&hdev->pdev->dev, 80 "mdio write fail when sending cmd, status is %d.\n", 81 ret); 82 return ret; 83 } 84 85 return 0; 86 } 87 88 static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum) 89 { 90 struct hclge_mdio_cfg_cmd *mdio_cmd; 91 struct hclge_dev *hdev = bus->priv; 92 struct hclge_desc desc; 93 int ret; 94 95 if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) 96 return 0; 97 98 hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true); 99 100 mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data; 101 102 hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M, 103 HCLGE_MDIO_PHYID_S, phyid); 104 hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M, 105 HCLGE_MDIO_PHYREG_S, regnum); 106 107 hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1); 108 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M, 109 HCLGE_MDIO_CTRL_ST_S, 1); 110 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M, 111 HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ); 112 113 /* Read out phy data */ 114 ret = hclge_cmd_send(&hdev->hw, &desc, 1); 115 if (ret) { 116 dev_err(&hdev->pdev->dev, 117 "mdio read fail when get data, status is %d.\n", 118 ret); 119 return ret; 120 } 121 122 if (hnae3_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) { 123 dev_err(&hdev->pdev->dev, "mdio read data error\n"); 124 return -EIO; 125 } 126 127 return le16_to_cpu(mdio_cmd->data_rd); 128 } 129 130 int hclge_mac_mdio_config(struct hclge_dev *hdev) 131 { 132 struct hclge_mac *mac = &hdev->hw.mac; 133 struct phy_device *phydev; 134 struct mii_bus *mdio_bus; 135 int ret; 136 137 if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR) { 138 dev_err(&hdev->pdev->dev, "phy_addr(%d) is too large.\n", 139 hdev->hw.mac.phy_addr); 140 return -EINVAL; 141 } 142 143 mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev); 144 if (!mdio_bus) 145 return -ENOMEM; 146 147 mdio_bus->name = "hisilicon MII bus"; 148 mdio_bus->read = hclge_mdio_read; 149 mdio_bus->write = hclge_mdio_write; 150 snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii", 151 dev_name(&hdev->pdev->dev)); 152 153 mdio_bus->parent = &hdev->pdev->dev; 154 mdio_bus->priv = hdev; 155 mdio_bus->phy_mask = ~(1 << mac->phy_addr); 156 ret = mdiobus_register(mdio_bus); 157 if (ret) { 158 dev_err(mdio_bus->parent, 159 "Failed to register MDIO bus ret = %#x\n", ret); 160 return ret; 161 } 162 163 phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr); 164 if (!phydev) { 165 dev_err(mdio_bus->parent, "Failed to get phy device\n"); 166 mdiobus_unregister(mdio_bus); 167 return -EIO; 168 } 169 170 mac->phydev = phydev; 171 mac->mdio_bus = mdio_bus; 172 173 return 0; 174 } 175 176 static void hclge_mac_adjust_link(struct net_device *netdev) 177 { 178 struct hnae3_handle *h = *((void **)netdev_priv(netdev)); 179 struct hclge_vport *vport = hclge_get_vport(h); 180 struct hclge_dev *hdev = vport->back; 181 int duplex, speed; 182 int ret; 183 184 speed = netdev->phydev->speed; 185 duplex = netdev->phydev->duplex; 186 187 ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex); 188 if (ret) 189 netdev_err(netdev, "failed to adjust link.\n"); 190 191 ret = hclge_cfg_flowctrl(hdev); 192 if (ret) 193 netdev_err(netdev, "failed to configure flow control.\n"); 194 } 195 196 int hclge_mac_connect_phy(struct hclge_dev *hdev) 197 { 198 struct net_device *netdev = hdev->vport[0].nic.netdev; 199 struct phy_device *phydev = hdev->hw.mac.phydev; 200 int ret; 201 202 if (!phydev) 203 return 0; 204 205 phydev->supported &= ~SUPPORTED_FIBRE; 206 207 ret = phy_connect_direct(netdev, phydev, 208 hclge_mac_adjust_link, 209 PHY_INTERFACE_MODE_SGMII); 210 if (ret) { 211 netdev_err(netdev, "phy_connect_direct err.\n"); 212 return ret; 213 } 214 215 phydev->supported &= HCLGE_PHY_SUPPORTED_FEATURES; 216 phydev->advertising = phydev->supported; 217 218 return 0; 219 } 220 221 void hclge_mac_disconnect_phy(struct hclge_dev *hdev) 222 { 223 struct phy_device *phydev = hdev->hw.mac.phydev; 224 225 if (!phydev) 226 return; 227 228 phy_disconnect(phydev); 229 } 230 231 void hclge_mac_start_phy(struct hclge_dev *hdev) 232 { 233 struct phy_device *phydev = hdev->hw.mac.phydev; 234 235 if (!phydev) 236 return; 237 238 phy_start(phydev); 239 } 240 241 void hclge_mac_stop_phy(struct hclge_dev *hdev) 242 { 243 struct net_device *netdev = hdev->vport[0].nic.netdev; 244 struct phy_device *phydev = netdev->phydev; 245 246 if (!phydev) 247 return; 248 249 phy_stop(phydev); 250 } 251