1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright (c) 2024 Hisilicon Limited. 3 4 #include <linux/phy.h> 5 #include <linux/rtnetlink.h> 6 #include "hbg_common.h" 7 #include "hbg_hw.h" 8 #include "hbg_mdio.h" 9 #include "hbg_reg.h" 10 11 #define HBG_MAC_GET_PRIV(mac) ((struct hbg_priv *)(mac)->mdio_bus->priv) 12 #define HBG_MII_BUS_GET_MAC(bus) (&((struct hbg_priv *)(bus)->priv)->mac) 13 14 #define HBG_MDIO_C22_MODE 0x1 15 #define HBG_MDIO_C22_REG_WRITE 0x1 16 #define HBG_MDIO_C22_REG_READ 0x2 17 18 #define HBG_MDIO_OP_TIMEOUT_US (1 * 1000 * 1000) 19 #define HBG_MDIO_OP_INTERVAL_US (5 * 1000) 20 21 #define HBG_NP_LINK_FAIL_RETRY_TIMES 5 22 23 static void hbg_mdio_set_command(struct hbg_mac *mac, u32 cmd) 24 { 25 hbg_reg_write(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_COMMAND_ADDR, cmd); 26 } 27 28 static void hbg_mdio_get_command(struct hbg_mac *mac, u32 *cmd) 29 { 30 *cmd = hbg_reg_read(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_COMMAND_ADDR); 31 } 32 33 static void hbg_mdio_set_wdata_reg(struct hbg_mac *mac, u16 wdata_value) 34 { 35 hbg_reg_write_field(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_WDATA_ADDR, 36 HBG_REG_MDIO_WDATA_M, wdata_value); 37 } 38 39 static u32 hbg_mdio_get_rdata_reg(struct hbg_mac *mac) 40 { 41 return hbg_reg_read_field(HBG_MAC_GET_PRIV(mac), 42 HBG_REG_MDIO_RDATA_ADDR, 43 HBG_REG_MDIO_WDATA_M); 44 } 45 46 static int hbg_mdio_wait_ready(struct hbg_mac *mac) 47 { 48 struct hbg_priv *priv = HBG_MAC_GET_PRIV(mac); 49 u32 cmd = 0; 50 int ret; 51 52 ret = readl_poll_timeout(priv->io_base + HBG_REG_MDIO_COMMAND_ADDR, cmd, 53 !FIELD_GET(HBG_REG_MDIO_COMMAND_START_B, cmd), 54 HBG_MDIO_OP_INTERVAL_US, 55 HBG_MDIO_OP_TIMEOUT_US); 56 57 return ret ? -ETIMEDOUT : 0; 58 } 59 60 static int hbg_mdio_cmd_send(struct hbg_mac *mac, u32 prt_addr, u32 dev_addr, 61 u32 type, u32 op_code) 62 { 63 u32 cmd = 0; 64 65 hbg_mdio_get_command(mac, &cmd); 66 hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_ST_M, type); 67 hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_OP_M, op_code); 68 hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_PRTAD_M, prt_addr); 69 hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_DEVAD_M, dev_addr); 70 71 /* if auto scan enabled, this value need fix to 0 */ 72 hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_START_B, 0x1); 73 74 hbg_mdio_set_command(mac, cmd); 75 76 /* wait operation complete and check the result */ 77 return hbg_mdio_wait_ready(mac); 78 } 79 80 static int hbg_mdio_read22(struct mii_bus *bus, int phy_addr, int regnum) 81 { 82 struct hbg_mac *mac = HBG_MII_BUS_GET_MAC(bus); 83 int ret; 84 85 ret = hbg_mdio_cmd_send(mac, phy_addr, regnum, HBG_MDIO_C22_MODE, 86 HBG_MDIO_C22_REG_READ); 87 if (ret) 88 return ret; 89 90 return hbg_mdio_get_rdata_reg(mac); 91 } 92 93 static int hbg_mdio_write22(struct mii_bus *bus, int phy_addr, int regnum, 94 u16 val) 95 { 96 struct hbg_mac *mac = HBG_MII_BUS_GET_MAC(bus); 97 98 hbg_mdio_set_wdata_reg(mac, val); 99 return hbg_mdio_cmd_send(mac, phy_addr, regnum, HBG_MDIO_C22_MODE, 100 HBG_MDIO_C22_REG_WRITE); 101 } 102 103 static void hbg_mdio_init_hw(struct hbg_priv *priv) 104 { 105 u32 freq = priv->dev_specs.mdio_frequency; 106 struct hbg_mac *mac = &priv->mac; 107 u32 cmd = 0; 108 109 cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_ST_M, HBG_MDIO_C22_MODE); 110 cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_AUTO_SCAN_B, HBG_STATUS_DISABLE); 111 112 /* freq use two bits, which are stored in clk_sel and clk_sel_exp */ 113 cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_CLK_SEL_B, freq & 0x1); 114 cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_CLK_SEL_EXP_B, 115 (freq >> 1) & 0x1); 116 117 hbg_mdio_set_command(mac, cmd); 118 } 119 120 static void hbg_flowctrl_cfg(struct hbg_priv *priv) 121 { 122 struct phy_device *phydev = priv->mac.phydev; 123 bool rx_pause; 124 bool tx_pause; 125 126 if (!priv->mac.pause_autoneg) 127 return; 128 129 phy_get_pause(phydev, &tx_pause, &rx_pause); 130 hbg_hw_set_pause_enable(priv, tx_pause, rx_pause); 131 } 132 133 void hbg_fix_np_link_fail(struct hbg_priv *priv) 134 { 135 struct device *dev = &priv->pdev->dev; 136 137 rtnl_lock(); 138 139 if (priv->stats.np_link_fail_cnt >= HBG_NP_LINK_FAIL_RETRY_TIMES) { 140 dev_err(dev, "failed to fix the MAC link status\n"); 141 priv->stats.np_link_fail_cnt = 0; 142 goto unlock; 143 } 144 145 if (!priv->mac.phydev->link) 146 goto unlock; 147 148 priv->stats.np_link_fail_cnt++; 149 dev_err(dev, "failed to link between MAC and PHY, try to fix...\n"); 150 151 /* Replace phy_reset() with phy_stop() and phy_start(), 152 * as suggested by Andrew. 153 */ 154 hbg_phy_stop(priv); 155 hbg_phy_start(priv); 156 157 unlock: 158 rtnl_unlock(); 159 } 160 161 static void hbg_phy_adjust_link(struct net_device *netdev) 162 { 163 struct hbg_priv *priv = netdev_priv(netdev); 164 struct phy_device *phydev = netdev->phydev; 165 u32 speed; 166 167 if (phydev->link != priv->mac.link_status) { 168 if (phydev->link) { 169 switch (phydev->speed) { 170 case SPEED_10: 171 speed = HBG_PORT_MODE_SGMII_10M; 172 break; 173 case SPEED_100: 174 speed = HBG_PORT_MODE_SGMII_100M; 175 break; 176 case SPEED_1000: 177 speed = HBG_PORT_MODE_SGMII_1000M; 178 break; 179 default: 180 return; 181 } 182 183 priv->mac.speed = speed; 184 priv->mac.duplex = phydev->duplex; 185 priv->mac.autoneg = phydev->autoneg; 186 hbg_hw_adjust_link(priv, speed, phydev->duplex); 187 hbg_flowctrl_cfg(priv); 188 } 189 190 priv->mac.link_status = phydev->link; 191 phy_print_status(phydev); 192 } 193 } 194 195 static void hbg_phy_disconnect(void *data) 196 { 197 phy_disconnect((struct phy_device *)data); 198 } 199 200 static int hbg_phy_connect(struct hbg_priv *priv) 201 { 202 struct phy_device *phydev = priv->mac.phydev; 203 struct device *dev = &priv->pdev->dev; 204 int ret; 205 206 ret = phy_connect_direct(priv->netdev, phydev, hbg_phy_adjust_link, 207 PHY_INTERFACE_MODE_SGMII); 208 if (ret) 209 return dev_err_probe(dev, ret, "failed to connect phy\n"); 210 211 ret = devm_add_action_or_reset(dev, hbg_phy_disconnect, phydev); 212 if (ret) 213 return ret; 214 215 phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); 216 phy_support_asym_pause(phydev); 217 phy_attached_info(phydev); 218 219 return 0; 220 } 221 222 void hbg_phy_start(struct hbg_priv *priv) 223 { 224 phy_start(priv->mac.phydev); 225 } 226 227 void hbg_phy_stop(struct hbg_priv *priv) 228 { 229 phy_stop(priv->mac.phydev); 230 } 231 232 int hbg_mdio_init(struct hbg_priv *priv) 233 { 234 struct device *dev = &priv->pdev->dev; 235 struct hbg_mac *mac = &priv->mac; 236 struct phy_device *phydev; 237 struct mii_bus *mdio_bus; 238 int ret; 239 240 mac->phy_addr = priv->dev_specs.phy_addr; 241 mdio_bus = devm_mdiobus_alloc(dev); 242 if (!mdio_bus) 243 return dev_err_probe(dev, -ENOMEM, 244 "failed to alloc MDIO bus\n"); 245 246 mdio_bus->parent = dev; 247 mdio_bus->priv = priv; 248 mdio_bus->phy_mask = ~(1 << mac->phy_addr); 249 mdio_bus->name = "hibmcge mii bus"; 250 mac->mdio_bus = mdio_bus; 251 252 mdio_bus->read = hbg_mdio_read22; 253 mdio_bus->write = hbg_mdio_write22; 254 snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii", dev_name(dev)); 255 256 ret = devm_mdiobus_register(dev, mdio_bus); 257 if (ret) 258 return dev_err_probe(dev, ret, "failed to register MDIO bus\n"); 259 260 phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr); 261 if (!phydev) 262 return dev_err_probe(dev, -ENODEV, 263 "failed to get phy device\n"); 264 265 mac->phydev = phydev; 266 hbg_mdio_init_hw(priv); 267 return hbg_phy_connect(priv); 268 } 269