1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2024 Hisilicon Limited.
5 #include "hbg_common.h"
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)
13 #define HBG_MDIO_C22_MODE 0x1
14 #define HBG_MDIO_C22_REG_WRITE 0x1
15 #define HBG_MDIO_C22_REG_READ 0x2
17 #define HBG_MDIO_OP_TIMEOUT_US (1 * 1000 * 1000)
18 #define HBG_MDIO_OP_INTERVAL_US (5 * 1000)
20 static void hbg_mdio_set_command(struct hbg_mac
*mac
, u32 cmd
)
22 hbg_reg_write(HBG_MAC_GET_PRIV(mac
), HBG_REG_MDIO_COMMAND_ADDR
, cmd
);
25 static void hbg_mdio_get_command(struct hbg_mac
*mac
, u32
*cmd
)
27 *cmd
= hbg_reg_read(HBG_MAC_GET_PRIV(mac
), HBG_REG_MDIO_COMMAND_ADDR
);
30 static void hbg_mdio_set_wdata_reg(struct hbg_mac
*mac
, u16 wdata_value
)
32 hbg_reg_write_field(HBG_MAC_GET_PRIV(mac
), HBG_REG_MDIO_WDATA_ADDR
,
33 HBG_REG_MDIO_WDATA_M
, wdata_value
);
36 static u32
hbg_mdio_get_rdata_reg(struct hbg_mac
*mac
)
38 return hbg_reg_read_field(HBG_MAC_GET_PRIV(mac
),
39 HBG_REG_MDIO_RDATA_ADDR
,
40 HBG_REG_MDIO_WDATA_M
);
43 static int hbg_mdio_wait_ready(struct hbg_mac
*mac
)
45 struct hbg_priv
*priv
= HBG_MAC_GET_PRIV(mac
);
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
);
54 return ret
? -ETIMEDOUT
: 0;
57 static int hbg_mdio_cmd_send(struct hbg_mac
*mac
, u32 prt_addr
, u32 dev_addr
,
58 u32 type
, u32 op_code
)
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
);
68 /* if auto scan enabled, this value need fix to 0 */
69 hbg_field_modify(cmd
, HBG_REG_MDIO_COMMAND_START_B
, 0x1);
71 hbg_mdio_set_command(mac
, cmd
);
73 /* wait operation complete and check the result */
74 return hbg_mdio_wait_ready(mac
);
77 static int hbg_mdio_read22(struct mii_bus
*bus
, int phy_addr
, int regnum
)
79 struct hbg_mac
*mac
= HBG_MII_BUS_GET_MAC(bus
);
82 ret
= hbg_mdio_cmd_send(mac
, phy_addr
, regnum
, HBG_MDIO_C22_MODE
,
83 HBG_MDIO_C22_REG_READ
);
87 return hbg_mdio_get_rdata_reg(mac
);
90 static int hbg_mdio_write22(struct mii_bus
*bus
, int phy_addr
, int regnum
,
93 struct hbg_mac
*mac
= HBG_MII_BUS_GET_MAC(bus
);
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
);
100 static void hbg_mdio_init_hw(struct hbg_priv
*priv
)
102 u32 freq
= priv
->dev_specs
.mdio_frequency
;
103 struct hbg_mac
*mac
= &priv
->mac
;
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
);
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
,
114 hbg_mdio_set_command(mac
, cmd
);
117 static void hbg_phy_adjust_link(struct net_device
*netdev
)
119 struct hbg_priv
*priv
= netdev_priv(netdev
);
120 struct phy_device
*phydev
= netdev
->phydev
;
123 if (phydev
->link
!= priv
->mac
.link_status
) {
125 switch (phydev
->speed
) {
127 speed
= HBG_PORT_MODE_SGMII_10M
;
130 speed
= HBG_PORT_MODE_SGMII_100M
;
133 speed
= HBG_PORT_MODE_SGMII_1000M
;
139 priv
->mac
.speed
= speed
;
140 priv
->mac
.duplex
= phydev
->duplex
;
141 priv
->mac
.autoneg
= phydev
->autoneg
;
142 hbg_hw_adjust_link(priv
, speed
, phydev
->duplex
);
145 priv
->mac
.link_status
= phydev
->link
;
146 phy_print_status(phydev
);
150 static void hbg_phy_disconnect(void *data
)
152 phy_disconnect((struct phy_device
*)data
);
155 static int hbg_phy_connect(struct hbg_priv
*priv
)
157 struct phy_device
*phydev
= priv
->mac
.phydev
;
158 struct device
*dev
= &priv
->pdev
->dev
;
161 ret
= phy_connect_direct(priv
->netdev
, phydev
, hbg_phy_adjust_link
,
162 PHY_INTERFACE_MODE_SGMII
);
164 return dev_err_probe(dev
, ret
, "failed to connect phy\n");
166 ret
= devm_add_action_or_reset(dev
, hbg_phy_disconnect
, phydev
);
170 phy_remove_link_mode(phydev
, ETHTOOL_LINK_MODE_1000baseT_Half_BIT
);
171 phy_attached_info(phydev
);
176 void hbg_phy_start(struct hbg_priv
*priv
)
178 phy_start(priv
->mac
.phydev
);
181 void hbg_phy_stop(struct hbg_priv
*priv
)
183 phy_stop(priv
->mac
.phydev
);
186 int hbg_mdio_init(struct hbg_priv
*priv
)
188 struct device
*dev
= &priv
->pdev
->dev
;
189 struct hbg_mac
*mac
= &priv
->mac
;
190 struct phy_device
*phydev
;
191 struct mii_bus
*mdio_bus
;
194 mac
->phy_addr
= priv
->dev_specs
.phy_addr
;
195 mdio_bus
= devm_mdiobus_alloc(dev
);
197 return dev_err_probe(dev
, -ENOMEM
,
198 "failed to alloc MDIO bus\n");
200 mdio_bus
->parent
= dev
;
201 mdio_bus
->priv
= priv
;
202 mdio_bus
->phy_mask
= ~(1 << mac
->phy_addr
);
203 mdio_bus
->name
= "hibmcge mii bus";
204 mac
->mdio_bus
= mdio_bus
;
206 mdio_bus
->read
= hbg_mdio_read22
;
207 mdio_bus
->write
= hbg_mdio_write22
;
208 snprintf(mdio_bus
->id
, MII_BUS_ID_SIZE
, "%s-%s", "mii", dev_name(dev
));
210 ret
= devm_mdiobus_register(dev
, mdio_bus
);
212 return dev_err_probe(dev
, ret
, "failed to register MDIO bus\n");
214 phydev
= mdiobus_get_phy(mdio_bus
, mac
->phy_addr
);
216 return dev_err_probe(dev
, -ENODEV
,
217 "failed to get phy device\n");
219 mac
->phydev
= phydev
;
220 hbg_mdio_init_hw(priv
);
221 return hbg_phy_connect(priv
);