Skip to content

Commit d1d7712

Browse files
catalin-popescudavem330
authored andcommitted
net: phy: dp83826: support TX data voltage tuning
DP83826 offers the possibility to tune the voltage of logical levels of the MLT-3 encoded TX data. This is useful when there is a voltage drop in between the PHY and the connector and we want to increase the voltage levels to compensate for that drop. Prior to PHY configuration, the driver SW resets the PHY which has the same effect as the HW reset pin according to the datasheet. Hence, there's no need to force update the VOD_CFG registers to make sure they hold their reset values. VOD_CFG registers need to be updated only if the DT has been configured with values other than the reset ones. Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: Catalin Popescu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ed1d7da commit d1d7712

File tree

1 file changed

+126
-4
lines changed

1 file changed

+126
-4
lines changed

drivers/net/phy/dp83822.c

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/of.h>
1313
#include <linux/phy.h>
1414
#include <linux/netdevice.h>
15+
#include <linux/bitfield.h>
1516

1617
#define DP83822_PHY_ID 0x2000a240
1718
#define DP83825S_PHY_ID 0x2000a140
@@ -34,6 +35,10 @@
3435
#define MII_DP83822_GENCFG 0x465
3536
#define MII_DP83822_SOR1 0x467
3637

38+
/* DP83826 specific registers */
39+
#define MII_DP83826_VOD_CFG1 0x30b
40+
#define MII_DP83826_VOD_CFG2 0x30c
41+
3742
/* GENCFG */
3843
#define DP83822_SIG_DET_LOW BIT(0)
3944

@@ -110,6 +115,19 @@
110115
#define DP83822_RX_ER_STR_MASK GENMASK(9, 8)
111116
#define DP83822_RX_ER_SHIFT 8
112117

118+
/* DP83826: VOD_CFG1 & VOD_CFG2 */
119+
#define DP83826_VOD_CFG1_MINUS_MDIX_MASK GENMASK(13, 12)
120+
#define DP83826_VOD_CFG1_MINUS_MDI_MASK GENMASK(11, 6)
121+
#define DP83826_VOD_CFG2_MINUS_MDIX_MASK GENMASK(15, 12)
122+
#define DP83826_VOD_CFG2_PLUS_MDIX_MASK GENMASK(11, 6)
123+
#define DP83826_VOD_CFG2_PLUS_MDI_MASK GENMASK(5, 0)
124+
#define DP83826_CFG_DAC_MINUS_MDIX_5_TO_4 GENMASK(5, 4)
125+
#define DP83826_CFG_DAC_MINUS_MDIX_3_TO_0 GENMASK(3, 0)
126+
#define DP83826_CFG_DAC_PERCENT_PER_STEP 625
127+
#define DP83826_CFG_DAC_PERCENT_DEFAULT 10000
128+
#define DP83826_CFG_DAC_MINUS_DEFAULT 0x30
129+
#define DP83826_CFG_DAC_PLUS_DEFAULT 0x10
130+
113131
#define MII_DP83822_FIBER_ADVERTISE (ADVERTISED_TP | ADVERTISED_MII | \
114132
ADVERTISED_FIBRE | \
115133
ADVERTISED_Pause | ADVERTISED_Asym_Pause)
@@ -118,6 +136,8 @@ struct dp83822_private {
118136
bool fx_signal_det_low;
119137
int fx_enabled;
120138
u16 fx_sd_enable;
139+
u8 cfg_dac_minus;
140+
u8 cfg_dac_plus;
121141
};
122142

123143
static int dp83822_set_wol(struct phy_device *phydev,
@@ -233,7 +253,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
233253
DP83822_ENERGY_DET_INT_EN |
234254
DP83822_LINK_QUAL_INT_EN);
235255

236-
/* Private data pointer is NULL on DP83825/26 */
256+
/* Private data pointer is NULL on DP83825 */
237257
if (!dp83822 || !dp83822->fx_enabled)
238258
misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
239259
DP83822_DUP_MODE_CHANGE_INT_EN |
@@ -254,7 +274,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
254274
DP83822_PAGE_RX_INT_EN |
255275
DP83822_EEE_ERROR_CHANGE_INT_EN);
256276

257-
/* Private data pointer is NULL on DP83825/26 */
277+
/* Private data pointer is NULL on DP83825 */
258278
if (!dp83822 || !dp83822->fx_enabled)
259279
misr_status |= DP83822_ANEG_ERR_INT_EN |
260280
DP83822_WOL_PKT_INT_EN;
@@ -474,6 +494,43 @@ static int dp83822_config_init(struct phy_device *phydev)
474494
return dp8382x_disable_wol(phydev);
475495
}
476496

