The branch main has been updated by mw:

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

commit 59061c7ebcaae90e59551320f641a762ae31080d
Author:     Marcin Wojtas <[email protected]>
AuthorDate: 2021-05-19 14:31:35 +0000
Commit:     Marcin Wojtas <[email protected]>
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 <[email protected]>
    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
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to