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> 651574da8SJijie Shao #include "hbg_common.h" 7e8d13548SJijie Shao #include "hbg_ethtool.h" 851574da8SJijie Shao #include "hbg_hw.h" 951574da8SJijie Shao 1051574da8SJijie Shao enum hbg_reg_dump_type { 1151574da8SJijie Shao HBG_DUMP_REG_TYPE_SPEC = 0, 1251574da8SJijie Shao HBG_DUMP_REG_TYPE_MDIO, 1351574da8SJijie Shao HBG_DUMP_REG_TYPE_GMAC, 1451574da8SJijie Shao HBG_DUMP_REG_TYPE_PCU, 1551574da8SJijie Shao }; 1651574da8SJijie Shao 1751574da8SJijie Shao struct hbg_reg_info { 1851574da8SJijie Shao u32 type; 1951574da8SJijie Shao u32 offset; 2051574da8SJijie Shao u32 val; 2151574da8SJijie Shao }; 2251574da8SJijie Shao 2351574da8SJijie Shao #define HBG_DUMP_SPEC_I(offset) {HBG_DUMP_REG_TYPE_SPEC, offset, 0} 2451574da8SJijie Shao #define HBG_DUMP_MDIO_I(offset) {HBG_DUMP_REG_TYPE_MDIO, offset, 0} 2551574da8SJijie Shao #define HBG_DUMP_GMAC_I(offset) {HBG_DUMP_REG_TYPE_GMAC, offset, 0} 2651574da8SJijie Shao #define HBG_DUMP_PCU_I(offset) {HBG_DUMP_REG_TYPE_PCU, offset, 0} 2751574da8SJijie Shao 2851574da8SJijie Shao static const struct hbg_reg_info hbg_dump_reg_infos[] = { 2951574da8SJijie Shao /* dev specs */ 3051574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_SPEC_VALID_ADDR), 3151574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_EVENT_REQ_ADDR), 3251574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MAC_ID_ADDR), 3351574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_PHY_ID_ADDR), 3451574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_ADDR), 3551574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_HIGH_ADDR), 3651574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_UC_MAC_NUM_ADDR), 3751574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MDIO_FREQ_ADDR), 3851574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MAX_MTU_ADDR), 3951574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_MIN_MTU_ADDR), 4051574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_TX_FIFO_NUM_ADDR), 4151574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_RX_FIFO_NUM_ADDR), 4251574da8SJijie Shao HBG_DUMP_SPEC_I(HBG_REG_VLAN_LAYERS_ADDR), 4351574da8SJijie Shao 4451574da8SJijie Shao /* mdio */ 4551574da8SJijie Shao HBG_DUMP_MDIO_I(HBG_REG_MDIO_COMMAND_ADDR), 4651574da8SJijie Shao HBG_DUMP_MDIO_I(HBG_REG_MDIO_ADDR_ADDR), 4751574da8SJijie Shao HBG_DUMP_MDIO_I(HBG_REG_MDIO_WDATA_ADDR), 4851574da8SJijie Shao HBG_DUMP_MDIO_I(HBG_REG_MDIO_RDATA_ADDR), 4951574da8SJijie Shao HBG_DUMP_MDIO_I(HBG_REG_MDIO_STA_ADDR), 5051574da8SJijie Shao 5151574da8SJijie Shao /* gmac */ 5251574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_DUPLEX_TYPE_ADDR), 5351574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_FD_FC_TYPE_ADDR), 5451574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_FC_TX_TIMER_ADDR), 5551574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_LOW_ADDR), 5651574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_HIGH_ADDR), 5751574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_MAX_FRAME_SIZE_ADDR), 5851574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_PORT_MODE_ADDR), 5951574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_PORT_ENABLE_ADDR), 6051574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_PAUSE_ENABLE_ADDR), 6151574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_AN_NEG_STATE_ADDR), 6251574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_TRANSMIT_CTRL_ADDR), 6351574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_REC_FILT_CTRL_ADDR), 6451574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_LINE_LOOP_BACK_ADDR), 6551574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_CF_CRC_STRIP_ADDR), 6651574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_MODE_CHANGE_EN_ADDR), 6751574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_LOOP_REG_ADDR), 6851574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_RECV_CTRL_ADDR), 6951574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_VLAN_CODE_ADDR), 7051574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_0_ADDR), 7151574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_0_ADDR), 7251574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_1_ADDR), 7351574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_1_ADDR), 7451574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_2_ADDR), 7551574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_2_ADDR), 7651574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_3_ADDR), 7751574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_3_ADDR), 7851574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_4_ADDR), 7951574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_4_ADDR), 8051574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_5_ADDR), 8151574da8SJijie Shao HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_5_ADDR), 8251574da8SJijie Shao 8351574da8SJijie Shao /* pcu */ 8451574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_TX_FIFO_THRSLD_ADDR), 8551574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_FIFO_THRSLD_ADDR), 8651574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CFG_FIFO_THRSLD_ADDR), 8751574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_MSK_ADDR), 8851574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_STAT_ADDR), 8951574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_CLR_ADDR), 9051574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_TX_BUS_ERR_ADDR_ADDR), 9151574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_BUS_ERR_ADDR_ADDR), 9251574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_MAX_FRAME_LEN_ADDR), 9351574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_DEBUG_ST_MCH_ADDR), 9451574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_FIFO_CURR_STATUS_ADDR), 9551574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_FIFO_HIST_STATUS_ADDR), 9651574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_CFF_DATA_NUM_ADDR), 9751574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_TX_PAUSE_ADDR), 9851574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_CFF_ADDR_ADDR), 9951574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_BUF_SIZE_ADDR), 10051574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_BUS_CTRL_ADDR), 10151574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_CTRL_ADDR), 10251574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_RX_PKT_MODE_ADDR), 10351574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_DBG_ST0_ADDR), 10451574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_DBG_ST1_ADDR), 10551574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_DBG_ST2_ADDR), 10651574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_BUS_RST_EN_ADDR), 10751574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_MSK_ADDR), 10851574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_STAT_ADDR), 10951574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_CLR_ADDR), 11051574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_MSK_ADDR), 11151574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_STAT_ADDR), 11251574da8SJijie Shao HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_CLR_ADDR), 11351574da8SJijie Shao }; 11451574da8SJijie Shao 11551574da8SJijie Shao static const u32 hbg_dump_type_base_array[] = { 11651574da8SJijie Shao [HBG_DUMP_REG_TYPE_SPEC] = 0, 11751574da8SJijie Shao [HBG_DUMP_REG_TYPE_MDIO] = HBG_REG_MDIO_BASE, 11851574da8SJijie Shao [HBG_DUMP_REG_TYPE_GMAC] = HBG_REG_SGMII_BASE, 11951574da8SJijie Shao [HBG_DUMP_REG_TYPE_PCU] = HBG_REG_SGMII_BASE, 12051574da8SJijie Shao }; 12151574da8SJijie Shao 12251574da8SJijie Shao static int hbg_ethtool_get_regs_len(struct net_device *netdev) 12351574da8SJijie Shao { 12451574da8SJijie Shao return ARRAY_SIZE(hbg_dump_reg_infos) * sizeof(struct hbg_reg_info); 12551574da8SJijie Shao } 12651574da8SJijie Shao 12751574da8SJijie Shao static void hbg_ethtool_get_regs(struct net_device *netdev, 12851574da8SJijie Shao struct ethtool_regs *regs, void *data) 12951574da8SJijie Shao { 13051574da8SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 13151574da8SJijie Shao struct hbg_reg_info *info; 13251574da8SJijie Shao u32 i, offset = 0; 13351574da8SJijie Shao 13451574da8SJijie Shao regs->version = 0; 13551574da8SJijie Shao for (i = 0; i < ARRAY_SIZE(hbg_dump_reg_infos); i++) { 13651574da8SJijie Shao info = data + offset; 13751574da8SJijie Shao 13851574da8SJijie Shao *info = hbg_dump_reg_infos[i]; 13951574da8SJijie Shao info->val = hbg_reg_read(priv, info->offset); 14051574da8SJijie Shao info->offset -= hbg_dump_type_base_array[info->type]; 14151574da8SJijie Shao 14251574da8SJijie Shao offset += sizeof(*info); 14351574da8SJijie Shao } 14451574da8SJijie Shao } 145e8d13548SJijie Shao 146*3a03763fSJijie Shao static void hbg_ethtool_get_pauseparam(struct net_device *net_dev, 147*3a03763fSJijie Shao struct ethtool_pauseparam *param) 148*3a03763fSJijie Shao { 149*3a03763fSJijie Shao struct hbg_priv *priv = netdev_priv(net_dev); 150*3a03763fSJijie Shao 151*3a03763fSJijie Shao param->autoneg = priv->mac.pause_autoneg; 152*3a03763fSJijie Shao hbg_hw_get_pause_enable(priv, ¶m->tx_pause, ¶m->rx_pause); 153*3a03763fSJijie Shao } 154*3a03763fSJijie Shao 155*3a03763fSJijie Shao static int hbg_ethtool_set_pauseparam(struct net_device *net_dev, 156*3a03763fSJijie Shao struct ethtool_pauseparam *param) 157*3a03763fSJijie Shao { 158*3a03763fSJijie Shao struct hbg_priv *priv = netdev_priv(net_dev); 159*3a03763fSJijie Shao 160*3a03763fSJijie Shao priv->mac.pause_autoneg = param->autoneg; 161*3a03763fSJijie Shao phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause); 162*3a03763fSJijie Shao 163*3a03763fSJijie Shao if (!param->autoneg) 164*3a03763fSJijie Shao hbg_hw_set_pause_enable(priv, param->tx_pause, param->rx_pause); 165*3a03763fSJijie Shao 166*3a03763fSJijie Shao return 0; 167*3a03763fSJijie Shao } 168*3a03763fSJijie Shao 169e8d13548SJijie Shao static const struct ethtool_ops hbg_ethtool_ops = { 170e8d13548SJijie Shao .get_link = ethtool_op_get_link, 171e8d13548SJijie Shao .get_link_ksettings = phy_ethtool_get_link_ksettings, 172e8d13548SJijie Shao .set_link_ksettings = phy_ethtool_set_link_ksettings, 17351574da8SJijie Shao .get_regs_len = hbg_ethtool_get_regs_len, 17451574da8SJijie Shao .get_regs = hbg_ethtool_get_regs, 175*3a03763fSJijie Shao .get_pauseparam = hbg_ethtool_get_pauseparam, 176*3a03763fSJijie Shao .set_pauseparam = hbg_ethtool_set_pauseparam, 177e8d13548SJijie Shao }; 178e8d13548SJijie Shao 179e8d13548SJijie Shao void hbg_ethtool_set_ops(struct net_device *netdev) 180e8d13548SJijie Shao { 181e8d13548SJijie Shao netdev->ethtool_ops = &hbg_ethtool_ops; 182e8d13548SJijie Shao } 183