Commit 9ec092d2 authored by Christian 'Ansuel' Marangi's avatar Christian 'Ansuel' Marangi Committed by Paolo Abeni
Browse files

net: ethernet: stmmac: add missing sgmii configure for ipq806x



The different gmacid require different configuration based on the soc
and on the gmac id. Add these missing configuration taken from the
original driver.

Signed-off-by: default avatarChristian 'Ansuel' Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20220614112228.1998-1-ansuelsmth@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent cfbc80e3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ config DWMAC_IPQ806X
	default ARCH_QCOM
	depends on OF && (ARCH_QCOM || COMPILE_TEST)
	select MFD_SYSCON
	select QCOM_SOCINFO
	help
	  Support for QCA IPQ806X DWMAC Ethernet.

+77 −16
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#include <linux/stmmac.h>
#include <linux/of_mdio.h>
#include <linux/module.h>
#include <linux/sys_soc.h>
#include <linux/bitfield.h>

#include "stmmac_platform.h"

@@ -75,11 +77,20 @@
#define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
#define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
#define QSGMII_PHY_QSGMII_EN			BIT(7)
#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
#define QSGMII_PHY_DEEMPHASIS_LVL_MASK		GENMASK(11, 10)
#define QSGMII_PHY_DEEMPHASIS_LVL(x)		FIELD_PREP(QSGMII_PHY_DEEMPHASIS_LVL_MASK, (x))
#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		GENMASK(14, 12)
#define QSGMII_PHY_PHASE_LOOP_GAIN(x)		FIELD_PREP(QSGMII_PHY_PHASE_LOOP_GAIN_MASK, (x))
#define QSGMII_PHY_RX_DC_BIAS_MASK		GENMASK(19, 18)
#define QSGMII_PHY_RX_DC_BIAS(x)		FIELD_PREP(QSGMII_PHY_RX_DC_BIAS_MASK, (x))
#define QSGMII_PHY_RX_INPUT_EQU_MASK		GENMASK(21, 20)
#define QSGMII_PHY_RX_INPUT_EQU(x)		FIELD_PREP(QSGMII_PHY_RX_INPUT_EQU_MASK, (x))
#define QSGMII_PHY_CDR_PI_SLEW_MASK		GENMASK(23, 22)
#define QSGMII_PHY_CDR_PI_SLEW(x)		FIELD_PREP(QSGMII_PHY_CDR_PI_SLEW_MASK, (x))
#define QSGMII_PHY_TX_SLEW_MASK			GENMASK(27, 26)
#define QSGMII_PHY_TX_SLEW(x)			FIELD_PREP(QSGMII_PHY_TX_SLEW_MASK, (x))
#define QSGMII_PHY_TX_DRV_AMP_MASK		GENMASK(31, 28)
#define QSGMII_PHY_TX_DRV_AMP(x)		FIELD_PREP(QSGMII_PHY_TX_DRV_AMP_MASK, (x))

struct ipq806x_gmac {
	struct platform_device *pdev;
@@ -242,6 +253,64 @@ static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
	ipq806x_gmac_set_speed(gmac, speed);
}

static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = {
	{
		.revision = "1.*",
	},
	{
		/* sentinel */
	}
};

static int
ipq806x_gmac_configure_qsgmii_params(struct ipq806x_gmac *gmac)
{
	struct platform_device *pdev = gmac->pdev;
	const struct soc_device_attribute *soc;
	struct device *dev = &pdev->dev;
	u32 qsgmii_param;

	switch (gmac->id) {
	case 1:
		soc = soc_device_match(ipq806x_gmac_soc_v1);

		if (soc)
			qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xc) |
				       QSGMII_PHY_TX_SLEW(0x2) |
				       QSGMII_PHY_DEEMPHASIS_LVL(0x2);
		else
			qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xd) |
				       QSGMII_PHY_TX_SLEW(0x0) |
				       QSGMII_PHY_DEEMPHASIS_LVL(0x0);

		qsgmii_param |= QSGMII_PHY_RX_DC_BIAS(0x2);
		break;
	case 2:
	case 3:
		qsgmii_param = QSGMII_PHY_RX_DC_BIAS(0x3) |
			       QSGMII_PHY_TX_DRV_AMP(0xc);
		break;
	default: /* gmac 0 can't be set in SGMII mode */
		dev_err(dev, "gmac id %d can't be in SGMII mode", gmac->id);
		return -EINVAL;
	}

	/* Common params across all gmac id */
	qsgmii_param |= QSGMII_PHY_CDR_EN |
			QSGMII_PHY_RX_FRONT_EN |
			QSGMII_PHY_RX_SIGNAL_DETECT_EN |
			QSGMII_PHY_TX_DRIVER_EN |
			QSGMII_PHY_QSGMII_EN |
			QSGMII_PHY_PHASE_LOOP_GAIN(0x4) |
			QSGMII_PHY_RX_INPUT_EQU(0x1) |
			QSGMII_PHY_CDR_PI_SLEW(0x2);

	regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
		     qsgmii_param);

	return 0;
}

static int ipq806x_gmac_probe(struct platform_device *pdev)
{
	struct plat_stmmacenet_data *plat_dat;
@@ -328,17 +397,9 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);

	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
			     QSGMII_PHY_CDR_EN |
			     QSGMII_PHY_RX_FRONT_EN |
			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
			     QSGMII_PHY_TX_DRIVER_EN |
			     QSGMII_PHY_QSGMII_EN |
			     0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
			     0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET |
			     0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
		err = ipq806x_gmac_configure_qsgmii_params(gmac);
		if (err)
			goto err_remove_config_dt;
	}

	plat_dat->has_gmac = true;