Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70523e63 authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller
Browse files

drivers: net: stmmac: reworking the PCS code.



The 3.xx and 4.xx synopsys gmacs have a very similar
PCS embedded module and they share almost the same registers:
for example:
  AN_Control, AN_Status, AN_Advertisement, AN_Link_Partner_Ability,
  AN_Expansion, TBI_Extended_Status.

Just the RGMII/SMII Control/Status register differs.

So This patch aims to reorganize and enhance the PCS support.
It removes the existent support from the dwmac1000/dwmac4_core.c
moving basic PCS functions inside a new file called: stmmac_pcs.h.

The patch also reviews the available APIs to be better shared among
different hardware and easily enhanced to support new features.

Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5e4bd99
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ Please see the following document:
 o mmc_core.c/mmc.h: Management MAC Counters;
 o stmmac_hwtstamp.c: HW timestamp support for PTP;
 o stmmac_ptp.c: PTP 1588 clock;
 o stmmac_pcs.h: Physical Coding Sublayer common implementation;
 o dwmac-<XXX>.c: these are for the platform glue-logic file; e.g. dwmac-sti.c
   for STMicroelectronics SoCs.

+11 −5
Original line number Diff line number Diff line
@@ -232,6 +232,11 @@ struct stmmac_extra_stats {
#define DMA_HW_FEAT_ACTPHYIF	0x70000000	/* Active/selected PHY iface */
#define DEFAULT_DMA_PBL		8

/* PCS status and mask defines */
#define	PCS_ANE_IRQ		BIT(2)	/* PCS Auto-Negotiation */
#define	PCS_LINK_IRQ		BIT(1)	/* PCS Link */
#define	PCS_RGSMIIIS_IRQ	BIT(0)	/* RGMII or SMII Interrupt */

/* Max/Min RI Watchdog Timer count value */
#define MAX_DMA_RIWT		0xff
#define MIN_DMA_RIWT		0x20
@@ -272,9 +277,6 @@ enum dma_irq_status {
#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 2)
#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 3)

#define	CORE_PCS_ANE_COMPLETE		(1 << 5)
#define	CORE_PCS_LINK_STATUS		(1 << 6)
#define	CORE_RGMII_IRQ			(1 << 7)
#define CORE_IRQ_MTL_RX_OVERFLOW	BIT(8)

/* Physical Coding Sublayer */
@@ -469,9 +471,12 @@ struct stmmac_ops {
	void (*reset_eee_mode)(struct mac_device_info *hw);
	void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
	void (*set_eee_pls)(struct mac_device_info *hw, int link);
	void (*ctrl_ane)(struct mac_device_info *hw, bool restart);
	void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
	void (*debug)(void __iomem *ioaddr, struct stmmac_extra_stats *x);
	/* PCS calls */
	void (*pcs_ctrl_ane)(void __iomem *ioaddr, bool ane, bool srgmi_ral,
			     bool loopback);
	void (*pcs_rane)(void __iomem *ioaddr, bool restart);
	void (*pcs_get_adv_lp)(void __iomem *ioaddr, struct rgmii_adv *adv);
};

/* PTP and HW Timer helpers */
@@ -546,6 +551,7 @@ void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable);

void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);

extern const struct stmmac_mode_ops ring_mode_ops;
extern const struct stmmac_mode_ops chain_mode_ops;
extern const struct stmmac_desc_ops dwmac4_desc_ops;
+17 −39
Original line number Diff line number Diff line
@@ -46,9 +46,6 @@ enum dwmac1000_irq_status {
	mmc_rx_irq = 0x0020,
	mmc_irq = 0x0010,
	pmt_irq = 0x0008,
	pcs_ane_irq = 0x0004,
	pcs_link_irq = 0x0002,
	rgmii_irq = 0x0001,
};
#define GMAC_INT_MASK		0x0000003c	/* interrupt mask register */

@@ -90,42 +87,23 @@ enum power_event {
				(reg * 8))
