2 * Copyright (c) 2016~2017 Hisilicon Limited.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
10 #include <linux/etherdevice.h>
11 #include <linux/kernel.h>
13 #include "hclge_cmd.h"
14 #include "hclge_main.h"
15 #include "hclge_mdio.h"
17 #define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
20 SUPPORTED_Asym_Pause | \
22 PHY_100BT_FEATURES | \
25 enum hclge_mdio_c22_op_seq
{
26 HCLGE_MDIO_C22_WRITE
= 1,
27 HCLGE_MDIO_C22_READ
= 2
30 #define HCLGE_MDIO_CTRL_START_B 0
31 #define HCLGE_MDIO_CTRL_ST_S 1
32 #define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S)
33 #define HCLGE_MDIO_CTRL_OP_S 3
34 #define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S)
36 #define HCLGE_MDIO_PHYID_S 0
37 #define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S)
39 #define HCLGE_MDIO_PHYREG_S 0
40 #define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S)
42 #define HCLGE_MDIO_STA_B 0
44 struct hclge_mdio_cfg_cmd
{
55 static int hclge_mdio_write(struct mii_bus
*bus
, int phyid
, int regnum
,
58 struct hclge_mdio_cfg_cmd
*mdio_cmd
;
59 struct hclge_dev
*hdev
= bus
->priv
;
60 struct hclge_desc desc
;
63 if (test_bit(HCLGE_STATE_RST_HANDLING
, &hdev
->state
))
66 hclge_cmd_setup_basic_desc(&desc
, HCLGE_OPC_MDIO_CONFIG
, false);
68 mdio_cmd
= (struct hclge_mdio_cfg_cmd
*)desc
.data
;
70 hnae_set_field(mdio_cmd
->phyid
, HCLGE_MDIO_PHYID_M
,
71 HCLGE_MDIO_PHYID_S
, phyid
);
72 hnae_set_field(mdio_cmd
->phyad
, HCLGE_MDIO_PHYREG_M
,
73 HCLGE_MDIO_PHYREG_S
, regnum
);
75 hnae_set_bit(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_START_B
, 1);
76 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_ST_M
,
77 HCLGE_MDIO_CTRL_ST_S
, 1);
78 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_OP_M
,
79 HCLGE_MDIO_CTRL_OP_S
, HCLGE_MDIO_C22_WRITE
);
81 mdio_cmd
->data_wr
= cpu_to_le16(data
);
83 ret
= hclge_cmd_send(&hdev
->hw
, &desc
, 1);
85 dev_err(&hdev
->pdev
->dev
,
86 "mdio write fail when sending cmd, status is %d.\n",
94 static int hclge_mdio_read(struct mii_bus
*bus
, int phyid
, int regnum
)
96 struct hclge_mdio_cfg_cmd
*mdio_cmd
;
97 struct hclge_dev
*hdev
= bus
->priv
;
98 struct hclge_desc desc
;
101 if (test_bit(HCLGE_STATE_RST_HANDLING
, &hdev
->state
))
104 hclge_cmd_setup_basic_desc(&desc
, HCLGE_OPC_MDIO_CONFIG
, true);
106 mdio_cmd
= (struct hclge_mdio_cfg_cmd
*)desc
.data
;
108 hnae_set_field(mdio_cmd
->phyid
, HCLGE_MDIO_PHYID_M
,
109 HCLGE_MDIO_PHYID_S
, phyid
);
110 hnae_set_field(mdio_cmd
->phyad
, HCLGE_MDIO_PHYREG_M
,
111 HCLGE_MDIO_PHYREG_S
, regnum
);
113 hnae_set_bit(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_START_B
, 1);
114 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_ST_M
,
115 HCLGE_MDIO_CTRL_ST_S
, 1);
116 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_OP_M
,
117 HCLGE_MDIO_CTRL_OP_S
, HCLGE_MDIO_C22_READ
);
119 /* Read out phy data */
120 ret
= hclge_cmd_send(&hdev
->hw
, &desc
, 1);
122 dev_err(&hdev
->pdev
->dev
,
123 "mdio read fail when get data, status is %d.\n",
128 if (hnae_get_bit(le16_to_cpu(mdio_cmd
->sta
), HCLGE_MDIO_STA_B
)) {
129 dev_err(&hdev
->pdev
->dev
, "mdio read data error\n");
133 return le16_to_cpu(mdio_cmd
->data_rd
);
136 int hclge_mac_mdio_config(struct hclge_dev
*hdev
)
138 struct hclge_mac
*mac
= &hdev
->hw
.mac
;
139 struct phy_device
*phydev
;
140 struct mii_bus
*mdio_bus
;
143 if (hdev
->hw
.mac
.phy_addr
>= PHY_MAX_ADDR
) {
144 dev_err(&hdev
->pdev
->dev
, "phy_addr(%d) is too large.\n",
145 hdev
->hw
.mac
.phy_addr
);
149 mdio_bus
= devm_mdiobus_alloc(&hdev
->pdev
->dev
);
153 mdio_bus
->name
= "hisilicon MII bus";
154 mdio_bus
->read
= hclge_mdio_read
;
155 mdio_bus
->write
= hclge_mdio_write
;
156 snprintf(mdio_bus
->id
, MII_BUS_ID_SIZE
, "%s-%s", "mii",
157 dev_name(&hdev
->pdev
->dev
));
159 mdio_bus
->parent
= &hdev
->pdev
->dev
;
160 mdio_bus
->priv
= hdev
;
161 mdio_bus
->phy_mask
= ~(1 << mac
->phy_addr
);
162 ret
= mdiobus_register(mdio_bus
);
164 dev_err(mdio_bus
->parent
,
165 "Failed to register MDIO bus ret = %#x\n", ret
);
169 phydev
= mdiobus_get_phy(mdio_bus
, mac
->phy_addr
);
171 dev_err(mdio_bus
->parent
, "Failed to get phy device\n");
172 mdiobus_unregister(mdio_bus
);
176 mac
->phydev
= phydev
;
177 mac
->mdio_bus
= mdio_bus
;
182 static void hclge_mac_adjust_link(struct net_device
*netdev
)
184 struct hnae3_handle
*h
= *((void **)netdev_priv(netdev
));
185 struct hclge_vport
*vport
= hclge_get_vport(h
);
186 struct hclge_dev
*hdev
= vport
->back
;
190 speed
= netdev
->phydev
->speed
;
191 duplex
= netdev
->phydev
->duplex
;
193 ret
= hclge_cfg_mac_speed_dup(hdev
, speed
, duplex
);
195 netdev_err(netdev
, "failed to adjust link.\n");
197 ret
= hclge_cfg_flowctrl(hdev
);
199 netdev_err(netdev
, "failed to configure flow control.\n");
202 int hclge_mac_start_phy(struct hclge_dev
*hdev
)
204 struct net_device
*netdev
= hdev
->vport
[0].nic
.netdev
;
205 struct phy_device
*phydev
= hdev
->hw
.mac
.phydev
;
211 ret
= phy_connect_direct(netdev
, phydev
,
212 hclge_mac_adjust_link
,
213 PHY_INTERFACE_MODE_SGMII
);
215 netdev_err(netdev
, "phy_connect_direct err.\n");
219 phydev
->supported
&= HCLGE_PHY_SUPPORTED_FEATURES
;
220 phydev
->advertising
= phydev
->supported
;
227 void hclge_mac_stop_phy(struct hclge_dev
*hdev
)
229 struct net_device
*netdev
= hdev
->vport
[0].nic
.netdev
;
230 struct phy_device
*phydev
= netdev
->phydev
;
236 phy_disconnect(phydev
);