From nobody Fri Feb 04 05:28:24 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id B2DFD19B1A56; Fri, 4 Feb 2022 05:28:25 +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 4JqkbF28lVz3Qfn; Fri, 4 Feb 2022 05:28:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1643952505; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e0pfFIUUWAcBR52vpmkGlyXAISY4SP9USrRk6d3+tVo=; b=GiqsSz9Wz3biMWik3AZPjHsJMUiRkCJgEP5Bq2z7/5IGM+j3NyJ97Fn2DnYn3qAoGZtsm8 +UFW0PM1zbNtDmuxyNbJtcoO1CUjUkV6TbiTl7QgUgSKTQVsGDhYa9u5EOs9A9X8fFT3zk Nu0AwX2Em+JmJWzJ00lPXqNmrX4OjoyKIpp1fk21iLuyeb8DhsESpplbGFVhuu/z5P7EH6 UJqB53J9l/tckuHc9dA4N3SnLHNWjmmgAlsgC/2WFTlZ+9lOlKlV45pvihEDq7cvm06A3u /7di/LORKzR8c1CzH0sqEou6SPm16tMeio6345Y/vW+DTS0skSraq+wn5LGT6g== 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 DCB7C25C5F; Fri, 4 Feb 2022 05:28:24 +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 2145SOfU031363; Fri, 4 Feb 2022 05:28:24 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2145SO2U031362; Fri, 4 Feb 2022 05:28:24 GMT (envelope-from git) Date: Fri, 4 Feb 2022 05:28:24 GMT Message-Id: <202202040528.2145SO2U031362@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: e388de98bd02 - main - ar40xx_switch: add initial switch for the IPQ4018/IPQ4019. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e388de98bd0272b4ba237dcd44dcf12360d70d41 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1643952505; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e0pfFIUUWAcBR52vpmkGlyXAISY4SP9USrRk6d3+tVo=; b=I8W7uVdsAXlSomrkPuNI9eno1HIgMi5j25pS1KhYrkPZXlubZJvbr/ADr+mbv7QdxWv/dP YlU8nhGOQr34+sfS1tjbF86tcLWnNxcQh/5t7X3PMNmlBMdo69u4D5GSca8bQzLXYgHtz/ CTAi56veN5LlcJlhFe6/xoZGHg26avk+k4s94hWZmq6/i9NzCEN82Trg5TO8GPAqqe0m+H W2JXPZeDn0D3Xa9BFmYUvhdaF8KjywovDrxvApfOcGXPpF9MdpMbgVaPogDEXm8GTM9C0t a29Po5CmKRwnqMBwETyHwjOhkw/GMpmJXpJzQTLlgjjQ+f9zVsTBPjtZLjjd8Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1643952505; a=rsa-sha256; cv=none; b=npwCdO4wjq3sa4rtjuODQTr/G2laeHxFexdI5ztmsIuSyHm0ubq4kUtwKARSUwV3O3zw72 BCDI+OqI7C9Gzk/J7QHTdUw6uxFve3fUl/ygPMlVqBM/QWcSmzVo88G/JehJPzHsZAd3fI d0FLigOM2WDZiK8uzaMP+roXoOEsUjy/xJeXteEvcABvGbpB53B7VuGXTZTpsJASuS2l1X 10MYv7bFCP5Ot+F42xhCeT70bUUly4N95YXdId7O6m+LtFEnXpmZIs9ldia4tzwLMEzRcr ficWnYw3pR3IxBNBNWvNYymxSggaoWlsTG0xaWe57EY2w4ehh+Lm4UZ/zTv6lA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=e388de98bd0272b4ba237dcd44dcf12360d70d41 commit e388de98bd0272b4ba237dcd44dcf12360d70d41 Author: Adrian Chadd AuthorDate: 2022-01-30 03:04:19 +0000 Commit: Adrian Chadd CommitDate: 2022-02-04 05:27:13 +0000 ar40xx_switch: add initial switch for the IPQ4018/IPQ4019. Summary: This switch is based off of the AR8327/AR8337 external switch/PHY. However unlike the AR8327/AR8337 it itself doesn't have any PHYs; instead an external PHY connects to it using the PSGMII port. Differential Revision: https://reviews.freebsd.org/D34112 Reviewed by: manu This code is inspired by the ar40xx code in openwrt, which itself is based on the Qualcomm QCA-SSDK. Both of these sources are, amusingly, BSD licenced - and thus I have included some of the comments in the hardware workaround paths to document some of the magic numbers. --- sys/arm/conf/std.qca | 2 + sys/arm/qualcomm/std.ipq4018 | 21 + sys/dev/etherswitch/ar40xx/ar40xx_debug.h | 44 ++ sys/dev/etherswitch/ar40xx/ar40xx_hw.c | 357 ++++++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw.h | 42 ++ sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.c | 216 ++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.h | 37 + sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.c | 129 ++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.h | 40 ++ sys/dev/etherswitch/ar40xx/ar40xx_hw_mib.c | 194 ++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_mib.h | 36 + sys/dev/etherswitch/ar40xx/ar40xx_hw_mirror.c | 132 ++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_mirror.h | 33 + sys/dev/etherswitch/ar40xx/ar40xx_hw_port.c | 287 ++++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_port.h | 42 ++ sys/dev/etherswitch/ar40xx/ar40xx_hw_psgmii.c | 437 ++++++++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_psgmii.h | 41 ++ sys/dev/etherswitch/ar40xx/ar40xx_hw_vtu.c | 196 ++++++ sys/dev/etherswitch/ar40xx/ar40xx_hw_vtu.h | 39 ++ sys/dev/etherswitch/ar40xx/ar40xx_main.c | 968 ++++++++++++++++++++++++++ sys/dev/etherswitch/ar40xx/ar40xx_phy.c | 252 +++++++ sys/dev/etherswitch/ar40xx/ar40xx_phy.h | 39 ++ sys/dev/etherswitch/ar40xx/ar40xx_reg.h | 348 +++++++++ sys/dev/etherswitch/ar40xx/ar40xx_var.h | 135 ++++ 24 files changed, 4067 insertions(+) diff --git a/sys/arm/conf/std.qca b/sys/arm/conf/std.qca index e7cfe58c6d5d..b7bd2729a0dc 100644 --- a/sys/arm/conf/std.qca +++ b/sys/arm/conf/std.qca @@ -78,3 +78,5 @@ device mdio device mii device miibus device qcom_mdio_ipq4018 +device etherswitch +device ar40xx_switch diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 index 8e8108669ac8..e6719efb9bce 100644 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -6,6 +6,27 @@ arm/qualcomm/qcom_cpu_kpssv2.c optional smp arm/qualcomm/ipq4018_usb_hs_phy.c optional qcom_ipq4018_hs_usbphy arm/qualcomm/ipq4018_usb_ss_phy.c optional qcom_ipq4018_ss_usbphy +dev/etherswitch/ar40xx/ar40xx_main.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_phy.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_atu.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_port.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_psgmii.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_mib.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_mirror.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_vtu.c \ + optional mdio etherswitch ar40xx_switch +dev/etherswitch/ar40xx/ar40xx_hw_mdio.c \ + optional mdio etherswitch ar40xx_switch + dev/qcom_dwc3/qcom_dwc3.c optional qcom_dwc3 dev/qcom_rnd/qcom_rnd.c optional qcom_rnd diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_debug.h b/sys/dev/etherswitch/ar40xx/ar40xx_debug.h new file mode 100644 index 000000000000..0aa5524dab71 --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_debug.h @@ -0,0 +1,44 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 __AR40XX_DEBUG_H__ +#define __AR40XX_DEBUG_H__ + +#define AR40XX_DBG_HW_INIT 0x00000001 +#define AR40XX_DBG_HW_RESET 0x00000002 +#define AR40XX_DBG_HW_PORT_INIT 0x00000004 +#define AR40XX_DBG_VTU_OP 0x00000008 +#define AR40XX_DBG_ATU_OP 0x00000010 +#define AR40XX_DBG_PORT_STATUS 0x00000020 + +#define AR40XX_DPRINTF(sc, flags, ...) \ + do { \ + if ((sc)->sc_debug & (flags)) \ + device_printf((sc)->sc_dev, __VA_ARGS__); \ + } while (0) + +#endif /* __AR40XX_DEBUG_H__ */ diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw.c b/sys/dev/etherswitch/ar40xx/ar40xx_hw.c new file mode 100644 index 000000000000..d932b8edc16a --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw.c @@ -0,0 +1,357 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* + * XXX these are here for now; move the code using these + * into main.c once this is all done! + */ +#include +#include +#include + +#include "mdio_if.h" +#include "miibus_if.h" +#include "etherswitch_if.h" + +/* + * Reset the ESS switch. This also resets the ESS ethernet + * and PSGMII block. + */ +int +ar40xx_hw_ess_reset(struct ar40xx_softc *sc) +{ + int ret; + + AR40XX_DPRINTF(sc, AR40XX_DBG_HW_RESET, "%s: called\n", __func__); + + ret = hwreset_assert(sc->sc_ess_rst); + if (ret != 0) { + device_printf(sc->sc_dev, "ERROR: failed to assert reset\n"); + return ret; + } + DELAY(10*1000); + + ret = hwreset_deassert(sc->sc_ess_rst); + if (ret != 0) { + device_printf(sc->sc_dev, + "ERROR: failed to deassert reset\n"); + return ret; + } + + DELAY(10*1000); + + return (0); +} + +int +ar40xx_hw_init_globals(struct ar40xx_softc *sc) +{ + uint32_t reg; + + AR40XX_DPRINTF(sc, AR40XX_DBG_HW_INIT, "%s: called\n", __func__); + + /* enable CPU port and disable mirror port */ + reg = AR40XX_FWD_CTRL0_CPU_PORT_EN + | AR40XX_FWD_CTRL0_MIRROR_PORT; + AR40XX_REG_WRITE(sc, AR40XX_REG_FWD_CTRL0, reg); + + /* forward multicast and broadcast frames to CPU */ + reg = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) + | (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) + | (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); + AR40XX_REG_WRITE(sc, AR40XX_REG_FWD_CTRL1, reg); + + /* enable jumbo frames */ + reg = AR40XX_REG_READ(sc, AR40XX_REG_MAX_FRAME_SIZE); + reg &= ~AR40XX_MAX_FRAME_SIZE_MTU; + reg |= 9018 + 8 + 2; + AR40XX_REG_WRITE(sc, AR40XX_REG_MAX_FRAME_SIZE, reg); + + /* Enable MIB counters */ + reg = AR40XX_REG_READ(sc, AR40XX_REG_MODULE_EN); + reg |= AR40XX_MODULE_EN_MIB; + AR40XX_REG_WRITE(sc, AR40XX_REG_MODULE_EN, reg); + + /* Disable AZ */ + AR40XX_REG_WRITE(sc, AR40XX_REG_EEE_CTRL, 0); + + /* set flowctrl thershold for cpu port */ + reg = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) + | AR40XX_PORT0_FC_THRESH_OFF_DFLT; + AR40XX_REG_WRITE(sc, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), reg); + + AR40XX_REG_BARRIER_WRITE(sc); + + return (0); +} + +int +ar40xx_hw_vlan_init(struct ar40xx_softc *sc) +{ + int i; + + AR40XX_DPRINTF(sc, AR40XX_DBG_HW_INIT, "%s: called\n", __func__); + + /* Enable VLANs by default */ + sc->sc_vlan.vlan = 1; + + /* Configure initial LAN/WAN bitmap and include CPU port as tagged */ + sc->sc_vlan.vlan_id[AR40XX_LAN_VLAN] = AR40XX_LAN_VLAN + | ETHERSWITCH_VID_VALID; + sc->sc_vlan.vlan_id[AR40XX_WAN_VLAN] = AR40XX_WAN_VLAN + | ETHERSWITCH_VID_VALID; + + sc->sc_vlan.vlan_ports[AR40XX_LAN_VLAN] = + sc->sc_config.switch_cpu_bmp | sc->sc_config.switch_lan_bmp; + sc->sc_vlan.vlan_untagged[AR40XX_LAN_VLAN] = + sc->sc_config.switch_lan_bmp; + + sc->sc_vlan.vlan_ports[AR40XX_WAN_VLAN] = + sc->sc_config.switch_cpu_bmp | sc->sc_config.switch_wan_bmp; + sc->sc_vlan.vlan_untagged[AR40XX_WAN_VLAN] = + sc->sc_config.switch_wan_bmp; + + /* Populate the per-port PVID - pvid[] is an index into vlan_id[] */ + for (i = 0; i < AR40XX_NUM_PORTS; i++) { + if (sc->sc_config.switch_lan_bmp & (1U << i)) + sc->sc_vlan.pvid[i] = AR40XX_LAN_VLAN; + if (sc->sc_config.switch_wan_bmp & (1U << i)) + sc->sc_vlan.pvid[i] = AR40XX_WAN_VLAN; + } + + return (0); +} + +/* + * Apply the per-port and global configuration from software. + * + * This is useful if we ever start doing the linux switch framework + * thing of updating the config in one hit and pushing it to the + * hardware. For now it's just used in the reset path. + */ +int +ar40xx_hw_sw_hw_apply(struct ar40xx_softc *sc) +{ + uint8_t portmask[AR40XX_NUM_PORTS]; + int i, j, ret; + + AR40XX_DPRINTF(sc, AR40XX_DBG_HW_INIT, "%s: called\n", __func__); + + /* + * Flush the VTU configuration. + */ + ret = ar40xx_hw_vtu_flush(sc); + if (ret != 0) { + device_printf(sc->sc_dev, + "ERROR: couldn't apply config; vtu flush failed (%d)\n", + ret); + return (ret); + } + + memset(portmask, 0, sizeof(portmask)); + + /* + * Configure the ports based on whether it's 802.1q + * VLANs, or just straight up per-port VLANs. + */ + if (sc->sc_vlan.vlan) { + device_printf(sc->sc_dev, "%s: configuring 802.1q VLANs\n", + __func__); + for (j = 0; j < AR40XX_NUM_VTU_ENTRIES; j++) { + uint8_t vp = sc->sc_vlan.vlan_ports[j]; + + if (!vp) + continue; + if ((sc->sc_vlan.vlan_id[j] + & ETHERSWITCH_VID_VALID) == 0) + continue; + + for (i = 0; i < AR40XX_NUM_PORTS; i++) { + uint8_t mask = (1U << i); + + if (vp & mask) + portmask[i] |= vp & ~mask; + } + + ar40xx_hw_vtu_load_vlan(sc, + sc->sc_vlan.vlan_id[j] & ETHERSWITCH_VID_MASK, + sc->sc_vlan.vlan_ports[j], + sc->sc_vlan.vlan_untagged[j]); + } + } else { + device_printf(sc->sc_dev, "%s: configuring per-port VLANs\n", + __func__); + for (i = 0; i < AR40XX_NUM_PORTS; i++) { + if (i == AR40XX_PORT_CPU) + continue; + + portmask[i] = (1U << AR40XX_PORT_CPU); + portmask[AR40XX_PORT_CPU] |= (1U << i); + } + } + + /* + * Update per-port destination mask, vlan tag settings + */ + for (i = 0; i < AR40XX_NUM_PORTS; i++) + (void) ar40xx_hw_port_setup(sc, i, portmask[i]); + + /* Set the mirror register config */ + ret = ar40xx_hw_mirror_set_registers(sc); + if (ret != 0) { + device_printf(sc->sc_dev, + "ERROR: couldn't apply config; mirror config failed" + " (%d)\n", + ret); + return (ret); + } + + return (0); +} + +int +ar40xx_hw_wait_bit(struct ar40xx_softc *sc, int reg, uint32_t mask, + uint32_t val) +{ + int timeout = 20; + uint32_t t; + + while (true) { + AR40XX_REG_BARRIER_READ(sc); + t = AR40XX_REG_READ(sc, reg); + if ((t & mask) == val) + return 0; + + if (timeout-- <= 0) + break; + + DELAY(20); + } + + device_printf(sc->sc_dev, "ERROR: timeout for reg " + "%08x: %08x & %08x != %08x\n", + (unsigned int)reg, t, mask, val); + return (ETIMEDOUT); +} + +/* + * Read the switch MAC address. + */ +int +ar40xx_hw_read_switch_mac_address(struct ar40xx_softc *sc, + struct ether_addr *ea) +{ + uint32_t ret0, ret1; + char *s; + + s = (void *) ea; + + AR40XX_LOCK_ASSERT(sc); + + AR40XX_REG_BARRIER_READ(sc); + ret0 = AR40XX_REG_READ(sc, AR40XX_REG_SW_MAC_ADDR0); + ret1 = AR40XX_REG_READ(sc, AR40XX_REG_SW_MAC_ADDR1); + + s[5] = MS(ret0, AR40XX_REG_SW_MAC_ADDR0_BYTE5); + s[4] = MS(ret0, AR40XX_REG_SW_MAC_ADDR0_BYTE4); + s[3] = MS(ret1, AR40XX_REG_SW_MAC_ADDR1_BYTE3); + s[2] = MS(ret1, AR40XX_REG_SW_MAC_ADDR1_BYTE2); + s[1] = MS(ret1, AR40XX_REG_SW_MAC_ADDR1_BYTE1); + s[0] = MS(ret1, AR40XX_REG_SW_MAC_ADDR1_BYTE0); + + return (0); +} + +/* + * Set the switch MAC address. + */ +int +ar40xx_hw_write_switch_mac_address(struct ar40xx_softc *sc, + struct ether_addr *ea) +{ + uint32_t ret0 = 0, ret1 = 0; + char *s; + + s = (void *) ea; + + AR40XX_LOCK_ASSERT(sc); + + ret0 |= SM(s[5], AR40XX_REG_SW_MAC_ADDR0_BYTE5); + ret0 |= SM(s[4], AR40XX_REG_SW_MAC_ADDR0_BYTE4); + + ret1 |= SM(s[3], AR40XX_REG_SW_MAC_ADDR1_BYTE3); + ret1 |= SM(s[2], AR40XX_REG_SW_MAC_ADDR1_BYTE2); + ret1 |= SM(s[1], AR40XX_REG_SW_MAC_ADDR1_BYTE1); + ret1 |= SM(s[0], AR40XX_REG_SW_MAC_ADDR1_BYTE0); + + AR40XX_REG_WRITE(sc, AR40XX_REG_SW_MAC_ADDR0, ret0); + AR40XX_REG_WRITE(sc, AR40XX_REG_SW_MAC_ADDR1, ret1); + + AR40XX_REG_BARRIER_WRITE(sc); + + return (0); +} diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw.h b/sys/dev/etherswitch/ar40xx/ar40xx_hw.h new file mode 100644 index 000000000000..75ef4f63c7a7 --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw.h @@ -0,0 +1,42 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 __AR40XX_HW_H__ +#define __AR40XX_HW_H__ + +extern int ar40xx_hw_ess_reset(struct ar40xx_softc *sc); +extern int ar40xx_hw_init_globals(struct ar40xx_softc *sc); +extern int ar40xx_hw_vlan_init(struct ar40xx_softc *sc); +extern int ar40xx_hw_sw_hw_apply(struct ar40xx_softc *sc); +extern int ar40xx_hw_wait_bit(struct ar40xx_softc *sc, int reg, + uint32_t mask, uint32_t val); +extern int ar40xx_hw_read_switch_mac_address(struct ar40xx_softc *sc, + struct ether_addr *ea); +extern int ar40xx_hw_write_switch_mac_address(struct ar40xx_softc *sc, + struct ether_addr *ea); + +#endif /* __AR40XX_HW_H__ */ + diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.c b/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.c new file mode 100644 index 000000000000..09ac9e134d73 --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.c @@ -0,0 +1,216 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "mdio_if.h" +#include "miibus_if.h" +#include "etherswitch_if.h" + +int +ar40xx_hw_atu_wait_busy(struct ar40xx_softc *sc) +{ + int ret; + + ret = ar40xx_hw_wait_bit(sc, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_BUSY, 0); + return (ret); +} + +int +ar40xx_hw_atu_flush_all(struct ar40xx_softc *sc) +{ + int ret; + + AR40XX_LOCK_ASSERT(sc); + + AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, "%s: called\n", __func__); + ret = ar40xx_hw_atu_wait_busy(sc); + if (ret != 0) + return (ret); + + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_OP_FLUSH + | AR40XX_ATU_FUNC_BUSY); + AR40XX_REG_BARRIER_WRITE(sc); + + return (ret); +} + +int +ar40xx_hw_atu_flush_port(struct ar40xx_softc *sc, int port) +{ + uint32_t val; + int ret; + + AR40XX_LOCK_ASSERT(sc); + + AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, "%s: called, port=%d\n", + __func__, port); + + if (port >= AR40XX_NUM_PORTS) { + return (EINVAL); + } + + ret = ar40xx_hw_atu_wait_busy(sc); + if (ret != 0) + return (ret); + + val = AR40XX_ATU_FUNC_OP_FLUSH_UNICAST; + val |= (port << AR40XX_ATU_FUNC_PORT_NUM_S) + & AR40XX_ATU_FUNC_PORT_NUM; + + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC, + val | AR40XX_ATU_FUNC_BUSY); + AR40XX_REG_BARRIER_WRITE(sc); + + return (0); +} + +int +ar40xx_hw_atu_fetch_entry(struct ar40xx_softc *sc, etherswitch_atu_entry_t *e, + int atu_fetch_op) +{ + uint32_t ret0, ret1, ret2, val; + int ret; + + AR40XX_LOCK_ASSERT(sc); + + switch (atu_fetch_op) { + case 0: + /* Initialise things for the first fetch */ + + AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, + "%s: initializing\n", __func__); + + ret = ar40xx_hw_atu_wait_busy(sc); + if (ret != 0) + return (ret); + + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_OP_GET_NEXT); + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA0, 0); + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA1, 0); + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_DATA2, 0); + AR40XX_REG_BARRIER_WRITE(sc); + + return (0); + case 1: + AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, + "%s: reading next\n", __func__); + /* + * Attempt to read the next address entry; don't modify what + * is there in these registers as its used for the next fetch + */ + ret = ar40xx_hw_atu_wait_busy(sc); + if (ret != 0) + return (ret); + + /* Begin the next read event; not modifying anything */ + AR40XX_REG_BARRIER_READ(sc); + val = AR40XX_REG_READ(sc, AR40XX_REG_ATU_FUNC); + val |= AR40XX_ATU_FUNC_BUSY; + AR40XX_REG_WRITE(sc, AR40XX_REG_ATU_FUNC, val); + AR40XX_REG_BARRIER_WRITE(sc); + + /* Wait for it to complete */ + ret = ar40xx_hw_atu_wait_busy(sc); + if (ret != 0) + return (ret); + + /* Fetch the ethernet address and ATU status */ + AR40XX_REG_BARRIER_READ(sc); + ret0 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA0); + ret1 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA1); + ret2 = AR40XX_REG_READ(sc, AR40XX_REG_ATU_DATA2); + + /* If the status is zero, then we're done */ + if (MS(ret2, AR40XX_ATU_FUNC_DATA2_STATUS) == 0) + return (ENOENT); + + /* MAC address */ + e->es_macaddr[5] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR3); + e->es_macaddr[4] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR2); + e->es_macaddr[3] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR1); + e->es_macaddr[2] = MS(ret0, AR40XX_ATU_DATA0_MAC_ADDR0); + e->es_macaddr[0] = MS(ret1, AR40XX_ATU_DATA1_MAC_ADDR5); + e->es_macaddr[1] = MS(ret1, AR40XX_ATU_DATA1_MAC_ADDR4); + + /* Bitmask of ports this entry is for */ + e->es_portmask = MS(ret1, AR40XX_ATU_DATA1_DEST_PORT); + + /* TODO: other flags that are interesting */ + + AR40XX_DPRINTF(sc, AR40XX_DBG_ATU_OP, + "%s: MAC %6D portmask 0x%08x\n", + __func__, + e->es_macaddr, ":", e->es_portmask); + return (0); + default: + return (EINVAL); + } + return (EINVAL); +} diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.h b/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.h new file mode 100644 index 000000000000..96ea59178f69 --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw_atu.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 __AR40XX_HW_ATU_H__ +#define __AR40XX_HW_ATU_H__ + +extern int ar40xx_hw_atu_wait_busy(struct ar40xx_softc *sc); +extern int ar40xx_hw_atu_flush_all(struct ar40xx_softc *sc); +extern int ar40xx_hw_atu_flush_port(struct ar40xx_softc *sc, int port); +extern int ar40xx_hw_atu_fetch_entry(struct ar40xx_softc *sc, + etherswitch_atu_entry_t *e, int atu_fetch_op); + +#endif /* __AR40XX_HW_ATU_H__ */ + diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.c b/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.c new file mode 100644 index 000000000000..36baf752c4d4 --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.c @@ -0,0 +1,129 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "mdio_if.h" +#include "miibus_if.h" +#include "etherswitch_if.h" + +int +ar40xx_hw_phy_dbg_write(struct ar40xx_softc *sc, int phy, uint16_t dbg, + uint16_t data) +{ + AR40XX_LOCK_ASSERT(sc); + device_printf(sc->sc_dev, "%s: TODO\n", __func__); + return (0); +} + +int +ar40xx_hw_phy_dbg_read(struct ar40xx_softc *sc, int phy, uint16_t dbg) +{ + AR40XX_LOCK_ASSERT(sc); + device_printf(sc->sc_dev, "%s: TODO\n", __func__); + return (-1); +} + +int +ar40xx_hw_phy_mmd_write(struct ar40xx_softc *sc, uint32_t phy_id, + uint16_t mmd_num, uint16_t reg_id, uint16_t reg_val) +{ + + AR40XX_LOCK_ASSERT(sc); + + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_ADDR, + mmd_num); + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_DATA, + reg_id); + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_DATA, + reg_val); + + return (0); +} + +int +ar40xx_hw_phy_mmd_read(struct ar40xx_softc *sc, uint32_t phy_id, + uint16_t mmd_num, uint16_t reg_id) +{ + uint16_t value; + + AR40XX_LOCK_ASSERT(sc); + + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_ADDR, + mmd_num); + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_DATA, + reg_id); + MDIO_WRITEREG(sc->sc_mdio_dev, phy_id, AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + + value = MDIO_READREG(sc->sc_mdio_dev, phy_id, + AR40XX_MII_ATH_MMD_DATA); + + return value; +} + diff --git a/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.h b/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.h new file mode 100644 index 000000000000..cbe68e7c7b7c --- /dev/null +++ b/sys/dev/etherswitch/ar40xx/ar40xx_hw_mdio.h @@ -0,0 +1,40 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Adrian Chadd . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + */ *** 3283 LINES SKIPPED ***