xref: /linux/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c (revision c284d3e423382be3591d5b1e402e330e6c3f726c)
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