Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20220614112228.1998-1-ansuelsmth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Christian 'Ansuel' Marangi and committed by
Paolo Abeni
9ec092d2 cfbc80e3

+78 -16
+1
drivers/net/ethernet/stmicro/stmmac/Kconfig
··· 83 83 default ARCH_QCOM 84 84 depends on OF && (ARCH_QCOM || COMPILE_TEST) 85 85 select MFD_SYSCON 86 + select QCOM_SOCINFO 86 87 help 87 88 Support for QCA IPQ806X DWMAC Ethernet. 88 89
+77 -16
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
··· 27 27 #include <linux/stmmac.h> 28 28 #include <linux/of_mdio.h> 29 29 #include <linux/module.h> 30 + #include <linux/sys_soc.h> 31 + #include <linux/bitfield.h> 30 32 31 33 #include "stmmac_platform.h" 32 34 ··· 77 75 #define QSGMII_PHY_RX_SIGNAL_DETECT_EN BIT(2) 78 76 #define QSGMII_PHY_TX_DRIVER_EN BIT(3) 79 77 #define QSGMII_PHY_QSGMII_EN BIT(7) 80 - #define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET 12 81 - #define QSGMII_PHY_RX_DC_BIAS_OFFSET 18 82 - #define QSGMII_PHY_RX_INPUT_EQU_OFFSET 20 83 - #define QSGMII_PHY_CDR_PI_SLEW_OFFSET 22 84 - #define QSGMII_PHY_TX_DRV_AMP_OFFSET 28 78 + #define QSGMII_PHY_DEEMPHASIS_LVL_MASK GENMASK(11, 10) 79 + #define QSGMII_PHY_DEEMPHASIS_LVL(x) FIELD_PREP(QSGMII_PHY_DEEMPHASIS_LVL_MASK, (x)) 80 + #define QSGMII_PHY_PHASE_LOOP_GAIN_MASK GENMASK(14, 12) 81 + #define QSGMII_PHY_PHASE_LOOP_GAIN(x) FIELD_PREP(QSGMII_PHY_PHASE_LOOP_GAIN_MASK, (x)) 82 + #define QSGMII_PHY_RX_DC_BIAS_MASK GENMASK(19, 18) 83 + #define QSGMII_PHY_RX_DC_BIAS(x) FIELD_PREP(QSGMII_PHY_RX_DC_BIAS_MASK, (x)) 84 + #define QSGMII_PHY_RX_INPUT_EQU_MASK GENMASK(21, 20) 85 + #define QSGMII_PHY_RX_INPUT_EQU(x) FIELD_PREP(QSGMII_PHY_RX_INPUT_EQU_MASK, (x)) 86 + #define QSGMII_PHY_CDR_PI_SLEW_MASK GENMASK(23, 22) 87 + #define QSGMII_PHY_CDR_PI_SLEW(x) FIELD_PREP(QSGMII_PHY_CDR_PI_SLEW_MASK, (x)) 88 + #define QSGMII_PHY_TX_SLEW_MASK GENMASK(27, 26) 89 + #define QSGMII_PHY_TX_SLEW(x) FIELD_PREP(QSGMII_PHY_TX_SLEW_MASK, (x)) 90 + #define QSGMII_PHY_TX_DRV_AMP_MASK GENMASK(31, 28) 91 + #define QSGMII_PHY_TX_DRV_AMP(x) FIELD_PREP(QSGMII_PHY_TX_DRV_AMP_MASK, (x)) 85 92 86 93 struct ipq806x_gmac { 87 94 struct platform_device *pdev; ··· 253 242 ipq806x_gmac_set_speed(gmac, speed); 254 243 } 255 244 245 + static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = { 246 + { 247 + .revision = "1.*", 248 + }, 249 + { 250 + /* sentinel */ 251 + } 252 + }; 253 + 254 + static int 255 + ipq806x_gmac_configure_qsgmii_params(struct ipq806x_gmac *gmac) 256 + { 257 + struct platform_device *pdev = gmac->pdev; 258 + const struct soc_device_attribute *soc; 259 + struct device *dev = &pdev->dev; 260 + u32 qsgmii_param; 261 + 262 + switch (gmac->id) { 263 + case 1: 264 + soc = soc_device_match(ipq806x_gmac_soc_v1); 265 + 266 + if (soc) 267 + qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xc) | 268 + QSGMII_PHY_TX_SLEW(0x2) | 269 + QSGMII_PHY_DEEMPHASIS_LVL(0x2); 270 + else 271 + qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xd) | 272 + QSGMII_PHY_TX_SLEW(0x0) | 273 + QSGMII_PHY_DEEMPHASIS_LVL(0x0); 274 + 275 + qsgmii_param |= QSGMII_PHY_RX_DC_BIAS(0x2); 276 + break; 277 + case 2: 278 + case 3: 279 + qsgmii_param = QSGMII_PHY_RX_DC_BIAS(0x3) | 280 + QSGMII_PHY_TX_DRV_AMP(0xc); 281 + break; 282 + default: /* gmac 0 can't be set in SGMII mode */ 283 + dev_err(dev, "gmac id %d can't be in SGMII mode", gmac->id); 284 + return -EINVAL; 285 + } 286 + 287 + /* Common params across all gmac id */ 288 + qsgmii_param |= QSGMII_PHY_CDR_EN | 289 + QSGMII_PHY_RX_FRONT_EN | 290 + QSGMII_PHY_RX_SIGNAL_DETECT_EN | 291 + QSGMII_PHY_TX_DRIVER_EN | 292 + QSGMII_PHY_QSGMII_EN | 293 + QSGMII_PHY_PHASE_LOOP_GAIN(0x4) | 294 + QSGMII_PHY_RX_INPUT_EQU(0x1) | 295 + QSGMII_PHY_CDR_PI_SLEW(0x2); 296 + 297 + regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id), 298 + qsgmii_param); 299 + 300 + return 0; 301 + } 302 + 256 303 static int ipq806x_gmac_probe(struct platform_device *pdev) 257 304 { 258 305 struct plat_stmmacenet_data *plat_dat; ··· 397 328 regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val); 398 329 399 330 if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) { 400 - regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id), 401 - QSGMII_PHY_CDR_EN | 402 - QSGMII_PHY_RX_FRONT_EN | 403 - QSGMII_PHY_RX_SIGNAL_DETECT_EN | 404 - QSGMII_PHY_TX_DRIVER_EN | 405 - QSGMII_PHY_QSGMII_EN | 406 - 0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET | 407 - 0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET | 408 - 0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET | 409 - 0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET | 410 - 0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET); 331 + err = ipq806x_gmac_configure_qsgmii_params(gmac); 332 + if (err) 333 + goto err_remove_config_dt; 411 334 } 412 335 413 336 plat_dat->has_gmac = true;