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