Thread (9 messages) flat view 9 messages, 4 authors, 2019-08-21

Re: [PATCH net-next 1/1] fec: add C45 MDIO read/write support

From: Marco Hartmann <hidden>
Date: 2019-08-21 11:45:08
Also in: lkml

On 20.08.19 04:08, Andy Duan wrote:
From: Marco Hartmann Sent: Tuesday, August 20, 2019 1:11 AM
quoted
IEEE 802.3ae clause 45 defines a modified MDIO protocol that uses a two
staged access model in order to increase the address space.

This patch adds support for C45 MDIO read and write accesses, which are
used whenever the MII_ADDR_C45 flag in the regnum argument is set.
In case it is not set, C22 accesses are used as before.

Co-developed-by: Christian Herber <redacted>
Signed-off-by: Christian Herber <redacted>
Signed-off-by: Marco Hartmann <redacted>
---
  drivers/net/ethernet/freescale/fec_main.c | 65
++++++++++++++++++++++++++++---
  1 file changed, 59 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c
b/drivers/net/ethernet/freescale/fec_main.c
index c01d3ec3e9af..73f8f9a149a1 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -208,8 +208,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
MAC address");

  /* FEC MII MMFR bits definition */
  #define FEC_MMFR_ST		(1 << 30)
+#define FEC_MMFR_ST_C45		(0)
  #define FEC_MMFR_OP_READ	(2 << 28)
+#define FEC_MMFR_OP_READ_C45	(3 << 28)
  #define FEC_MMFR_OP_WRITE	(1 << 28)
+#define FEC_MMFR_OP_ADDR_WRITE	(0)
  #define FEC_MMFR_PA(v)		((v & 0x1f) << 23)
  #define FEC_MMFR_RA(v)		((v & 0x1f) << 18)
  #define FEC_MMFR_TA		(2 << 16)
@@ -1767,7 +1770,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus,
int mii_id, int regnum)
  	struct fec_enet_private *fep = bus->priv;
  	struct device *dev = &fep->pdev->dev;
  	unsigned long time_left;
-	int ret = 0;
+	int ret = 0, frame_start, frame_addr, frame_op;
Add bool variable:

bool is_c45 = !!(regnum & MII_ADDR_C45);
quoted
  	ret = pm_runtime_get_sync(dev);
  	if (ret < 0)
@@ -1775,9 +1778,36 @@ static int fec_enet_mdio_read(struct mii_bus
*bus, int mii_id, int regnum)

  	reinit_completion(&fep->mdio_done);

+	if (MII_ADDR_C45 & regnum) {
if (is_c45)
quoted
+		frame_start = FEC_MMFR_ST_C45;
+
+		/* write address */
+		frame_addr = (regnum >> 16);
+		writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
+		       FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
+		       FEC_MMFR_TA | (regnum & 0xFFFF),
+		       fep->hwp + FEC_MII_DATA);
+
+		/* wait for end of transfer */
+		time_left = wait_for_completion_timeout(&fep->mdio_done,
+				usecs_to_jiffies(FEC_MII_TIMEOUT));
+		if (time_left == 0) {
+			netdev_err(fep->netdev, "MDIO address write timeout\n");
+			ret  = -ETIMEDOUT;
Should be:
goto out;
quoted
+		}
+
+		frame_op = FEC_MMFR_OP_READ_C45;
+
+	} else {
+		/* C22 read */
+		frame_op = FEC_MMFR_OP_READ;
+		frame_start = FEC_MMFR_ST;
+		frame_addr = regnum;
+	}
+
  	/* start a read op */
-	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
-		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
+	writel(frame_start | frame_op |
+		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
  		FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);

  	/* wait for end of transfer */
@@ -1804,7 +1834,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus,
int mii_id, int regnum,
  	struct fec_enet_private *fep = bus->priv;
  	struct device *dev = &fep->pdev->dev;
  	unsigned long time_left;
-	int ret;
+	int ret, frame_start, frame_addr;

  	ret = pm_runtime_get_sync(dev);
  	if (ret < 0)
@@ -1814,9 +1844,32 @@ static int fec_enet_mdio_write(struct mii_bus
*bus, int mii_id, int regnum,
bool is_c45 = !!(regnum & MII_ADDR_C45);
quoted
  	reinit_completion(&fep->mdio_done);

+	if (MII_ADDR_C45 & regnum) {
if (!is_c45) {
quoted
+		frame_start = FEC_MMFR_ST_C45;
+
+		/* write address */
+		frame_addr = (regnum >> 16);
+		writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
+		       FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
+		       FEC_MMFR_TA | (regnum & 0xFFFF),
+		       fep->hwp + FEC_MII_DATA);
+
+		/* wait for end of transfer */
+		time_left = wait_for_completion_timeout(&fep->mdio_done,
+			usecs_to_jiffies(FEC_MII_TIMEOUT));
+		if (time_left == 0) {
+			netdev_err(fep->netdev, "MDIO address write timeout\n");
+			ret  = -ETIMEDOUT;
Like mdio read, it should be:
goto out;
quoted
+		}
+	} else {
+		/* C22 write */
+		frame_start = FEC_MMFR_ST;
+		frame_addr = regnum;
+	}
+
  	/* start a write op */
-	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
-		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
+	writel(frame_start | FEC_MMFR_OP_WRITE |
+		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
  		FEC_MMFR_TA | FEC_MMFR_DATA(value),
  		fep->hwp + FEC_MII_DATA);

--
2.7.4
Thank you for your feedback,
the fixes are included in v2 of the patch.

Regards,
Marco
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help