#define GMAC_MAX_PERFECT_ADDRESSES	1

/* PCS registers (AN/TBI/SGMII/RGMII) offset */
#define GMAC_AN_CTRL	0x000000c0	/* AN control */
#define GMAC_AN_STATUS	0x000000c4	/* AN status */
#define GMAC_ANE_ADV	0x000000c8	/* Auto-Neg. Advertisement */
#define GMAC_ANE_LPA	0x000000cc	/* Auto-Neg. link partener ability */
#define GMAC_ANE_EXP	0x000000d0	/* ANE expansion */
#define GMAC_TBI	0x000000d4	/* TBI extend status */
#define GMAC_S_R_GMII	0x000000d8	/* SGMII RGMII status */

/* AN Configuration defines */
#define GMAC_AN_CTRL_RAN	0x00000200	/* Restart Auto-Negotiation */
#define GMAC_AN_CTRL_ANE	0x00001000	/* Auto-Negotiation Enable */
#define GMAC_AN_CTRL_ELE	0x00004000	/* External Loopback Enable */
#define GMAC_AN_CTRL_ECD	0x00010000	/* Enable Comma Detect */
#define GMAC_AN_CTRL_LR		0x00020000	/* Lock to Reference */
#define GMAC_AN_CTRL_SGMRAL	0x00040000	/* SGMII RAL Control */

/* AN Status defines */
#define GMAC_AN_STATUS_LS	0x00000004	/* Link Status 0:down 1:up */
#define GMAC_AN_STATUS_ANA	0x00000008	/* Auto-Negotiation Ability */
#define GMAC_AN_STATUS_ANC	0x00000020	/* Auto-Negotiation Complete */
#define GMAC_AN_STATUS_ES	0x00000100	/* Extended Status */

/* Register 54 (SGMII/RGMII status register) */
#define GMAC_S_R_GMII_LINK		0x8
#define GMAC_S_R_GMII_SPEED		0x5
#define GMAC_S_R_GMII_SPEED_SHIFT	0x1
#define GMAC_S_R_GMII_MODE		0x1
#define GMAC_S_R_GMII_SPEED_125		2
#define GMAC_S_R_GMII_SPEED_25		1

/* Common ADV and LPA defines */
#define GMAC_ANE_FD		(1 << 5)
#define GMAC_ANE_HD		(1 << 6)
#define GMAC_ANE_PSE		(3 << 7)
#define GMAC_ANE_PSE_SHIFT	7
#define GMAC_PCS_BASE		0x000000c0	/* PCS register base */
#define GMAC_RGSMIIIS		0x000000d8	/* RGMII/SMII status */

/* SGMII/RGMII status register */
#define GMAC_RGSMIIIS_LNKMODE		BIT(0)
#define GMAC_RGSMIIIS_SPEED		GENMASK(2, 1)
#define GMAC_RGSMIIIS_SPEED_SHIFT	1
#define GMAC_RGSMIIIS_LNKSTS		BIT(3)
#define GMAC_RGSMIIIS_JABTO		BIT(4)
#define GMAC_RGSMIIIS_FALSECARDET	BIT(5)
#define GMAC_RGSMIIIS_SMIDRXS		BIT(16)
/* LNKMOD */
#define GMAC_RGSMIIIS_LNKMOD_MASK	0x1
/* LNKSPEED */
#define GMAC_RGSMIIIS_SPEED_125		0x2
#define GMAC_RGSMIIIS_SPEED_25		0x1
#define GMAC_RGSMIIIS_SPEED_2_5		0x0

/* GMAC Configuration defines */
#define GMAC_CONTROL_2K 0x08000000	/* IEEE 802.3as 2K packets */
+51 −59
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <asm/io.h>
#include "stmmac_pcs.h"
#include "dwmac1000.h"

static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
@@ -241,6 +242,39 @@ static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
	writel(pmt, ioaddr + GMAC_PMT);
}

