linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
@ 2019-08-09  5:44 Tao Ren
  2019-08-09 20:21 ` Heiner Kallweit
  0 siblings, 1 reply; 6+ messages in thread
From: Tao Ren @ 2019-08-09  5:44 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc
  Cc: Tao Ren

The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
example, on Facebook CMM BMC platform), mainly because genphy functions
are designed for copper links, and 1000Base-X (clause 37) auto negotiation
needs to be handled differently.

This patch enables 1000Base-X support for BCM54616S by customizing 3
driver callbacks:

  - probe: probe callback detects PHY's operation mode based on
    INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
    Control register.

  - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
    1000Base-X mode; otherwise, genphy_config_aneg will be called.

  - read_status: calls genphy_c37_read_status when the PHY is running in
    1000Base-X mode; otherwise, genphy_read_status will be called.

Signed-off-by: Tao Ren <taoren@fb.com>
---
 Changes in v6:
  - nothing changed.
 Changes in v5:
  - include Heiner's patch "net: phy: add support for clause 37
    auto-negotiation" into the series.
  - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
    PHY driver's callback when the PHY is running in 1000Base-X mode.
 Changes in v4:
  - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
    1000Base-X mode.
 Changes in v3:
  - rename bcm5482_read_status to bcm54xx_read_status so the callback can
    be shared by BCM5482 and BCM54616S.
 Changes in v2:
  - Auto-detect PHY operation mode instead of passing DT node.
  - move PHY mode auto-detect logic from config_init to probe callback.
  - only set speed (not including duplex) in read_status callback.
  - update patch description with more background to avoid confusion.
  - patch #1 in the series ("net: phy: broadcom: set features explicitly
    for BCM54616") is dropped: the fix should go to get_features callback
    which may potentially depend on this patch.

 drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
 include/linux/brcmphy.h    | 10 +++++--
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 937d0059e8ac..fbd76a31c142 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
 		/*
 		 * Select 1000BASE-X register set (primary SerDes)
 		 */
-		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
-		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
-				     reg | BCM5482_SHD_MODE_1000BX);
+		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
+		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
+				     reg | BCM54XX_SHD_MODE_1000BX);
 
 		/*
 		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
@@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
 	return ret;
 }
 
+static int bcm54616s_probe(struct phy_device *phydev)
+{
+	int val, intf_sel;
+
+	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
+	if (val < 0)
+		return val;
+
+	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
+	 * is 01b.
+	 */
+	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
+	if (intf_sel == 1) {
+		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
+		if (val < 0)
+			return val;
+
+		/* Bit 0 of the SerDes 100-FX Control register, when set
+		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
+		 * When this bit is set to 0, it sets the GMII/RGMII ->
+		 * 1000BASE-X configuration.
+		 */
+		if (!(val & BCM54616S_100FX_MODE))
+			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
+	}
+
+	return 0;
+}
+
 static int bcm54616s_config_aneg(struct phy_device *phydev)
 {
 	int ret;
 
 	/* Aneg firsly. */
-	ret = genphy_config_aneg(phydev);
+	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
+		ret = genphy_c37_config_aneg(phydev);
+	else
+		ret = genphy_config_aneg(phydev);
 
 	/* Then we can set up the delay. */
 	bcm54xx_config_clock_delay(phydev);
@@ -464,6 +496,18 @@ static int bcm54616s_config_aneg(struct phy_device *phydev)
 	return ret;
 }
 
+static int bcm54616s_read_status(struct phy_device *phydev)
+{
+	int err;
+
+	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
+		err = genphy_c37_read_status(phydev);
+	else
+		err = genphy_read_status(phydev);
+
+	return err;
+}
+
 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
 {
 	int val;
@@ -655,6 +699,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_aneg	= bcm54616s_config_aneg,
 	.ack_interrupt	= bcm_phy_ack_intr,
 	.config_intr	= bcm_phy_config_intr,
+	.read_status	= bcm54616s_read_status,
+	.probe		= bcm54616s_probe,
 }, {
 	.phy_id		= PHY_ID_BCM5464,
 	.phy_id_mask	= 0xfffffff0,
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 6db2d9a6e503..b475e7f20d28 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -200,9 +200,15 @@
 #define BCM5482_SHD_SSD		0x14	/* 10100: Secondary SerDes control */
 #define BCM5482_SHD_SSD_LEDM	0x0008	/* SSD LED Mode enable */
 #define BCM5482_SHD_SSD_EN	0x0001	/* SSD enable */
-#define BCM5482_SHD_MODE	0x1f	/* 11111: Mode Control Register */
-#define BCM5482_SHD_MODE_1000BX	0x0001	/* Enable 1000BASE-X registers */
 
+/* 10011: SerDes 100-FX Control Register */
+#define BCM54616S_SHD_100FX_CTRL	0x13
+#define	BCM54616S_100FX_MODE		BIT(0)	/* 100-FX SerDes Enable */
+
+/* 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_MODE_1000BX		BIT(0)	/* Enable 1000-X registers */
 
 /*
  * EXPANSION SHADOW ACCESS REGISTERS.  (PHY REG 0x15, 0x16, and 0x17)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
  2019-08-09  5:44 [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S Tao Ren
@ 2019-08-09 20:21 ` Heiner Kallweit
  2019-08-09 20:54   ` Tao Ren
  0 siblings, 1 reply; 6+ messages in thread
From: Heiner Kallweit @ 2019-08-09 20:21 UTC (permalink / raw)
  To: Tao Ren, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc

On 09.08.2019 07:44, Tao Ren wrote:
> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
> example, on Facebook CMM BMC platform), mainly because genphy functions
> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
> needs to be handled differently.
> 
> This patch enables 1000Base-X support for BCM54616S by customizing 3
> driver callbacks:
> 
>   - probe: probe callback detects PHY's operation mode based on
>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>     Control register.
> 
>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
> 
>   - read_status: calls genphy_c37_read_status when the PHY is running in
>     1000Base-X mode; otherwise, genphy_read_status will be called.
> 
> Signed-off-by: Tao Ren <taoren@fb.com>
> ---
>  Changes in v6:
>   - nothing changed.
>  Changes in v5:
>   - include Heiner's patch "net: phy: add support for clause 37
>     auto-negotiation" into the series.
>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>  Changes in v4:
>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>     1000Base-X mode.
>  Changes in v3:
>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>     be shared by BCM5482 and BCM54616S.
>  Changes in v2:
>   - Auto-detect PHY operation mode instead of passing DT node.
>   - move PHY mode auto-detect logic from config_init to probe callback.
>   - only set speed (not including duplex) in read_status callback.
>   - update patch description with more background to avoid confusion.
>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>     for BCM54616") is dropped: the fix should go to get_features callback
>     which may potentially depend on this patch.
> 
>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>  include/linux/brcmphy.h    | 10 +++++--
>  2 files changed, 58 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
> index 937d0059e8ac..fbd76a31c142 100644
> --- a/drivers/net/phy/broadcom.c
> +++ b/drivers/net/phy/broadcom.c
> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>  		/*
>  		 * Select 1000BASE-X register set (primary SerDes)
>  		 */
> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
> -				     reg | BCM5482_SHD_MODE_1000BX);
> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
> +				     reg | BCM54XX_SHD_MODE_1000BX);
>  
>  		/*
>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>  	return ret;
>  }
>  
> +static int bcm54616s_probe(struct phy_device *phydev)
> +{
> +	int val, intf_sel;
> +
> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> +	if (val < 0)
> +		return val;
> +
> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
> +	 * is 01b.
> +	 */
> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
> +	if (intf_sel == 1) {
> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
> +		if (val < 0)
> +			return val;
> +
> +		/* Bit 0 of the SerDes 100-FX Control register, when set
> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
> +		 * 1000BASE-X configuration.
> +		 */
> +		if (!(val & BCM54616S_100FX_MODE))
> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
> +	}
> +
> +	return 0;
> +}
> +
>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>  {
>  	int ret;
>  
>  	/* Aneg firsly. */
> -	ret = genphy_config_aneg(phydev);
> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
> +		ret = genphy_c37_config_aneg(phydev);
> +	else
> +		ret = genphy_config_aneg(phydev);
>  

I'm just wondering whether it needs to be considered that 100base-FX
doesn't support auto-negotiation. I suppose BMSR reports aneg as
supported, therefore phylib will use aneg per default.
Not sure who could set 100Base-FX mode when, but maybe at that place
also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?

Heiner

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
  2019-08-09 20:21 ` Heiner Kallweit
