xref: /linux/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c (revision 0ad9617c78acbc71373fb341a6f75d4012b01d69)
1e8d13548SJijie Shao // SPDX-License-Identifier: GPL-2.0+
2e8d13548SJijie Shao // Copyright (c) 2024 Hisilicon Limited.
3e8d13548SJijie Shao 
4e8d13548SJijie Shao #include <linux/ethtool.h>
5e8d13548SJijie Shao #include <linux/phy.h>
63f5a61f6SJijie Shao #include <linux/rtnetlink.h>
751574da8SJijie Shao #include "hbg_common.h"
83f5a61f6SJijie Shao #include "hbg_err.h"
9e8d13548SJijie Shao #include "hbg_ethtool.h"
1051574da8SJijie Shao #include "hbg_hw.h"
1151574da8SJijie Shao 
1251574da8SJijie Shao enum hbg_reg_dump_type {
1351574da8SJijie Shao 	HBG_DUMP_REG_TYPE_SPEC = 0,
1451574da8SJijie Shao 	HBG_DUMP_REG_TYPE_MDIO,
1551574da8SJijie Shao 	HBG_DUMP_REG_TYPE_GMAC,
1651574da8SJijie Shao 	HBG_DUMP_REG_TYPE_PCU,
1751574da8SJijie Shao };
1851574da8SJijie Shao 
1951574da8SJijie Shao struct hbg_reg_info {
2051574da8SJijie Shao 	u32 type;
2151574da8SJijie Shao 	u32 offset;
2251574da8SJijie Shao 	u32 val;
2351574da8SJijie Shao };
2451574da8SJijie Shao 
2551574da8SJijie Shao #define HBG_DUMP_SPEC_I(offset) {HBG_DUMP_REG_TYPE_SPEC, offset, 0}
2651574da8SJijie Shao #define HBG_DUMP_MDIO_I(offset) {HBG_DUMP_REG_TYPE_MDIO, offset, 0}
2751574da8SJijie Shao #define HBG_DUMP_GMAC_I(offset) {HBG_DUMP_REG_TYPE_GMAC, offset, 0}
2851574da8SJijie Shao #define HBG_DUMP_PCU_I(offset) {HBG_DUMP_REG_TYPE_PCU, offset, 0}
2951574da8SJijie Shao 
3051574da8SJijie Shao static const struct hbg_reg_info hbg_dump_reg_infos[] = {
3151574da8SJijie Shao 	/* dev specs */
3251574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_SPEC_VALID_ADDR),
3351574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_EVENT_REQ_ADDR),
3451574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ID_ADDR),
3551574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_PHY_ID_ADDR),
3651574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_ADDR),
3751574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_HIGH_ADDR),
3851574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_UC_MAC_NUM_ADDR),
3951574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MDIO_FREQ_ADDR),
4051574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MAX_MTU_ADDR),
4151574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_MIN_MTU_ADDR),
4251574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_TX_FIFO_NUM_ADDR),
4351574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_RX_FIFO_NUM_ADDR),
4451574da8SJijie Shao 	HBG_DUMP_SPEC_I(HBG_REG_VLAN_LAYERS_ADDR),
4551574da8SJijie Shao 
4651574da8SJijie Shao 	/* mdio */
4751574da8SJijie Shao 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_COMMAND_ADDR),
4851574da8SJijie Shao 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_ADDR_ADDR),
4951574da8SJijie Shao 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_WDATA_ADDR),
5051574da8SJijie Shao 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_RDATA_ADDR),
5151574da8SJijie Shao 	HBG_DUMP_MDIO_I(HBG_REG_MDIO_STA_ADDR),
5251574da8SJijie Shao 
5351574da8SJijie Shao 	/* gmac */
5451574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_DUPLEX_TYPE_ADDR),
5551574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_TYPE_ADDR),
5651574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_FC_TX_TIMER_ADDR),
5751574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_LOW_ADDR),
5851574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_HIGH_ADDR),
5951574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_MAX_FRAME_SIZE_ADDR),
6051574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_PORT_MODE_ADDR),
6151574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_PORT_ENABLE_ADDR),
6251574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_PAUSE_ENABLE_ADDR),
6351574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_AN_NEG_STATE_ADDR),
6451574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_TRANSMIT_CTRL_ADDR),
6551574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_REC_FILT_CTRL_ADDR),
6651574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_LINE_LOOP_BACK_ADDR),
6751574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_CF_CRC_STRIP_ADDR),
6851574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_MODE_CHANGE_EN_ADDR),
6951574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_LOOP_REG_ADDR),
7051574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_RECV_CTRL_ADDR),
7151574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_VLAN_CODE_ADDR),
7251574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_0_ADDR),
7351574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_0_ADDR),
7451574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_1_ADDR),
7551574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_1_ADDR),
7651574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_2_ADDR),
7751574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_2_ADDR),
7851574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_3_ADDR),
7951574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_3_ADDR),
8051574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_4_ADDR),
8151574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_4_ADDR),
8251574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_5_ADDR),
8351574da8SJijie Shao 	HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_5_ADDR),
8451574da8SJijie Shao 
8551574da8SJijie Shao 	/* pcu */
8651574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_TX_FIFO_THRSLD_ADDR),
8751574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_FIFO_THRSLD_ADDR),
8851574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CFG_FIFO_THRSLD_ADDR),
8951574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_MSK_ADDR),
9051574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_STAT_ADDR),
9151574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_CLR_ADDR),
9251574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_TX_BUS_ERR_ADDR_ADDR),
9351574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_BUS_ERR_ADDR_ADDR),
9451574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_MAX_FRAME_LEN_ADDR),
9551574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_DEBUG_ST_MCH_ADDR),
9651574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_FIFO_CURR_STATUS_ADDR),
9751574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_FIFO_HIST_STATUS_ADDR),
9851574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_CFF_DATA_NUM_ADDR),
9951574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_TX_PAUSE_ADDR),
10051574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_CFF_ADDR_ADDR),
10151574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_BUF_SIZE_ADDR),
10251574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_BUS_CTRL_ADDR),
10351574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_CTRL_ADDR),
10451574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_RX_PKT_MODE_ADDR),
10551574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST0_ADDR),
10651574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST1_ADDR),
10751574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_DBG_ST2_ADDR),
10851574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_BUS_RST_EN_ADDR),
10951574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_MSK_ADDR),
11051574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_STAT_ADDR),
11151574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_CLR_ADDR),
11251574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_MSK_ADDR),
11351574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_STAT_ADDR),
11451574da8SJijie Shao 	HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_CLR_ADDR),
11551574da8SJijie Shao };
11651574da8SJijie Shao 
11751574da8SJijie Shao static const u32 hbg_dump_type_base_array[] = {
11851574da8SJijie Shao 	[HBG_DUMP_REG_TYPE_SPEC] = 0,
11951574da8SJijie Shao 	[HBG_DUMP_REG_TYPE_MDIO] = HBG_REG_MDIO_BASE,
12051574da8SJijie Shao 	[HBG_DUMP_REG_TYPE_GMAC] = HBG_REG_SGMII_BASE,
12151574da8SJijie Shao 	[HBG_DUMP_REG_TYPE_PCU] = HBG_REG_SGMII_BASE,
12251574da8SJijie Shao };
12351574da8SJijie Shao 
12451574da8SJijie Shao static int hbg_ethtool_get_regs_len(struct net_device *netdev)
12551574da8SJijie Shao {
12651574da8SJijie Shao 	return ARRAY_SIZE(hbg_dump_reg_infos) * sizeof(struct hbg_reg_info);
12751574da8SJijie Shao }
12851574da8SJijie Shao 
12951574da8SJijie Shao static void hbg_ethtool_get_regs(struct net_device *netdev,
13051574da8SJijie Shao 				 struct ethtool_regs *regs, void *data)
13151574da8SJijie Shao {
13251574da8SJijie Shao 	struct hbg_priv *priv = netdev_priv(netdev);
13351574da8SJijie Shao 	struct hbg_reg_info *info;
13451574da8SJijie Shao 	u32 i, offset = 0;
13551574da8SJijie Shao 
13651574da8SJijie Shao 	regs->version = 0;
13751574da8SJijie Shao 	for (i = 0; i < ARRAY_SIZE(hbg_dump_reg_infos); i++) {
13851574da8SJijie Shao 		info = data + offset;
13951574da8SJijie Shao 
14051574da8SJijie Shao 		*info = hbg_dump_reg_infos[i];
14151574da8SJijie Shao 		info->val = hbg_reg_read(priv, info->offset);
14251574da8SJijie Shao 		info->offset -= hbg_dump_type_base_array[info->type];
14351574da8SJijie Shao 
14451574da8SJijie Shao 		offset += sizeof(*info);
14551574da8SJijie Shao 	}
14651574da8SJijie Shao }
147e8d13548SJijie Shao 
1483a03763fSJijie Shao static void hbg_ethtool_get_pauseparam(struct net_device *net_dev,
1493a03763fSJijie Shao 				       struct ethtool_pauseparam *param)
1503a03763fSJijie Shao {
1513a03763fSJijie Shao 	struct hbg_priv *priv = netdev_priv(net_dev);
1523a03763fSJijie Shao 
1533a03763fSJijie Shao 	param->autoneg = priv->mac.pause_autoneg;
1543a03763fSJijie Shao 	hbg_hw_get_pause_enable(priv, &param->tx_pause, &param->rx_pause);
1553a03763fSJijie Shao }
1563a03763fSJijie Shao 
1573a03763fSJijie Shao static int hbg_ethtool_set_pauseparam(struct net_device *net_dev,
1583a03763fSJijie Shao 				      struct ethtool_pauseparam *param)
1593a03763fSJijie Shao {
1603a03763fSJijie Shao 	struct hbg_priv *priv = netdev_priv(net_dev);
1613a03763fSJijie Shao 
1623a03763fSJijie Shao 	priv->mac.pause_autoneg = param->autoneg;
1633a03763fSJijie Shao 	phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause);
1643a03763fSJijie Shao 
1653a03763fSJijie Shao 	if (!param->autoneg)
1663a03763fSJijie Shao 		hbg_hw_set_pause_enable(priv, param->tx_pause, param->rx_pause);
1673a03763fSJijie Shao 
1683f5a61f6SJijie Shao 	priv->user_def.pause_param = *param;
1693a03763fSJijie Shao 	return 0;
1703a03763fSJijie Shao }
1713a03763fSJijie Shao 
1723f5a61f6SJijie Shao static int hbg_ethtool_reset(struct net_device *netdev, u32 *flags)
1733f5a61f6SJijie Shao {
1743f5a61f6SJijie Shao 	struct hbg_priv *priv = netdev_priv(netdev);
1753f5a61f6SJijie Shao 
1763f5a61f6SJijie Shao 	if (*flags != ETH_RESET_DEDICATED)
1773f5a61f6SJijie Shao 		return -EOPNOTSUPP;
1783f5a61f6SJijie Shao 
1793f5a61f6SJijie Shao 	*flags = 0;
1803f5a61f6SJijie Shao 	return hbg_reset(priv);
1813f5a61f6SJijie Shao }
1823f5a61f6SJijie Shao 
183e8d13548SJijie Shao static const struct ethtool_ops hbg_ethtool_ops = {
184e8d13548SJijie Shao 	.get_link		= ethtool_op_get_link,
185e8d13548SJijie Shao 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
186e8d13548SJijie Shao 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
18751574da8SJijie Shao 	.get_regs_len		= hbg_ethtool_get_regs_len,
18851574da8SJijie Shao 	.get_regs		= hbg_ethtool_get_regs,
1893a03763fSJijie Shao 	.get_pauseparam         = hbg_ethtool_get_pauseparam,
1903a03763fSJijie Shao 	.set_pauseparam         = hbg_ethtool_set_pauseparam,
1913f5a61f6SJijie Shao 	.reset			= hbg_ethtool_reset,
192*adb42b1eSJijie Shao 	.nway_reset		= phy_ethtool_nway_reset,
193e8d13548SJijie Shao };
194e8d13548SJijie Shao 
195e8d13548SJijie Shao void hbg_ethtool_set_ops(struct net_device *netdev)
196e8d13548SJijie Shao {
197e8d13548SJijie Shao 	netdev->ethtool_ops = &hbg_ethtool_ops;
198e8d13548SJijie Shao }
199