[PATCH v8 13/14] net: phy: at803x: configure qca8084 work mode

Luo Jie posted 14 patches 2 years ago
[PATCH v8 13/14] net: phy: at803x: configure qca8084 work mode
Posted by Luo Jie 2 years ago
There are four kind of work modes supported by qca8084.
1. Quad PHYs work on 10g-qxgmii.
2. PHY1, PHY2, PHY3 wors on 10g-qxgmii, PHY4 works on sgmii.
3. Quad PHYs connected with internal MACs by GMII, which works
   on switch mode.
4. PHY1, PHY2, PHY3 connected with internal MACs by GMII, PHY4
   works on sgmii.

Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
 drivers/net/phy/at803x.c | 53 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 3ef4eacf40c7..ac72b0551ed8 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -317,6 +317,13 @@
 #define QCA8084_EPHY_ADDR3_MASK			GENMASK(19, 15)
 #define QCA8084_EPHY_LDO_EN			GENMASK(21, 20)
 
+#define QCA8084_WORK_MODE_CFG			0xc90f030
+#define QCA8084_WORK_MODE_MASK			GENMASK(5, 0)
+#define QCA8084_WORK_MODE_QXGMII		(BIT(5) | GENMASK(3, 0))
+#define QCA8084_WORK_MODE_QXGMII_PORT4_SGMII	(BIT(5) | GENMASK(2, 0))
+#define QCA8084_WORK_MODE_SWITCH		BIT(4)
+#define QCA8084_WORK_MODE_SWITCH_PORT4_SGMII	BIT(5)
+
 MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
 MODULE_AUTHOR("Matus Ujhelyi");
 MODULE_LICENSE("GPL");
@@ -1038,6 +1045,46 @@ static int qca8084_common_clock_init(struct phy_device *phydev)
 	return clk_prepare_enable(priv->clk[MDIO_MASTER_AHB_CLK]);
 }
 
+static int qca8084_parse_and_set_work_mode(struct phy_device *phydev)
+{
+	struct device_node *node;
+	struct at803x_priv *priv;
+	u32 value, work_mode;
+	int ret;
+
+	node = phydev->mdio.dev.of_node;
+	priv = phydev->priv;
+
+	/* The property "qcom,phy-work-mode" is only defined in one
+	 * PHY device tree node.
+	 */
+	ret = of_property_read_u32(node, "qcom,phy-work-mode", &value);
+	if (ret)
+		return ret == -EINVAL ? 0 : ret;
+
+	switch (value) {
+	case 0:
+		work_mode = QCA8084_WORK_MODE_QXGMII;
+		break;
+	case 1:
+		work_mode = QCA8084_WORK_MODE_QXGMII_PORT4_SGMII;
+		break;
+	case 2:
+		work_mode = QCA8084_WORK_MODE_SWITCH;
+		break;
+	case 3:
+		work_mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII;
+		break;
+	default:
+		phydev_err(phydev, "invalid qcom,phy-work-mode %d\n", value);
+		return -EINVAL;
+	}
+
+	return qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG,
+				  QCA8084_WORK_MODE_MASK,
+				  FIELD_PREP(QCA8084_WORK_MODE_MASK, work_mode));
+}
+
 static int qca8084_probe(struct phy_device *phydev)
 {
 	int ret;
@@ -1054,7 +1101,11 @@ static int qca8084_probe(struct phy_device *phydev)
 	if (ret)
 		return ret;
 
-	return qca8084_common_clock_init(phydev);
+	ret = qca8084_common_clock_init(phydev);
+	if (ret)
+		return ret;
+
+	return qca8084_parse_and_set_work_mode(phydev);
 }
 
 static int at803x_probe(struct phy_device *phydev)
-- 
2.42.0
Re: [PATCH v8 13/14] net: phy: at803x: configure qca8084 work mode
Posted by Simon Horman 2 years ago
On Fri, Dec 15, 2023 at 03:40:03PM +0800, Luo Jie wrote:

