net: txgbe: Implement PHYLINK for AML 25G/10G devices

There is a new PHY attached to AML 25G/10G NIC, which is different from
SP 10G/1G NIC. But the PHY configuration is handed over to firmware, and
also I2C is controlled by firmware. So the different PHYLINK fixed-link
mode is added for these devices.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/987B973A5929CD48+20250521064402.22348-5-jiawenwu@trustnetic.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Jiawen Wu 2025-05-21 14:43:57 +08:00 committed by Paolo Abeni
parent 39709fe4ba
commit 6f8b4c01a8
7 changed files with 195 additions and 6 deletions

View File

@ -2252,10 +2252,8 @@ int wx_stop_adapter(struct wx *wx)
}
EXPORT_SYMBOL(wx_stop_adapter);
void wx_reset_misc(struct wx *wx)
void wx_reset_mac(struct wx *wx)
{
int i;
/* receive packets that size > 2048 */
wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_JE, WX_MAC_RX_CFG_JE);
@ -2267,6 +2265,14 @@ void wx_reset_misc(struct wx *wx)
WX_MAC_RX_FLOW_CTRL_RFE, WX_MAC_RX_FLOW_CTRL_RFE);
wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
}
EXPORT_SYMBOL(wx_reset_mac);
void wx_reset_misc(struct wx *wx)
{
int i;
wx_reset_mac(wx);
wr32m(wx, WX_MIS_RST_ST,
WX_MIS_RST_ST_RST_INIT, 0x1E00);

View File

@ -42,6 +42,7 @@ void wx_configure(struct wx *wx);
void wx_start_hw(struct wx *wx);
int wx_disable_pcie_master(struct wx *wx);
int wx_stop_adapter(struct wx *wx);
void wx_reset_mac(struct wx *wx);
void wx_reset_misc(struct wx *wx);
int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
int wx_sw_init(struct wx *wx);

View File

@ -11,4 +11,5 @@ txgbe-objs := txgbe_main.o \
txgbe_phy.o \
txgbe_irq.o \
txgbe_fdir.o \
txgbe_ethtool.o
txgbe_ethtool.o \
txgbe_aml.o

View File

@ -0,0 +1,154 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
#include <linux/phylink.h>
#include <linux/iopoll.h>
#include <linux/pci.h>
#include <linux/phy.h>
#include "../libwx/wx_type.h"
#include "../libwx/wx_lib.h"
#include "../libwx/wx_hw.h"
#include "txgbe_type.h"
#include "txgbe_aml.h"
#include "txgbe_hw.h"
static void txgbe_get_phy_link(struct wx *wx, int *speed)
{
u32 status;
status = rd32(wx, TXGBE_CFG_PORT_ST);
if (!(status & TXGBE_CFG_PORT_ST_LINK_UP))
*speed = SPEED_UNKNOWN;
else if (status & TXGBE_CFG_PORT_ST_LINK_AML_25G)
*speed = SPEED_25000;
else if (status & TXGBE_CFG_PORT_ST_LINK_AML_10G)
*speed = SPEED_10000;
else
*speed = SPEED_UNKNOWN;
}
static void txgbe_get_link_state(struct phylink_config *config,
struct phylink_link_state *state)
{
struct wx *wx = phylink_to_wx(config);
int speed;
txgbe_get_phy_link(wx, &speed);
state->link = speed != SPEED_UNKNOWN;
state->speed = speed;
state->duplex = state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
}
static void txgbe_reconfig_mac(struct wx *wx)
{
u32 wdg, fc;
wdg = rd32(wx, WX_MAC_WDG_TIMEOUT);
fc = rd32(wx, WX_MAC_RX_FLOW_CTRL);
wr32(wx, WX_MIS_RST, TXGBE_MIS_RST_MAC_RST(wx->bus.func));
/* wait for MAC reset complete */
usleep_range(1000, 1500);
wr32m(wx, TXGBE_MAC_MISC_CTL, TXGBE_MAC_MISC_CTL_LINK_STS_MOD,
TXGBE_MAC_MISC_CTL_LINK_BOTH);
wx_reset_mac(wx);
wr32(wx, WX_MAC_WDG_TIMEOUT, wdg);
wr32(wx, WX_MAC_RX_FLOW_CTRL, fc);
}
static void txgbe_mac_link_up_aml(struct phylink_config *config,
struct phy_device *phy,
unsigned int mode,
phy_interface_t interface,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
struct wx *wx = phylink_to_wx(config);
u32 txcfg;
wx_fc_enable(wx, tx_pause, rx_pause);
txgbe_reconfig_mac(wx);
txcfg = rd32(wx, TXGBE_AML_MAC_TX_CFG);
txcfg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK;
switch (speed) {
case SPEED_25000:
txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_25G;
break;
case SPEED_10000:
txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_10G;
break;
default:
break;
}
wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);
wr32(wx, TXGBE_AML_MAC_TX_CFG, txcfg | TXGBE_AML_MAC_TX_CFG_TE);
wx->speed = speed;
}
static void txgbe_mac_link_down_aml(struct phylink_config *config,
unsigned int mode,
phy_interface_t interface)
{
struct wx *wx = phylink_to_wx(config);
wr32m(wx, TXGBE_AML_MAC_TX_CFG, TXGBE_AML_MAC_TX_CFG_TE, 0);
wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0);
wx->speed = SPEED_UNKNOWN;
}
static void txgbe_mac_config_aml(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
}
static const struct phylink_mac_ops txgbe_mac_ops_aml = {
.mac_config = txgbe_mac_config_aml,
.mac_link_down = txgbe_mac_link_down_aml,
.mac_link_up = txgbe_mac_link_up_aml,
};
int txgbe_phylink_init_aml(struct txgbe *txgbe)
{
struct phylink_link_state state;
struct phylink_config *config;
struct wx *wx = txgbe->wx;
phy_interface_t phy_mode;
struct phylink *phylink;
int err;
config = &wx->phylink_config;
config->dev = &wx->netdev->dev;
config->type = PHYLINK_NETDEV;
config->mac_capabilities = MAC_25000FD | MAC_10000FD |
MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
config->get_fixed_state = txgbe_get_link_state;
phy_mode = PHY_INTERFACE_MODE_25GBASER;
__set_bit(PHY_INTERFACE_MODE_25GBASER, config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
phylink = phylink_create(config, NULL, phy_mode, &txgbe_mac_ops_aml);
if (IS_ERR(phylink))
return PTR_ERR(phylink);
state.speed = SPEED_25000;
state.duplex = DUPLEX_FULL;
err = phylink_set_fixed_link(phylink, &state);
if (err) {
wx_err(wx, "Failed to set fixed link\n");
return err;
}
wx->phylink = phylink;
return 0;
}

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
#ifndef _TXGBE_AML_H_
#define _TXGBE_AML_H_
int txgbe_phylink_init_aml(struct txgbe *txgbe);
#endif /* _TXGBE_AML_H_ */

View File

@ -20,6 +20,7 @@
#include "../libwx/wx_mbx.h"
#include "../libwx/wx_hw.h"
#include "txgbe_type.h"
#include "txgbe_aml.h"
#include "txgbe_phy.h"
#include "txgbe_hw.h"
@ -318,7 +319,10 @@ irqreturn_t txgbe_link_irq_handler(int irq, void *data)
status = rd32(wx, TXGBE_CFG_PORT_ST);
up = !!(status & TXGBE_CFG_PORT_ST_LINK_UP);
phylink_pcs_change(txgbe->pcs, up);
if (txgbe->pcs)
phylink_pcs_change(txgbe->pcs, up);
else
phylink_mac_change(wx->phylink, up);
return IRQ_HANDLED;
}
@ -575,8 +579,9 @@ int txgbe_init_phy(struct txgbe *txgbe)
switch (wx->mac.type) {
case wx_mac_aml40:
case wx_mac_aml:
return 0;
case wx_mac_aml:
return txgbe_phylink_init_aml(txgbe);
case wx_mac_sp:
if (wx->media_type == wx_media_copper)
return txgbe_ext_phy_init(txgbe);
@ -648,7 +653,9 @@ void txgbe_remove_phy(struct txgbe *txgbe)
{
switch (txgbe->wx->mac.type) {
case wx_mac_aml40:
return;
case wx_mac_aml:
phylink_destroy(txgbe->wx->phylink);
return;
case wx_mac_sp:
if (txgbe->wx->media_type == wx_media_copper) {

View File

@ -50,6 +50,8 @@
/**************** SP Registers ****************************/
/* chip control Registers */
#define TXGBE_MIS_RST 0x1000C
#define TXGBE_MIS_RST_MAC_RST(_i) BIT(20 - (_i) * 3)
#define TXGBE_MIS_PRB_CTL 0x10010
#define TXGBE_MIS_PRB_CTL_LAN_UP(_i) BIT(1 - (_i))
/* FMGR Registers */
@ -62,6 +64,11 @@
#define TXGBE_TS_CTL 0x10300
#define TXGBE_TS_CTL_EVAL_MD BIT(31)
/* MAC Misc Registers */
#define TXGBE_MAC_MISC_CTL 0x11F00
#define TXGBE_MAC_MISC_CTL_LINK_STS_MOD BIT(0)
#define TXGBE_MAC_MISC_CTL_LINK_PCS FIELD_PREP(BIT(0), 0)
#define TXGBE_MAC_MISC_CTL_LINK_BOTH FIELD_PREP(BIT(0), 1)
/* GPIO register bit */
#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */
#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */
@ -88,6 +95,8 @@
/* Port cfg registers */
#define TXGBE_CFG_PORT_ST 0x14404
#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0)
#define TXGBE_CFG_PORT_ST_LINK_AML_25G BIT(3)
#define TXGBE_CFG_PORT_ST_LINK_AML_10G BIT(4)
#define TXGBE_CFG_VXLAN 0x14410
#define TXGBE_CFG_VXLAN_GPE 0x14414
#define TXGBE_CFG_GENEVE 0x14418
@ -151,9 +160,11 @@
/*************************** Amber Lite Registers ****************************/
#define TXGBE_PX_PF_BME 0x4B8
#define TXGBE_AML_MAC_TX_CFG 0x11000
#define TXGBE_AML_MAC_TX_CFG_TE BIT(0)
#define TXGBE_AML_MAC_TX_CFG_SPEED_MASK GENMASK(30, 27)
#define TXGBE_AML_MAC_TX_CFG_SPEED_40G FIELD_PREP(GENMASK(30, 27), 0)
#define TXGBE_AML_MAC_TX_CFG_SPEED_25G FIELD_PREP(GENMASK(30, 27), 2)
#define TXGBE_AML_MAC_TX_CFG_SPEED_10G FIELD_PREP(GENMASK(30, 27), 8)
#define TXGBE_RDM_RSC_CTL 0x1200C
#define TXGBE_RDM_RSC_CTL_FREE_CTL BIT(7)