Message ID | 20210213002825.2557444-2-robert.hancock@calian.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Broadcom PHY driver updates | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | success | CCed 8 of 8 maintainers |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 12 this patch: 12 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | warning | WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 12 this patch: 12 |
netdev/header_inline | success | Link |
netdev/stable | success | Stable not CCed |
On 2/12/2021 4:28 PM, 'Robert Hancock' via BCM-KERNEL-FEEDBACK-LIST,PDL wrote: > The default configuration for the BCM54616S PHY may not match the desired > mode when using 1000BaseX or SGMII interface modes, such as when it is on > an SFP module. Add code to explicitly set the correct mode using > programming sequences provided by Bel-Fuse: > > https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-05-series.pdf > https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-06-series.pdf > > Signed-off-by: Robert Hancock <robert.hancock@calian.com> > --- > drivers/net/phy/broadcom.c | 83 ++++++++++++++++++++++++++++++++------ > include/linux/brcmphy.h | 4 ++ > 2 files changed, 75 insertions(+), 12 deletions(-) > > diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c > index 0472b3470c59..78542580f2b2 100644 > --- a/drivers/net/phy/broadcom.c > +++ b/drivers/net/phy/broadcom.c > @@ -64,6 +64,63 @@ static int bcm54612e_config_init(struct phy_device *phydev) > return 0; > } > > +static int bcm54616s_config_init(struct phy_device *phydev) > +{ > + int rc, val; > + > + if (phydev->interface == PHY_INTERFACE_MODE_SGMII || > + phydev->interface == PHY_INTERFACE_MODE_1000BASEX) { Can you reverse the condition so as to save a level of identation? > + /* Ensure proper interface mode is selected. */ > + /* Disable RGMII mode */ > + val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); > + if (val < 0) > + return val; > + val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; > + rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, > + val); > + if (rc < 0) > + return rc; I don't think this write is making it through since you are not setting MII_BCM54XX_AUXCTL_MISC_WREN in val, I know this is an annoying detail, and we could probably fold that to be within bcm54xx_auxctl_write() directly, similarly to what bcm_phy_write_shadow() does. The reset of the sequence and changes looks fine to me.
On Fri, 2021-02-12 at 17:26 -0800, Florian Fainelli wrote: > > On 2/12/2021 4:28 PM, 'Robert Hancock' via BCM-KERNEL-FEEDBACK-LIST,PDL > wrote: > > The default configuration for the BCM54616S PHY may not match the desired > > mode when using 1000BaseX or SGMII interface modes, such as when it is on > > an SFP module. Add code to explicitly set the correct mode using > > programming sequences provided by Bel-Fuse: > > > > https://urldefense.com/v3/__https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-05-series.pdf__;!!IOGos0k!20FhZqRHEiz2-qFJ7J8XC4xX2qG-ajZ17Ma1W-VwDgwdQZeIhHEpWKlNldWW8DyFaQo$ > > https://urldefense.com/v3/__https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-06-series.pdf__;!!IOGos0k!20FhZqRHEiz2-qFJ7J8XC4xX2qG-ajZ17Ma1W-VwDgwdQZeIhHEpWKlNldWW58K3fY4$ > > > > Signed-off-by: Robert Hancock <robert.hancock@calian.com> > > --- > > drivers/net/phy/broadcom.c | 83 ++++++++++++++++++++++++++++++++------ > > include/linux/brcmphy.h | 4 ++ > > 2 files changed, 75 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c > > index 0472b3470c59..78542580f2b2 100644 > > --- a/drivers/net/phy/broadcom.c > > +++ b/drivers/net/phy/broadcom.c > > @@ -64,6 +64,63 @@ static int bcm54612e_config_init(struct phy_device > > *phydev) > > return 0; > > } > > > > +static int bcm54616s_config_init(struct phy_device *phydev) > > +{ > > + int rc, val; > > + > > + if (phydev->interface == PHY_INTERFACE_MODE_SGMII || > > + phydev->interface == PHY_INTERFACE_MODE_1000BASEX) { > > Can you reverse the condition so as to save a level of identation? Can do. > > > + /* Ensure proper interface mode is selected. */ > > + /* Disable RGMII mode */ > > + val = bcm54xx_auxctl_read(phydev, > > MII_BCM54XX_AUXCTL_SHDWSEL_MISC); > > + if (val < 0) > > + return val; > > + val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; > > + rc = bcm54xx_auxctl_write(phydev, > > MII_BCM54XX_AUXCTL_SHDWSEL_MISC, > > + val); > > + if (rc < 0) > > + return rc; > > I don't think this write is making it through since you are not setting > MII_BCM54XX_AUXCTL_MISC_WREN in val, I know this is an annoying detail, > and we could probably fold that to be within bcm54xx_auxctl_write() > directly, similarly to what bcm_phy_write_shadow() does. Ah, indeed. I assume that is specific to the MII_BCM54XX_AUXCTL_SHDWSEL_MISC register? I suppose bcm54xx_auxctl_write could add that automatically for writes to that register. Not sure if that is too much magic for that function or not.. > > The reset of the sequence and changes looks fine to me.
On 2/12/2021 5:45 PM, Robert Hancock wrote: > On Fri, 2021-02-12 at 17:26 -0800, Florian Fainelli wrote: >> >> On 2/12/2021 4:28 PM, 'Robert Hancock' via BCM-KERNEL-FEEDBACK-LIST,PDL >> wrote: >>> The default configuration for the BCM54616S PHY may not match the desired >>> mode when using 1000BaseX or SGMII interface modes, such as when it is on >>> an SFP module. Add code to explicitly set the correct mode using >>> programming sequences provided by Bel-Fuse: >>> >>> https://urldefense.com/v3/__https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-05-series.pdf__;!!IOGos0k!20FhZqRHEiz2-qFJ7J8XC4xX2qG-ajZ17Ma1W-VwDgwdQZeIhHEpWKlNldWW8DyFaQo$ >>> https://urldefense.com/v3/__https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-06-series.pdf__;!!IOGos0k!20FhZqRHEiz2-qFJ7J8XC4xX2qG-ajZ17Ma1W-VwDgwdQZeIhHEpWKlNldWW58K3fY4$ >>> >>> Signed-off-by: Robert Hancock <robert.hancock@calian.com> >>> --- >>> drivers/net/phy/broadcom.c | 83 ++++++++++++++++++++++++++++++++------ >>> include/linux/brcmphy.h | 4 ++ >>> 2 files changed, 75 insertions(+), 12 deletions(-) >>> >>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c >>> index 0472b3470c59..78542580f2b2 100644 >>> --- a/drivers/net/phy/broadcom.c >>> +++ b/drivers/net/phy/broadcom.c >>> @@ -64,6 +64,63 @@ static int bcm54612e_config_init(struct phy_device >>> *phydev) >>> return 0; >>> } >>> >>> +static int bcm54616s_config_init(struct phy_device *phydev) >>> +{ >>> + int rc, val; >>> + >>> + if (phydev->interface == PHY_INTERFACE_MODE_SGMII || >>> + phydev->interface == PHY_INTERFACE_MODE_1000BASEX) { >> >> Can you reverse the condition so as to save a level of identation? > > Can do. > >> >>> + /* Ensure proper interface mode is selected. */ >>> + /* Disable RGMII mode */ >>> + val = bcm54xx_auxctl_read(phydev, >>> MII_BCM54XX_AUXCTL_SHDWSEL_MISC); >>> + if (val < 0) >>> + return val; >>> + val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; >>> + rc = bcm54xx_auxctl_write(phydev, >>> MII_BCM54XX_AUXCTL_SHDWSEL_MISC, >>> + val); >>> + if (rc < 0) >>> + return rc; >> >> I don't think this write is making it through since you are not setting >> MII_BCM54XX_AUXCTL_MISC_WREN in val, I know this is an annoying detail, >> and we could probably fold that to be within bcm54xx_auxctl_write() >> directly, similarly to what bcm_phy_write_shadow() does. > > Ah, indeed. I assume that is specific to the MII_BCM54XX_AUXCTL_SHDWSEL_MISC > register? I suppose bcm54xx_auxctl_write could add that automatically for > writes to that register. Not sure if that is too much magic for that function > or not.. Upon closer look it's a bit more subtle than that, as we need to apply the write enable bit only when targeting the "misc" shadow register, a million ways to die in the west :)
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 0472b3470c59..78542580f2b2 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -64,6 +64,63 @@ static int bcm54612e_config_init(struct phy_device *phydev) return 0; } +static int bcm54616s_config_init(struct phy_device *phydev) +{ + int rc, val; + + if (phydev->interface == PHY_INTERFACE_MODE_SGMII || + phydev->interface == PHY_INTERFACE_MODE_1000BASEX) { + /* Ensure proper interface mode is selected. */ + /* Disable RGMII mode */ + val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); + if (val < 0) + return val; + val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; + rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, + val); + if (rc < 0) + return rc; + + /* Select 1000BASE-X register set (primary SerDes) */ + val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); + if (val < 0) + return val; + val |= BCM54XX_SHD_MODE_1000BX; + rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); + if (rc < 0) + return rc; + + /* Power down SerDes interface */ + rc = phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN); + if (rc < 0) + return rc; + + /* Select proper interface mode */ + val &= ~BCM54XX_SHD_INTF_SEL_MASK; + val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ? + BCM54XX_SHD_INTF_SEL_SGMII : + BCM54XX_SHD_INTF_SEL_GBIC; + rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); + if (rc < 0) + return rc; + + /* Power up SerDes interface */ + rc = phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN); + if (rc < 0) + return rc; + + /* Select copper register set */ + val &= ~BCM54XX_SHD_MODE_1000BX; + rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); + if (rc < 0) + return rc; + + /* Power up copper interface */ + return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN); + } + return 0; +} + static int bcm54xx_config_clock_delay(struct phy_device *phydev) { int rc, val; @@ -283,15 +340,17 @@ static int bcm54xx_config_init(struct phy_device *phydev) bcm54xx_adjust_rxrefclk(phydev); - if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) { + switch (BRCM_PHY_MODEL(phydev)) { + case PHY_ID_BCM54210E: err = bcm54210e_config_init(phydev); - if (err) - return err; - } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) { + break; + case PHY_ID_BCM54612E: err = bcm54612e_config_init(phydev); - if (err) - return err; - } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) { + break; + case PHY_ID_BCM54616S: + err = bcm54616s_config_init(phydev); + break; + case PHY_ID_BCM54810: /* For BCM54810, we need to disable BroadR-Reach function */ val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL); @@ -299,9 +358,10 @@ static int bcm54xx_config_init(struct phy_device *phydev) err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, val); - if (err < 0) - return err; + break; } + if (err) + return err; bcm54xx_phydsp_config(phydev); @@ -385,7 +445,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev) static int bcm54616s_probe(struct phy_device *phydev) { - int val, intf_sel; + int val; val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); if (val < 0) @@ -397,8 +457,7 @@ static int bcm54616s_probe(struct phy_device *phydev) * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX * support is still missing as of now. */ - intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1; - if (intf_sel == 1) { + if ((val & BCM54XX_SHD_INTF_SEL_MASK) == BCM54XX_SHD_INTF_SEL_RGMII) { val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL); if (val < 0) return val; diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index de9430d55c90..b0a73b91d5ba 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -137,6 +137,7 @@ #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x07 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN 0x0010 +#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN 0x0080 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN 0x0100 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200 #define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000 @@ -223,6 +224,9 @@ /* 11111: Mode Control Register */ #define BCM54XX_SHD_MODE 0x1f #define BCM54XX_SHD_INTF_SEL_MASK GENMASK(2, 1) /* INTERF_SEL[1:0] */ +#define BCM54XX_SHD_INTF_SEL_RGMII 0x02 +#define BCM54XX_SHD_INTF_SEL_SGMII 0x04 +#define BCM54XX_SHD_INTF_SEL_GBIC 0x06 #define BCM54XX_SHD_MODE_1000BX BIT(0) /* Enable 1000-X registers */ /*
The default configuration for the BCM54616S PHY may not match the desired mode when using 1000BaseX or SGMII interface modes, such as when it is on an SFP module. Add code to explicitly set the correct mode using programming sequences provided by Bel-Fuse: https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-05-series.pdf https://www.belfuse.com/resources/datasheets/powersolutions/ds-bps-sfp-1gbt-06-series.pdf Signed-off-by: Robert Hancock <robert.hancock@calian.com> --- drivers/net/phy/broadcom.c | 83 ++++++++++++++++++++++++++++++++------ include/linux/brcmphy.h | 4 ++ 2 files changed, 75 insertions(+), 12 deletions(-)