/* RGMII or SMII interface */
static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)
{
	u32 status;

	status = readl(ioaddr + GMAC_RGSMIIIS);
	x->irq_rgmii_n++;

	/* Check the link status */
	if (status & GMAC_RGSMIIIS_LNKSTS) {
		int speed_value;

		x->pcs_link = 1;

		speed_value = ((status & GMAC_RGSMIIIS_SPEED) >>
			       GMAC_RGSMIIIS_SPEED_SHIFT);
		if (speed_value == GMAC_RGSMIIIS_SPEED_125)
			x->pcs_speed = SPEED_1000;
		else if (speed_value == GMAC_RGSMIIIS_SPEED_25)
			x->pcs_speed = SPEED_100;
		else
			x->pcs_speed = SPEED_10;

		x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK);

		pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,
			x->pcs_duplex ? "Full" : "Half");
	} else {
		x->pcs_link = 0;
		pr_info("Link is Down\n");
	}
}

static int dwmac1000_irq_status(struct mac_device_info *hw,
				struct stmmac_extra_stats *x)
{
@@ -260,6 +294,7 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
		readl(ioaddr + GMAC_PMT);
		x->irq_receive_pmt_irq_n++;
	}

	/* MAC trx/rx EEE LPI entry/exit interrupts */
	if (intr_status & lpiis_irq) {
		/* Clean LPI interrupt by reading the Reg 12 */
@@ -275,36 +310,10 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
			x->irq_rx_path_exit_lpi_mode_n++;
	}

	if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) {
		readl(ioaddr + GMAC_AN_STATUS);
		x->irq_pcs_ane_n++;
	}
	if (intr_status & rgmii_irq) {
		u32 status = readl(ioaddr + GMAC_S_R_GMII);
		x->irq_rgmii_n++;

		/* Save and dump the link status. */
		if (status & GMAC_S_R_GMII_LINK) {
			int speed_value = (status & GMAC_S_R_GMII_SPEED) >>
			    GMAC_S_R_GMII_SPEED_SHIFT;
			x->pcs_duplex = (status & GMAC_S_R_GMII_MODE);

			if (speed_value == GMAC_S_R_GMII_SPEED_125)
				x->pcs_speed = SPEED_1000;
			else if (speed_value == GMAC_S_R_GMII_SPEED_25)
				x->pcs_speed = SPEED_100;
			else
				x->pcs_speed = SPEED_10;
	dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);

			x->pcs_link = 1;
			pr_debug("%s: Link is Up - %d/%s\n", __func__,
				 (int)x->pcs_speed,
				 x->pcs_duplex ? "Full" : "Half");
		} else {
			x->pcs_link = 0;
			pr_debug("%s: Link is Down\n", __func__);
		}
	}
	if (intr_status & PCS_RGSMIIIS_IRQ)
		dwmac1000_rgsmii(ioaddr, x);

	return ret;
}
@@ -363,38 +372,20 @@ static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
	writel(value, ioaddr + LPI_TIMER_CTRL);
}

static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart)
static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral,
			       bool loopback)
{
	void __iomem *ioaddr = hw->pcsr;
	/* auto negotiation enable and External Loopback enable */
	u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;

	if (restart)
		value |= GMAC_AN_CTRL_RAN;

	writel(value, ioaddr + GMAC_AN_CTRL);
	dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback);
}

static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv)
static void dwmac1000_rane(void __iomem *ioaddr, bool restart)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value = readl(ioaddr + GMAC_ANE_ADV);

	if (value & GMAC_ANE_FD)
		adv->duplex = DUPLEX_FULL;
	if (value & GMAC_ANE_HD)
		adv->duplex |= DUPLEX_HALF;

	adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;

	value = readl(ioaddr + GMAC_ANE_LPA);

	if (value & GMAC_ANE_FD)
		adv->lp_duplex = DUPLEX_FULL;
	if (value & GMAC_ANE_HD)
		adv->lp_duplex = DUPLEX_HALF;
	dwmac_rane(ioaddr, GMAC_PCS_BASE, restart);
}

	adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv)
{
	dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv);
}

