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