Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Jun 2021 11:12:41 GMT
From:      Marcin Wojtas <mw@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 59061c7ebcaa - main - Introduce MDIO read/write functions for LS1028A.
Message-ID:  <202106241112.15OBCfKg065274@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mw:

URL: https://cgit.FreeBSD.org/src/commit/?id=59061c7ebcaae90e59551320f641a762ae31080d

commit 59061c7ebcaae90e59551320f641a762ae31080d
Author:     Marcin Wojtas <mw@FreeBSD.org>
AuthorDate: 2021-05-19 14:31:35 +0000
Commit:     Marcin Wojtas <mw@FreeBSD.org>
CommitDate: 2021-06-24 11:01:05 +0000

    Introduce MDIO read/write functions for LS1028A.
    
    Provide common MDIO code for two LS1028 ENETC controllers -
    an external one found on the PCI bus and internal one found in ENETC.
    
    Submitted by: Lukasz Hajec <lha@semihalf.com>
    Reviewed by: manu
    Obtained from: Semihalf
    Sponsored by: Alstom Group
    Differential Revision: https://reviews.freebsd.org/D30730
---
 sys/dev/enetc/enetc_mdio.c | 155 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/enetc/enetc_mdio.h |  58 +++++++++++++++++
 2 files changed, 213 insertions(+)

diff --git a/sys/dev/enetc/enetc_mdio.c b/sys/dev/enetc/enetc_mdio.c
new file mode 100644
index 000000000000..c998f31a041d
--- /dev/null
+++ b/sys/dev/enetc/enetc_mdio.c
@@ -0,0 +1,155 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Alstom Group.
+ * Copyright (c) 2021 Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/enetc/enetc_hw.h>
+#include <dev/enetc/enetc_mdio.h>
+
+#define ENETC_MDIO_RD4(regs, base, off) \
+	bus_read_4((regs), (base) + (off))
+#define ENETC_MDIO_WR4(regs, base, off, value) \
+	bus_write_4((regs), (base) + (off), (value))
+
+static int
+enetc_mdio_wait(struct resource *regs, int mdio_base)
+{
+	int i;
+	uint32_t val;
+
+	i = 0;
+	do {
+		DELAY(100);
+		val = ENETC_MDIO_RD4(regs, mdio_base, ENETC_MDIO_CFG);
+		if ((val & MDIO_CFG_BSY) == 0)
+			return (0);
+	} while (i++ < ENETC_TIMEOUT);
+
+	return (ETIMEDOUT);
+}
+
+int
+enetc_mdio_read(struct resource *regs, int mdio_base, int phy, int reg)
+{
+	uint32_t mdio_cfg, mdio_ctl;
+	uint16_t dev_addr;
+
+	mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
+	if (reg & MII_ADDR_C45) {
+		/* clause 45 */
+		dev_addr = (reg >> 16) & 0x1f;
+		mdio_cfg |= MDIO_CFG_ENC45;
+	} else {
+		/* clause 22 */
+		dev_addr = reg & 0x1f;
+		mdio_cfg &= ~MDIO_CFG_ENC45;
+	}
+
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_CFG, mdio_cfg);
+
+	if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+		return (EIO);
+
+	/* Set port and device addr. */
+	mdio_ctl = MDIO_CTL_PORT_ADDR(phy) | MDIO_CTL_DEV_ADDR(dev_addr);
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_CTL, mdio_ctl);
+
+	/* Set the register address. */
+	if (reg & MII_ADDR_C45) {
+		ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_ADDR, reg & 0xffff);
+
+		if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+			return (EIO);
+	}
+
+	/* Initiate the read. */
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
+
+	if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+		return (EIO);
+
+	/* Check if any error occurred while reading PHY register. */
+	if (ENETC_MDIO_RD4(regs, mdio_base, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER)
+		return (ENXIO);
+
+	return (MDIO_DATA(ENETC_MDIO_RD4(regs, mdio_base, ENETC_MDIO_DATA)));
+}
+
+int
+enetc_mdio_write(struct resource *regs, int mdio_base, int phy, int reg,
+    int data)
+{
+	uint32_t mdio_cfg, mdio_ctl;
+	uint16_t dev_addr;
+
+	mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
+	if (reg & MII_ADDR_C45) {
+		/* clause 45 */
+		dev_addr = (reg >> 16) & 0x1f;
+		mdio_cfg |= MDIO_CFG_ENC45;
+	} else {
+		/* clause 22 */
+		dev_addr = reg & 0x1f;
+		mdio_cfg &= ~MDIO_CFG_ENC45;
+	}
+
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_CFG, mdio_cfg);
+
+	if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+		return (EIO);
+
+	/* Set port and device addr. */
+	mdio_ctl = MDIO_CTL_PORT_ADDR(phy) | MDIO_CTL_DEV_ADDR(dev_addr);
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_CTL, mdio_ctl);
+
+	/* Set the register address. */
+	if (reg & MII_ADDR_C45) {
+		ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_ADDR, reg & 0xffff);
+
+		if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+			return (EIO);
+	}
+
+	/* Write the value. */
+	ENETC_MDIO_WR4(regs, mdio_base, ENETC_MDIO_DATA, MDIO_DATA(data));
+
+	if (enetc_mdio_wait(regs, mdio_base) == ETIMEDOUT)
+		return (EIO);
+
+	return (0);
+}
diff --git a/sys/dev/enetc/enetc_mdio.h b/sys/dev/enetc/enetc_mdio.h
new file mode 100644
index 000000000000..782748a6fd88
--- /dev/null
+++ b/sys/dev/enetc/enetc_mdio.h
@@ -0,0 +1,58 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Alstom Group.
+ * Copyright (c) 2021 Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ENETC_MDIO_H_
+#define _ENETC_MDIO_H_
+
+/* MDIO registers */
+#define ENETC_MDIO_CFG		0x0	/* MDIO configuration and status */
+#define MDIO_CFG_CLKDIV(x)	((((x) >> 1) & 0xff) << 8)
+
+#define ENETC_MDIO_CTL		0x4	/* MDIO control */
+#define MDIO_CTL_DEV_ADDR(x)	((x) & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x)	(((x) & 0x1f) << 5)
+
+#define ENETC_MDIO_DATA		0x8	/* MDIO data */
+#define MDIO_DATA(x)		((x) & 0xffff)
+
+#define ENETC_MDIO_ADDR		0xc	/* MDIO address */
+
+#define MDIO_CFG_BSY		BIT(0)
+#define MDIO_CFG_RD_ER		BIT(1)
+#define MDIO_CFG_ENC45		BIT(6)
+#define MDIO_CFG_NEG		BIT(23)
+#define MDIO_CTL_READ		BIT(15)
+#define MII_ADDR_C45		BIT(30)
+
+/* MDIO configuration and helpers */
+#define ENETC_MDC_DIV		258
+#define ENETC_TIMEOUT		1000
+
+int enetc_mdio_write(struct resource*, int, int, int, int);
+int enetc_mdio_read(struct resource*, int, int, int);
+
+#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106241112.15OBCfKg065274>