diff mbox series

[v1,1/6] net: mv88e61xx: Add support for checking addressing mode

Message ID 20230601100005.2216345-2-lukma@denx.de
State Changes Requested
Delegated to: Ramon Fried
Headers show
Series Provide support for mv88e6020 Marvell switch | expand

Commit Message

Lukasz Majewski June 1, 2023, 10 a.m. UTC
Some Marvell switch devices are dual chip ones, like mv88e6020, which
use direct MDIO addressing to access its ports' registers. Such approach
allows connecting two such devices in a single MDIO bus with simple
addressing scheme.

Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
---

 drivers/net/phy/mv88e61xx.c | 42 +++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 85778106eddc..31f9b57456d6 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -194,6 +194,7 @@  struct mv88e61xx_phy_priv {
 	u8 phy_ctrl1_en_det_shift; /* 'EDet' bit field offset */
 	u8 phy_ctrl1_en_det_width; /* Width of 'EDet' bit field */
 	u8 phy_ctrl1_en_det_ctrl;  /* 'EDet' control value */
+	u8 direct_access;          /* Access switch device directly */
 };
 
 static inline int smi_cmd(int cmd, int addr, int reg)
@@ -920,6 +921,40 @@  static int mv88e61xx_priv_reg_offs_pre_init(struct phy_device *phydev)
 	return -ENODEV;
 }
 
+static int mv88e61xx_check_addressing(struct phy_device *phydev)
+{
+	if (!CONFIG_IS_ENABLED(OF_CONTROL))
+		return 0;
+
+	/*
+	 * Some devices - like mv88e6020 are dual chip - i.e. two
+	 * such devices can be directly accessed via SMI bus.
+	 * The addressing depends on R0_LED/ADDR4 pin value duing
+	 * bootstrap.
+	 *
+	 * This means that there is no need for indirect access.
+	 */
+	struct mv88e61xx_phy_priv *priv = phydev->priv;
+
+	/*
+	 * As this function is called very early and hence the phydev
+	 * is not yet initialized we use aliast and DTS to asses if
+	 * device shall be directly accessed or not.
+	 */
+	ofnode sw0;
+	int ret;
+
+	sw0 = ofnode_get_aliases_node("switch0");
+	if (!ofnode_valid(sw0))
+		return -ENODEV;
+
+	ret = ofnode_device_is_compatible(sw0, "marvell,mv88e6020");
+	if (ret)
+		priv->direct_access = 1;
+
+	return 0;
+}
+
 static int mv88e61xx_probe(struct phy_device *phydev)
 {
 	struct mii_dev *smi_wrapper;
@@ -974,6 +1009,8 @@  static int mv88e61xx_probe(struct phy_device *phydev)
 
 	phydev->priv = priv;
 
+	mv88e61xx_check_addressing(phydev);
+
 	res = mv88e61xx_priv_reg_offs_pre_init(phydev);
 	if (res < 0)
 		return res;
@@ -1180,6 +1217,11 @@  int get_phy_id(struct mii_dev *bus, int smi_addr, int devad, u32 *phy_id)
 	temp_phy.priv = &temp_priv;
 	temp_mii.priv = &temp_phy;
 
+	mv88e61xx_check_addressing(&temp_phy);
+	/* For direct access the phy address equals to smi_addr */
+	if (temp_priv.direct_access)
+		temp_phy.addr = smi_addr;
+
 	/*
 	 * get_phy_id() can be called by framework before mv88e61xx driver
 	 * probing, in this case the global register offsets are not