@ 2019-08-09 20:54   ` Tao Ren
  2019-08-09 21:13     ` [Potential Spoof] " Tao Ren
  0 siblings, 1 reply; 6+ messages in thread
From: Tao Ren @ 2019-08-09 20:54 UTC (permalink / raw)
  To: Heiner Kallweit, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc

Hi Heiner,

On 8/9/19 1:21 PM, Heiner Kallweit wrote:
> On 09.08.2019 07:44, Tao Ren wrote:
>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>> example, on Facebook CMM BMC platform), mainly because genphy functions
>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>> needs to be handled differently.
>>
>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>> driver callbacks:
>>
>>   - probe: probe callback detects PHY's operation mode based on
>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>     Control register.
>>
>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>
>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>
>> Signed-off-by: Tao Ren <taoren@fb.com>
>> ---
>>  Changes in v6:
>>   - nothing changed.
>>  Changes in v5:
>>   - include Heiner's patch "net: phy: add support for clause 37
>>     auto-negotiation" into the series.
>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>  Changes in v4:
>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>     1000Base-X mode.
>>  Changes in v3:
>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>     be shared by BCM5482 and BCM54616S.
>>  Changes in v2:
>>   - Auto-detect PHY operation mode instead of passing DT node.
>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>   - only set speed (not including duplex) in read_status callback.
>>   - update patch description with more background to avoid confusion.
>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>     for BCM54616") is dropped: the fix should go to get_features callback
>>     which may potentially depend on this patch.
>>
>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>  include/linux/brcmphy.h    | 10 +++++--
>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>> index 937d0059e8ac..fbd76a31c142 100644
>> --- a/drivers/net/phy/broadcom.c
>> +++ b/drivers/net/phy/broadcom.c
>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>  		/*
>>  		 * Select 1000BASE-X register set (primary SerDes)
>>  		 */
>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>> -				     reg | BCM5482_SHD_MODE_1000BX);
>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>  
>>  		/*
>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>  	return ret;
>>  }
>>  
>> +static int bcm54616s_probe(struct phy_device *phydev)
>> +{
>> +	int val, intf_sel;
>> +
>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>> +	if (val < 0)
>> +		return val;
>> +
>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>> +	 * is 01b.
>> +	 */
>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>> +	if (intf_sel == 1) {
>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>> +		if (val < 0)
>> +			return val;
>> +
>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>> +		 * 1000BASE-X configuration.
>> +		 */
>> +		if (!(val & BCM54616S_100FX_MODE))
>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>  {
>>  	int ret;
>>  
>>  	/* Aneg firsly. */
>> -	ret = genphy_config_aneg(phydev);
>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>> +		ret = genphy_c37_config_aneg(phydev);
>> +	else
>> +		ret = genphy_config_aneg(phydev);
>>  
> 
> I'm just wondering whether it needs to be considered that 100base-FX
> doesn't support auto-negotiation. I suppose BMSR reports aneg as
> supported, therefore phylib will use aneg per default.
> Not sure who could set 100Base-FX mode when, but maybe at that place
> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?

I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.

Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.


Thanks,

Tao

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Potential Spoof] Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
  2019-08-09 20:54   ` Tao Ren
@ 2019-08-09 21:13     ` Tao Ren
  2019-08-09 21:59       ` Heiner Kallweit
  0 siblings, 1 reply; 6+ messages in thread
From: Tao Ren @ 2019-08-09 21:13 UTC (permalink / raw)
  To: Heiner Kallweit, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc

On 8/9/19 1:54 PM, Tao Ren wrote:
> Hi Heiner,
> 
> On 8/9/19 1:21 PM, Heiner Kallweit wrote:
>> On 09.08.2019 07:44, Tao Ren wrote:
>>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>>> example, on Facebook CMM BMC platform), mainly because genphy functions
>>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>>> needs to be handled differently.
>>>
>>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>>> driver callbacks:
>>>
>>>   - probe: probe callback detects PHY's operation mode based on
>>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>>     Control register.
>>>
>>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>>
>>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>>
>>> Signed-off-by: Tao Ren <taoren@fb.com>
>>> ---
>>>  Changes in v6:
>>>   - nothing changed.
>>>  Changes in v5:
>>>   - include Heiner's patch "net: phy: add support for clause 37
>>>     auto-negotiation" into the series.
>>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>>  Changes in v4:
>>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>>     1000Base-X mode.
>>>  Changes in v3:
>>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>>     be shared by BCM5482 and BCM54616S.
>>>  Changes in v2:
>>>   - Auto-detect PHY operation mode instead of passing DT node.
>>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>>   - only set speed (not including duplex) in read_status callback.
>>>   - update patch description with more background to avoid confusion.
>>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>>     for BCM54616") is dropped: the fix should go to get_features callback
>>>     which may potentially depend on this patch.
>>>
>>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>>  include/linux/brcmphy.h    | 10 +++++--
>>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>>> index 937d0059e8ac..fbd76a31c142 100644
>>> --- a/drivers/net/phy/broadcom.c
>>> +++ b/drivers/net/phy/broadcom.c
>>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>>  		/*
>>>  		 * Select 1000BASE-X register set (primary SerDes)
>>>  		 */
>>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>>> -				     reg | BCM5482_SHD_MODE_1000BX);
>>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>>  
>>>  		/*
>>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>>  	return ret;
>>>  }
>>>  
>>> +static int bcm54616s_probe(struct phy_device *phydev)
>>> +{
>>> +	int val, intf_sel;
>>> +
>>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>> +	if (val < 0)
>>> +		return val;
>>> +
>>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>>> +	 * is 01b.
>>> +	 */
>>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>>> +	if (intf_sel == 1) {
>>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>>> +		if (val < 0)
>>> +			return val;
>>> +
>>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>>> +		 * 1000BASE-X configuration.
>>> +		 */
>>> +		if (!(val & BCM54616S_100FX_MODE))
>>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>>  {
>>>  	int ret;
>>>  
>>>  	/* Aneg firsly. */
>>> -	ret = genphy_config_aneg(phydev);
>>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>>> +		ret = genphy_c37_config_aneg(phydev);
>>> +	else
>>> +		ret = genphy_config_aneg(phydev);
>>>  
>>
>> I'm just wondering whether it needs to be considered that 100base-FX
>> doesn't support auto-negotiation. I suppose BMSR reports aneg as
>> supported, therefore phylib will use aneg per default.
>> Not sure who could set 100Base-FX mode when, but maybe at that place
>> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?
> 
> I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.
> 
> Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.

I can prepare a patch for 100Base-FX based on my understanding of bcm54616s datasheet, but the patch would be just compile-tested 


Thanks,

Tao

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Potential Spoof] Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
  2019-08-09 21:13     ` [Potential Spoof] " Tao Ren
@ 2019-08-09 21:59       ` Heiner Kallweit
  2019-08-09 22:16         ` Tao Ren
  0 siblings, 1 reply; 6+ messages in thread
From: Heiner Kallweit @ 2019-08-09 21:59 UTC (permalink / raw)
  To: Tao Ren, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc

On 09.08.2019 23:13, Tao Ren wrote:
> On 8/9/19 1:54 PM, Tao Ren wrote:
>> Hi Heiner,
>>
>> On 8/9/19 1:21 PM, Heiner Kallweit wrote:
>>> On 09.08.2019 07:44, Tao Ren wrote:
>>>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>>>> example, on Facebook CMM BMC platform), mainly because genphy functions
>>>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>>>> needs to be handled differently.
>>>>
>>>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>>>> driver callbacks:
>>>>
>>>>   - probe: probe callback detects PHY's operation mode based on
>>>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>>>     Control register.
>>>>
>>>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>>>
>>>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>>>
>>>> Signed-off-by: Tao Ren <taoren@fb.com>
>>>> ---
>>>>  Changes in v6:
>>>>   - nothing changed.
>>>>  Changes in v5:
>>>>   - include Heiner's patch "net: phy: add support for clause 37
>>>>     auto-negotiation" into the series.
>>>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>>>  Changes in v4:
>>>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>>>     1000Base-X mode.
>>>>  Changes in v3:
>>>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>>>     be shared by BCM5482 and BCM54616S.
>>>>  Changes in v2:
>>>>   - Auto-detect PHY operation mode instead of passing DT node.
>>>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>>>   - only set speed (not including duplex) in read_status callback.
>>>>   - update patch description with more background to avoid confusion.
>>>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>>>     for BCM54616") is dropped: the fix should go to get_features callback
>>>>     which may potentially depend on this patch.
>>>>
>>>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>>>  include/linux/brcmphy.h    | 10 +++++--
>>>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>>>> index 937d0059e8ac..fbd76a31c142 100644
>>>> --- a/drivers/net/phy/broadcom.c
>>>> +++ b/drivers/net/phy/broadcom.c
>>>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>>>  		/*
>>>>  		 * Select 1000BASE-X register set (primary SerDes)
>>>>  		 */
>>>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>>>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>>>> -				     reg | BCM5482_SHD_MODE_1000BX);
>>>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>>>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>>>  
>>>>  		/*
>>>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>>>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>>>  	return ret;
>>>>  }
>>>>  
>>>> +static int bcm54616s_probe(struct phy_device *phydev)
>>>> +{
>>>> +	int val, intf_sel;
>>>> +
>>>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>> +	if (val < 0)
>>>> +		return val;
>>>> +
>>>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>>>> +	 * is 01b.
>>>> +	 */
>>>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>>>> +	if (intf_sel == 1) {
>>>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>>>> +		if (val < 0)
>>>> +			return val;
>>>> +
>>>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>>>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>>>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>>>> +		 * 1000BASE-X configuration.
>>>> +		 */
>>>> +		if (!(val & BCM54616S_100FX_MODE))
>>>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>>>  {
>>>>  	int ret;
>>>>  
>>>>  	/* Aneg firsly. */
>>>> -	ret = genphy_config_aneg(phydev);
>>>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>>>> +		ret = genphy_c37_config_aneg(phydev);
>>>> +	else
>>>> +		ret = genphy_config_aneg(phydev);
>>>>  
>>>
>>> I'm just wondering whether it needs to be considered that 100base-FX
>>> doesn't support auto-negotiation. I suppose BMSR reports aneg as
>>> supported, therefore phylib will use aneg per default.
>>> Not sure who could set 100Base-FX mode when, but maybe at that place
>>> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?
>>
>> I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.
>>
>> Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.
> 
> I can prepare a patch for 100Base-FX based on my understanding of bcm54616s datasheet, but the patch would be just compile-tested 
> 
Support for 1000Base-X should be sufficient. Best mention the missing support for
100Base-FX in the commit message and at a suited place in the driver code.

> 
> Thanks,
> 
> Tao
> 
Heiner

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Potential Spoof] Re: [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S
  2019-08-09 21:59       ` Heiner Kallweit
@ 2019-08-09 22:16         ` Tao Ren
  0 siblings, 0 replies; 6+ messages in thread
From: Tao Ren @ 2019-08-09 22:16 UTC (permalink / raw)
  To: Heiner Kallweit, Andrew Lunn, Florian Fainelli, David S . Miller,
	Arun Parameswaran, Justin Chen, Vladimir Oltean, netdev,
	linux-kernel, openbmc

On 8/9/19 2:59 PM, Heiner Kallweit wrote:
> On 09.08.2019 23:13, Tao Ren wrote:
>> On 8/9/19 1:54 PM, Tao Ren wrote:
>>> Hi Heiner,
>>>
>>> On 8/9/19 1:21 PM, Heiner Kallweit wrote:
>>>> On 09.08.2019 07:44, Tao Ren wrote:
>>>>> The BCM54616S PHY cannot work properly in RGMII->1000Base-KX mode (for
>>>>> example, on Facebook CMM BMC platform), mainly because genphy functions
>>>>> are designed for copper links, and 1000Base-X (clause 37) auto negotiation
>>>>> needs to be handled differently.
>>>>>
>>>>> This patch enables 1000Base-X support for BCM54616S by customizing 3
>>>>> driver callbacks:
>>>>>
>>>>>   - probe: probe callback detects PHY's operation mode based on
>>>>>     INTERF_SEL[1:0] pins and 1000X/100FX selection bit in SerDES 100-FX
>>>>>     Control register.
>>>>>
>>>>>   - config_aneg: calls genphy_c37_config_aneg when the PHY is running in
>>>>>     1000Base-X mode; otherwise, genphy_config_aneg will be called.
>>>>>
>>>>>   - read_status: calls genphy_c37_read_status when the PHY is running in
>>>>>     1000Base-X mode; otherwise, genphy_read_status will be called.
>>>>>
>>>>> Signed-off-by: Tao Ren <taoren@fb.com>
>>>>> ---
>>>>>  Changes in v6:
>>>>>   - nothing changed.
>>>>>  Changes in v5:
>>>>>   - include Heiner's patch "net: phy: add support for clause 37
>>>>>     auto-negotiation" into the series.
>>>>>   - use genphy_c37_config_aneg and genphy_c37_read_status in BCM54616S
>>>>>     PHY driver's callback when the PHY is running in 1000Base-X mode.
>>>>>  Changes in v4:
>>>>>   - add bcm54616s_config_aneg_1000bx() to deal with auto negotiation in
>>>>>     1000Base-X mode.
>>>>>  Changes in v3:
>>>>>   - rename bcm5482_read_status to bcm54xx_read_status so the callback can
>>>>>     be shared by BCM5482 and BCM54616S.
>>>>>  Changes in v2:
>>>>>   - Auto-detect PHY operation mode instead of passing DT node.
>>>>>   - move PHY mode auto-detect logic from config_init to probe callback.
>>>>>   - only set speed (not including duplex) in read_status callback.
>>>>>   - update patch description with more background to avoid confusion.
>>>>>   - patch #1 in the series ("net: phy: broadcom: set features explicitly
>>>>>     for BCM54616") is dropped: the fix should go to get_features callback
>>>>>     which may potentially depend on this patch.
>>>>>
>>>>>  drivers/net/phy/broadcom.c | 54 +++++++++++++++++++++++++++++++++++---
>>>>>  include/linux/brcmphy.h    | 10 +++++--
>>>>>  2 files changed, 58 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
>>>>> index 937d0059e8ac..fbd76a31c142 100644
>>>>> --- a/drivers/net/phy/broadcom.c
>>>>> +++ b/drivers/net/phy/broadcom.c
>>>>> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
>>>>>  		/*
>>>>>  		 * Select 1000BASE-X register set (primary SerDes)
>>>>>  		 */
>>>>> -		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
>>>>> -		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
>>>>> -				     reg | BCM5482_SHD_MODE_1000BX);
>>>>> +		reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>>> +		bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
>>>>> +				     reg | BCM54XX_SHD_MODE_1000BX);
>>>>>  
>>>>>  		/*
>>>>>  		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
>>>>> @@ -451,12 +451,44 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
>>>>>  	return ret;
>>>>>  }
>>>>>  
>>>>> +static int bcm54616s_probe(struct phy_device *phydev)
>>>>> +{
>>>>> +	int val, intf_sel;
>>>>> +
>>>>> +	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
>>>>> +	if (val < 0)
>>>>> +		return val;
>>>>> +
>>>>> +	/* The PHY is strapped in RGMII to fiber mode when INTERF_SEL[1:0]
>>>>> +	 * is 01b.
>>>>> +	 */
>>>>> +	intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1;
>>>>> +	if (intf_sel == 1) {
>>>>> +		val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);
>>>>> +		if (val < 0)
>>>>> +			return val;
>>>>> +
>>>>> +		/* Bit 0 of the SerDes 100-FX Control register, when set
>>>>> +		 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
>>>>> +		 * When this bit is set to 0, it sets the GMII/RGMII ->
>>>>> +		 * 1000BASE-X configuration.
>>>>> +		 */
>>>>> +		if (!(val & BCM54616S_100FX_MODE))
>>>>> +			phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
>>>>> +	}
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>>  static int bcm54616s_config_aneg(struct phy_device *phydev)
>>>>>  {
>>>>>  	int ret;
>>>>>  
>>>>>  	/* Aneg firsly. */
>>>>> -	ret = genphy_config_aneg(phydev);
>>>>> +	if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
>>>>> +		ret = genphy_c37_config_aneg(phydev);
>>>>> +	else
>>>>> +		ret = genphy_config_aneg(phydev);
>>>>>  
>>>>
>>>> I'm just wondering whether it needs to be considered that 100base-FX
>>>> doesn't support auto-negotiation. I suppose BMSR reports aneg as
>>>> supported, therefore phylib will use aneg per default.
>>>> Not sure who could set 100Base-FX mode when, but maybe at that place
>>>> also phydev->autoneg needs to be cleared. Did you test 100Base-FX mode?
>>>
>>> I'm doubting if 100Base-FX works. Besides auto-negotiation, 100Base-FX Control/Status registers are defined in shadow register instead of MII_BMCR and MII_BMSR.
>>>
>>> Unfortunately I don't have environment to test 100Base-FX and that's why I only make changes when the PHY is working in 1000X mode.
>>
>> I can prepare a patch for 100Base-FX based on my understanding of bcm54616s datasheet, but the patch would be just compile-tested 
>>
> Support for 1000Base-X should be sufficient. Best mention the missing support for
> 100Base-FX in the commit message and at a suited place in the driver code.

Make sense. Will do it soon.


Thanks,

Tao

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-08-09 22:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-09  5:44 [PATCH net-next v6 3/3] net: phy: broadcom: add 1000Base-X support for BCM54616S Tao Ren
2019-08-09 20:21 ` Heiner Kallweit
2019-08-09 20:54   ` Tao Ren
2019-08-09 21:13     ` [Potential Spoof] " Tao Ren
2019-08-09 21:59       ` Heiner Kallweit
2019-08-09 22:16         ` Tao Ren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).