Commit a4414dd1 authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller
Browse files

net: txgbe: support switching mode to 1000BASE-X and SGMII



Disable data path before PCS VR reset while switching PCS mode, to prevent
the blocking of data path. Enable AN interrupt for CL37 auto-negotiation.

Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab928c24
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -205,6 +205,8 @@
#define WX_TSC_CTL                   0x1D000
#define WX_TSC_CTL_TX_DIS            BIT(1)
#define WX_TSC_CTL_TSEC_DIS          BIT(0)
#define WX_TSC_ST                    0x1D004
#define WX_TSC_ST_SECTX_RDY          BIT(0)
#define WX_TSC_BUF_AE                0x1D00C
#define WX_TSC_BUF_AE_THR            GENMASK(9, 0)

+28 −0
Original line number Diff line number Diff line
@@ -13,6 +13,34 @@
#include "txgbe_type.h"
#include "txgbe_hw.h"

/**
 *  txgbe_disable_sec_tx_path - Stops the transmit data path
 *  @wx: pointer to hardware structure
 *
 *  Stops the transmit data path and waits for the HW to internally empty
 *  the tx security block
 **/
int txgbe_disable_sec_tx_path(struct wx *wx)
{
	int val;

	wr32m(wx, WX_TSC_CTL, WX_TSC_CTL_TX_DIS, WX_TSC_CTL_TX_DIS);
	return read_poll_timeout(rd32, val, val & WX_TSC_ST_SECTX_RDY,
				 1000, 20000, false, wx, WX_TSC_ST);
}

/**
 *  txgbe_enable_sec_tx_path - Enables the transmit data path
 *  @wx: pointer to hardware structure
 *
 *  Enables the transmit data path.
 **/
void txgbe_enable_sec_tx_path(struct wx *wx)
{
	wr32m(wx, WX_TSC_CTL, WX_TSC_CTL_TX_DIS, 0);
	WX_WRITE_FLUSH(wx);
}

/**
 *  txgbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds
 *  @wx: pointer to hardware structure
+2 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
#ifndef _TXGBE_HW_H_
#define _TXGBE_HW_H_

int txgbe_disable_sec_tx_path(struct wx *wx);
void txgbe_enable_sec_tx_path(struct wx *wx);
int txgbe_read_pba_string(struct wx *wx, u8 *pba_num, u32 pba_num_size);
int txgbe_validate_eeprom_checksum(struct wx *wx, u16 *checksum_val);
int txgbe_reset_hw(struct wx *wx);
+29 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "../libwx/wx_hw.h"
#include "txgbe_type.h"
#include "txgbe_phy.h"
#include "txgbe_hw.h"

static int txgbe_swnodes_register(struct txgbe *txgbe)
{
@@ -210,8 +211,32 @@ static void txgbe_mac_link_up(struct phylink_config *config,
	wr32(wx, WX_MAC_WDG_TIMEOUT, wdg);
}

static int txgbe_mac_prepare(struct phylink_config *config, unsigned int mode,
			     phy_interface_t interface)
{
	struct wx *wx = netdev_priv(to_net_dev(config->dev));

	wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
	wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, 0);

	return txgbe_disable_sec_tx_path(wx);
}

static int txgbe_mac_finish(struct phylink_config *config, unsigned int mode,
			    phy_interface_t interface)
{
	struct wx *wx = netdev_priv(to_net_dev(config->dev));

	txgbe_enable_sec_tx_path(wx);
	wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);

	return 0;
}

static const struct phylink_mac_ops txgbe_mac_ops = {
	.mac_select_pcs = txgbe_phylink_mac_select,
	.mac_prepare = txgbe_mac_prepare,
	.mac_finish = txgbe_mac_finish,
	.mac_config = txgbe_mac_config,
	.mac_link_down = txgbe_mac_link_down,
	.mac_link_up = txgbe_mac_link_up,
@@ -234,6 +259,8 @@ static int txgbe_phylink_init(struct txgbe *txgbe)
	config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
	phy_mode = PHY_INTERFACE_MODE_10GBASER;
	__set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
	__set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces);
	__set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces);
	fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]);
	phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops);
	if (IS_ERR(phylink))
@@ -431,7 +458,8 @@ static void txgbe_irq_handler(struct irq_desc *desc)

	chained_irq_exit(chip, desc);

	if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) {
	if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN |
		    TXGBE_PX_MISC_ETH_AN)) {
		u32 reg = rd32(wx, TXGBE_CFG_PORT_ST);

		phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));