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