From owner-dev-commits-src-all@freebsd.org Thu Jun 24 11:12:42 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 680F56494BF; Thu, 24 Jun 2021 11:12:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4G9ctL23FMz3rZJ; Thu, 24 Jun 2021 11:12:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0BC3816E64; Thu, 24 Jun 2021 11:12:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 15OBCfCB065275; Thu, 24 Jun 2021 11:12:41 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 15OBCfKg065274; Thu, 24 Jun 2021 11:12:41 GMT (envelope-from git) Date: Thu, 24 Jun 2021 11:12:41 GMT Message-Id: <202106241112.15OBCfKg065274@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Marcin Wojtas Subject: git: 59061c7ebcaa - main - Introduce MDIO read/write functions for LS1028A. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mw X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 59061c7ebcaae90e59551320f641a762ae31080d Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Jun 2021 11:12:42 -0000 The branch main has been updated by mw: URL: https://cgit.FreeBSD.org/src/commit/?id=59061c7ebcaae90e59551320f641a762ae31080d commit 59061c7ebcaae90e59551320f641a762ae31080d Author: Marcin Wojtas AuthorDate: 2021-05-19 14:31:35 +0000 Commit: Marcin Wojtas 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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