497+
static int dp83826_config_init(struct phy_device *phydev)
498+
{
499+
struct dp83822_private *dp83822 = phydev->priv;
500+
u16 val, mask;
501+
int ret;
502+
503+
if (dp83822->cfg_dac_minus != DP83826_CFG_DAC_MINUS_DEFAULT) {
504+
val = FIELD_PREP(DP83826_VOD_CFG1_MINUS_MDI_MASK, dp83822->cfg_dac_minus) |
505+
FIELD_PREP(DP83826_VOD_CFG1_MINUS_MDIX_MASK,
506+
FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_5_TO_4,
507+
dp83822->cfg_dac_minus));
508+
mask = DP83826_VOD_CFG1_MINUS_MDIX_MASK | DP83826_VOD_CFG1_MINUS_MDI_MASK;
509+
ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG1, mask, val);
510+
if (ret)
511+
return ret;
512+
513+
val = FIELD_PREP(DP83826_VOD_CFG2_MINUS_MDIX_MASK,
514+
FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_3_TO_0,
515+
dp83822->cfg_dac_minus));
516+
mask = DP83826_VOD_CFG2_MINUS_MDIX_MASK;
517+
ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);
518+
if (ret)
519+
return ret;
520+
}
521+
522+
if (dp83822->cfg_dac_plus != DP83826_CFG_DAC_PLUS_DEFAULT) {
523+
val = FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDIX_MASK, dp83822->cfg_dac_plus) |
524+
FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDI_MASK, dp83822->cfg_dac_plus);
525+
mask = DP83826_VOD_CFG2_PLUS_MDIX_MASK | DP83826_VOD_CFG2_PLUS_MDI_MASK;
526+
ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);
527+
if (ret)
528+
return ret;
529+
}
530+
531+
return 0;
532+
}
533+
477534
static int dp8382x_config_init(struct phy_device *phydev)
478535
{
479536
return dp8382x_disable_wol(phydev);
@@ -509,11 +566,44 @@ static int dp83822_of_init(struct phy_device *phydev)
509566

510567
return 0;
511568
}
569+
570+
static int dp83826_to_dac_minus_one_regval(int percent)
571+
{
572+
int tmp = DP83826_CFG_DAC_PERCENT_DEFAULT - percent;
573+
574+
return tmp / DP83826_CFG_DAC_PERCENT_PER_STEP;
575+
}
576+
577+
static int dp83826_to_dac_plus_one_regval(int percent)
578+
{
579+
int tmp = percent - DP83826_CFG_DAC_PERCENT_DEFAULT;
580+
581+
return tmp / DP83826_CFG_DAC_PERCENT_PER_STEP;
582+
}
583+
584+
static void dp83826_of_init(struct phy_device *phydev)
585+
{
586+
struct dp83822_private *dp83822 = phydev->priv;
587+
struct device *dev = &phydev->mdio.dev;
588+
u32 val;
589+
590+
dp83822->cfg_dac_minus = DP83826_CFG_DAC_MINUS_DEFAULT;
591+
if (!device_property_read_u32(dev, "ti,cfg-dac-minus-one-bp", &val))
592+
dp83822->cfg_dac_minus += dp83826_to_dac_minus_one_regval(val);
593+
594+
dp83822->cfg_dac_plus = DP83826_CFG_DAC_PLUS_DEFAULT;
595+
if (!device_property_read_u32(dev, "ti,cfg-dac-plus-one-bp", &val))
596+
dp83822->cfg_dac_plus += dp83826_to_dac_plus_one_regval(val);
597+
}
512598
#else
513599
static int dp83822_of_init(struct phy_device *phydev)
514600
{
515601
return 0;
516602
}
603+
604+
static void dp83826_of_init(struct phy_device *phydev)
605+
{
606+
}
517607
#endif /* CONFIG_OF_MDIO */
518608

519609
static int dp83822_read_straps(struct phy_device *phydev)
@@ -567,6 +657,22 @@ static int dp83822_probe(struct phy_device *phydev)
567657
return 0;
568658
}
569659

660+
static int dp83826_probe(struct phy_device *phydev)
661+
{
662+
struct dp83822_private *dp83822;
663+
664+
dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822),
665+
GFP_KERNEL);
666+
if (!dp83822)
667+
return -ENOMEM;
668+
669+
phydev->priv = dp83822;
670+
671+
dp83826_of_init(phydev);
672+
673+
return 0;
674+
}
675+
570676
static int dp83822_suspend(struct phy_device *phydev)
571677
{
572678
int value;
@@ -610,6 +716,22 @@ static int dp83822_resume(struct phy_device *phydev)
610716
.resume = dp83822_resume, \
611717
}
612718

719+
#define DP83826_PHY_DRIVER(_id, _name) \
720+
{ \
721+
PHY_ID_MATCH_MODEL(_id), \
722+
.name = (_name), \
723+
/* PHY_BASIC_FEATURES */ \
724+
.probe = dp83826_probe, \
725+
.soft_reset = dp83822_phy_reset, \
726+
.config_init = dp83826_config_init, \
727+
.get_wol = dp83822_get_wol, \
728+
.set_wol = dp83822_set_wol, \
729+
.config_intr = dp83822_config_intr, \
730+
.handle_interrupt = dp83822_handle_interrupt, \
731+
.suspend = dp83822_suspend, \
732+
.resume = dp83822_resume, \
733+
}
734+
613735
#define DP8382X_PHY_DRIVER(_id, _name) \
614736
{ \
615737
PHY_ID_MATCH_MODEL(_id), \
@@ -628,8 +750,8 @@ static int dp83822_resume(struct phy_device *phydev)
628750
static struct phy_driver dp83822_driver[] = {
629751
DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),
630752
DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
631-
DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
632-
DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
753+
DP83826_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
754+
DP83826_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
633755
DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
634756
DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
635757
DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),

0 commit comments

Comments
 (0)