...

> @@ -1038,6 +1045,46 @@ static int qca8084_common_clock_init(struct phy_device *phydev)
>  	return clk_prepare_enable(priv->clk[MDIO_MASTER_AHB_CLK]);
>  }
>  
> +static int qca8084_parse_and_set_work_mode(struct phy_device *phydev)
> +{
> +	struct device_node *node;
> +	struct at803x_priv *priv;
> +	u32 value, work_mode;
> +	int ret;
> +
> +	node = phydev->mdio.dev.of_node;
> +	priv = phydev->priv;

Hi Luo Jie,

a minor nit from my side: priv is set but otherwise unused in this function.

> +
> +	/* The property "qcom,phy-work-mode" is only defined in one
> +	 * PHY device tree node.
> +	 */
> +	ret = of_property_read_u32(node, "qcom,phy-work-mode", &value);
> +	if (ret)
> +		return ret == -EINVAL ? 0 : ret;
> +
> +	switch (value) {
> +	case 0:
> +		work_mode = QCA8084_WORK_MODE_QXGMII;
> +		break;
> +	case 1:
> +		work_mode = QCA8084_WORK_MODE_QXGMII_PORT4_SGMII;
> +		break;
> +	case 2:
> +		work_mode = QCA8084_WORK_MODE_SWITCH;
> +		break;
> +	case 3:
> +		work_mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII;
> +		break;
> +	default:
> +		phydev_err(phydev, "invalid qcom,phy-work-mode %d\n", value);
> +		return -EINVAL;
> +	}
> +
> +	return qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG,
> +				  QCA8084_WORK_MODE_MASK,
> +				  FIELD_PREP(QCA8084_WORK_MODE_MASK, work_mode));
> +}

...
Re: [PATCH v8 13/14] net: phy: at803x: configure qca8084 work mode
Posted by Jie Luo 2 years ago

On 12/17/2023 9:02 PM, Simon Horman wrote:
> On Fri, Dec 15, 2023 at 03:40:03PM +0800, Luo Jie wrote:
> 
> ...
> 
>> @@ -1038,6 +1045,46 @@ static int qca8084_common_clock_init(struct phy_device *phydev)
>>   	return clk_prepare_enable(priv->clk[MDIO_MASTER_AHB_CLK]);
>>   }
>>   
>> +static int qca8084_parse_and_set_work_mode(struct phy_device *phydev)
>> +{
>> +	struct device_node *node;
>> +	struct at803x_priv *priv;
>> +	u32 value, work_mode;
>> +	int ret;
>> +
>> +	node = phydev->mdio.dev.of_node;
>> +	priv = phydev->priv;
> 
> Hi Luo Jie,
> 
> a minor nit from my side: priv is set but otherwise unused in this function.

Thanks Simon, i will update it to remove it.

> 
>> +
>> +	/* The property "qcom,phy-work-mode" is only defined in one
>> +	 * PHY device tree node.
>> +	 */
>> +	ret = of_property_read_u32(node, "qcom,phy-work-mode", &value);
>> +	if (ret)
>> +		return ret == -EINVAL ? 0 : ret;
>> +
>> +	switch (value) {
>> +	case 0:
>> +		work_mode = QCA8084_WORK_MODE_QXGMII;
>> +		break;
>> +	case 1:
>> +		work_mode = QCA8084_WORK_MODE_QXGMII_PORT4_SGMII;
>> +		break;
>> +	case 2:
>> +		work_mode = QCA8084_WORK_MODE_SWITCH;
>> +		break;
>> +	case 3:
>> +		work_mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII;
>> +		break;
>> +	default:
>> +		phydev_err(phydev, "invalid qcom,phy-work-mode %d\n", value);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG,
>> +				  QCA8084_WORK_MODE_MASK,
>> +				  FIELD_PREP(QCA8084_WORK_MODE_MASK, work_mode));
>> +}
> 
> ...