// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2026 Broadcom.
#include <linux/linkmode.h>
#include "bnge.h"
#include "bnge_link.h"
#include "bnge_hwrm_lib.h"
enum bnge_media_type {
BNGE_MEDIA_UNKNOWN = 0,
BNGE_MEDIA_CR,
BNGE_MEDIA_SR,
BNGE_MEDIA_LR_ER_FR,
BNGE_MEDIA_KR,
__BNGE_MEDIA_END,
};
static const enum bnge_media_type bnge_phy_types[] = {
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR4] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR4] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR4] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER4] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR10] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR4] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR4] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR4] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER4] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASECR] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASESR] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASELR] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASEER] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR2] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR2] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR2] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER2] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR2] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR2] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR2] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER2] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR8] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR8] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR8] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER8] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR4] = BNGE_MEDIA_CR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR4] = BNGE_MEDIA_SR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR4] = BNGE_MEDIA_LR_ER_FR,
[PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER4] = BNGE_MEDIA_LR_ER_FR,
};
static u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed)
{
switch (fw_link_speed) {
case BNGE_LINK_SPEED_50GB:
case BNGE_LINK_SPEED_50GB_PAM4:
return SPEED_50000;
case BNGE_LINK_SPEED_100GB:
case BNGE_LINK_SPEED_100GB_PAM4:
case BNGE_LINK_SPEED_100GB_PAM4_112:
return SPEED_100000;
case BNGE_LINK_SPEED_200GB:
case BNGE_LINK_SPEED_200GB_PAM4:
case BNGE_LINK_SPEED_200GB_PAM4_112:
return SPEED_200000;
case BNGE_LINK_SPEED_400GB:
case BNGE_LINK_SPEED_400GB_PAM4:
case BNGE_LINK_SPEED_400GB_PAM4_112:
return SPEED_400000;
case BNGE_LINK_SPEED_800GB:
case BNGE_LINK_SPEED_800GB_PAM4_112:
return SPEED_800000;
default:
return SPEED_UNKNOWN;
}
}
static void bnge_set_auto_speed(struct bnge_net *bn)
{
struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info;
struct bnge_link_info *link_info;
link_info = &bn->bd->link_info;
elink_info->advertising = link_info->auto_link_speeds2;
}
static void bnge_set_force_speed(struct bnge_net *bn)
{
struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info;
struct bnge_link_info *link_info;
link_info = &bn->bd->link_info;
elink_info->req_link_speed