static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x)
@@ -485,9 +476,10 @@ static const struct stmmac_ops dwmac1000_ops = {
	.reset_eee_mode = dwmac1000_reset_eee_mode,
	.set_eee_timer = dwmac1000_set_eee_timer,
	.set_eee_pls = dwmac1000_set_eee_pls,
	.ctrl_ane = dwmac1000_ctrl_ane,
	.get_adv = dwmac1000_get_adv,
	.debug = dwmac1000_debug,
	.pcs_ctrl_ane = dwmac1000_ctrl_ane,
	.pcs_rane = dwmac1000_rane,
	.pcs_get_adv_lp = dwmac1000_get_adv_lp,
};

struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+19 −15
Original line number Diff line number Diff line
@@ -24,10 +24,8 @@
#define GMAC_QX_TX_FLOW_CTRL(x)		(0x70 + x * 4)
#define GMAC_INT_STATUS			0x000000b0
#define GMAC_INT_EN			0x000000b4
#define GMAC_AN_CTRL			0x000000e0
#define GMAC_AN_STATUS			0x000000e4
#define GMAC_AN_ADV			0x000000e8
#define GMAC_AN_LPA			0x000000ec
#define GMAC_PCS_BASE			0x000000e0
#define GMAC_PHYIF_CONTROL_STATUS	0x000000f8
#define GMAC_PMT			0x000000c0
#define GMAC_VERSION			0x00000110
#define GMAC_DEBUG			0x00000114
@@ -64,19 +62,8 @@ enum dwmac4_irq_status {
	mmc_rx_irq = 0x00000200,
	mmc_irq = 0x00000100,
	pmt_irq = 0x00000010,
	pcs_ane_irq = 0x00000004,
	pcs_link_irq = 0x00000002,
};

/* MAC Auto-Neg bitmap*/
#define	GMAC_AN_CTRL_RAN		BIT(9)
#define	GMAC_AN_CTRL_ANE		BIT(12)
#define GMAC_AN_CTRL_ELE		BIT(14)
#define GMAC_AN_FD			BIT(5)
#define GMAC_AN_HD			BIT(6)
#define GMAC_AN_PSE_MASK		GENMASK(8, 7)
#define GMAC_AN_PSE_SHIFT		7

/* MAC PMT bitmap */
enum power_event {
	pointer_reset =	0x80000000,
@@ -250,6 +237,23 @@ enum power_event {
#define MTL_DEBUG_RRCSTS_FLUSH		3
#define MTL_DEBUG_RWCSTS		BIT(0)

/* SGMII/RGMII status register */
#define GMAC_PHYIF_CTRLSTATUS_TC		BIT(0)
#define GMAC_PHYIF_CTRLSTATUS_LUD		BIT(1)
#define GMAC_PHYIF_CTRLSTATUS_SMIDRXS		BIT(4)
#define GMAC_PHYIF_CTRLSTATUS_LNKMOD		BIT(16)
#define GMAC_PHYIF_CTRLSTATUS_SPEED		GENMASK(18, 17)
#define GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT	17
#define GMAC_PHYIF_CTRLSTATUS_LNKSTS		BIT(19)
#define GMAC_PHYIF_CTRLSTATUS_JABTO		BIT(20)
#define GMAC_PHYIF_CTRLSTATUS_FALSECARDET	BIT(21)
/* LNKMOD */
#define GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK	0x1
/* LNKSPEED */
#define GMAC_PHYIF_CTRLSTATUS_SPEED_125		0x2
#define GMAC_PHYIF_CTRLSTATUS_SPEED_25		0x1
#define GMAC_PHYIF_CTRLSTATUS_SPEED_2_5		0x0

extern const struct stmmac_dma_ops dwmac4_dma_ops;
extern const struct stmmac_dma_ops dwmac410_dma_ops;
#endif /* __DWMAC4_H__ */
Loading