From patchwork Mon Sep 20 09:52:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12504997 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A09BCC433FE for ; Mon, 20 Sep 2021 09:51:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 867BA60F23 for ; Mon, 20 Sep 2021 09:51:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236473AbhITJwv (ORCPT ); Mon, 20 Sep 2021 05:52:51 -0400 Received: from esa.microchip.iphmx.com ([68.232.154.123]:39035 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236343AbhITJwn (ORCPT ); Mon, 20 Sep 2021 05:52:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131477; x=1663667477; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vLPXuzc49sx/gA5stoXpDQug7nsLIUub/azXcaJOa7U=; b=dU5tX2mJ/6AP3g9uqLHL6scIFPvDGdd+vSk3Oi+En/llU0Yu9ReZjozC ySRk6jsFXNQivHPsjZml2c7b+/IeThoeRFr6pBqh3IZuG1fPvaVGE4oCX Q5Z1ne9n0NrHyG/qBm1INYsBm3Il8LIfYVAO3FbrSlAnCFjMKS/VkD4Wn lib6Ow0kbP1JmZvjjtE8S1JLZq5SP/h00HWyy6viJqny60QcGAa8aBsdS Q0W1gpuWSpdT43M0B/4ofMxqUZ07d3IN4+hzItps0+cIgBbmyBBRyCF8m 9wpr8deGVcBI2fRBhWyKJUTpOrHvWxYspZYrMiUTv5K9kxBMOIbVNgFme Q==; IronPort-SDR: RvL5tJO8cV5cETkjkdzfqC52IULYir7rkvJzZ+H6vH6OyeGtb2uILxjgKqf+/0gPaO6dUMKFA0 gNNSP5grgRl9P9rWOPPtaNg2dWqKUqZWmnCJEwE2fp/sfTrPYg1HfVLRIOLc2NYBYdPTCHJq8g P0npY5r3jVmEHqwDzHMufbehbtD97yK+mYLtsmlGPrhYyQR3dDxSWOcww/rYVoVvN7jNko3epy OUEwak+78/X5IkH5bW3QbKDAS5HFAi/YgrrehIPGoK5wF0D4pVZMaY4J5U+XOOeWzNY37QCP+n MKBKgc4R7QFBmgSfzWHCXppQ X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="69899282" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:16 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:15 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:12 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 01/12] net: mdio: mscc-miim: Fix the mdio controller Date: Mon, 20 Sep 2021 11:52:07 +0200 Message-ID: <20210920095218.1108151-2-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC According to the documentation the second resource is optional. But the blamed commit ignores that and if the resource is not there it just fails. This patch reverts that to still allow the second resource to be optional because other SoC have the some MDIO controller and doesn't need to second resource. Fixes: 672a1c394950 ("net: mdio: mscc-miim: Make use of the helper function devm_platform_ioremap_resource()") Signed-off-by: Horatiu Vultur --- drivers/net/mdio/mdio-mscc-miim.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c index 1ee592d3eae4..bef026a80074 100644 --- a/drivers/net/mdio/mdio-mscc-miim.c +++ b/drivers/net/mdio/mdio-mscc-miim.c @@ -134,8 +134,9 @@ static int mscc_miim_reset(struct mii_bus *bus) static int mscc_miim_probe(struct platform_device *pdev) { - struct mii_bus *bus; struct mscc_miim_dev *dev; + struct resource *res; + struct mii_bus *bus; int ret; bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev)); @@ -156,10 +157,13 @@ static int mscc_miim_probe(struct platform_device *pdev) return PTR_ERR(dev->regs); } - dev->phy_regs = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(dev->phy_regs)) { - dev_err(&pdev->dev, "Unable to map internal phy registers\n"); - return PTR_ERR(dev->phy_regs); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) { + dev->phy_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->phy_regs)) { + dev_err(&pdev->dev, "Unable to map internal phy registers\n"); + return PTR_ERR(dev->phy_regs); + } } ret = of_mdiobus_register(bus, pdev->dev.of_node); From patchwork Mon Sep 20 09:52:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12504999 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 176D9C433EF for ; Mon, 20 Sep 2021 09:51:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EE17F60F9B for ; Mon, 20 Sep 2021 09:51:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236591AbhITJxD (ORCPT ); Mon, 20 Sep 2021 05:53:03 -0400 Received: from esa.microchip.iphmx.com ([68.232.154.123]:37420 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236367AbhITJwq (ORCPT ); Mon, 20 Sep 2021 05:52:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131479; x=1663667479; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VnYOMjMEpb5JvuNo/2w6R+bDMUQ9dU4MVRLlawFW0TM=; b=AR8Gi8QE2HCevgOP863K7uU/PMaLAJXHAtcPY669sKXVS375zqo5aR3p WJXGkWi+429aaO5p2DDOciZ1ec6YzVXOiDaVt5vzZYaj+WJPcu9ozwoW6 s0tn7U19bjhj5NCbEwKdJUiBZDft8UjD3vuGtrIXlNKh5gyrF/9UIiF3d vi0RDVAblHBcgqw0aVni6cytoFAiotg3FsLqsYtXjGnClAXReGcuEQ2EI Ub+2bkioUWq9lLUHpxARAmFARsxxvQIoth4q+xwLzBktTTe4090HnHZVV b8WQOZ71cpnLWGB+I1YxWYufknYUt5ZtGCabjZnjsg+JgdFGX76zjkuok Q==; IronPort-SDR: UPUJcA8xRPYPnN0ZEhJ0IssqSBzCZsZb4x4xkdq1fRsg+Ita8zTv9meZP+Ow5gLYKE/jwR1Ls+ TSSSXOca+xydBF1AE4urawSsohEHp/z3f9aGn9g8fwGngSIlHOBhxdCWjODdw+de8xVT5wGMDw fhR4mSH76A4o7hJuJCRJl0Acr6l01/lEzMOgzaZTs5Q64D/GrelBjc4KY2Pwshxf/3YqDnK5Kl T6Mf/iSmktrrS5llrRCHQs+tKgxak++BUUAsK2opurDT32B/+l9/aHeqmhdbu9NHRrATzTEaVt 0XBtF+10TKE5NSfnSHQV4N46 X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="129913557" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:18 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:18 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:15 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 02/12] net: phy: mchp: Add support for LAN8804 PHY Date: Mon, 20 Sep 2021 11:52:08 +0200 Message-ID: <20210920095218.1108151-3-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The LAN8804 SKY has same features as that of LAN8804 SKY except that it doesn't support 1588, SyncE or Q-USGMII. This PHY is found inside the LAN966X switches. Signed-off-by: Horatiu Vultur --- drivers/net/phy/micrel.c | 73 ++++++++++++++++++++++++++++++++++++++ include/linux/micrel_phy.h | 1 + 2 files changed, 74 insertions(+) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 5c928f827173..34800b547004 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1537,6 +1537,65 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev, return ret; } +#define LAN_EXT_PAGE_ACCESS_CONTROL 0x16 +#define LAN_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17 +#define LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC 0x4000 + +#define LAN8804_ALIGN_SWAP 0x4a +#define LAN8804_ALIGN_TX_A_B_SWAP 0x1 +#define LAN8804_ALIGN_TX_A_B_SWAP_MASK GENMASK(2, 0) +#define LAN8814_CLOCK_MANAGEMENT 0xd +#define LAN8814_LINK_QUALITY 0x8e + +static int lanphy_read_page_reg(struct phy_device *phydev, int page, u32 addr) +{ + u32 data; + + phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page); + phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr); + phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, + (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC)); + data = phy_read(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA); + + return data; +} + +static int lanphy_write_page_reg(struct phy_device *phydev, int page, u16 addr, + u16 val) +{ + phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page); + phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr); + phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, + (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC)); + + val = phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, val); + if (val) { + phydev_err(phydev, "Error: phy_write has returned error %d\n", + val); + return val; + } + return 0; +} + +static int lan8804_config_init(struct phy_device *phydev) +{ + int val; + + /* MDI-X setting for swap A,B transmit */ + val = lanphy_read_page_reg(phydev, 2, LAN8804_ALIGN_SWAP); + val &= ~LAN8804_ALIGN_TX_A_B_SWAP_MASK; + val |= LAN8804_ALIGN_TX_A_B_SWAP; + lanphy_write_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, val); + + /* Make sure that the PHY will not stop generating the clock when the + * link partner goes down + */ + lanphy_write_page_reg(phydev, 31, LAN8814_CLOCK_MANAGEMENT, 0x27e); + lanphy_read_page_reg(phydev, 1, LAN8814_LINK_QUALITY); + + return 0; +} + static struct phy_driver ksphy_driver[] = { { .phy_id = PHY_ID_KS8737, @@ -1718,6 +1777,20 @@ static struct phy_driver ksphy_driver[] = { .get_stats = kszphy_get_stats, .suspend = genphy_suspend, .resume = kszphy_resume, +}, { + .phy_id = PHY_ID_LAN8804, + .phy_id_mask = MICREL_PHY_ID_MASK, + .name = "Microchip LAN966X Gigabit PHY", + .config_init = lan8804_config_init, + .driver_data = &ksz9021_type, + .probe = kszphy_probe, + .soft_reset = genphy_soft_reset, + .read_status = ksz9031_read_status, + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, + .suspend = genphy_suspend, + .resume = kszphy_resume, }, { .phy_id = PHY_ID_KSZ9131, .phy_id_mask = MICREL_PHY_ID_MASK, diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 3d43c60b49fa..1f7c33b2f5a3 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -28,6 +28,7 @@ #define PHY_ID_KSZ9031 0x00221620 #define PHY_ID_KSZ9131 0x00221640 #define PHY_ID_LAN8814 0x00221660 +#define PHY_ID_LAN8804 0x00221670 #define PHY_ID_KSZ886X 0x00221430 #define PHY_ID_KSZ8863 0x00221435 From patchwork Mon Sep 20 09:52:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505001 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UPPERCASE_50_75,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83742C433F5 for ; Mon, 20 Sep 2021 09:51:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 63D4A60FC0 for ; Mon, 20 Sep 2021 09:51:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236637AbhITJxF (ORCPT ); Mon, 20 Sep 2021 05:53:05 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:10199 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236430AbhITJwu (ORCPT ); Mon, 20 Sep 2021 05:52:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131483; x=1663667483; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WyASN8zWFFVzSw2n0JZnDopMWHmS5GJeAcLhhkBwFpQ=; b=rjIbSkz5fiuq+oU1PLogZhX3a8d+PyWf+qCnURYFEa/eNRFNRRU3loF7 8PzpUp69MgBtKN5IsWrw23V+Mwi8knr38jd8NrMkIQDmBWv6HsnRyXXKS wK0L9cg2wYq532D9z6Oo1yJEBdFk5RST8e6Eiy7H8ragNu8W5wtnp9Lw8 /L0ilbf+DAtNhE3ueqm76zczaNtRJgPRnLPbESw0/Tof+5nrgTT0WjhQQ GTST3fI3EQ1Bdhhy+ChfP5mxukbau/BZpMmIGpzAlXSVrXaLDr1VUVNpp EBRWzWpQe336QnLKcGTRftqJocwFwvAk2ulnMGLldubux4WLylb8W+ztp A==; IronPort-SDR: N9OEJF4x5St+N1hTxny3bnCV0MJxhdP0062Vkeae+tiWyCN5kNBfAJBRQgkG4KmDHpNGurAOpT 2pTA1CSiFqGkcQwOxBrGZb7F56/6P+7XqVmN/SxGXNy4MBTWu2G18SRBuaOfrhLHgwxXHe14o+ J3CT3EvQo/YZ87J3Em5N/JvskAWjK37uLYABSJN70gICQAKXyVDHZkQSyY2E25q7cG8X2sJsdw +yTS5kbpl39yKbhmHlJGG6vDbXXmjKtW/HTFzOSYJUpT8+cf/EExtM5/MWpR9HaYaoat/a3Uf6 luZ383bQu45O/ktBRsKYURTM X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="137192372" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:22 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:22 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:19 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 03/12] phy: Add lan966x ethernet serdes PHY driver Date: Mon, 20 Sep 2021 11:52:09 +0200 Message-ID: <20210920095218.1108151-4-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Add the Microchip lan966x ethernet serdes PHY driver for 1G interfaces available in the lan966x SoC. Signed-off-by: Horatiu Vultur --- drivers/phy/microchip/Kconfig | 8 + drivers/phy/microchip/Makefile | 1 + drivers/phy/microchip/lan966x_serdes.c | 525 ++++++++++++++++++++ drivers/phy/microchip/lan966x_serdes_regs.h | 482 ++++++++++++++++++ include/dt-bindings/phy/lan966x_serdes.h | 14 + 5 files changed, 1030 insertions(+) create mode 100644 drivers/phy/microchip/lan966x_serdes.c create mode 100644 drivers/phy/microchip/lan966x_serdes_regs.h create mode 100644 include/dt-bindings/phy/lan966x_serdes.h diff --git a/drivers/phy/microchip/Kconfig b/drivers/phy/microchip/Kconfig index 3728a284bf64..38039ed0754c 100644 --- a/drivers/phy/microchip/Kconfig +++ b/drivers/phy/microchip/Kconfig @@ -11,3 +11,11 @@ config PHY_SPARX5_SERDES depends on HAS_IOMEM help Enable this for support of the 10G/25G SerDes on Microchip Sparx5. + +config PHY_LAN966X_SERDES + tristate "SerDes PHY driver for Microchip LAN966X" + select GENERIC_PHY + depends on OF + depends on MFD_SYSCON + help + Enable this for supporting SerDes muxing with Microchip LAN966X diff --git a/drivers/phy/microchip/Makefile b/drivers/phy/microchip/Makefile index 7b98345712aa..fd73b87960a5 100644 --- a/drivers/phy/microchip/Makefile +++ b/drivers/phy/microchip/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_SPARX5_SERDES) := sparx5_serdes.o +obj-$(CONFIG_PHY_LAN966X_SERDES) := lan966x_serdes.o diff --git a/drivers/phy/microchip/lan966x_serdes.c b/drivers/phy/microchip/lan966x_serdes.c new file mode 100644 index 000000000000..80811af40dca --- /dev/null +++ b/drivers/phy/microchip/lan966x_serdes.c @@ -0,0 +1,525 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lan966x_serdes_regs.h" + +static const char *gcb_syscon = "microchip,lan966x-switch-syscon"; + +#define lan_offset_(id, tinst, tcnt, \ + gbase, ginst, gcnt, gwidth, \ + raddr, rinst, rcnt, rwidth) \ + (gbase + ((ginst) * gwidth) + raddr + ((rinst) * rwidth)) +#define lan_offset(...) lan_offset_(__VA_ARGS__) + +#define lan_rmw(val, mask, reg, off) \ + regmap_update_bits(reg, lan_offset(off), mask, val) + +struct serdes_ctrl { + struct regmap *regs; + struct device *dev; + struct phy *phys[SERDES_MAX]; + int ref125; +}; + +struct serdes_macro { + u8 idx; + int port; + struct serdes_ctrl *ctrl; +}; + +enum lan966x_sd6g40_mode { + LAN966X_SD6G40_MODE_QSGMII, + LAN966X_SD6G40_MODE_SGMII, +}; + +enum lan966x_sd6g40_ltx2rx { + LAN966X_SD6G40_TX2RX_LOOP_NONE, + LAN966X_SD6G40_LTX2RX +}; + +struct lan966x_sd6g40_setup_args { + enum lan966x_sd6g40_mode mode; + enum lan966x_sd6g40_ltx2rx tx2rx_loop; + bool txinvert; + bool rxinvert; + bool refclk125M; + bool mute; +}; + +struct lan966x_sd6g40_mode_args { + enum lan966x_sd6g40_mode mode; + u8 lane_10bit_sel; + u8 mpll_multiplier; + u8 ref_clkdiv2; + u8 tx_rate; + u8 rx_rate; +}; + +struct lan966x_sd6g40_setup { + u8 rx_term_en; + u8 lane_10bit_sel; + u8 tx_invert; + u8 rx_invert; + u8 mpll_multiplier; + u8 lane_loopbk_en; + u8 ref_clkdiv2; + u8 tx_rate; + u8 rx_rate; +}; + +static int lan966x_sd6g40_reg_cfg(struct serdes_macro *macro, + struct lan966x_sd6g40_setup *res_struct, + u32 idx) +{ + u32 value; + + /* Note: SerDes HSIO is configured in 1G_LAN mode */ + lan_rmw(HSIO_SD_CFG_LANE_10BIT_SEL(res_struct->lane_10bit_sel) | + HSIO_SD_CFG_RX_RATE(res_struct->rx_rate) | + HSIO_SD_CFG_TX_RATE(res_struct->tx_rate) | + HSIO_SD_CFG_TX_INVERT(res_struct->tx_invert) | + HSIO_SD_CFG_RX_INVERT(res_struct->rx_invert) | + HSIO_SD_CFG_LANE_LOOPBK_EN(res_struct->lane_loopbk_en) | + HSIO_SD_CFG_RX_RESET(0) | + HSIO_SD_CFG_TX_RESET(0), + HSIO_SD_CFG_LANE_10BIT_SEL_M | + HSIO_SD_CFG_RX_RATE_M | + HSIO_SD_CFG_TX_RATE_M | + HSIO_SD_CFG_TX_INVERT_M | + HSIO_SD_CFG_RX_INVERT_M | + HSIO_SD_CFG_LANE_LOOPBK_EN_M | + HSIO_SD_CFG_RX_RESET_M | + HSIO_SD_CFG_TX_RESET_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + lan_rmw(HSIO_MPLL_CFG_MPLL_MULTIPLIER(res_struct->mpll_multiplier) | + HSIO_MPLL_CFG_REF_CLKDIV2(res_struct->ref_clkdiv2), + HSIO_MPLL_CFG_MPLL_MULTIPLIER_M | + HSIO_MPLL_CFG_REF_CLKDIV2_M, + macro->ctrl->regs, HSIO_MPLL_CFG(idx)); + + lan_rmw(HSIO_SD_CFG_RX_TERM_EN(res_struct->rx_term_en), + HSIO_SD_CFG_RX_TERM_EN_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + lan_rmw(HSIO_MPLL_CFG_REF_SSP_EN(1), + HSIO_MPLL_CFG_REF_SSP_EN_M, + macro->ctrl->regs, HSIO_MPLL_CFG(idx)); + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + + lan_rmw(HSIO_SD_CFG_PHY_RESET(0), + HSIO_SD_CFG_PHY_RESET_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + + lan_rmw(HSIO_MPLL_CFG_MPLL_EN(1), + HSIO_MPLL_CFG_MPLL_EN_M, + macro->ctrl->regs, HSIO_MPLL_CFG(idx)); + + usleep_range(7 * USEC_PER_MSEC, 8 * USEC_PER_MSEC); + + regmap_read(macro->ctrl->regs, lan_offset(HSIO_SD_STAT(idx)), &value); + value = HSIO_SD_STAT_MPLL_STATE_X(value); + if (value != 0x1) { + pr_info("Unexpected sd_sd_stat[%u] mpll_state was 0x1 but is 0x%x\n", + idx, value); + return 1; + } + + lan_rmw(HSIO_SD_CFG_TX_CM_EN(1), + HSIO_SD_CFG_TX_CM_EN_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + + regmap_read(macro->ctrl->regs, lan_offset(HSIO_SD_STAT(idx)), &value); + value = HSIO_SD_STAT_TX_CM_STATE_X(value); + if (value != 0x1) { + pr_info("Unexpected sd_sd_stat[%u] tx_cm_state was 0x1 but is 0x%x\n", + idx, value); + return 1; + } + + lan_rmw(HSIO_SD_CFG_RX_PLL_EN(1) | + HSIO_SD_CFG_TX_EN(1), + HSIO_SD_CFG_RX_PLL_EN_M | + HSIO_SD_CFG_TX_EN_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + + /* Waiting for serdes 0 rx DPLL to lock... */ + regmap_read(macro->ctrl->regs, lan_offset(HSIO_SD_STAT(idx)), &value); + value = HSIO_SD_STAT_RX_PLL_STATE_X(value); + if (value != 0x1) { + pr_info("Unexpected sd_sd_stat[%u] rx_pll_state was 0x1 but is 0x%x\n", + idx, value); + return 1; + } + + /* Waiting for serdes 0 tx operational... */ + regmap_read(macro->ctrl->regs, lan_offset(HSIO_SD_STAT(idx)), &value); + value = HSIO_SD_STAT_TX_STATE_X(value); + if (value != 0x1) { + pr_info("Unexpected sd_sd_stat[%u] tx_state was 0x1 but is 0x%x\n", + idx, value); + return 1; + } + + lan_rmw(HSIO_SD_CFG_TX_DATA_EN(1) | + HSIO_SD_CFG_RX_DATA_EN(1), + HSIO_SD_CFG_TX_DATA_EN_M | + HSIO_SD_CFG_RX_DATA_EN_M, + macro->ctrl->regs, HSIO_SD_CFG(idx)); + + return 0; +} + +static int lan966x_sd6g40_get_conf_from_mode(enum lan966x_sd6g40_mode f_mode, + bool ref125M, + struct lan966x_sd6g40_mode_args *ret_val) +{ + switch (f_mode) { + case LAN966X_SD6G40_MODE_QSGMII: + ret_val->lane_10bit_sel = 0; + if (ref125M) { + ret_val->mpll_multiplier = 40; + ret_val->ref_clkdiv2 = 0x1; + ret_val->tx_rate = 0x0; + ret_val->rx_rate = 0x0; + } else { + ret_val->mpll_multiplier = 100; + ret_val->ref_clkdiv2 = 0x0; + ret_val->tx_rate = 0x0; + ret_val->rx_rate = 0x0; + } + break; + case LAN966X_SD6G40_MODE_SGMII: + ret_val->lane_10bit_sel = 1; + if (ref125M) { + ret_val->mpll_multiplier = 40; + ret_val->ref_clkdiv2 = 0x1; + ret_val->tx_rate = 0x2; + ret_val->rx_rate = 0x2; + } else { + ret_val->mpll_multiplier = 100; + ret_val->ref_clkdiv2 = 0x0; + ret_val->tx_rate = 0x2; + ret_val->rx_rate = 0x2; + } + break; + default: + return -1; + } + + return 0; +} + +static int lan966x_calc_sd6g40_setup_lane(struct lan966x_sd6g40_setup_args config, + struct lan966x_sd6g40_setup *ret_val) +{ + struct lan966x_sd6g40_mode_args sd6g40_mode; + struct lan966x_sd6g40_mode_args *mode_args = &sd6g40_mode; + + if (lan966x_sd6g40_get_conf_from_mode(config.mode, config.refclk125M, + mode_args)) + return -1; + + ret_val->lane_10bit_sel = mode_args->lane_10bit_sel; + ret_val->rx_rate = mode_args->rx_rate; + ret_val->tx_rate = mode_args->tx_rate; + ret_val->mpll_multiplier = mode_args->mpll_multiplier; + ret_val->ref_clkdiv2 = mode_args->ref_clkdiv2; + ret_val->rx_term_en = 0; + + if (config.tx2rx_loop == LAN966X_SD6G40_LTX2RX) + ret_val->lane_loopbk_en = 1; + else + ret_val->lane_loopbk_en = 0; + + if (config.txinvert) + ret_val->tx_invert = 1; + else + ret_val->tx_invert = 0; + + if (config.rxinvert) + ret_val->rx_invert = 1; + else + ret_val->rx_invert = 0; + + return 0; +} + +static int lan966x_sd6g40_setup_lane(struct serdes_macro *macro, + struct lan966x_sd6g40_setup_args config, + u32 idx) +{ + struct lan966x_sd6g40_setup calc_results; + int ret; + + memset(&calc_results, 0x0, sizeof(calc_results)); + + ret = lan966x_calc_sd6g40_setup_lane(config, &calc_results); + if (ret) + return ret; + + return lan966x_sd6g40_reg_cfg(macro, &calc_results, idx); +} + +static int lan966x_sd6g40_setup(struct serdes_macro *macro, u32 idx, int mode) +{ + struct lan966x_sd6g40_setup_args conf; + + memset(&conf, 0x0, sizeof(conf)); + conf.refclk125M = macro->ctrl->ref125; + + if (mode == PHY_INTERFACE_MODE_QSGMII) + conf.mode = LAN966X_SD6G40_MODE_QSGMII; + else + conf.mode = LAN966X_SD6G40_MODE_SGMII; + + return lan966x_sd6g40_setup_lane(macro, conf, idx); +} + +struct serdes_mux { + u8 idx; + u8 port; + enum phy_mode mode; + int submode; + u32 mask; + u32 mux; +}; + +#define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \ + .idx = _idx, \ + .port = _port, \ + .mode = _mode, \ + .submode = _submode, \ + .mask = _mask, \ + .mux = _mux, \ +} + +#define SERDES_MUX_GMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_GMII, m, c) +#define SERDES_MUX_SGMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c) +#define SERDES_MUX_QSGMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c) +#define SERDES_MUX_RGMII(i, p, m, c) \ + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c) + +static const struct serdes_mux lan966x_serdes_muxes[] = { + SERDES_MUX_QSGMII(SERDES6G(1), 0, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(0))), + SERDES_MUX_QSGMII(SERDES6G(1), 1, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(0))), + SERDES_MUX_QSGMII(SERDES6G(1), 2, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(0))), + SERDES_MUX_QSGMII(SERDES6G(1), 3, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(0))), + + SERDES_MUX_QSGMII(SERDES6G(2), 4, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(1))), + SERDES_MUX_QSGMII(SERDES6G(2), 5, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(1))), + SERDES_MUX_QSGMII(SERDES6G(2), 6, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(1))), + SERDES_MUX_QSGMII(SERDES6G(2), 7, HSIO_HW_CFG_QSGMII_ENA_M, + HSIO_HW_CFG_QSGMII_ENA(BIT(1))), + + SERDES_MUX_GMII(CU(0), 0, HSIO_HW_CFG_GMII_ENA_M, + HSIO_HW_CFG_GMII_ENA(BIT(0))), + SERDES_MUX_GMII(CU(1), 1, HSIO_HW_CFG_GMII_ENA_M, + HSIO_HW_CFG_GMII_ENA(BIT(1))), + + SERDES_MUX_SGMII(SERDES6G(0), 0, HSIO_HW_CFG_SD6G_0_CFG_M, 0), + SERDES_MUX_SGMII(SERDES6G(1), 1, HSIO_HW_CFG_SD6G_1_CFG_M, 0), + SERDES_MUX_SGMII(SERDES6G(0), 2, HSIO_HW_CFG_SD6G_0_CFG_M, + HSIO_HW_CFG_SD6G_0_CFG(1)), + SERDES_MUX_SGMII(SERDES6G(1), 3, HSIO_HW_CFG_SD6G_1_CFG_M, + HSIO_HW_CFG_SD6G_1_CFG(1)), + + SERDES_MUX_RGMII(RG(0), 2, HSIO_HW_CFG_RGMII_0_CFG_M | + HSIO_HW_CFG_RGMII_ENA_M, + HSIO_HW_CFG_RGMII_0_CFG(BIT(0)) | + HSIO_HW_CFG_RGMII_ENA(BIT(0))), + SERDES_MUX_RGMII(RG(1), 3, HSIO_HW_CFG_RGMII_1_CFG_M | + HSIO_HW_CFG_RGMII_ENA_M, + HSIO_HW_CFG_RGMII_1_CFG(BIT(0)) | + HSIO_HW_CFG_RGMII_ENA(BIT(1))), + SERDES_MUX_RGMII(RG(0), 5, HSIO_HW_CFG_RGMII_0_CFG_M | + HSIO_HW_CFG_RGMII_ENA_M, + HSIO_HW_CFG_RGMII_0_CFG(BIT(0)) | + HSIO_HW_CFG_RGMII_ENA(BIT(0))), + SERDES_MUX_RGMII(RG(1), 6, HSIO_HW_CFG_RGMII_1_CFG_M | + HSIO_HW_CFG_RGMII_ENA_M, + HSIO_HW_CFG_RGMII_1_CFG(BIT(0)) | + HSIO_HW_CFG_RGMII_ENA(BIT(1))), +}; + +static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct serdes_macro *macro = phy_get_drvdata(phy); + unsigned int i; + int val; + int ret; + + /* As of now only PHY_MODE_ETHERNET is supported */ + if (mode != PHY_MODE_ETHERNET) + return -EOPNOTSUPP; + + for (i = 0; i < ARRAY_SIZE(lan966x_serdes_muxes); i++) { + if (macro->idx != lan966x_serdes_muxes[i].idx || + mode != lan966x_serdes_muxes[i].mode || + submode != lan966x_serdes_muxes[i].submode || + macro->port != lan966x_serdes_muxes[i].port) + continue; + + ret = regmap_read(macro->ctrl->regs, lan_offset(HSIO_HW_CFG), + &val); + if (ret) + return ret; + + ret = regmap_update_bits(macro->ctrl->regs, + lan_offset(HSIO_HW_CFG), + lan966x_serdes_muxes[i].mask, + val | lan966x_serdes_muxes[i].mux); + if (ret) + return ret; + + if (macro->idx < CU_MAX) + return 0; + + if (macro->idx < SERDES6G_MAX) + return lan966x_sd6g40_setup(macro, + macro->idx - (CU_MAX + 1), + lan966x_serdes_muxes[i].submode); + + if (macro->idx < RG_MAX) + return 0; + + return -EOPNOTSUPP; + } + + return -EINVAL; +} + +static const struct phy_ops serdes_ops = { + .set_mode = serdes_set_mode, + .owner = THIS_MODULE, +}; + +static struct phy *serdes_simple_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct serdes_ctrl *ctrl = dev_get_drvdata(dev); + unsigned int port, idx, i; + + if (args->args_count != 2) + return ERR_PTR(-EINVAL); + + port = args->args[0]; + idx = args->args[1]; + + for (i = 0; i < SERDES_MAX; i++) { + struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]); + + if (idx != macro->idx) + continue; + + macro->port = port; + return ctrl->phys[i]; + } + + return ERR_PTR(-ENODEV); +} + +static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy) +{ + struct serdes_macro *macro; + + *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops); + if (IS_ERR(*phy)) + return PTR_ERR(*phy); + + macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL); + if (!macro) + return -ENOMEM; + + macro->idx = idx; + macro->ctrl = ctrl; + macro->port = -1; + + phy_set_drvdata(*phy, macro); + + return 0; +} + +static int serdes_probe(struct platform_device *pdev) +{ + struct phy_provider *provider; + struct serdes_ctrl *ctrl; + struct regmap *gcb_ctrl; + unsigned int i; + u32 val; + int ret; + + ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->dev = &pdev->dev; + ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(ctrl->regs)) + return PTR_ERR(ctrl->regs); + + gcb_ctrl = syscon_regmap_lookup_by_compatible(gcb_syscon); + if (IS_ERR(gcb_ctrl)) { + dev_err(&pdev->dev, "No gcb_syscon: %s\n", gcb_syscon); + return PTR_ERR(gcb_ctrl); + } + + for (i = 0; i < SERDES_MAX; i++) { + ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]); + if (ret) + return ret; + } + + regmap_read(gcb_ctrl, 0x4, &val); + val &= GENMASK(2, 0); + ctrl->ref125 = (val == 1 || val == 2); + + dev_set_drvdata(&pdev->dev, ctrl); + + provider = devm_of_phy_provider_register(ctrl->dev, + serdes_simple_xlate); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct of_device_id serdes_ids[] = { + { .compatible = "microchip,lan966x-serdes", }, + {}, +}; +MODULE_DEVICE_TABLE(of, serdes_ids); + +static struct platform_driver mscc_lan966x_serdes = { + .probe = serdes_probe, + .driver = { + .name = "microchip,lan966x-serdes", + .of_match_table = of_match_ptr(serdes_ids), + }, +}; + +module_platform_driver(mscc_lan966x_serdes); diff --git a/drivers/phy/microchip/lan966x_serdes_regs.h b/drivers/phy/microchip/lan966x_serdes_regs.h new file mode 100644 index 000000000000..c3d3d16c1e97 --- /dev/null +++ b/drivers/phy/microchip/lan966x_serdes_regs.h @@ -0,0 +1,482 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Microchip LAN966x Switch driver + * + * License: Dual MIT/GPL + * Copyright (c) 2020 Microchip Technology Inc. + */ + +/* This file is autogenerated by cml-utils 2021-05-12 15:48:55 +0200. + * Commit ID: dbe188f718027a2c414b90d45f152b73468cbc5c (dirty) + */ + +#ifndef _LAN966X_HSIO_REGS_H_ +#define _LAN966X_HSIO_REGS_H_ + +#include + +#define LAN966X_BUILD_ID_REG GCB_BUILDID +enum lan966x_target { + TARGET_HSIO = 32, + NUM_TARGETS = 66 +}; + +#define __REG(...) __VA_ARGS__ + +/* HSIO:SYNC_ETH_CFG:SYNC_ETH_CFG */ +#define HSIO_SYNC_ETH_CFG(r) __REG(TARGET_HSIO,\ + 0, 1, 0, 0, 1, 8, 0, r, 2, 4) + +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC(x) (((x) << 4) & GENMASK(6, 4)) +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_M GENMASK(6, 4) +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_X(x) (((x) & GENMASK(6, 4)) >> 4) + +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV(x) (((x) << 1) & GENMASK(3, 1)) +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_M GENMASK(3, 1) +#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_X(x) (((x) & GENMASK(3, 1)) >> 1) + +#define HSIO_SYNC_ETH_CFG_RECO_CLK_ENA(x) ((x) & GENMASK(0, 0)) +#define HSIO_SYNC_ETH_CFG_RECO_CLK_ENA_M GENMASK(0, 0) +#define HSIO_SYNC_ETH_CFG_RECO_CLK_ENA_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:SD:SD_CFG */ +#define HSIO_SD_CFG(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 0, 0, 1, 4) + +#define HSIO_SD_CFG_TEST_POWERDOWN(x) (((x) << 28) & GENMASK(28, 28)) +#define HSIO_SD_CFG_TEST_POWERDOWN_M GENMASK(28, 28) +#define HSIO_SD_CFG_TEST_POWERDOWN_X(x) (((x) & GENMASK(28, 28)) >> 28) + +#define HSIO_SD_CFG_PHY_RESET(x) (((x) << 27) & GENMASK(27, 27)) +#define HSIO_SD_CFG_PHY_RESET_M GENMASK(27, 27) +#define HSIO_SD_CFG_PHY_RESET_X(x) (((x) & GENMASK(27, 27)) >> 27) + +#define HSIO_SD_CFG_RX_LOS_FILT_CNT(x) (((x) << 20) & GENMASK(26, 20)) +#define HSIO_SD_CFG_RX_LOS_FILT_CNT_M GENMASK(26, 20) +#define HSIO_SD_CFG_RX_LOS_FILT_CNT_X(x) (((x) & GENMASK(26, 20)) >> 20) + +#define HSIO_SD_CFG_TX_VBOOST_EN(x) (((x) << 19) & GENMASK(19, 19)) +#define HSIO_SD_CFG_TX_VBOOST_EN_M GENMASK(19, 19) +#define HSIO_SD_CFG_TX_VBOOST_EN_X(x) (((x) & GENMASK(19, 19)) >> 19) + +#define HSIO_SD_CFG_TX_RESET(x) (((x) << 18) & GENMASK(18, 18)) +#define HSIO_SD_CFG_TX_RESET_M GENMASK(18, 18) +#define HSIO_SD_CFG_TX_RESET_X(x) (((x) & GENMASK(18, 18)) >> 18) + +#define HSIO_SD_CFG_TX_RATE(x) (((x) << 16) & GENMASK(17, 16)) +#define HSIO_SD_CFG_TX_RATE_M GENMASK(17, 16) +#define HSIO_SD_CFG_TX_RATE_X(x) (((x) & GENMASK(17, 16)) >> 16) + +#define HSIO_SD_CFG_TX_INVERT(x) (((x) << 15) & GENMASK(15, 15)) +#define HSIO_SD_CFG_TX_INVERT_M GENMASK(15, 15) +#define HSIO_SD_CFG_TX_INVERT_X(x) (((x) & GENMASK(15, 15)) >> 15) + +#define HSIO_SD_CFG_TX_EN(x) (((x) << 14) & GENMASK(14, 14)) +#define HSIO_SD_CFG_TX_EN_M GENMASK(14, 14) +#define HSIO_SD_CFG_TX_EN_X(x) (((x) & GENMASK(14, 14)) >> 14) + +#define HSIO_SD_CFG_TX_DETECT_RX_REQ(x) (((x) << 13) & GENMASK(13, 13)) +#define HSIO_SD_CFG_TX_DETECT_RX_REQ_M GENMASK(13, 13) +#define HSIO_SD_CFG_TX_DETECT_RX_REQ_X(x) (((x) & GENMASK(13, 13)) >> 13) + +#define HSIO_SD_CFG_TX_DATA_EN(x) (((x) << 12) & GENMASK(12, 12)) +#define HSIO_SD_CFG_TX_DATA_EN_M GENMASK(12, 12) +#define HSIO_SD_CFG_TX_DATA_EN_X(x) (((x) & GENMASK(12, 12)) >> 12) + +#define HSIO_SD_CFG_TX_CM_EN(x) (((x) << 11) & GENMASK(11, 11)) +#define HSIO_SD_CFG_TX_CM_EN_M GENMASK(11, 11) +#define HSIO_SD_CFG_TX_CM_EN_X(x) (((x) & GENMASK(11, 11)) >> 11) + +#define HSIO_SD_CFG_LANE_10BIT_SEL(x) (((x) << 10) & GENMASK(10, 10)) +#define HSIO_SD_CFG_LANE_10BIT_SEL_M GENMASK(10, 10) +#define HSIO_SD_CFG_LANE_10BIT_SEL_X(x) (((x) & GENMASK(10, 10)) >> 10) + +#define HSIO_SD_CFG_RX_TERM_EN(x) (((x) << 9) & GENMASK(9, 9)) +#define HSIO_SD_CFG_RX_TERM_EN_M GENMASK(9, 9) +#define HSIO_SD_CFG_RX_TERM_EN_X(x) (((x) & GENMASK(9, 9)) >> 9) + +#define HSIO_SD_CFG_RX_RESET(x) (((x) << 8) & GENMASK(8, 8)) +#define HSIO_SD_CFG_RX_RESET_M GENMASK(8, 8) +#define HSIO_SD_CFG_RX_RESET_X(x) (((x) & GENMASK(8, 8)) >> 8) + +#define HSIO_SD_CFG_RX_RATE(x) (((x) << 6) & GENMASK(7, 6)) +#define HSIO_SD_CFG_RX_RATE_M GENMASK(7, 6) +#define HSIO_SD_CFG_RX_RATE_X(x) (((x) & GENMASK(7, 6)) >> 6) + +#define HSIO_SD_CFG_RX_PLL_EN(x) (((x) << 5) & GENMASK(5, 5)) +#define HSIO_SD_CFG_RX_PLL_EN_M GENMASK(5, 5) +#define HSIO_SD_CFG_RX_PLL_EN_X(x) (((x) & GENMASK(5, 5)) >> 5) + +#define HSIO_SD_CFG_RX_LOS_EN(x) (((x) << 4) & GENMASK(4, 4)) +#define HSIO_SD_CFG_RX_LOS_EN_M GENMASK(4, 4) +#define HSIO_SD_CFG_RX_LOS_EN_X(x) (((x) & GENMASK(4, 4)) >> 4) + +#define HSIO_SD_CFG_RX_INVERT(x) (((x) << 3) & GENMASK(3, 3)) +#define HSIO_SD_CFG_RX_INVERT_M GENMASK(3, 3) +#define HSIO_SD_CFG_RX_INVERT_X(x) (((x) & GENMASK(3, 3)) >> 3) + +#define HSIO_SD_CFG_RX_DATA_EN(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_SD_CFG_RX_DATA_EN_M GENMASK(2, 2) +#define HSIO_SD_CFG_RX_DATA_EN_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_SD_CFG_RX_ALIGN_EN(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_SD_CFG_RX_ALIGN_EN_M GENMASK(1, 1) +#define HSIO_SD_CFG_RX_ALIGN_EN_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_SD_CFG_LANE_LOOPBK_EN(x) ((x) & GENMASK(0, 0)) +#define HSIO_SD_CFG_LANE_LOOPBK_EN_M GENMASK(0, 0) +#define HSIO_SD_CFG_LANE_LOOPBK_EN_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:SD:SD_CFG2 */ +#define HSIO_SD_CFG2(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 4, 0, 1, 4) + +#define HSIO_SD_CFG2_RX_EQ(x) (((x) << 25) & GENMASK(27, 25)) +#define HSIO_SD_CFG2_RX_EQ_M GENMASK(27, 25) +#define HSIO_SD_CFG2_RX_EQ_X(x) (((x) & GENMASK(27, 25)) >> 25) + +#define HSIO_SD_CFG2_TX_TERM_OFFSET(x) (((x) << 20) & GENMASK(24, 20)) +#define HSIO_SD_CFG2_TX_TERM_OFFSET_M GENMASK(24, 20) +#define HSIO_SD_CFG2_TX_TERM_OFFSET_X(x) (((x) & GENMASK(24, 20)) >> 20) + +#define HSIO_SD_CFG2_TX_VBOOST_LVL(x) (((x) << 17) & GENMASK(19, 17)) +#define HSIO_SD_CFG2_TX_VBOOST_LVL_M GENMASK(19, 17) +#define HSIO_SD_CFG2_TX_VBOOST_LVL_X(x) (((x) & GENMASK(19, 17)) >> 17) + +#define HSIO_SD_CFG2_LOS_BIAS(x) (((x) << 14) & GENMASK(16, 14)) +#define HSIO_SD_CFG2_LOS_BIAS_M GENMASK(16, 14) +#define HSIO_SD_CFG2_LOS_BIAS_X(x) (((x) & GENMASK(16, 14)) >> 14) + +#define HSIO_SD_CFG2_TX_AMPLITUDE(x) (((x) << 7) & GENMASK(13, 7)) +#define HSIO_SD_CFG2_TX_AMPLITUDE_M GENMASK(13, 7) +#define HSIO_SD_CFG2_TX_AMPLITUDE_X(x) (((x) & GENMASK(13, 7)) >> 7) + +#define HSIO_SD_CFG2_TX_PREEMPH(x) ((x) & GENMASK(6, 0)) +#define HSIO_SD_CFG2_TX_PREEMPH_M GENMASK(6, 0) +#define HSIO_SD_CFG2_TX_PREEMPH_X(x) ((x) & GENMASK(6, 0)) + +/* HSIO:SD:MPLL_CFG */ +#define HSIO_MPLL_CFG(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 8, 0, 1, 4) + +#define HSIO_MPLL_CFG_REF_SSP_EN(x) (((x) << 18) & GENMASK(18, 18)) +#define HSIO_MPLL_CFG_REF_SSP_EN_M GENMASK(18, 18) +#define HSIO_MPLL_CFG_REF_SSP_EN_X(x) (((x) & GENMASK(18, 18)) >> 18) + +#define HSIO_MPLL_CFG_REF_CLKDIV2(x) (((x) << 17) & GENMASK(17, 17)) +#define HSIO_MPLL_CFG_REF_CLKDIV2_M GENMASK(17, 17) +#define HSIO_MPLL_CFG_REF_CLKDIV2_X(x) (((x) & GENMASK(17, 17)) >> 17) + +#define HSIO_MPLL_CFG_MPLL_EN(x) (((x) << 16) & GENMASK(16, 16)) +#define HSIO_MPLL_CFG_MPLL_EN_M GENMASK(16, 16) +#define HSIO_MPLL_CFG_MPLL_EN_X(x) (((x) & GENMASK(16, 16)) >> 16) + +#define HSIO_MPLL_CFG_SSC_REF_CLK_SEL(x) (((x) << 7) & GENMASK(15, 7)) +#define HSIO_MPLL_CFG_SSC_REF_CLK_SEL_M GENMASK(15, 7) +#define HSIO_MPLL_CFG_SSC_REF_CLK_SEL_X(x) (((x) & GENMASK(15, 7)) >> 7) + +#define HSIO_MPLL_CFG_MPLL_MULTIPLIER(x) ((x) & GENMASK(6, 0)) +#define HSIO_MPLL_CFG_MPLL_MULTIPLIER_M GENMASK(6, 0) +#define HSIO_MPLL_CFG_MPLL_MULTIPLIER_X(x) ((x) & GENMASK(6, 0)) + +/* HSIO:SD:SD_STAT */ +#define HSIO_SD_STAT(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 12, 0, 1, 4) + +#define HSIO_SD_STAT_MPLL_STATE(x) (((x) << 6) & GENMASK(6, 6)) +#define HSIO_SD_STAT_MPLL_STATE_M GENMASK(6, 6) +#define HSIO_SD_STAT_MPLL_STATE_X(x) (((x) & GENMASK(6, 6)) >> 6) + +#define HSIO_SD_STAT_TX_STATE(x) (((x) << 5) & GENMASK(5, 5)) +#define HSIO_SD_STAT_TX_STATE_M GENMASK(5, 5) +#define HSIO_SD_STAT_TX_STATE_X(x) (((x) & GENMASK(5, 5)) >> 5) + +#define HSIO_SD_STAT_TX_DETECT_RX_RESULT(x) (((x) << 4) & GENMASK(4, 4)) +#define HSIO_SD_STAT_TX_DETECT_RX_RESULT_M GENMASK(4, 4) +#define HSIO_SD_STAT_TX_DETECT_RX_RESULT_X(x) (((x) & GENMASK(4, 4)) >> 4) + +#define HSIO_SD_STAT_TX_DETECT_RX_ACK(x) (((x) << 3) & GENMASK(3, 3)) +#define HSIO_SD_STAT_TX_DETECT_RX_ACK_M GENMASK(3, 3) +#define HSIO_SD_STAT_TX_DETECT_RX_ACK_X(x) (((x) & GENMASK(3, 3)) >> 3) + +#define HSIO_SD_STAT_TX_CM_STATE(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_SD_STAT_TX_CM_STATE_M GENMASK(2, 2) +#define HSIO_SD_STAT_TX_CM_STATE_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_SD_STAT_RX_VALID(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_SD_STAT_RX_VALID_M GENMASK(1, 1) +#define HSIO_SD_STAT_RX_VALID_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_SD_STAT_RX_PLL_STATE(x) ((x) & GENMASK(0, 0)) +#define HSIO_SD_STAT_RX_PLL_STATE_M GENMASK(0, 0) +#define HSIO_SD_STAT_RX_PLL_STATE_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:SD:CR_ACCESS */ +#define HSIO_CR_ACCESS(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 16, 0, 1, 4) + +#define HSIO_CR_ACCESS_WRITE(x) (((x) << 19) & GENMASK(19, 19)) +#define HSIO_CR_ACCESS_WRITE_M GENMASK(19, 19) +#define HSIO_CR_ACCESS_WRITE_X(x) (((x) & GENMASK(19, 19)) >> 19) + +#define HSIO_CR_ACCESS_READ(x) (((x) << 18) & GENMASK(18, 18)) +#define HSIO_CR_ACCESS_READ_M GENMASK(18, 18) +#define HSIO_CR_ACCESS_READ_X(x) (((x) & GENMASK(18, 18)) >> 18) + +#define HSIO_CR_ACCESS_CAP_DATA(x) (((x) << 17) & GENMASK(17, 17)) +#define HSIO_CR_ACCESS_CAP_DATA_M GENMASK(17, 17) +#define HSIO_CR_ACCESS_CAP_DATA_X(x) (((x) & GENMASK(17, 17)) >> 17) + +#define HSIO_CR_ACCESS_CAP_ADDR(x) (((x) << 16) & GENMASK(16, 16)) +#define HSIO_CR_ACCESS_CAP_ADDR_M GENMASK(16, 16) +#define HSIO_CR_ACCESS_CAP_ADDR_X(x) (((x) & GENMASK(16, 16)) >> 16) + +#define HSIO_CR_ACCESS_DATA_IN(x) ((x) & GENMASK(15, 0)) +#define HSIO_CR_ACCESS_DATA_IN_M GENMASK(15, 0) +#define HSIO_CR_ACCESS_DATA_IN_X(x) ((x) & GENMASK(15, 0)) + +/* HSIO:SD:CR_OUTPUT */ +#define HSIO_CR_OUTPUT(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 20, 0, 1, 4) + +#define HSIO_CR_OUTPUT_ACK(x) (((x) << 16) & GENMASK(16, 16)) +#define HSIO_CR_OUTPUT_ACK_M GENMASK(16, 16) +#define HSIO_CR_OUTPUT_ACK_X(x) (((x) & GENMASK(16, 16)) >> 16) + +#define HSIO_CR_OUTPUT_DATA_OUT(x) ((x) & GENMASK(15, 0)) +#define HSIO_CR_OUTPUT_DATA_OUT_M GENMASK(15, 0) +#define HSIO_CR_OUTPUT_DATA_OUT_X(x) ((x) & GENMASK(15, 0)) + +/* HSIO:SD:SYNC_ETH_SD_CFG */ +#define HSIO_SYNC_ETH_SD_CFG(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 24, 0, 1, 4) + +#define HSIO_SYNC_ETH_SD_CFG_SD_RECO_CLK_DIV(x) (((x) << 4) & GENMASK(5, 4)) +#define HSIO_SYNC_ETH_SD_CFG_SD_RECO_CLK_DIV_M GENMASK(5, 4) +#define HSIO_SYNC_ETH_SD_CFG_SD_RECO_CLK_DIV_X(x) (((x) & GENMASK(5, 4)) >> 4) + +#define HSIO_SYNC_ETH_SD_CFG_SD_LINK_STAT_ENA(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_SYNC_ETH_SD_CFG_SD_LINK_STAT_ENA_M GENMASK(1, 1) +#define HSIO_SYNC_ETH_SD_CFG_SD_LINK_STAT_ENA_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_SYNC_ETH_SD_CFG_SD_AUTO_SQUELCH_ENA(x) ((x) & GENMASK(0, 0)) +#define HSIO_SYNC_ETH_SD_CFG_SD_AUTO_SQUELCH_ENA_M GENMASK(0, 0) +#define HSIO_SYNC_ETH_SD_CFG_SD_AUTO_SQUELCH_ENA_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:SD:SIGDET_CFG */ +#define HSIO_SIGDET_CFG(g) __REG(TARGET_HSIO,\ + 0, 1, 8, g, 3, 32, 28, 0, 1, 4) + +#define HSIO_SIGDET_CFG_SD_SEL(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_SIGDET_CFG_SD_SEL_M GENMASK(2, 2) +#define HSIO_SIGDET_CFG_SD_SEL_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_SIGDET_CFG_SD_POL(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_SIGDET_CFG_SD_POL_M GENMASK(1, 1) +#define HSIO_SIGDET_CFG_SD_POL_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_SIGDET_CFG_SD_ENA(x) ((x) & GENMASK(0, 0)) +#define HSIO_SIGDET_CFG_SD_ENA_M GENMASK(0, 0) +#define HSIO_SIGDET_CFG_SD_ENA_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:HW_CFGSTAT:HW_CFG */ +#define HSIO_HW_CFG __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 0, 0, 1, 4) + +#define HSIO_HW_CFG_RGMII_1_CFG(x) (((x) << 15) & GENMASK(15, 15)) +#define HSIO_HW_CFG_RGMII_1_CFG_M GENMASK(15, 15) +#define HSIO_HW_CFG_RGMII_1_CFG_X(x) (((x) & GENMASK(15, 15)) >> 15) + +#define HSIO_HW_CFG_RGMII_0_CFG(x) (((x) << 14) & GENMASK(14, 14)) +#define HSIO_HW_CFG_RGMII_0_CFG_M GENMASK(14, 14) +#define HSIO_HW_CFG_RGMII_0_CFG_X(x) (((x) & GENMASK(14, 14)) >> 14) + +#define HSIO_HW_CFG_RGMII_ENA(x) (((x) << 12) & GENMASK(13, 12)) +#define HSIO_HW_CFG_RGMII_ENA_M GENMASK(13, 12) +#define HSIO_HW_CFG_RGMII_ENA_X(x) (((x) & GENMASK(13, 12)) >> 12) + +#define HSIO_HW_CFG_SD6G_0_CFG(x) (((x) << 11) & GENMASK(11, 11)) +#define HSIO_HW_CFG_SD6G_0_CFG_M GENMASK(11, 11) +#define HSIO_HW_CFG_SD6G_0_CFG_X(x) (((x) & GENMASK(11, 11)) >> 11) + +#define HSIO_HW_CFG_SD6G_1_CFG(x) (((x) << 10) & GENMASK(10, 10)) +#define HSIO_HW_CFG_SD6G_1_CFG_M GENMASK(10, 10) +#define HSIO_HW_CFG_SD6G_1_CFG_X(x) (((x) & GENMASK(10, 10)) >> 10) + +#define HSIO_HW_CFG_GMII_ENA(x) (((x) << 2) & GENMASK(9, 2)) +#define HSIO_HW_CFG_GMII_ENA_M GENMASK(9, 2) +#define HSIO_HW_CFG_GMII_ENA_X(x) (((x) & GENMASK(9, 2)) >> 2) + +#define HSIO_HW_CFG_QSGMII_ENA(x) ((x) & GENMASK(1, 0)) +#define HSIO_HW_CFG_QSGMII_ENA_M GENMASK(1, 0) +#define HSIO_HW_CFG_QSGMII_ENA_X(x) ((x) & GENMASK(1, 0)) + +/* HSIO:HW_CFGSTAT:GPIO_PI_CFG */ +#define HSIO_GPIO_PI_CFG __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 4, 0, 1, 4) + +#define HSIO_GPIO_PI_CFG_PI_MUX_ENA(x) ((x) & GENMASK(26, 0)) +#define HSIO_GPIO_PI_CFG_PI_MUX_ENA_M GENMASK(26, 0) +#define HSIO_GPIO_PI_CFG_PI_MUX_ENA_X(x) ((x) & GENMASK(26, 0)) + +/* HSIO:HW_CFGSTAT:QSGMII_CFG */ +#define HSIO_QSGMII_CFG __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 8, 0, 1, 4) + +#define HSIO_QSGMII_CFG_SHYST_DIS(x) (((x) << 4) & GENMASK(4, 4)) +#define HSIO_QSGMII_CFG_SHYST_DIS_M GENMASK(4, 4) +#define HSIO_QSGMII_CFG_SHYST_DIS_X(x) (((x) & GENMASK(4, 4)) >> 4) + +#define HSIO_QSGMII_CFG_E_DET_ENA(x) (((x) << 3) & GENMASK(3, 3)) +#define HSIO_QSGMII_CFG_E_DET_ENA_M GENMASK(3, 3) +#define HSIO_QSGMII_CFG_E_DET_ENA_X(x) (((x) & GENMASK(3, 3)) >> 3) + +#define HSIO_QSGMII_CFG_USE_I1_ENA(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_QSGMII_CFG_USE_I1_ENA_M GENMASK(2, 2) +#define HSIO_QSGMII_CFG_USE_I1_ENA_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_QSGMII_CFG_FLIP_LANES(x) ((x) & GENMASK(1, 0)) +#define HSIO_QSGMII_CFG_FLIP_LANES_M GENMASK(1, 0) +#define HSIO_QSGMII_CFG_FLIP_LANES_X(x) ((x) & GENMASK(1, 0)) + +/* HSIO:HW_CFGSTAT:QSGMII_STAT */ +#define HSIO_QSGMII_STAT(r) __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 12, r, 2, 4) + +#define HSIO_QSGMII_STAT_DELAY_VAR_X200PS(x) (((x) << 2) & GENMASK(7, 2)) +#define HSIO_QSGMII_STAT_DELAY_VAR_X200PS_M GENMASK(7, 2) +#define HSIO_QSGMII_STAT_DELAY_VAR_X200PS_X(x) (((x) & GENMASK(7, 2)) >> 2) + +#define HSIO_QSGMII_STAT_SYNC(x) ((x) & GENMASK(1, 0)) +#define HSIO_QSGMII_STAT_SYNC_M GENMASK(1, 0) +#define HSIO_QSGMII_STAT_SYNC_X(x) ((x) & GENMASK(1, 0)) + +/* HSIO:HW_CFGSTAT:RGMII_CFG */ +#define HSIO_RGMII_CFG(r) __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 20, r, 2, 4) + +#define HSIO_RGMII_CFG_IB_RX_LINK_STATUS(x) (((x) << 15) & GENMASK(15, 15)) +#define HSIO_RGMII_CFG_IB_RX_LINK_STATUS_M GENMASK(15, 15) +#define HSIO_RGMII_CFG_IB_RX_LINK_STATUS_X(x) (((x) & GENMASK(15, 15)) >> 15) + +#define HSIO_RGMII_CFG_IB_RX_DUPLEX(x) (((x) << 14) & GENMASK(14, 14)) +#define HSIO_RGMII_CFG_IB_RX_DUPLEX_M GENMASK(14, 14) +#define HSIO_RGMII_CFG_IB_RX_DUPLEX_X(x) (((x) & GENMASK(14, 14)) >> 14) + +#define HSIO_RGMII_CFG_IB_RX_SPEED(x) (((x) << 12) & GENMASK(13, 12)) +#define HSIO_RGMII_CFG_IB_RX_SPEED_M GENMASK(13, 12) +#define HSIO_RGMII_CFG_IB_RX_SPEED_X(x) (((x) & GENMASK(13, 12)) >> 12) + +#define HSIO_RGMII_CFG_IB_TX_LINK_STATUS(x) (((x) << 11) & GENMASK(11, 11)) +#define HSIO_RGMII_CFG_IB_TX_LINK_STATUS_M GENMASK(11, 11) +#define HSIO_RGMII_CFG_IB_TX_LINK_STATUS_X(x) (((x) & GENMASK(11, 11)) >> 11) + +#define HSIO_RGMII_CFG_IB_TX_FDX(x) (((x) << 10) & GENMASK(10, 10)) +#define HSIO_RGMII_CFG_IB_TX_FDX_M GENMASK(10, 10) +#define HSIO_RGMII_CFG_IB_TX_FDX_X(x) (((x) & GENMASK(10, 10)) >> 10) + +#define HSIO_RGMII_CFG_IB_TX_MII_SPD(x) (((x) << 9) & GENMASK(9, 9)) +#define HSIO_RGMII_CFG_IB_TX_MII_SPD_M GENMASK(9, 9) +#define HSIO_RGMII_CFG_IB_TX_MII_SPD_X(x) (((x) & GENMASK(9, 9)) >> 9) + +#define HSIO_RGMII_CFG_IB_TX_SPD_1G(x) (((x) << 8) & GENMASK(8, 8)) +#define HSIO_RGMII_CFG_IB_TX_SPD_1G_M GENMASK(8, 8) +#define HSIO_RGMII_CFG_IB_TX_SPD_1G_X(x) (((x) & GENMASK(8, 8)) >> 8) + +#define HSIO_RGMII_CFG_IB_TX_ENA(x) (((x) << 7) & GENMASK(7, 7)) +#define HSIO_RGMII_CFG_IB_TX_ENA_M GENMASK(7, 7) +#define HSIO_RGMII_CFG_IB_TX_ENA_X(x) (((x) & GENMASK(7, 7)) >> 7) + +#define HSIO_RGMII_CFG_IB_RX_ENA(x) (((x) << 6) & GENMASK(6, 6)) +#define HSIO_RGMII_CFG_IB_RX_ENA_M GENMASK(6, 6) +#define HSIO_RGMII_CFG_IB_RX_ENA_X(x) (((x) & GENMASK(6, 6)) >> 6) + +#define HSIO_RGMII_CFG_IB_ENA(x) (((x) << 5) & GENMASK(5, 5)) +#define HSIO_RGMII_CFG_IB_ENA_M GENMASK(5, 5) +#define HSIO_RGMII_CFG_IB_ENA_X(x) (((x) & GENMASK(5, 5)) >> 5) + +#define HSIO_RGMII_CFG_TX_CLK_CFG(x) (((x) << 2) & GENMASK(4, 2)) +#define HSIO_RGMII_CFG_TX_CLK_CFG_M GENMASK(4, 2) +#define HSIO_RGMII_CFG_TX_CLK_CFG_X(x) (((x) & GENMASK(4, 2)) >> 2) + +#define HSIO_RGMII_CFG_RGMII_TX_RST(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_RGMII_CFG_RGMII_TX_RST_M GENMASK(1, 1) +#define HSIO_RGMII_CFG_RGMII_TX_RST_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_RGMII_CFG_RGMII_RX_RST(x) ((x) & GENMASK(0, 0)) +#define HSIO_RGMII_CFG_RGMII_RX_RST_M GENMASK(0, 0) +#define HSIO_RGMII_CFG_RGMII_RX_RST_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:HW_CFGSTAT:RMII_CFG */ +#define HSIO_RMII_CFG(r) __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 28, r, 2, 4) + +#define HSIO_RMII_CFG_REF_CLK_SEL(x) (((x) << 6) & GENMASK(6, 6)) +#define HSIO_RMII_CFG_REF_CLK_SEL_M GENMASK(6, 6) +#define HSIO_RMII_CFG_REF_CLK_SEL_X(x) (((x) & GENMASK(6, 6)) >> 6) + +#define HSIO_RMII_CFG_CFG_TX_EDGE(x) (((x) << 5) & GENMASK(5, 5)) +#define HSIO_RMII_CFG_CFG_TX_EDGE_M GENMASK(5, 5) +#define HSIO_RMII_CFG_CFG_TX_EDGE_X(x) (((x) & GENMASK(5, 5)) >> 5) + +#define HSIO_RMII_CFG_FDX_CFG(x) (((x) << 4) & GENMASK(4, 4)) +#define HSIO_RMII_CFG_FDX_CFG_M GENMASK(4, 4) +#define HSIO_RMII_CFG_FDX_CFG_X(x) (((x) & GENMASK(4, 4)) >> 4) + +#define HSIO_RMII_CFG_SPEED_CFG(x) (((x) << 3) & GENMASK(3, 3)) +#define HSIO_RMII_CFG_SPEED_CFG_M GENMASK(3, 3) +#define HSIO_RMII_CFG_SPEED_CFG_X(x) (((x) & GENMASK(3, 3)) >> 3) + +#define HSIO_RMII_CFG_RMII_TX_RST(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_RMII_CFG_RMII_TX_RST_M GENMASK(2, 2) +#define HSIO_RMII_CFG_RMII_TX_RST_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_RMII_CFG_RMII_RX_RST(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_RMII_CFG_RMII_RX_RST_M GENMASK(1, 1) +#define HSIO_RMII_CFG_RMII_RX_RST_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_RMII_CFG_RMII_ENA(x) ((x) & GENMASK(0, 0)) +#define HSIO_RMII_CFG_RMII_ENA_M GENMASK(0, 0) +#define HSIO_RMII_CFG_RMII_ENA_X(x) ((x) & GENMASK(0, 0)) + +/* HSIO:HW_CFGSTAT:DLL_CFG */ +#define HSIO_DLL_CFG(r) __REG(TARGET_HSIO,\ + 0, 1, 104, 0, 1, 52, 36, r, 4, 4) + +#define HSIO_DLL_CFG_DLL_CLK_ENA(x) (((x) << 20) & GENMASK(20, 20)) +#define HSIO_DLL_CFG_DLL_CLK_ENA_M GENMASK(20, 20) +#define HSIO_DLL_CFG_DLL_CLK_ENA_X(x) (((x) & GENMASK(20, 20)) >> 20) + +#define HSIO_DLL_CFG_BIST_PASS(x) (((x) << 19) & GENMASK(19, 19)) +#define HSIO_DLL_CFG_BIST_PASS_M GENMASK(19, 19) +#define HSIO_DLL_CFG_BIST_PASS_X(x) (((x) & GENMASK(19, 19)) >> 19) + +#define HSIO_DLL_CFG_BIST_END(x) (((x) << 18) & GENMASK(18, 18)) +#define HSIO_DLL_CFG_BIST_END_M GENMASK(18, 18) +#define HSIO_DLL_CFG_BIST_END_X(x) (((x) & GENMASK(18, 18)) >> 18) + +#define HSIO_DLL_CFG_BIST_START(x) (((x) << 17) & GENMASK(17, 17)) +#define HSIO_DLL_CFG_BIST_START_M GENMASK(17, 17) +#define HSIO_DLL_CFG_BIST_START_X(x) (((x) & GENMASK(17, 17)) >> 17) + +#define HSIO_DLL_CFG_TAP_SEL(x) (((x) << 10) & GENMASK(16, 10)) +#define HSIO_DLL_CFG_TAP_SEL_M GENMASK(16, 10) +#define HSIO_DLL_CFG_TAP_SEL_X(x) (((x) & GENMASK(16, 10)) >> 10) + +#define HSIO_DLL_CFG_TAP_ADJ(x) (((x) << 3) & GENMASK(9, 3)) +#define HSIO_DLL_CFG_TAP_ADJ_M GENMASK(9, 3) +#define HSIO_DLL_CFG_TAP_ADJ_X(x) (((x) & GENMASK(9, 3)) >> 3) + +#define HSIO_DLL_CFG_DELAY_ENA(x) (((x) << 2) & GENMASK(2, 2)) +#define HSIO_DLL_CFG_DELAY_ENA_M GENMASK(2, 2) +#define HSIO_DLL_CFG_DELAY_ENA_X(x) (((x) & GENMASK(2, 2)) >> 2) + +#define HSIO_DLL_CFG_DLL_ENA(x) (((x) << 1) & GENMASK(1, 1)) +#define HSIO_DLL_CFG_DLL_ENA_M GENMASK(1, 1) +#define HSIO_DLL_CFG_DLL_ENA_X(x) (((x) & GENMASK(1, 1)) >> 1) + +#define HSIO_DLL_CFG_DLL_RST(x) ((x) & GENMASK(0, 0)) +#define HSIO_DLL_CFG_DLL_RST_M GENMASK(0, 0) +#define HSIO_DLL_CFG_DLL_RST_X(x) ((x) & GENMASK(0, 0)) + +#endif /* _LAN966X_HSIO_REGS_H_ */ diff --git a/include/dt-bindings/phy/lan966x_serdes.h b/include/dt-bindings/phy/lan966x_serdes.h new file mode 100644 index 000000000000..0e2097b1bfcf --- /dev/null +++ b/include/dt-bindings/phy/lan966x_serdes.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ + +#ifndef __PHY_LAN966X_SERDES_H__ +#define __PHY_LAN966X_SERDES_H__ + +#define CU(x) (x) +#define CU_MAX CU(2) +#define SERDES6G(x) (CU_MAX + 1 + (x)) +#define SERDES6G_MAX SERDES6G(3) +#define RG(x) (SERDES6G_MAX + 1 + (x)) +#define RG_MAX RG(2) +#define SERDES_MAX (RG_MAX + 1) + +#endif From patchwork Mon Sep 20 09:52:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505003 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0B097C4332F for ; Mon, 20 Sep 2021 09:52:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E95FA60240 for ; Mon, 20 Sep 2021 09:52:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236486AbhITJx2 (ORCPT ); Mon, 20 Sep 2021 05:53:28 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:10199 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234935AbhITJww (ORCPT ); Mon, 20 Sep 2021 05:52:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131486; x=1663667486; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=epnho9O5xG1dOE7FuOlq6UtUNvkMiFANBOevGHC00ZQ=; b=I0qijL1BWMDeavkjxwrzwgDme1eXZmK+QkAVSvg4/jugJmGZkKtrfbDv tk3qySqot45MVJbWV2WQ99NUTZ10+lER8Omo6O8UhqD4OBlHS91rIfYNc B100JO/BjgqR4EpJuJTgfaoWAd46h7iPe1ZRHKC7r5fFpqrZ36XLQ/5Nv LQX/Q7wsSBktiNxPTxe51uXUz4kfnaTST4ZwRh26dlwdFoSrCbRz9xCMj VhE5Jx5dJzkm9S/XaR4fYFeyNj8B2fvEdnakr+zw4WRC8R1Ith9JN9w3Y 10f5Vn1iumwFrufoaIcJLfCEwQkruOi1XGse3uEaegROUZMgp5VJXnnJX w==; IronPort-SDR: NN3n1DQFdaLsdSeLWhSkemH3KPp5v4kIcA2aZjl1TUXQfM+F0zlmBw1AYGV2p3a8IznIpGn2E6 4Jy6VUPoAhOx/JX/hTvf6jV0HCVg9jq+/Y8e29JK2eE9dmEmJ8wvLvQ4PYbO1ICBn7n+S3dxa/ g5aZYnWUrmXcrGOCWtP9KK/oQUszWHRM19sGUnj25ym2+4h7wQf2F/22GWIvviwJkWXb1xGloo u9Dzzezr/K0ke8F1ms2Wfr56Yxiqwnuspy7L4JKq/SLPaqbXLSKmDRxmRWYoEsyMUY61rZsLML 11nXe+A1CFal8t9WMXe6JlA2 X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="137192382" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:25 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:25 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:22 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 04/12] dt-bindings: reset: Add lan966x switch reset bindings Date: Mon, 20 Sep 2021 11:52:10 +0200 Message-ID: <20210920095218.1108151-5-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Document the lan966x switch reset device driver bindings Signed-off-by: Horatiu Vultur --- .../bindings/reset/lan966x,rst.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/lan966x,rst.yaml diff --git a/Documentation/devicetree/bindings/reset/lan966x,rst.yaml b/Documentation/devicetree/bindings/reset/lan966x,rst.yaml new file mode 100644 index 000000000000..97d6334e4e0a --- /dev/null +++ b/Documentation/devicetree/bindings/reset/lan966x,rst.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/reset/lan966x,rst.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Microchip lan966x Switch Reset Controller + +maintainers: + - Horatiu Vultur + - UNGLinuxDriver@microchip.com + +description: | + The Microchip lan966x Switch provides reset control and implements the + following + functions + - One Time Switch Core Reset (Soft Reset) + +properties: + $nodename: + pattern: "^reset-controller$" + + compatible: + const: microchip,lan966x-switch-reset + + "#reset-cells": + const: 1 + + cpu-syscon: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: syscon used to access CPU reset + + switch-syscon: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: syscon used to access SWITCH reset + + chip-syscon: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: syscon used to access CHIP reset + +required: + - compatible + - "#reset-cells" + - cpu-syscon + - switch-syscon + - chip-syscon + +additionalProperties: false + +examples: + - | + reset: reset-controller { + compatible = "microchip,lan966x-switch-reset"; + #reset-cells = <1>; + cpu-syscon = <&cpu_ctrl>; + switch-syscon = <&switch_ctrl>; + chip-syscon = <&chip_ctrl>; + }; From patchwork Mon Sep 20 09:52:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505005 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51040C433FE for ; Mon, 20 Sep 2021 09:52:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 398EB60240 for ; Mon, 20 Sep 2021 09:52:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236940AbhITJxb (ORCPT ); Mon, 20 Sep 2021 05:53:31 -0400 Received: from esa.microchip.iphmx.com ([68.232.154.123]:62192 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236515AbhITJw4 (ORCPT ); Mon, 20 Sep 2021 05:52:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131490; x=1663667490; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+uznXalaLE+P10gWuj/wsDZ+JtTg3F/3Ho8CxZ4ZLO0=; b=eWyMPop9CvgcVO/U6+PqkaZc2M5Sy+guLSJ5Q/vjR7bG8+iMSAGAINEM 4FkEx7+I/sT0GgfSMIBtEP8byRtJSY6iwTPdCsnLzLvyZJgPW+kgGvQ+s W0pNyFc0cXfmNf+7g/nwMrrP2aFXJL9UgPutjOGUdlJIF57qb1mFuFu0Z F5C95bWe2Qx9rIFGnIOYSAXppTcC+2fCIETLJe5nAv9rJGwGNrfpxegn0 Qg8KJWwiAOYCBZ9015G5kgQ1hPV+vNzYRRBqcVzxmfRZHzsHhtppO3uqz UbaUN+HjzAVmZ+xCGWiG/ebrNm8hK2uJETnNoFdKTC1KRuoFWLwdEXQNk g==; IronPort-SDR: YAvvO3EKM2UzLHtAekGuoC7kHPzMKd+k/UMtVj7b3r0IJQzCpXvwray0yH9E/0u0gPq1BQmA0Q t7uTJwRQNKZKVpnH5ZW7uw2UyHEjvor6EL8ZuYON0Jl0ygwkmWAgp9bqncQKpc4nT5acaYKA1N rM+QzMSSsSCxR3blHfeb3aP9nKTbiExDxeBd/y/k+iQPjaWnHBBOnFlegjY08uNIRcWaylLZiw Nw7/oARzDO3PK302E/IV+dQb06t7pD3fOgwwm6DNhKOrcOA3lhSLyRMo30XI2ByX28eabDU+yR gIi8gp9Ag4AUuvSdREkXoN7Y X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="132434729" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:29 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:28 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:25 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 05/12] reset: lan966x: Add switch reset driver Date: Mon, 20 Sep 2021 11:52:11 +0200 Message-ID: <20210920095218.1108151-6-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The lan966x switch SoC has a number of components that can be reset indiviually, but at least the switch core needs to be in a well defined state at power on, when any of the lan966x drivers starts to access the switch core, this reset driver is available. The reset driver is loaded early via the postcore_initcall interface, and will then be available for the other lan966x drivers (SGPIO, SwitchDev etc) that are loaded next, and the first of them to be loaded can perform the one-time switch core reset that is needed. Signed-off-by: Horatiu Vultur --- drivers/reset/Kconfig | 8 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-lan966x.c | 128 ++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/reset/reset-lan966x.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index be799a5abf8a..93f19303ebac 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -108,6 +108,14 @@ config RESET_LANTIQ help This enables the reset controller driver for Lantiq / Intel XWAY SoCs. +config RESET_LAN966X + bool "Microchip LAN966X Reset Driver" + depends on HAS_IOMEM || COMPILE_TEST + default y if LAN966X_SWITCH + select MFD_SYSCON + help + This driver supports switch core reset for the Microchip LAN966X SoC. + config RESET_LPC18XX bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST default ARCH_LPC18XX diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 21d46d8869ff..3358f491e617 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o obj-$(CONFIG_RESET_K210) += reset-k210.o +obj-$(CONFIG_RESET_LAN966X) += reset-lan966x.o obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o diff --git a/drivers/reset/reset-lan966x.c b/drivers/reset/reset-lan966x.c new file mode 100644 index 000000000000..3d4fe31653db --- /dev/null +++ b/drivers/reset/reset-lan966x.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries. */ + +#include +#include +#include +#include +#include +#include + +#define PROTECT_REG 0x88 +#define PROTECT_BIT BIT(5) +#define SOFT_RESET_REG 0x00 +#define SOFT_RESET_BIT BIT(1) +#define CHIP_COMMON_REG 0x10 +#define CHIP_COMMON_BIT BIT(0) + +struct mchp_reset_context { + struct regmap *cpu_ctrl; + struct regmap *switch_ctrl; + struct regmap *chip_ctrl; + struct reset_controller_dev rcdev; +}; + +static int lan966x_switch_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct mchp_reset_context *ctx = + container_of(rcdev, struct mchp_reset_context, rcdev); + u32 val; + int ret; + + /* Make sure the core is PROTECTED from reset */ + regmap_update_bits(ctx->cpu_ctrl, PROTECT_REG, PROTECT_BIT, PROTECT_BIT); + + /* Start soft reset */ + regmap_write(ctx->switch_ctrl, SOFT_RESET_REG, SOFT_RESET_BIT); + + /* Wait for soft reset done */ + ret = regmap_read_poll_timeout(ctx->switch_ctrl, SOFT_RESET_REG, val, + (val & SOFT_RESET_BIT) == 0, 1, 100); + if (ret) + return ret; + + /* Release the reset of internal PHY */ + regmap_update_bits(ctx->chip_ctrl, CHIP_COMMON_REG, CHIP_COMMON_BIT, + CHIP_COMMON_BIT); + + return 0; +} + +static const struct reset_control_ops lan966x_reset_ops = { + .reset = lan966x_switch_reset, +}; + +static int mchp_lan966x_map_syscon(struct platform_device *pdev, char *name, + struct regmap **target) +{ + struct device_node *syscon_np; + struct regmap *regmap; + int err; + + syscon_np = of_parse_phandle(pdev->dev.of_node, name, 0); + if (!syscon_np) + return -ENODEV; + regmap = syscon_node_to_regmap(syscon_np); + of_node_put(syscon_np); + if (IS_ERR(regmap)) { + err = PTR_ERR(regmap); + dev_err(&pdev->dev, "No '%s' map: %d\n", name, err); + return err; + } + + *target = regmap; + return 0; +} + +static int mchp_lan966x_reset_probe(struct platform_device *pdev) +{ + struct device_node *dn = pdev->dev.of_node; + struct mchp_reset_context *ctx; + int err; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + err = mchp_lan966x_map_syscon(pdev, "cpu-syscon", &ctx->cpu_ctrl); + if (err) + return err; + + err = mchp_lan966x_map_syscon(pdev, "switch-syscon", &ctx->switch_ctrl); + if (err) + return err; + + err = mchp_lan966x_map_syscon(pdev, "chip-syscon", &ctx->chip_ctrl); + if (err) + return err; + + ctx->rcdev.owner = THIS_MODULE; + ctx->rcdev.nr_resets = 1; + ctx->rcdev.ops = &lan966x_reset_ops; + ctx->rcdev.of_node = dn; + + return devm_reset_controller_register(&pdev->dev, &ctx->rcdev); +} + +static const struct of_device_id mchp_lan966x_reset_of_match[] = { + { + .compatible = "microchip,lan966x-switch-reset", + }, + { } +}; + +static struct platform_driver mchp_lan966x_reset_driver = { + .probe = mchp_lan966x_reset_probe, + .driver = { + .name = "lan966x-switch-reset", + .of_match_table = mchp_lan966x_reset_of_match, + }, +}; + +static int __init mchp_lan966x_reset_init(void) +{ + return platform_driver_register(&mchp_lan966x_reset_driver); +} + +postcore_initcall(mchp_lan966x_reset_init); From patchwork Mon Sep 20 09:52:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505007 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0082C433FE for ; Mon, 20 Sep 2021 09:52:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DBCA760240 for ; Mon, 20 Sep 2021 09:52:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237016AbhITJxe (ORCPT ); Mon, 20 Sep 2021 05:53:34 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:11415 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236534AbhITJw7 (ORCPT ); Mon, 20 Sep 2021 05:52:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131492; x=1663667492; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZEHpommCSL8ojew2FKcV/eSvyPSOisfjZXiNWmXORXQ=; b=uAxNDDin+q8p2ErUHeNFaepLceXUxu4NJkNTk7Hc5hF0Qtz05/JsKYXY qauiAuzbaxGC0sTtdK+Ht3kr9nS7oPKRsgTaLTBsj7kCxrZUwJFHCrAfy TfY6vdMIhbKQXYJ4FwHFtKPyGblhGBsX/lRPeLOL5Sv6ZB0hIWVGcPsT0 l1YroYFFAzs8gUbB4fxqkzrZwZLdEsOovO0QHetWXv7ZZAkbuk/YTTqlr xlohoi5dL6jdmQ9qr/u5L2MQGRGIC7k7YDREY0HNV4eqRH8F3neI9ir3U tfMfpYGM41mkIn/LMjVQtUFoq11dQACq6/FLhx2EIQtfkDTc9SKNY91fA w==; IronPort-SDR: /VIa/E1EPeAc4amqqBCs797uYYeQ+iKJohFqTZvxAroYcVpxBMbeOkpgo292OGc3PMDu71kYZ1 U03DqAils8YMz5lDMtCUjWg8/gxs56rcJBiIruPTIOI4+UrDi1Njpmn7mEiYAU1DTI6t4+9HZX o7ZCp8EpBlYpC16ddMldHeonBlQZVMzQQqDFhGKG0yuOH+F/sy+DvYBtwLueRguTD2Ulg7ryVN sQTl5n7X3jNDuB09rCIppRhF7lj3dqHabddfb0II40yH0b7qz01PcHMdI/CHHYky4usJgHPFge +1wI3BT7DaGSVuJJTAbIlkKF X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="137192394" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:31 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:31 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:28 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 06/12] dt-bindings: reset: Add lan966x power reset bindings Date: Mon, 20 Sep 2021 11:52:12 +0200 Message-ID: <20210920095218.1108151-7-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Document the lan966x power reset device driver bindings Signed-off-by: Horatiu Vultur --- .../bindings/power/lan966x,power.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/lan966x,power.yaml diff --git a/Documentation/devicetree/bindings/power/lan966x,power.yaml b/Documentation/devicetree/bindings/power/lan966x,power.yaml new file mode 100644 index 000000000000..d10eec10089b --- /dev/null +++ b/Documentation/devicetree/bindings/power/lan966x,power.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/power/lan966x,power.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Microchip Lan966x Power Reset Controller + +maintainers: + - Horatiu Vultur + - UNGLinuxDriver@microchip.com + +description: | + The Microchip Lan966x SoC provides power reset control. + +properties: + $nodename: + pattern: "^chip-controller$" + + compatible: + const: microchip,lan966x-chip-reset + + "#reset-cells": + const: 1 + + cpu-syscon: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: syscon used to access CPU reset + + switch-syscon: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: syscon used to access SWITCH reset + +required: + - compatible + - "#reset-cells" + - cpu-syscon + - switch-syscon + +additionalProperties: false + +examples: + - | + reset: chip-controller { + compatible = "microchip,lan966x-chip-reset"; + #reset-cells = <1>; + cpu-syscon = <&cpu_ctrl>; + switch-syscon = <&switch_ctrl>; + }; From patchwork Mon Sep 20 09:52:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505011 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ACCF8C433EF for ; Mon, 20 Sep 2021 09:52:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9339860240 for ; Mon, 20 Sep 2021 09:52:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236684AbhITJxk (ORCPT ); Mon, 20 Sep 2021 05:53:40 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:34025 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236564AbhITJxC (ORCPT ); Mon, 20 Sep 2021 05:53:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131496; x=1663667496; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=V0cRVTs8okspyQRslFZu0Mma4o7oiAMrkzAAMlvxVPM=; b=rf21rt38Wnuqvvov3xlpOJFV8cu21D05Vv/Uet/Yws7AI8Xd1O9KB2c3 69u/6hF+jY0Ru07sdrC/OLGCgD2mn+rqq/onOtd9+p4U8l3FyR5Eh4bDa 6V4qcLqFs6rqpN8iDzIAKK8jiEPjC6bTUCoQO6/oBz2ZS8skA/XgBBWtX 6hsZzMMxUTFetn0/9R88JFyZeN4YSm/s+EPcD9fvzNd66iOQkuZP/ZjKA RYaiobMSwMkdHgNM5goA7NHF2rlp0AUmhfmyvJ4p8HPluTajMdYXmAWjb RG2WVpIQdUXb9Mo6FJPkDH1XjELxWFmr26qJBVqSe7BUKVWVFhxe9Xyp4 g==; IronPort-SDR: XN/p8TY7fE99+HQpujKoIm22iH0+Fx/3OaJVNsR9dx7iK9eXeYwObLGCXNEgkO/JYorAdxS0X8 Doze4XnidpLfc4rgpuv0wAZW5NIqzVholGlE8SjYrzEdvaqtMkX12n5wsTmkLs6CpX7+bszQ8C GIg7HGyxtdw8yswSeebA0SkOeySJFKgz8PzB9Bsokth5b863i9/d3tlw6sFWnG2HEB/2cReJwf W4MquQUrM0xcZmOFkN+VnKm4JTf3okMXJoGj+o5SXRIPsXBy1EJLdsgpIk4pUJbh+NsoIP98/Q 3JrbkpUS24n0beCgXOU1OXdD X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="136598682" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:35 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:34 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:31 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 07/12] power: reset: Add lan966x power reset driver Date: Mon, 20 Sep 2021 11:52:13 +0200 Message-ID: <20210920095218.1108151-8-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This adds a driver for lan966x to allow a software reset. Signed-off-by: Horatiu Vultur --- drivers/power/reset/Kconfig | 6 ++ drivers/power/reset/Makefile | 1 + drivers/power/reset/lan966x-reset.c | 90 +++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 drivers/power/reset/lan966x-reset.c diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 4b563db3ab3e..755b60c143da 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -158,6 +158,12 @@ config POWER_RESET_PIIX4_POWEROFF southbridge SOff state is entered in response to a request to power off the system. +config POWER_RESET_LAN966X + bool "Microchip Lan966x reset driver" + select MFD_SYSCON + help + This driver supports restart for Microchip Lan966x. + config POWER_RESET_LTC2952 bool "LTC2952 PowerPath power-off driver" depends on OF_GPIO diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index f606a2f60539..0fbc817c4eb6 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o +obj-$(CONFIG_POWER_RESET_LAN966X) += lan966x-reset.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o diff --git a/drivers/power/reset/lan966x-reset.c b/drivers/power/reset/lan966x-reset.c new file mode 100644 index 000000000000..612705b680fe --- /dev/null +++ b/drivers/power/reset/lan966x-reset.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * License: Dual MIT/GPL + * Copyright (c) 2020 Microchip Corporation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *cpu_syscon = "microchip,lan966x-cpu-syscon"; +static const char *gcb_syscon = "microchip,lan966x-switch-syscon"; + +struct lan966x_reset_context { + struct regmap *gcb_ctrl; + struct regmap *cpu_ctrl; + struct notifier_block restart_handler; +}; + +#define PROTECT_REG 0x88 +#define PROTECT_BIT BIT(5) +#define SOFT_RESET_REG 0x00 +#define SOFT_RESET_BIT BIT(1) + +static int lan966x_restart_handle(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct lan966x_reset_context *ctx = container_of(this, struct lan966x_reset_context, + restart_handler); + + /* Make sure the core is not protected from reset */ + regmap_update_bits(ctx->cpu_ctrl, PROTECT_REG, PROTECT_BIT, 0); + + pr_emerg("Resetting SoC\n"); + + regmap_write(ctx->gcb_ctrl, SOFT_RESET_REG, SOFT_RESET_BIT); + + pr_emerg("Unable to restart system\n"); + return NOTIFY_DONE; +} + +static int lan966x_reset_probe(struct platform_device *pdev) +{ + struct lan966x_reset_context *ctx; + struct device *dev = &pdev->dev; + int err; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->gcb_ctrl = syscon_regmap_lookup_by_compatible(gcb_syscon); + if (IS_ERR(ctx->gcb_ctrl)) { + dev_err(dev, "No gcb_syscon map: %s\n", gcb_syscon); + return PTR_ERR(ctx->gcb_ctrl); + } + + ctx->cpu_ctrl = syscon_regmap_lookup_by_compatible(cpu_syscon); + if (IS_ERR(ctx->cpu_ctrl)) { + dev_err(dev, "No cpu_syscon map: %s\n", cpu_syscon); + return PTR_ERR(ctx->cpu_ctrl); + } + + ctx->restart_handler.notifier_call = lan966x_restart_handle; + ctx->restart_handler.priority = 192; + err = register_restart_handler(&ctx->restart_handler); + if (err) + dev_err(dev, "can't register restart notifier (err=%d)\n", err); + + return err; +} + +static const struct of_device_id lan966x_reset_of_match[] = { + { .compatible = "microchip,lan966x-chip-reset", }, + { /*sentinel*/ } +}; + +static struct platform_driver lan966x_reset_driver = { + .probe = lan966x_reset_probe, + .driver = { + .name = "lan966x-chip-reset", + .of_match_table = lan966x_reset_of_match, + }, +}; +builtin_platform_driver(lan966x_reset_driver); From patchwork Mon Sep 20 09:52:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505009 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3579C433F5 for ; Mon, 20 Sep 2021 09:52:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9DA6460240 for ; Mon, 20 Sep 2021 09:52:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237054AbhITJxi (ORCPT ); Mon, 20 Sep 2021 05:53:38 -0400 Received: from esa.microchip.iphmx.com ([68.232.154.123]:37452 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236659AbhITJxF (ORCPT ); Mon, 20 Sep 2021 05:53:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131498; x=1663667498; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v2p9zB2T0M+VqtAMlG8d1u3L/QbMvNcyT4xgvitDt3Q=; b=qv7IesJ5oO2JlwNLiJpQF9Ffs4YxjBd5fhk0H6pI2Dda0bxH7kNU9Q86 GEG9hOw6ZhD41ZMAev7WR1gNavWCpO02MdRxqf/0qIm0gzueemNrZobzB /h+zcakiyi1Z2gZoVul0B2oxxXycIv8RRH2OQDKaJG++0DNvL9vbOc1yV sxdQ60+7o4yzIRjA83hPFoZAUrQtrSf2nkUDPQjkxfzDNybO5pqap6QIr +r9xCzMbYvM7GqmQTRrw2CmneMC05/6l1ugsr7cRHnaiFbMWVQNCgj4bw UHnCZbCVsyiqofzP7Jh6gVOCIFrV7eWFe3G/NSRRyRXCLhPyKKYaHtTnf Q==; IronPort-SDR: ycOvQIoYZElp25Zole7n3xeYbOUN6GvZTQAkvL1FUfLT6CfHv2SK/9PN0hoWCidP+u6hIfqA51 NDpIfYetjSjwwwdWbCet425cXbXwVmXDl5Vncg35v1kX1io5LfkaF6VsRCtPcRhNeH2j2EE0ou CXGROvBg5WsPb3e56V6ebzv92Jh+fn5rRwRJ8yVFSVfjIHUAZbq/c3veGRKM5WQQ7pPc69VO8y gkMfnhko+4smU5okFlSJPnWrzx02ZK89x1dRJyrzvnEx1EhPXm4fZbB2tQAYbZRYJrvzpw5gSa 2BpE1XI450dVyMb5SCyD2x7q X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="129913585" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:37 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:38 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:35 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 08/12] dt-bindings: net: lan966x: Add lan966x-switch bindings Date: Mon, 20 Sep 2021 11:52:14 +0200 Message-ID: <20210920095218.1108151-9-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Document the lan966x switch device driver bindings Signed-off-by: Horatiu Vultur --- .../net/microchip,lan966x-switch.yaml | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/microchip,lan966x-switch.yaml diff --git a/Documentation/devicetree/bindings/net/microchip,lan966x-switch.yaml b/Documentation/devicetree/bindings/net/microchip,lan966x-switch.yaml new file mode 100644 index 000000000000..53d72a65c168 --- /dev/null +++ b/Documentation/devicetree/bindings/net/microchip,lan966x-switch.yaml @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/microchip,lan966x-switch.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Lan966x Ethernet switch controller + +maintainers: + - Horatiu Vultur + - UNGLinuxDriver@microchip.com + +description: | + The Lan966x Enterprise Ethernet switch family provides a rich set of + Enterprise switching features such as advanced TCAM-based VLAN and + QoS processing enabling delivery of differentiated services, and + security through TCAM-based frame processing using versatile content + aware processor (VCAP). + +properties: + $nodename: + pattern: "^switch@[0-9a-f]+$" + + compatible: + const: microchip,lan966x-switch + + reg: + items: + - description: cpu target + - description: devices target + - description: general control block target + + reg-names: + items: + - const: cpu + - const: devices + - const: gcb + + interrupts: + minItems: 1 + items: + - description: register based extraction + + interrupt-names: + minItems: 1 + items: + - const: xtr + + mac-address: true + + ethernet-ports: + type: object + patternProperties: + "^port@[0-9a-f]+$": + type: object + + properties: + '#address-cells': + const: 1 + '#size-cells': + const: 0 + + reg: + description: Switch port number + + phy-mode: + description: + This specifies the interface used by the Ethernet SerDes towards + the PHY or SFP. + + phy-handle: + description: + phandle of a Ethernet PHY. + + required: + - reg + - phy-mode + - phy-handle + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - ethernet-ports + +additionalProperties: false + +examples: + - | + #include + switch: switch@600000000 { + compatible = "microchip,lan966x-switch"; + reg = <0 0x401000>, + <0x10004000 0x7fc000>, + <0x11010000 0xaf0000>; + reg-names = "cpu", "devices", "gcb"; + interrupts = ; + interrupt-names = "xtr"; + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + phy-mode = "gmii"; + }; + }; + }; + +... +# vim: set ts=2 sw=2 sts=2 tw=80 et cc=80 ft=yaml : From patchwork Mon Sep 20 09:52:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505013 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UPPERCASE_50_75,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1DEBC433EF for ; Mon, 20 Sep 2021 09:52:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D95D360240 for ; Mon, 20 Sep 2021 09:52:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236989AbhITJxq (ORCPT ); Mon, 20 Sep 2021 05:53:46 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:11429 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236686AbhITJxI (ORCPT ); Mon, 20 Sep 2021 05:53:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131502; x=1663667502; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ceHtQV4wksUjkp+UF2+oQrI1Yiac9ttanC9sGh+HWew=; b=wHKhbsXLtDEEP+YhuDtwMriAJYyaxzfCGC7P0zfFVA9C26JzR9x99IDX ia/KBjbsKuIeaXgG+1ffrwRmcAPvEp65EIaawrE9mAsDP1EQebBM4ts5z T9nkanCF0K9xl0IuggoiDj+HscbfQ6jyNyi16BFjBH9k3UXnfV7FC5ptW I55QIdW0Mrwjq51QHVWXeB2ABYWIXfnsUKUUHx2HuCOfItIewRTHLE3Xn lBy/cuRJ6uT9hnxdOWwk4V3hMjl4nJiTx5myttjCC7cYP+OhHqEmPLUKW TDuWddCcSAjTs7HjiifuuzEVNTxFIMCqtLb9rWsdNw2GHixhi90mfA3Op g==; IronPort-SDR: K4mGDpYI/y+3WD+q/c4pjFb6bCoKk4/mIMSVFHFpF6sFX8v4iXUAw+M6t7+dX9f2WfXyD/Wb02 M/q3wmk0KmMtyv2rUR5uKfLQsmiJmNvgID80tTIOkfoWQBWSL2XFePVI8mGiMsIDDHZBizihj1 8yQrYzjZAMkpm7Z4Ab1q4PPowobIYwyZYU5eCcKRrr2meQOdIy9SX21G9hLDCEBOMu/3OE54fR FBn4PBS5NE9Hko3WQ1cGR0tTfBwPumEs4NaXkyFddw9SH8QI4WHViA7TMiuUMeZlfCPSpLZLJi miAaDmv2Xn4yi0NogHjO4k7Y X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="137192406" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:41 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:41 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:38 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 09/12] net: lan966x: add the basic lan966x driver Date: Mon, 20 Sep 2021 11:52:15 +0200 Message-ID: <20210920095218.1108151-10-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This patch adds basic SwitchDev driver framework for lan966x. It includes only the IO range mapping and probing of the switch. Signed-off-by: Horatiu Vultur --- drivers/net/ethernet/microchip/Kconfig | 1 + drivers/net/ethernet/microchip/Makefile | 1 + .../net/ethernet/microchip/lan966x/Kconfig | 7 + .../net/ethernet/microchip/lan966x/Makefile | 8 + .../ethernet/microchip/lan966x/lan966x_main.c | 350 +++++++++ .../ethernet/microchip/lan966x/lan966x_main.h | 105 +++ .../ethernet/microchip/lan966x/lan966x_regs.h | 704 ++++++++++++++++++ 7 files changed, 1176 insertions(+) create mode 100644 drivers/net/ethernet/microchip/lan966x/Kconfig create mode 100644 drivers/net/ethernet/microchip/lan966x/Makefile create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_main.c create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_main.h create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_regs.h diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 735eea1dacf1..ed7a35c3ceac 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -55,6 +55,7 @@ config LAN743X To compile this driver as a module, choose M here. The module will be called lan743x. +source "drivers/net/ethernet/microchip/lan966x/Kconfig" source "drivers/net/ethernet/microchip/sparx5/Kconfig" endif # NET_VENDOR_MICROCHIP diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile index c77dc0379bfd..9faa41436198 100644 --- a/drivers/net/ethernet/microchip/Makefile +++ b/drivers/net/ethernet/microchip/Makefile @@ -9,4 +9,5 @@ obj-$(CONFIG_LAN743X) += lan743x.o lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o +obj-$(CONFIG_LAN966X_SWITCH) += lan966x/ obj-$(CONFIG_SPARX5_SWITCH) += sparx5/ diff --git a/drivers/net/ethernet/microchip/lan966x/Kconfig b/drivers/net/ethernet/microchip/lan966x/Kconfig new file mode 100644 index 000000000000..83ac4266b417 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/Kconfig @@ -0,0 +1,7 @@ +config LAN966X_SWITCH + tristate "Lan966x switch driver" + depends on HAS_IOMEM + depends on OF + select PHYLINK + help + This driver supports the Lan966x network switch device. diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile new file mode 100644 index 000000000000..7ea90410a0b2 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for the Microchip Lan966x network device drivers. +# + +obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o + +lan966x-switch-objs := lan966x_main.o diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c new file mode 100644 index 000000000000..2984f510ae27 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include + +#include "lan966x_main.h" + +#define READL_SLEEP_US 10 +#define READL_TIMEOUT_US 100000000 + +#define IO_RANGES 2 + +static const struct of_device_id lan966x_match[] = { + { .compatible = "microchip,lan966x-switch" }, + { } +}; +MODULE_DEVICE_TABLE(of, mchp_lan966x_match); + +struct lan966x_main_io_resource { + enum lan966x_target id; + phys_addr_t offset; + int range; +}; + +static const struct lan966x_main_io_resource lan966x_main_iomap[] = { + { TARGET_CPU, 0xc0000, 0 }, /* 0xe00c0000 */ + { TARGET_ORG, 0, 1 }, /* 0xe2000000 */ + { TARGET_GCB, 0x4000, 1 }, /* 0xe2004000 */ + { TARGET_QS, 0x8000, 1 }, /* 0xe2008000 */ + { TARGET_CHIP_TOP, 0x10000, 1 }, /* 0xe2010000 */ + { TARGET_REW, 0x14000, 1 }, /* 0xe2014000 */ + { TARGET_SYS, 0x28000, 1 }, /* 0xe2028000 */ + { TARGET_HSIO, 0x2c000, 1 }, /* 0xe202c000 */ + { TARGET_DEV, 0x34000, 1 }, /* 0xe2034000 */ + { TARGET_DEV + 1, 0x38000, 1 }, /* 0xe2038000 */ + { TARGET_DEV + 2, 0x3c000, 1 }, /* 0xe203c000 */ + { TARGET_DEV + 3, 0x40000, 1 }, /* 0xe2040000 */ + { TARGET_DEV + 4, 0x44000, 1 }, /* 0xe2044000 */ + { TARGET_DEV + 5, 0x48000, 1 }, /* 0xe2048000 */ + { TARGET_DEV + 6, 0x4c000, 1 }, /* 0xe204c000 */ + { TARGET_DEV + 7, 0x50000, 1 }, /* 0xe2050000 */ + { TARGET_QSYS, 0x100000, 1 }, /* 0xe2100000 */ + { TARGET_AFI, 0x120000, 1 }, /* 0xe2120000 */ + { TARGET_ANA, 0x140000, 1 }, /* 0xe2140000 */ +}; + +static int lan966x_create_targets(struct platform_device *pdev, + struct lan966x *lan966x) +{ + struct resource *iores[IO_RANGES]; + void __iomem *iomem[IO_RANGES]; + void __iomem *begin[IO_RANGES]; + int idx; + + for (idx = 0; idx < IO_RANGES; idx++) { + iores[idx] = platform_get_resource(pdev, IORESOURCE_MEM, + idx); + iomem[idx] = devm_ioremap(&pdev->dev, + iores[idx]->start, + resource_size(iores[idx])); + if (IS_ERR(iomem[idx])) { + dev_err(&pdev->dev, "Unable to get registers: %s\n", + iores[idx]->name); + return PTR_ERR(iomem[idx]); + } + + begin[idx] = iomem[idx]; + } + + for (idx = 0; idx < ARRAY_SIZE(lan966x_main_iomap); idx++) { + const struct lan966x_main_io_resource *iomap = + &lan966x_main_iomap[idx]; + + lan966x->regs[iomap->id] = begin[iomap->range] + iomap->offset; + } + + return 0; +} + +static int lan966x_probe_port(struct lan966x *lan966x, u8 port, + phy_interface_t phy_mode) +{ + struct lan966x_port *lan966x_port; + + if (port >= lan966x->num_phys_ports) + return -EINVAL; + + lan966x_port = devm_kzalloc(lan966x->dev, sizeof(*lan966x_port), + GFP_KERNEL); + + lan966x_port->lan966x = lan966x; + lan966x_port->chip_port = port; + lan966x_port->pvid = PORT_PVID; + lan966x->ports[port] = lan966x_port; + + return 0; +} + +static void lan966x_init(struct lan966x *lan966x) +{ + u32 port, i; + + /* Flush queues */ + lan_wr(lan_rd(lan966x, QS_XTR_FLUSH) | + GENMASK(1, 0), + lan966x, QS_XTR_FLUSH); + + /* Allow to drain */ + mdelay(1); + + /* All Queues normal */ + lan_wr(lan_rd(lan966x, QS_XTR_FLUSH) & + ~(GENMASK(1, 0)), + lan966x, QS_XTR_FLUSH); + + /* Set MAC age time to default value, the entry is aged after + * 2 * AGE_PERIOD + */ + lan_wr(ANA_AUTOAGE_AGE_PERIOD_SET(BR_DEFAULT_AGEING_TIME / 2 / HZ), + lan966x, ANA_AUTOAGE); + + /* Disable learning for frames discarded by VLAN ingress filtering */ + lan_rmw(ANA_ADVLEARN_VLAN_CHK_SET(1), + ANA_ADVLEARN_VLAN_CHK, + lan966x, ANA_ADVLEARN); + + /* Setup frame ageing - "2 sec" - The unit is 6.5 us on lan966x */ + lan_wr(SYS_FRM_AGING_AGE_TX_ENA_SET(1) | + (20000000 / 65), + lan966x, SYS_FRM_AGING); + + /* Map the 8 CPU extraction queues to CPU port */ + lan_wr(0, lan966x, QSYS_CPU_GROUP_MAP); + + /* Do byte-swap and expect status after last data word + * Extraction: Mode: manual extraction) | Byte_swap + */ + lan_wr(QS_XTR_GRP_CFG_MODE_SET(1) | + QS_XTR_GRP_CFG_BYTE_SWAP_SET(1), + lan966x, QS_XTR_GRP_CFG(0)); + + /* Injection: Mode: manual injection | Byte_swap */ + lan_wr(QS_INJ_GRP_CFG_MODE_SET(1) | + QS_INJ_GRP_CFG_BYTE_SWAP_SET(1), + lan966x, QS_INJ_GRP_CFG(0)); + + lan_rmw(QS_INJ_CTRL_GAP_SIZE_SET(0), + QS_INJ_CTRL_GAP_SIZE, + lan966x, QS_INJ_CTRL(0)); + + /* Enable IFH insertion/parsing on CPU ports */ + lan_wr(SYS_PORT_MODE_INCL_INJ_HDR_SET(1) | + SYS_PORT_MODE_INCL_XTR_HDR_SET(1), + lan966x, SYS_PORT_MODE(CPU_PORT)); + + /* Setup flooding PGIDs */ + lan_wr(ANA_FLOODING_IPMC_FLD_MC4_DATA_SET(PGID_MCIPV4) | + ANA_FLOODING_IPMC_FLD_MC4_CTRL_SET(PGID_MC) | + ANA_FLOODING_IPMC_FLD_MC6_DATA_SET(PGID_MC) | + ANA_FLOODING_IPMC_FLD_MC6_CTRL_SET(PGID_MC), + lan966x, ANA_FLOODING_IPMC); + + /* There are 8 priorities */ + for (i = 0; i < 8; ++i) + lan_rmw(ANA_FLOODING_FLD_MULTICAST_SET(PGID_MC) | + ANA_FLOODING_FLD_BROADCAST_SET(PGID_BC), + ANA_FLOODING_FLD_MULTICAST | + ANA_FLOODING_FLD_BROADCAST, + lan966x, ANA_FLOODING(i)); + + for (i = 0; i < PGID_ENTRIES; ++i) + /* Set all the entries to obey VLAN_VLAN */ + lan_rmw(ANA_PGID_CFG_OBEY_VLAN_SET(1), + ANA_PGID_CFG_OBEY_VLAN, + lan966x, ANA_PGID_CFG(i)); + + for (port = 0; port < lan966x->num_phys_ports; port++) { + /* Disable bridging by default */ + lan_rmw(ANA_PGID_PGID_SET(0x0), + ANA_PGID_PGID, + lan966x, ANA_PGID(port + PGID_SRC)); + + /* Do not forward BPDU frames to the front ports and copy them + * to CPU + */ + lan_wr(0xffff, lan966x, ANA_CPU_FWD_BPDU_CFG(port)); + } + + /* Set source buffer size for each priority and each port to 1500 bytes */ + for (i = 0; i <= QSYS_Q_RSRV; ++i) { + lan_wr(1500 / 64, lan966x, QSYS_RES_CFG(i)); + lan_wr(1500 / 64, lan966x, QSYS_RES_CFG(512 + i)); + } + + /* Enable switching to/from cpu port */ + lan_wr(QSYS_SW_PORT_MODE_PORT_ENA_SET(1) | + QSYS_SW_PORT_MODE_SCH_NEXT_CFG_SET(1) | + QSYS_SW_PORT_MODE_INGRESS_DROP_MODE_SET(1), + lan966x, QSYS_SW_PORT_MODE(CPU_PORT)); + + /* Configure and enable the CPU port */ + lan_rmw(ANA_PGID_PGID_SET(0), + ANA_PGID_PGID, + lan966x, ANA_PGID(CPU_PORT)); + lan_rmw(ANA_PGID_PGID_SET(BIT(CPU_PORT)), + ANA_PGID_PGID, + lan966x, ANA_PGID(PGID_CPU)); + + /* Multicast to all other ports */ + lan_rmw(GENMASK(lan966x->num_phys_ports - 1, 0), + ANA_PGID_PGID, + lan966x, ANA_PGID(PGID_MC)); + + /* This will be controlled by mrouter ports */ + lan_rmw(GENMASK(lan966x->num_phys_ports - 1, 0), + ANA_PGID_PGID, + lan966x, ANA_PGID(PGID_MCIPV4)); + + /* Broadcast to the CPU port and to other ports */ + lan_rmw(ANA_PGID_PGID_SET(BIT(CPU_PORT) | GENMASK(lan966x->num_phys_ports - 1, 0)), + ANA_PGID_PGID, + lan966x, ANA_PGID(PGID_BC)); + + lan_wr(REW_PORT_CFG_NO_REWRITE_SET(1), + lan966x, REW_PORT_CFG(CPU_PORT)); + + lan_rmw(ANA_ANAINTR_INTR_ENA_SET(1), + ANA_ANAINTR_INTR_ENA, + lan966x, ANA_ANAINTR); +} + +static int lan966x_ram_init(struct lan966x *lan966x) +{ + return lan_rd(lan966x, SYS_RAM_INIT); +} + +static int lan966x_reset_switch(struct lan966x *lan966x) +{ + struct reset_control *reset; + int val = 0; + int ret; + + reset = devm_reset_control_get_shared(lan966x->dev, "switch"); + if (IS_ERR(reset)) + dev_warn(lan966x->dev, "Could not obtain reset control: %ld\n", + PTR_ERR(reset)); + else + reset_control_reset(reset); + + lan_wr(SYS_RESET_CFG_CORE_ENA_SET(0), lan966x, SYS_RESET_CFG); + lan_wr(SYS_RAM_INIT_RAM_INIT_SET(1), lan966x, SYS_RAM_INIT); + ret = readx_poll_timeout(lan966x_ram_init, lan966x, + val, (val & BIT(1)) == 0, READL_SLEEP_US, + READL_TIMEOUT_US); + if (ret) + return ret; + + lan_wr(SYS_RESET_CFG_CORE_ENA_SET(1), lan966x, SYS_RESET_CFG); + + return 0; +} + +static int lan966x_probe(struct platform_device *pdev) +{ + struct fwnode_handle *ports, *portnp; + struct lan966x *lan966x; + int err, i; + + lan966x = devm_kzalloc(&pdev->dev, sizeof(*lan966x), GFP_KERNEL); + if (!lan966x) + return -ENOMEM; + + platform_set_drvdata(pdev, lan966x); + lan966x->dev = &pdev->dev; + + ports = device_get_named_child_node(&pdev->dev, "ethernet-ports"); + if (!ports) { + dev_err(&pdev->dev, "no ethernet-ports child not found\n"); + err = -ENODEV; + goto out; + } + + err = lan966x_create_targets(pdev, lan966x); + if (err) + goto out; + + if (lan966x_reset_switch(lan966x)) { + err = -EINVAL; + goto out; + } + + i = 0; + fwnode_for_each_available_child_node(ports, portnp) + ++i; + + lan966x->num_phys_ports = i; + lan966x->ports = devm_kcalloc(&pdev->dev, lan966x->num_phys_ports, + sizeof(struct lan966x_port *), + GFP_KERNEL); + + /* There QS system has 32KB of memory */ + lan966x->shared_queue_sz = LAN966X_BUFFER_MEMORY; + + /* init switch */ + lan966x_init(lan966x); + + /* go over the child nodes */ + fwnode_for_each_available_child_node(ports, portnp) { + phy_interface_t phy_mode; + struct phy *serdes; + u32 port; + + if (fwnode_property_read_u32(portnp, "reg", &port)) + continue; + + phy_mode = fwnode_get_phy_mode(portnp); + err = lan966x_probe_port(lan966x, port, phy_mode); + if (err) + return err; + } + + return 0; + +out: + return err; +} + +static int lan966x_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver lan966x_driver = { + .probe = lan966x_probe, + .remove = lan966x_remove, + .driver = { + .name = "lan966x-switch", + .of_match_table = lan966x_match, + }, +}; +module_platform_driver(lan966x_driver); + +MODULE_DESCRIPTION("Microchip LAN966X switch driver"); +MODULE_AUTHOR("Horatiu Vultur "); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h new file mode 100644 index 000000000000..0c5fa14437a5 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __LAN966X_MAIN_H__ +#define __LAN966X_MAIN_H__ + +#include "lan966x_regs.h" + +#define LAN966X_BUFFER_CELL_SZ 64 +#define LAN966X_BUFFER_MEMORY (160 * 1024) +#define LAN966X_BUFFER_MIN_SZ 60 + +#define PGID_AGGR 64 +#define PGID_SRC 80 +#define PGID_ENTRIES 89 + +#define PORT_PVID 0 + +/* Reserved amount for (SRC, PRIO) at index 8*SRC + PRIO */ +#define QSYS_Q_RSRV 95 + +/* Reserved PGIDs */ +#define PGID_CPU (PGID_AGGR - 6) +#define PGID_UC (PGID_AGGR - 5) +#define PGID_BC (PGID_AGGR - 4) +#define PGID_MC (PGID_AGGR - 3) +#define PGID_MCIPV4 (PGID_AGGR - 2) +#define PGID_MCIPV6 (PGID_AGGR - 1) + +#define LAN966X_SPEED_NONE 0 +#define LAN966X_SPEED_1000 1 +#define LAN966X_SPEED_100 2 +#define LAN966X_SPEED_10 3 + +#define CPU_PORT 8 + +struct lan966x_port; + +struct lan966x { + struct device *dev; + + u8 num_phys_ports; + struct lan966x_port **ports; + + void __iomem *regs[NUM_TARGETS]; + + int shared_queue_sz; +}; + +struct lan966x_port { + struct lan966x *lan966x; + + u8 chip_port; + u16 pvid; + + void __iomem *regs; +}; + +static inline void __iomem *lan_addr(void __iomem *base[], + int id, int tinst, int tcnt, + int gbase, int ginst, + int gcnt, int gwidth, + int raddr, int rinst, + int rcnt, int rwidth) +{ + WARN_ON((tinst) >= tcnt); + WARN_ON((ginst) >= gcnt); + WARN_ON((rinst) >= rcnt); + return base[id + (tinst)] + + gbase + ((ginst) * gwidth) + + raddr + ((rinst) * rwidth); +} + +static inline u32 lan_rd(struct lan966x *lan966x, int id, int tinst, int tcnt, + int gbase, int ginst, int gcnt, int gwidth, + int raddr, int rinst, int rcnt, int rwidth) +{ + return readl(lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst, + gcnt, gwidth, raddr, rinst, rcnt, rwidth)); +} + +static inline void lan_wr(u32 val, struct lan966x *lan966x, + int id, int tinst, int tcnt, + int gbase, int ginst, int gcnt, int gwidth, + int raddr, int rinst, int rcnt, int rwidth) +{ + writel(val, lan_addr(lan966x->regs, id, tinst, tcnt, + gbase, ginst, gcnt, gwidth, + raddr, rinst, rcnt, rwidth)); +} + +static inline void lan_rmw(u32 val, u32 mask, struct lan966x *lan966x, + int id, int tinst, int tcnt, + int gbase, int ginst, int gcnt, int gwidth, + int raddr, int rinst, int rcnt, int rwidth) +{ + u32 nval; + + nval = readl(lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst, + gcnt, gwidth, raddr, rinst, rcnt, rwidth)); + nval = (nval & ~mask) | (val & mask); + writel(nval, lan_addr(lan966x->regs, id, tinst, tcnt, gbase, ginst, + gcnt, gwidth, raddr, rinst, rcnt, rwidth)); +} + +#endif /* __LAN966X_MAIN_H__ */ diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h new file mode 100644 index 000000000000..d2ffb4cc122c --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h @@ -0,0 +1,704 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ + +/* This file is autogenerated by cml-utils 2021-07-23 13:13:18 +0200. + * Commit ID: 82017f2e7bc0232de70264fd8a07e1fec9257afa (dirty) + */ + +#ifndef _LAN966X_REGS_H_ +#define _LAN966X_REGS_H_ + +#include +#include +#include + +enum lan966x_target { + TARGET_AFI = 2, + TARGET_ANA = 3, + TARGET_CHIP_TOP = 5, + TARGET_CPU = 6, + TARGET_DEV = 13, + TARGET_GCB = 27, + TARGET_HSIO = 32, + TARGET_ORG = 36, + TARGET_QS = 42, + TARGET_QSYS = 46, + TARGET_REW = 47, + TARGET_SYS = 52, + NUM_TARGETS = 66 +}; + +#define __REG(...) __VA_ARGS__ + +/* AFI:PORT_TBL:PORT_FRM_OUT */ +#define AFI_PORT_FRM_OUT(g) __REG(TARGET_AFI, 0, 1, 98816, g, 10, 8, 0, 0, 1, 4) + +#define AFI_PORT_FRM_OUT_FRM_OUT_CNT GENMASK(26, 16) +#define AFI_PORT_FRM_OUT_FRM_OUT_CNT_SET(x)\ + FIELD_PREP(AFI_PORT_FRM_OUT_FRM_OUT_CNT, x) +#define AFI_PORT_FRM_OUT_FRM_OUT_CNT_GET(x)\ + FIELD_GET(AFI_PORT_FRM_OUT_FRM_OUT_CNT, x) + +/* AFI:PORT_TBL:PORT_CFG */ +#define AFI_PORT_CFG(g) __REG(TARGET_AFI, 0, 1, 98816, g, 10, 8, 4, 0, 1, 4) + +#define AFI_PORT_CFG_FC_SKIP_TTI_INJ BIT(16) +#define AFI_PORT_CFG_FC_SKIP_TTI_INJ_SET(x)\ + FIELD_PREP(AFI_PORT_CFG_FC_SKIP_TTI_INJ, x) +#define AFI_PORT_CFG_FC_SKIP_TTI_INJ_GET(x)\ + FIELD_GET(AFI_PORT_CFG_FC_SKIP_TTI_INJ, x) + +#define AFI_PORT_CFG_FRM_OUT_MAX GENMASK(9, 0) +#define AFI_PORT_CFG_FRM_OUT_MAX_SET(x)\ + FIELD_PREP(AFI_PORT_CFG_FRM_OUT_MAX, x) +#define AFI_PORT_CFG_FRM_OUT_MAX_GET(x)\ + FIELD_GET(AFI_PORT_CFG_FRM_OUT_MAX, x) + +/* ANA:ANA:ADVLEARN */ +#define ANA_ADVLEARN __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 0, 0, 1, 4) + +#define ANA_ADVLEARN_VLAN_CHK BIT(0) +#define ANA_ADVLEARN_VLAN_CHK_SET(x)\ + FIELD_PREP(ANA_ADVLEARN_VLAN_CHK, x) +#define ANA_ADVLEARN_VLAN_CHK_GET(x)\ + FIELD_GET(ANA_ADVLEARN_VLAN_CHK, x) + +/* ANA:ANA:ANAINTR */ +#define ANA_ANAINTR __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 16, 0, 1, 4) + +#define ANA_ANAINTR_INTR BIT(1) +#define ANA_ANAINTR_INTR_SET(x)\ + FIELD_PREP(ANA_ANAINTR_INTR, x) +#define ANA_ANAINTR_INTR_GET(x)\ + FIELD_GET(ANA_ANAINTR_INTR, x) + +#define ANA_ANAINTR_INTR_ENA BIT(0) +#define ANA_ANAINTR_INTR_ENA_SET(x)\ + FIELD_PREP(ANA_ANAINTR_INTR_ENA, x) +#define ANA_ANAINTR_INTR_ENA_GET(x)\ + FIELD_GET(ANA_ANAINTR_INTR_ENA, x) + +/* ANA:ANA:AUTOAGE */ +#define ANA_AUTOAGE __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 44, 0, 1, 4) + +#define ANA_AUTOAGE_AGE_PERIOD GENMASK(20, 1) +#define ANA_AUTOAGE_AGE_PERIOD_SET(x)\ + FIELD_PREP(ANA_AUTOAGE_AGE_PERIOD, x) +#define ANA_AUTOAGE_AGE_PERIOD_GET(x)\ + FIELD_GET(ANA_AUTOAGE_AGE_PERIOD, x) + +/* ANA:ANA:FLOODING */ +#define ANA_FLOODING(r) __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 68, r, 8, 4) + +#define ANA_FLOODING_FLD_BROADCAST GENMASK(11, 6) +#define ANA_FLOODING_FLD_BROADCAST_SET(x)\ + FIELD_PREP(ANA_FLOODING_FLD_BROADCAST, x) +#define ANA_FLOODING_FLD_BROADCAST_GET(x)\ + FIELD_GET(ANA_FLOODING_FLD_BROADCAST, x) + +#define ANA_FLOODING_FLD_MULTICAST GENMASK(5, 0) +#define ANA_FLOODING_FLD_MULTICAST_SET(x)\ + FIELD_PREP(ANA_FLOODING_FLD_MULTICAST, x) +#define ANA_FLOODING_FLD_MULTICAST_GET(x)\ + FIELD_GET(ANA_FLOODING_FLD_MULTICAST, x) + +/* ANA:ANA:FLOODING_IPMC */ +#define ANA_FLOODING_IPMC __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 100, 0, 1, 4) + +#define ANA_FLOODING_IPMC_FLD_MC4_CTRL GENMASK(23, 18) +#define ANA_FLOODING_IPMC_FLD_MC4_CTRL_SET(x)\ + FIELD_PREP(ANA_FLOODING_IPMC_FLD_MC4_CTRL, x) +#define ANA_FLOODING_IPMC_FLD_MC4_CTRL_GET(x)\ + FIELD_GET(ANA_FLOODING_IPMC_FLD_MC4_CTRL, x) + +#define ANA_FLOODING_IPMC_FLD_MC4_DATA GENMASK(17, 12) +#define ANA_FLOODING_IPMC_FLD_MC4_DATA_SET(x)\ + FIELD_PREP(ANA_FLOODING_IPMC_FLD_MC4_DATA, x) +#define ANA_FLOODING_IPMC_FLD_MC4_DATA_GET(x)\ + FIELD_GET(ANA_FLOODING_IPMC_FLD_MC4_DATA, x) + +#define ANA_FLOODING_IPMC_FLD_MC6_CTRL GENMASK(11, 6) +#define ANA_FLOODING_IPMC_FLD_MC6_CTRL_SET(x)\ + FIELD_PREP(ANA_FLOODING_IPMC_FLD_MC6_CTRL, x) +#define ANA_FLOODING_IPMC_FLD_MC6_CTRL_GET(x)\ + FIELD_GET(ANA_FLOODING_IPMC_FLD_MC6_CTRL, x) + +#define ANA_FLOODING_IPMC_FLD_MC6_DATA GENMASK(5, 0) +#define ANA_FLOODING_IPMC_FLD_MC6_DATA_SET(x)\ + FIELD_PREP(ANA_FLOODING_IPMC_FLD_MC6_DATA, x) +#define ANA_FLOODING_IPMC_FLD_MC6_DATA_GET(x)\ + FIELD_GET(ANA_FLOODING_IPMC_FLD_MC6_DATA, x) + +/* ANA:PGID:PGID */ +#define ANA_PGID(g) __REG(TARGET_ANA, 0, 1, 27648, g, 89, 8, 0, 0, 1, 4) + +#define ANA_PGID_PGID GENMASK(8, 0) +#define ANA_PGID_PGID_SET(x)\ + FIELD_PREP(ANA_PGID_PGID, x) +#define ANA_PGID_PGID_GET(x)\ + FIELD_GET(ANA_PGID_PGID, x) + +/* ANA:PGID:PGID_CFG */ +#define ANA_PGID_CFG(g) __REG(TARGET_ANA, 0, 1, 27648, g, 89, 8, 4, 0, 1, 4) + +#define ANA_PGID_CFG_OBEY_VLAN BIT(0) +#define ANA_PGID_CFG_OBEY_VLAN_SET(x)\ + FIELD_PREP(ANA_PGID_CFG_OBEY_VLAN, x) +#define ANA_PGID_CFG_OBEY_VLAN_GET(x)\ + FIELD_GET(ANA_PGID_CFG_OBEY_VLAN, x) + +/* ANA:ANA_TABLES:MACHDATA */ +#define ANA_MACHDATA __REG(TARGET_ANA, 0, 1, 27520, 0, 1, 128, 40, 0, 1, 4) + +/* ANA:ANA_TABLES:MACLDATA */ +#define ANA_MACLDATA __REG(TARGET_ANA, 0, 1, 27520, 0, 1, 128, 44, 0, 1, 4) + +/* ANA:ANA_TABLES:MACACCESS */ +#define ANA_MACACCESS __REG(TARGET_ANA, 0, 1, 27520, 0, 1, 128, 48, 0, 1, 4) + +#define ANA_MACACCESS_CHANGE2SW BIT(17) +#define ANA_MACACCESS_CHANGE2SW_SET(x)\ + FIELD_PREP(ANA_MACACCESS_CHANGE2SW, x) +#define ANA_MACACCESS_CHANGE2SW_GET(x)\ + FIELD_GET(ANA_MACACCESS_CHANGE2SW, x) + +#define ANA_MACACCESS_VALID BIT(12) +#define ANA_MACACCESS_VALID_SET(x)\ + FIELD_PREP(ANA_MACACCESS_VALID, x) +#define ANA_MACACCESS_VALID_GET(x)\ + FIELD_GET(ANA_MACACCESS_VALID, x) + +#define ANA_MACACCESS_ENTRYTYPE GENMASK(11, 10) +#define ANA_MACACCESS_ENTRYTYPE_SET(x)\ + FIELD_PREP(ANA_MACACCESS_ENTRYTYPE, x) +#define ANA_MACACCESS_ENTRYTYPE_GET(x)\ + FIELD_GET(ANA_MACACCESS_ENTRYTYPE, x) + +#define ANA_MACACCESS_DEST_IDX GENMASK(9, 4) +#define ANA_MACACCESS_DEST_IDX_SET(x)\ + FIELD_PREP(ANA_MACACCESS_DEST_IDX, x) +#define ANA_MACACCESS_DEST_IDX_GET(x)\ + FIELD_GET(ANA_MACACCESS_DEST_IDX, x) + +#define ANA_MACACCESS_MAC_TABLE_CMD GENMASK(3, 0) +#define ANA_MACACCESS_MAC_TABLE_CMD_SET(x)\ + FIELD_PREP(ANA_MACACCESS_MAC_TABLE_CMD, x) +#define ANA_MACACCESS_MAC_TABLE_CMD_GET(x)\ + FIELD_GET(ANA_MACACCESS_MAC_TABLE_CMD, x) + +/* ANA:PORT:CPU_FWD_CFG */ +#define ANA_CPU_FWD_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 96, 0, 1, 4) + +#define ANA_CPU_FWD_CFG_SRC_COPY_ENA BIT(3) +#define ANA_CPU_FWD_CFG_SRC_COPY_ENA_SET(x)\ + FIELD_PREP(ANA_CPU_FWD_CFG_SRC_COPY_ENA, x) +#define ANA_CPU_FWD_CFG_SRC_COPY_ENA_GET(x)\ + FIELD_GET(ANA_CPU_FWD_CFG_SRC_COPY_ENA, x) + +/* ANA:PORT:CPU_FWD_BPDU_CFG */ +#define ANA_CPU_FWD_BPDU_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 100, 0, 1, 4) + +/* ANA:PORT:PORT_CFG */ +#define ANA_PORT_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 112, 0, 1, 4) + +#define ANA_PORT_CFG_LEARNAUTO BIT(6) +#define ANA_PORT_CFG_LEARNAUTO_SET(x)\ + FIELD_PREP(ANA_PORT_CFG_LEARNAUTO, x) +#define ANA_PORT_CFG_LEARNAUTO_GET(x)\ + FIELD_GET(ANA_PORT_CFG_LEARNAUTO, x) + +#define ANA_PORT_CFG_RECV_ENA BIT(4) +#define ANA_PORT_CFG_RECV_ENA_SET(x)\ + FIELD_PREP(ANA_PORT_CFG_RECV_ENA, x) +#define ANA_PORT_CFG_RECV_ENA_GET(x)\ + FIELD_GET(ANA_PORT_CFG_RECV_ENA, x) + +#define ANA_PORT_CFG_PORTID_VAL GENMASK(3, 0) +#define ANA_PORT_CFG_PORTID_VAL_SET(x)\ + FIELD_PREP(ANA_PORT_CFG_PORTID_VAL, x) +#define ANA_PORT_CFG_PORTID_VAL_GET(x)\ + FIELD_GET(ANA_PORT_CFG_PORTID_VAL, x) + +/* ANA:PFC:PFC_CFG */ +#define ANA_PFC_CFG(g) __REG(TARGET_ANA, 0, 1, 30720, g, 8, 64, 0, 0, 1, 4) + +#define ANA_PFC_CFG_FC_LINK_SPEED GENMASK(1, 0) +#define ANA_PFC_CFG_FC_LINK_SPEED_SET(x)\ + FIELD_PREP(ANA_PFC_CFG_FC_LINK_SPEED, x) +#define ANA_PFC_CFG_FC_LINK_SPEED_GET(x)\ + FIELD_GET(ANA_PFC_CFG_FC_LINK_SPEED, x) + +/* CHIP_TOP:CUPHY_CFG:CUPHY_PORT_CFG */ +#define CHIP_TOP_CUPHY_PORT_CFG(r) __REG(TARGET_CHIP_TOP, 0, 1, 16, 0, 1, 20, 8, r, 2, 4) + +#define CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA BIT(0) +#define CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_SET(x)\ + FIELD_PREP(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA, x) +#define CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_GET(x)\ + FIELD_GET(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA, x) + +/* CHIP_TOP:CUPHY_CFG:CUPHY_COMMON_CFG */ +#define CHIP_TOP_CUPHY_COMMON_CFG __REG(TARGET_CHIP_TOP, 0, 1, 16, 0, 1, 20, 16, 0, 1, 4) + +#define CHIP_TOP_CUPHY_COMMON_CFG_RESET_N BIT(0) +#define CHIP_TOP_CUPHY_COMMON_CFG_RESET_N_SET(x)\ + FIELD_PREP(CHIP_TOP_CUPHY_COMMON_CFG_RESET_N, x) +#define CHIP_TOP_CUPHY_COMMON_CFG_RESET_N_GET(x)\ + FIELD_GET(CHIP_TOP_CUPHY_COMMON_CFG_RESET_N, x) + +/* CPU:CPU_REGS:RESET_PROT_STAT */ +#define CPU_RESET_PROT_STAT __REG(TARGET_CPU, 0, 1, 0, 0, 1, 168, 136, 0, 1, 4) + +#define CPU_RESET_PROT_STAT_SYS_RST_PROT_VCORE BIT(5) +#define CPU_RESET_PROT_STAT_SYS_RST_PROT_VCORE_SET(x)\ + FIELD_PREP(CPU_RESET_PROT_STAT_SYS_RST_PROT_VCORE, x) +#define CPU_RESET_PROT_STAT_SYS_RST_PROT_VCORE_GET(x)\ + FIELD_GET(CPU_RESET_PROT_STAT_SYS_RST_PROT_VCORE, x) + +/* DEV:PORT_MODE:CLOCK_CFG */ +#define DEV_CLOCK_CFG(t) __REG(TARGET_DEV, t, 8, 0, 0, 1, 28, 0, 0, 1, 4) + +#define DEV_CLOCK_CFG_MAC_TX_RST BIT(7) +#define DEV_CLOCK_CFG_MAC_TX_RST_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_MAC_TX_RST, x) +#define DEV_CLOCK_CFG_MAC_TX_RST_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_MAC_TX_RST, x) + +#define DEV_CLOCK_CFG_MAC_RX_RST BIT(6) +#define DEV_CLOCK_CFG_MAC_RX_RST_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_MAC_RX_RST, x) +#define DEV_CLOCK_CFG_MAC_RX_RST_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_MAC_RX_RST, x) + +#define DEV_CLOCK_CFG_PCS_TX_RST BIT(5) +#define DEV_CLOCK_CFG_PCS_TX_RST_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_PCS_TX_RST, x) +#define DEV_CLOCK_CFG_PCS_TX_RST_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_PCS_TX_RST, x) + +#define DEV_CLOCK_CFG_PCS_RX_RST BIT(4) +#define DEV_CLOCK_CFG_PCS_RX_RST_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_PCS_RX_RST, x) +#define DEV_CLOCK_CFG_PCS_RX_RST_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_PCS_RX_RST, x) + +#define DEV_CLOCK_CFG_PORT_RST BIT(3) +#define DEV_CLOCK_CFG_PORT_RST_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_PORT_RST, x) +#define DEV_CLOCK_CFG_PORT_RST_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_PORT_RST, x) + +#define DEV_CLOCK_CFG_LINK_SPEED GENMASK(1, 0) +#define DEV_CLOCK_CFG_LINK_SPEED_SET(x)\ + FIELD_PREP(DEV_CLOCK_CFG_LINK_SPEED, x) +#define DEV_CLOCK_CFG_LINK_SPEED_GET(x)\ + FIELD_GET(DEV_CLOCK_CFG_LINK_SPEED, x) + +/* DEV:MAC_CFG_STATUS:MAC_ENA_CFG */ +#define DEV_MAC_ENA_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 0, 0, 1, 4) + +#define DEV_MAC_ENA_CFG_RX_ENA BIT(4) +#define DEV_MAC_ENA_CFG_RX_ENA_SET(x)\ + FIELD_PREP(DEV_MAC_ENA_CFG_RX_ENA, x) +#define DEV_MAC_ENA_CFG_RX_ENA_GET(x)\ + FIELD_GET(DEV_MAC_ENA_CFG_RX_ENA, x) + +#define DEV_MAC_ENA_CFG_TX_ENA BIT(0) +#define DEV_MAC_ENA_CFG_TX_ENA_SET(x)\ + FIELD_PREP(DEV_MAC_ENA_CFG_TX_ENA, x) +#define DEV_MAC_ENA_CFG_TX_ENA_GET(x)\ + FIELD_GET(DEV_MAC_ENA_CFG_TX_ENA, x) + +/* DEV:MAC_CFG_STATUS:MAC_MODE_CFG */ +#define DEV_MAC_MODE_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 4, 0, 1, 4) + +#define DEV_MAC_MODE_CFG_GIGA_MODE_ENA BIT(4) +#define DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(x)\ + FIELD_PREP(DEV_MAC_MODE_CFG_GIGA_MODE_ENA, x) +#define DEV_MAC_MODE_CFG_GIGA_MODE_ENA_GET(x)\ + FIELD_GET(DEV_MAC_MODE_CFG_GIGA_MODE_ENA, x) + +/* DEV:MAC_CFG_STATUS:MAC_MAXLEN_CFG */ +#define DEV_MAC_MAXLEN_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 8, 0, 1, 4) + +#define DEV_MAC_MAXLEN_CFG_MAX_LEN GENMASK(15, 0) +#define DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(x)\ + FIELD_PREP(DEV_MAC_MAXLEN_CFG_MAX_LEN, x) +#define DEV_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\ + FIELD_GET(DEV_MAC_MAXLEN_CFG_MAX_LEN, x) + +/* DEV:MAC_CFG_STATUS:MAC_IFG_CFG */ +#define DEV_MAC_IFG_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 20, 0, 1, 4) + +#define DEV_MAC_IFG_CFG_TX_IFG GENMASK(12, 8) +#define DEV_MAC_IFG_CFG_TX_IFG_SET(x)\ + FIELD_PREP(DEV_MAC_IFG_CFG_TX_IFG, x) +#define DEV_MAC_IFG_CFG_TX_IFG_GET(x)\ + FIELD_GET(DEV_MAC_IFG_CFG_TX_IFG, x) + +/* DEV:MAC_CFG_STATUS:MAC_HDX_CFG */ +#define DEV_MAC_HDX_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 24, 0, 1, 4) + +#define DEV_MAC_HDX_CFG_SEED GENMASK(23, 16) +#define DEV_MAC_HDX_CFG_SEED_SET(x)\ + FIELD_PREP(DEV_MAC_HDX_CFG_SEED, x) +#define DEV_MAC_HDX_CFG_SEED_GET(x)\ + FIELD_GET(DEV_MAC_HDX_CFG_SEED, x) + +#define DEV_MAC_HDX_CFG_SEED_LOAD BIT(12) +#define DEV_MAC_HDX_CFG_SEED_LOAD_SET(x)\ + FIELD_PREP(DEV_MAC_HDX_CFG_SEED_LOAD, x) +#define DEV_MAC_HDX_CFG_SEED_LOAD_GET(x)\ + FIELD_GET(DEV_MAC_HDX_CFG_SEED_LOAD, x) + +/* DEV:MAC_CFG_STATUS:MAC_FC_MAC_LOW_CFG */ +#define DEV_FC_MAC_LOW_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 32, 0, 1, 4) + +/* DEV:MAC_CFG_STATUS:MAC_FC_MAC_HIGH_CFG */ +#define DEV_FC_MAC_HIGH_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 36, 0, 1, 4) + +/* DEV:PCS1G_CFG_STATUS:PCS1G_CFG */ +#define DEV_PCS1G_CFG(t) __REG(TARGET_DEV, t, 8, 72, 0, 1, 68, 0, 0, 1, 4) + +#define DEV_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS_ENA_SET(x)\ + FIELD_PREP(DEV_PCS1G_CFG_PCS_ENA, x) +#define DEV_PCS1G_CFG_PCS_ENA_GET(x)\ + FIELD_GET(DEV_PCS1G_CFG_PCS_ENA, x) + +/* DEV:PCS1G_CFG_STATUS:PCS1G_SD_CFG */ +#define DEV_PCS1G_SD_CFG(t) __REG(TARGET_DEV, t, 8, 72, 0, 1, 68, 8, 0, 1, 4) + +#define DEV_PCS1G_SD_CFG_SD_ENA BIT(0) +#define DEV_PCS1G_SD_CFG_SD_ENA_SET(x)\ + FIELD_PREP(DEV_PCS1G_SD_CFG_SD_ENA, x) +#define DEV_PCS1G_SD_CFG_SD_ENA_GET(x)\ + FIELD_GET(DEV_PCS1G_SD_CFG_SD_ENA, x) + +/* DEVCPU_GCB:CHIP_REGS:SOFT_RST */ +#define GCB_SOFT_RST __REG(TARGET_GCB, 0, 1, 0, 0, 1, 68, 12, 0, 1, 4) + +/* HSIO:HW_CFGSTAT:HW_CFG */ +#define HSIO_HW_CFG __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 0, 0, 1, 4) + +#define HSIO_HW_CFG_RGMII_1_CFG BIT(15) +#define HSIO_HW_CFG_RGMII_1_CFG_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_RGMII_1_CFG, x) +#define HSIO_HW_CFG_RGMII_1_CFG_GET(x)\ + FIELD_GET(HSIO_HW_CFG_RGMII_1_CFG, x) + +#define HSIO_HW_CFG_RGMII_0_CFG BIT(14) +#define HSIO_HW_CFG_RGMII_0_CFG_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_RGMII_0_CFG, x) +#define HSIO_HW_CFG_RGMII_0_CFG_GET(x)\ + FIELD_GET(HSIO_HW_CFG_RGMII_0_CFG, x) + +#define HSIO_HW_CFG_RGMII_ENA GENMASK(13, 12) +#define HSIO_HW_CFG_RGMII_ENA_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_RGMII_ENA, x) +#define HSIO_HW_CFG_RGMII_ENA_GET(x)\ + FIELD_GET(HSIO_HW_CFG_RGMII_ENA, x) + +#define HSIO_HW_CFG_SD6G_0_CFG BIT(11) +#define HSIO_HW_CFG_SD6G_0_CFG_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_SD6G_0_CFG, x) +#define HSIO_HW_CFG_SD6G_0_CFG_GET(x)\ + FIELD_GET(HSIO_HW_CFG_SD6G_0_CFG, x) + +#define HSIO_HW_CFG_SD6G_1_CFG BIT(10) +#define HSIO_HW_CFG_SD6G_1_CFG_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_SD6G_1_CFG, x) +#define HSIO_HW_CFG_SD6G_1_CFG_GET(x)\ + FIELD_GET(HSIO_HW_CFG_SD6G_1_CFG, x) + +#define HSIO_HW_CFG_GMII_ENA GENMASK(9, 2) +#define HSIO_HW_CFG_GMII_ENA_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_GMII_ENA, x) +#define HSIO_HW_CFG_GMII_ENA_GET(x)\ + FIELD_GET(HSIO_HW_CFG_GMII_ENA, x) + +#define HSIO_HW_CFG_QSGMII_ENA GENMASK(1, 0) +#define HSIO_HW_CFG_QSGMII_ENA_SET(x)\ + FIELD_PREP(HSIO_HW_CFG_QSGMII_ENA, x) +#define HSIO_HW_CFG_QSGMII_ENA_GET(x)\ + FIELD_GET(HSIO_HW_CFG_QSGMII_ENA, x) + +/* DEVCPU_QS:XTR:XTR_GRP_CFG */ +#define QS_XTR_GRP_CFG(r) __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 0, r, 2, 4) + +#define QS_XTR_GRP_CFG_MODE GENMASK(3, 2) +#define QS_XTR_GRP_CFG_MODE_SET(x)\ + FIELD_PREP(QS_XTR_GRP_CFG_MODE, x) +#define QS_XTR_GRP_CFG_MODE_GET(x)\ + FIELD_GET(QS_XTR_GRP_CFG_MODE, x) + +#define QS_XTR_GRP_CFG_BYTE_SWAP BIT(0) +#define QS_XTR_GRP_CFG_BYTE_SWAP_SET(x)\ + FIELD_PREP(QS_XTR_GRP_CFG_BYTE_SWAP, x) +#define QS_XTR_GRP_CFG_BYTE_SWAP_GET(x)\ + FIELD_GET(QS_XTR_GRP_CFG_BYTE_SWAP, x) + +/* DEVCPU_QS:XTR:XTR_RD */ +#define QS_XTR_RD(r) __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 8, r, 2, 4) + +/* DEVCPU_QS:XTR:XTR_FLUSH */ +#define QS_XTR_FLUSH __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 24, 0, 1, 4) + +/* DEVCPU_QS:XTR:XTR_DATA_PRESENT */ +#define QS_XTR_DATA_PRESENT __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 28, 0, 1, 4) + +/* DEVCPU_QS:INJ:INJ_GRP_CFG */ +#define QS_INJ_GRP_CFG(r) __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 0, r, 2, 4) + +#define QS_INJ_GRP_CFG_MODE GENMASK(3, 2) +#define QS_INJ_GRP_CFG_MODE_SET(x)\ + FIELD_PREP(QS_INJ_GRP_CFG_MODE, x) +#define QS_INJ_GRP_CFG_MODE_GET(x)\ + FIELD_GET(QS_INJ_GRP_CFG_MODE, x) + +#define QS_INJ_GRP_CFG_BYTE_SWAP BIT(0) +#define QS_INJ_GRP_CFG_BYTE_SWAP_SET(x)\ + FIELD_PREP(QS_INJ_GRP_CFG_BYTE_SWAP, x) +#define QS_INJ_GRP_CFG_BYTE_SWAP_GET(x)\ + FIELD_GET(QS_INJ_GRP_CFG_BYTE_SWAP, x) + +/* DEVCPU_QS:INJ:INJ_WR */ +#define QS_INJ_WR(r) __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 8, r, 2, 4) + +/* DEVCPU_QS:INJ:INJ_CTRL */ +#define QS_INJ_CTRL(r) __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 16, r, 2, 4) + +#define QS_INJ_CTRL_GAP_SIZE GENMASK(24, 21) +#define QS_INJ_CTRL_GAP_SIZE_SET(x)\ + FIELD_PREP(QS_INJ_CTRL_GAP_SIZE, x) +#define QS_INJ_CTRL_GAP_SIZE_GET(x)\ + FIELD_GET(QS_INJ_CTRL_GAP_SIZE, x) + +#define QS_INJ_CTRL_EOF BIT(19) +#define QS_INJ_CTRL_EOF_SET(x)\ + FIELD_PREP(QS_INJ_CTRL_EOF, x) +#define QS_INJ_CTRL_EOF_GET(x)\ + FIELD_GET(QS_INJ_CTRL_EOF, x) + +#define QS_INJ_CTRL_SOF BIT(18) +#define QS_INJ_CTRL_SOF_SET(x)\ + FIELD_PREP(QS_INJ_CTRL_SOF, x) +#define QS_INJ_CTRL_SOF_GET(x)\ + FIELD_GET(QS_INJ_CTRL_SOF, x) + +#define QS_INJ_CTRL_VLD_BYTES GENMASK(17, 16) +#define QS_INJ_CTRL_VLD_BYTES_SET(x)\ + FIELD_PREP(QS_INJ_CTRL_VLD_BYTES, x) +#define QS_INJ_CTRL_VLD_BYTES_GET(x)\ + FIELD_GET(QS_INJ_CTRL_VLD_BYTES, x) + +/* DEVCPU_QS:INJ:INJ_STATUS */ +#define QS_INJ_STATUS __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 24, 0, 1, 4) + +#define QS_INJ_STATUS_WMARK_REACHED GENMASK(5, 4) +#define QS_INJ_STATUS_WMARK_REACHED_SET(x)\ + FIELD_PREP(QS_INJ_STATUS_WMARK_REACHED, x) +#define QS_INJ_STATUS_WMARK_REACHED_GET(x)\ + FIELD_GET(QS_INJ_STATUS_WMARK_REACHED, x) + +#define QS_INJ_STATUS_FIFO_RDY GENMASK(3, 2) +#define QS_INJ_STATUS_FIFO_RDY_SET(x)\ + FIELD_PREP(QS_INJ_STATUS_FIFO_RDY, x) +#define QS_INJ_STATUS_FIFO_RDY_GET(x)\ + FIELD_GET(QS_INJ_STATUS_FIFO_RDY, x) + +/* QSYS:SYSTEM:PORT_MODE */ +#define QSYS_PORT_MODE(r) __REG(TARGET_QSYS, 0, 1, 28008, 0, 1, 216, 0, r, 10, 4) + +#define QSYS_PORT_MODE_DEQUEUE_DIS BIT(1) +#define QSYS_PORT_MODE_DEQUEUE_DIS_SET(x)\ + FIELD_PREP(QSYS_PORT_MODE_DEQUEUE_DIS, x) +#define QSYS_PORT_MODE_DEQUEUE_DIS_GET(x)\ + FIELD_GET(QSYS_PORT_MODE_DEQUEUE_DIS, x) + +/* QSYS:SYSTEM:SWITCH_PORT_MODE */ +#define QSYS_SW_PORT_MODE(r) __REG(TARGET_QSYS, 0, 1, 28008, 0, 1, 216, 80, r, 9, 4) + +#define QSYS_SW_PORT_MODE_PORT_ENA BIT(18) +#define QSYS_SW_PORT_MODE_PORT_ENA_SET(x)\ + FIELD_PREP(QSYS_SW_PORT_MODE_PORT_ENA, x) +#define QSYS_SW_PORT_MODE_PORT_ENA_GET(x)\ + FIELD_GET(QSYS_SW_PORT_MODE_PORT_ENA, x) + +#define QSYS_SW_PORT_MODE_SCH_NEXT_CFG GENMASK(16, 14) +#define QSYS_SW_PORT_MODE_SCH_NEXT_CFG_SET(x)\ + FIELD_PREP(QSYS_SW_PORT_MODE_SCH_NEXT_CFG, x) +#define QSYS_SW_PORT_MODE_SCH_NEXT_CFG_GET(x)\ + FIELD_GET(QSYS_SW_PORT_MODE_SCH_NEXT_CFG, x) + +#define QSYS_SW_PORT_MODE_INGRESS_DROP_MODE BIT(12) +#define QSYS_SW_PORT_MODE_INGRESS_DROP_MODE_SET(x)\ + FIELD_PREP(QSYS_SW_PORT_MODE_INGRESS_DROP_MODE, x) +#define QSYS_SW_PORT_MODE_INGRESS_DROP_MODE_GET(x)\ + FIELD_GET(QSYS_SW_PORT_MODE_INGRESS_DROP_MODE, x) + +#define QSYS_SW_PORT_MODE_TX_PFC_ENA GENMASK(11, 4) +#define QSYS_SW_PORT_MODE_TX_PFC_ENA_SET(x)\ + FIELD_PREP(QSYS_SW_PORT_MODE_TX_PFC_ENA, x) +#define QSYS_SW_PORT_MODE_TX_PFC_ENA_GET(x)\ + FIELD_GET(QSYS_SW_PORT_MODE_TX_PFC_ENA, x) + +#define QSYS_SW_PORT_MODE_AGING_MODE GENMASK(1, 0) +#define QSYS_SW_PORT_MODE_AGING_MODE_SET(x)\ + FIELD_PREP(QSYS_SW_PORT_MODE_AGING_MODE, x) +#define QSYS_SW_PORT_MODE_AGING_MODE_GET(x)\ + FIELD_GET(QSYS_SW_PORT_MODE_AGING_MODE, x) + +/* QSYS:SYSTEM:SW_STATUS */ +#define QSYS_SW_STATUS(r) __REG(TARGET_QSYS, 0, 1, 28008, 0, 1, 216, 164, r, 9, 4) + +#define QSYS_SW_STATUS_EQ_AVAIL GENMASK(7, 0) +#define QSYS_SW_STATUS_EQ_AVAIL_SET(x)\ + FIELD_PREP(QSYS_SW_STATUS_EQ_AVAIL, x) +#define QSYS_SW_STATUS_EQ_AVAIL_GET(x)\ + FIELD_GET(QSYS_SW_STATUS_EQ_AVAIL, x) + +/* QSYS:SYSTEM:CPU_GROUP_MAP */ +#define QSYS_CPU_GROUP_MAP __REG(TARGET_QSYS, 0, 1, 28008, 0, 1, 216, 204, 0, 1, 4) + +/* QSYS:RES_CTRL:RES_CFG */ +#define QSYS_RES_CFG(g) __REG(TARGET_QSYS, 0, 1, 32768, g, 1024, 8, 0, 0, 1, 4) + +/* REW:PORT:PORT_CFG */ +#define REW_PORT_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 8, 0, 1, 4) + +#define REW_PORT_CFG_NO_REWRITE BIT(0) +#define REW_PORT_CFG_NO_REWRITE_SET(x)\ + FIELD_PREP(REW_PORT_CFG_NO_REWRITE, x) +#define REW_PORT_CFG_NO_REWRITE_GET(x)\ + FIELD_GET(REW_PORT_CFG_NO_REWRITE, x) + +/* SYS:SYSTEM:RESET_CFG */ +#define SYS_RESET_CFG __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 0, 0, 1, 4) + +#define SYS_RESET_CFG_CORE_ENA BIT(0) +#define SYS_RESET_CFG_CORE_ENA_SET(x)\ + FIELD_PREP(SYS_RESET_CFG_CORE_ENA, x) +#define SYS_RESET_CFG_CORE_ENA_GET(x)\ + FIELD_GET(SYS_RESET_CFG_CORE_ENA, x) + +/* SYS:SYSTEM:PORT_MODE */ +#define SYS_PORT_MODE(r) __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 44, r, 10, 4) + +#define SYS_PORT_MODE_INCL_INJ_HDR GENMASK(5, 4) +#define SYS_PORT_MODE_INCL_INJ_HDR_SET(x)\ + FIELD_PREP(SYS_PORT_MODE_INCL_INJ_HDR, x) +#define SYS_PORT_MODE_INCL_INJ_HDR_GET(x)\ + FIELD_GET(SYS_PORT_MODE_INCL_INJ_HDR, x) + +#define SYS_PORT_MODE_INCL_XTR_HDR GENMASK(3, 2) +#define SYS_PORT_MODE_INCL_XTR_HDR_SET(x)\ + FIELD_PREP(SYS_PORT_MODE_INCL_XTR_HDR, x) +#define SYS_PORT_MODE_INCL_XTR_HDR_GET(x)\ + FIELD_GET(SYS_PORT_MODE_INCL_XTR_HDR, x) + +/* SYS:SYSTEM:FRONT_PORT_MODE */ +#define SYS_FRONT_PORT_MODE(r) __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 84, r, 8, 4) + +#define SYS_FRONT_PORT_MODE_HDX_MODE BIT(1) +#define SYS_FRONT_PORT_MODE_HDX_MODE_SET(x)\ + FIELD_PREP(SYS_FRONT_PORT_MODE_HDX_MODE, x) +#define SYS_FRONT_PORT_MODE_HDX_MODE_GET(x)\ + FIELD_GET(SYS_FRONT_PORT_MODE_HDX_MODE, x) + +/* SYS:SYSTEM:FRM_AGING */ +#define SYS_FRM_AGING __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 116, 0, 1, 4) + +#define SYS_FRM_AGING_AGE_TX_ENA BIT(20) +#define SYS_FRM_AGING_AGE_TX_ENA_SET(x)\ + FIELD_PREP(SYS_FRM_AGING_AGE_TX_ENA, x) +#define SYS_FRM_AGING_AGE_TX_ENA_GET(x)\ + FIELD_GET(SYS_FRM_AGING_AGE_TX_ENA, x) + +/* SYS:SYSTEM:STAT_CFG */ +#define SYS_STAT_CFG __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 120, 0, 1, 4) + +#define SYS_STAT_CFG_STAT_VIEW GENMASK(9, 0) +#define SYS_STAT_CFG_STAT_VIEW_SET(x)\ + FIELD_PREP(SYS_STAT_CFG_STAT_VIEW, x) +#define SYS_STAT_CFG_STAT_VIEW_GET(x)\ + FIELD_GET(SYS_STAT_CFG_STAT_VIEW, x) + +/* SYS:PAUSE_CFG:PAUSE_CFG */ +#define SYS_PAUSE_CFG(r) __REG(TARGET_SYS, 0, 1, 4296, 0, 1, 112, 0, r, 9, 4) + +#define SYS_PAUSE_CFG_PAUSE_START GENMASK(18, 10) +#define SYS_PAUSE_CFG_PAUSE_START_SET(x)\ + FIELD_PREP(SYS_PAUSE_CFG_PAUSE_START, x) +#define SYS_PAUSE_CFG_PAUSE_START_GET(x)\ + FIELD_GET(SYS_PAUSE_CFG_PAUSE_START, x) + +#define SYS_PAUSE_CFG_PAUSE_STOP GENMASK(9, 1) +#define SYS_PAUSE_CFG_PAUSE_STOP_SET(x)\ + FIELD_PREP(SYS_PAUSE_CFG_PAUSE_STOP, x) +#define SYS_PAUSE_CFG_PAUSE_STOP_GET(x)\ + FIELD_GET(SYS_PAUSE_CFG_PAUSE_STOP, x) + +#define SYS_PAUSE_CFG_PAUSE_ENA BIT(0) +#define SYS_PAUSE_CFG_PAUSE_ENA_SET(x)\ + FIELD_PREP(SYS_PAUSE_CFG_PAUSE_ENA, x) +#define SYS_PAUSE_CFG_PAUSE_ENA_GET(x)\ + FIELD_GET(SYS_PAUSE_CFG_PAUSE_ENA, x) + +/* SYS:PAUSE_CFG:ATOP */ +#define SYS_ATOP(r) __REG(TARGET_SYS, 0, 1, 4296, 0, 1, 112, 40, r, 9, 4) + +/* SYS:PAUSE_CFG:ATOP_TOT_CFG */ +#define SYS_ATOP_TOT_CFG __REG(TARGET_SYS, 0, 1, 4296, 0, 1, 112, 76, 0, 1, 4) + +/* SYS:PAUSE_CFG:MAC_FC_CFG */ +#define SYS_MAC_FC_CFG(r) __REG(TARGET_SYS, 0, 1, 4296, 0, 1, 112, 80, r, 8, 4) + +#define SYS_MAC_FC_CFG_FC_LINK_SPEED GENMASK(27, 26) +#define SYS_MAC_FC_CFG_FC_LINK_SPEED_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_FC_LINK_SPEED, x) +#define SYS_MAC_FC_CFG_FC_LINK_SPEED_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_FC_LINK_SPEED, x) + +#define SYS_MAC_FC_CFG_FC_LATENCY_CFG GENMASK(25, 20) +#define SYS_MAC_FC_CFG_FC_LATENCY_CFG_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_FC_LATENCY_CFG, x) +#define SYS_MAC_FC_CFG_FC_LATENCY_CFG_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_FC_LATENCY_CFG, x) + +#define SYS_MAC_FC_CFG_ZERO_PAUSE_ENA BIT(18) +#define SYS_MAC_FC_CFG_ZERO_PAUSE_ENA_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_ZERO_PAUSE_ENA, x) +#define SYS_MAC_FC_CFG_ZERO_PAUSE_ENA_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_ZERO_PAUSE_ENA, x) + +#define SYS_MAC_FC_CFG_TX_FC_ENA BIT(17) +#define SYS_MAC_FC_CFG_TX_FC_ENA_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_TX_FC_ENA, x) +#define SYS_MAC_FC_CFG_TX_FC_ENA_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_TX_FC_ENA, x) + +#define SYS_MAC_FC_CFG_RX_FC_ENA BIT(16) +#define SYS_MAC_FC_CFG_RX_FC_ENA_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_RX_FC_ENA, x) +#define SYS_MAC_FC_CFG_RX_FC_ENA_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_RX_FC_ENA, x) + +#define SYS_MAC_FC_CFG_PAUSE_VAL_CFG GENMASK(15, 0) +#define SYS_MAC_FC_CFG_PAUSE_VAL_CFG_SET(x)\ + FIELD_PREP(SYS_MAC_FC_CFG_PAUSE_VAL_CFG, x) +#define SYS_MAC_FC_CFG_PAUSE_VAL_CFG_GET(x)\ + FIELD_GET(SYS_MAC_FC_CFG_PAUSE_VAL_CFG, x) + +/* SYS:STAT:CNT */ +#define SYS_CNT(g) __REG(TARGET_SYS, 0, 1, 0, g, 896, 4, 0, 0, 1, 4) + +/* SYS:RAM_CTRL:RAM_INIT */ +#define SYS_RAM_INIT __REG(TARGET_SYS, 0, 1, 4432, 0, 1, 4, 0, 0, 1, 4) + +#define SYS_RAM_INIT_RAM_INIT BIT(1) +#define SYS_RAM_INIT_RAM_INIT_SET(x)\ + FIELD_PREP(SYS_RAM_INIT_RAM_INIT, x) +#define SYS_RAM_INIT_RAM_INIT_GET(x)\ + FIELD_GET(SYS_RAM_INIT_RAM_INIT, x) + +#endif /* _LAN966X_REGS_H_ */ From patchwork Mon Sep 20 09:52:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505015 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6C39C4332F for ; Mon, 20 Sep 2021 09:52:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8D60F60240 for ; Mon, 20 Sep 2021 09:52:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237380AbhITJyH (ORCPT ); Mon, 20 Sep 2021 05:54:07 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:34042 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236730AbhITJxM (ORCPT ); Mon, 20 Sep 2021 05:53:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131506; x=1663667506; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GUqZ7Khjr5MzRh8sPunaHS801JTODiz0d6pHAmJBsM8=; b=K3IJCel9YGhnuhgWcwmRdmWyJSwXhLRssJQGzCMIGOBLWh+r85PiwWKb /TmW/QkhL5ame2BLc/Fy/lEQA3TbTHm9oBXacv8owJyIndz8Kn9E0u/Wm pOo8QGZ0SGmbwg3jFG+iisomasP/40L6VPS8U6PWX0Q4rE3wrTC2RqeRM +2uipL8r48zyAdeuZB95x4juu4/iL3nWU+F7Zp1ZrpHyHJ9sWPhmMWTbN CvcmBElY+2SMrkifaQT3aau/8gvaZH6hTIvuUeWFgn/HotU8rQ9OSpxTD b+bl8FPI3XSmZAfHIUOQd+UypiTB1LGgxSpsUTLD+W0YQTWpzVNMo2jZH g==; IronPort-SDR: MsEL6RDQTq7Zh7oT+bYqAWDlbUt3c34o+fbdU/NGtXiiE1atERu9WpMAHzenSfrIT8HbyqbcpB PCGREOhVjORQxRA9PgpHTDUpWjIBOExRe3+aUVhNot7DtkgEvU4yU52ZXYyEvY3we2yCBlnpFk cp4DuPFdfu0oio8p0nGfqvbYJQabHTuv1sLLqe7+C/h4YZ8YSYOmiDVZQpkDZ8pugj1SBY/Gn4 1WwSyzkVhS/pJhhLDInuuDBl6o+fOm4YZahJ3lojxbDU1sifKLiYLWLjGPOFnazHEbDSZtnlvS fG2KRkPSYLGd0MX9lBAGoRkE X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="136598695" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:45 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:44 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:41 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 10/12] net: lan966x: add port module support Date: Mon, 20 Sep 2021 11:52:16 +0200 Message-ID: <20210920095218.1108151-11-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This patch adds support for netdev and phylink in the switch. The injection + extraction is register based. This will be replaced with DMA accees. Signed-off-by: Horatiu Vultur --- .../net/ethernet/microchip/lan966x/Makefile | 2 +- .../ethernet/microchip/lan966x/lan966x_ifh.h | 173 +++++++ .../ethernet/microchip/lan966x/lan966x_main.c | 481 +++++++++++++++++- .../ethernet/microchip/lan966x/lan966x_main.h | 38 ++ .../microchip/lan966x/lan966x_phylink.c | 92 ++++ .../ethernet/microchip/lan966x/lan966x_port.c | 301 +++++++++++ 6 files changed, 1083 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_ifh.h create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_port.c diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile index 7ea90410a0b2..e18c9b2d0bb7 100644 --- a/drivers/net/ethernet/microchip/lan966x/Makefile +++ b/drivers/net/ethernet/microchip/lan966x/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o -lan966x-switch-objs := lan966x_main.o +lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ifh.h b/drivers/net/ethernet/microchip/lan966x/lan966x_ifh.h new file mode 100644 index 000000000000..ca3314789d18 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ifh.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __LAN966X_IFH_H__ +#define __LAN966X_IFH_H__ + +/* Fields with description (*) should just be cleared upon injection + * IFH is transmitted MSByte first (Highest bit pos sent as MSB of first byte) + */ + +#define IFH_LEN 7 + +/* Timestamp for frame */ +#define IFH_POS_TIMESTAMP 192 + +/* Bypass analyzer with a prefilled IFH */ +#define IFH_POS_BYPASS 191 + +/* Masqueraded injection with masq_port defining logical source port */ +#define IFH_POS_MASQ 190 + +/* Masqueraded port number for injection */ +#define IFH_POS_MASQ_PORT 186 + +/* Frame length (*) */ +#define IFH_POS_LEN 178 + +/* Cell filling mode. Full(0),Etype(1), LlctOpt(2), Llct(3) */ +#define IFH_POS_WRDMODE 176 + +/* Frame has 16 bits rtag removed compared to line data */ +#define IFH_POS_RTAG48 175 + +/* Frame has a redundancy tag */ +#define IFH_POS_HAS_RED_TAG 174 + +/* Frame has been cut through forwarded (*) */ +#define IFH_POS_CUTTHRU 173 + +/* Rewriter command */ +#define IFH_POS_REW_CMD 163 + +/* Enable OAM-related rewriting. PDU_TYPE encodes OAM type. */ +#define IFH_POS_REW_OAM 162 + +/* PDU type. Encoding: (0-NONE, 1-Y1731_CCM, 2-MRP_TST, 3-MRP_ITST, 4-DLR_BCN, + * 5-DLR_ADV, 6-RTE_NULL_INJ, 7-IPV4, 8-IPV6, 9-Y1731_NON_CCM). + */ +#define IFH_POS_PDU_TYPE 158 + +/* Update FCS before transmission */ +#define IFH_POS_FCS_UPD 157 + +/* Classified DSCP value of frame */ +#define IFH_POS_DSCP 151 + +/* Yellow indication */ +#define IFH_POS_DP 150 + +/* Process in RTE/inbound */ +#define IFH_POS_RTE_INB_UPDATE 149 + +/* Number of tags to pop from frame */ +#define IFH_POS_POP_CNT 147 + +/* Number of tags in front of the ethertype */ +#define IFH_POS_ETYPE_OFS 145 + +/* Logical source port of frame (*) */ +#define IFH_POS_SRCPORT 141 + +/* Sequence number in redundancy tag */ +#define IFH_POS_SEQ_NUM 120 + +/* Stagd flag and classified TCI of frame (PCP/DEI/VID) */ +#define IFH_POS_TCI 103 + +/* Classified internal priority for queuing */ +#define IFH_POS_QOS_CLASS 100 + +/* Bit mask with eight cpu copy classses */ +#define IFH_POS_CPUQ 92 + +/* Relearn + learn flags (*) */ +#define IFH_POS_LEARN_FLAGS 90 + +/* SFLOW identifier for frame (0-8: Tx port, 9: Rx sampling, 15: No sampling) */ +#define IFH_POS_SFLOW_ID 86 + +/* Set if an ACL/S2 rule was hit (*). + * Super priority: acl_hit=0 and acl_hit(4)=1. + */ +#define IFH_POS_ACL_HIT 85 + +/* S2 rule index hit (*) */ +#define IFH_POS_ACL_IDX 79 + +/* ISDX as classified by S1 */ +#define IFH_POS_ISDX 71 + +/* Destination ports for frame */ +#define IFH_POS_DSTS 62 + +/* Storm policer to be applied: None/Uni/Multi/Broad (*) */ +#define IFH_POS_FLOOD 60 + +/* Redundancy tag operation */ +#define IFH_POS_SEQ_OP 58 + +/* Classified internal priority for resourcemgt, tagging etc */ +#define IFH_POS_IPV 55 + +/* Frame is for AFI use */ +#define IFH_POS_AFI 54 + +/* Internal aging value (*) */ +#define IFH_POS_AGED 52 + +/* RTP Identifier */ +#define IFH_POS_RTP_ID 42 + +/* RTP MRPD flow */ +#define IFH_POS_RTP_SUBID 41 + +/* Profinet DataStatus or opcua GroupVersion MSB */ +#define IFH_POS_PN_DATA_STATUS 33 + +/* Profinet transfer status (1 iff the status is 0) */ +#define IFH_POS_PN_TRANSF_STATUS_ZERO 32 + +/* Profinet cycle counter or opcua NetworkMessageNumber */ +#define IFH_POS_PN_CC 16 + +#define IFH_WID_TIMESTAMP 32 +#define IFH_WID_BYPASS 1 +#define IFH_WID_MASQ 1 +#define IFH_WID_MASQ_PORT 4 +#define IFH_WID_LEN 14 +#define IFH_WID_WRDMODE 2 +#define IFH_WID_RTAG48 1 +#define IFH_WID_HAS_RED_TAG 1 +#define IFH_WID_CUTTHRU 1 +#define IFH_WID_REW_CMD 10 +#define IFH_WID_REW_OAM 1 +#define IFH_WID_PDU_TYPE 4 +#define IFH_WID_FCS_UPD 1 +#define IFH_WID_DSCP 6 +#define IFH_WID_DP 1 +#define IFH_WID_RTE_INB_UPDATE 1 +#define IFH_WID_POP_CNT 2 +#define IFH_WID_ETYPE_OFS 2 +#define IFH_WID_SRCPORT 4 +#define IFH_WID_SEQ_NUM 16 +#define IFH_WID_TCI 17 +#define IFH_WID_QOS_CLASS 3 +#define IFH_WID_CPUQ 8 +#define IFH_WID_LEARN_FLAGS 2 +#define IFH_WID_SFLOW_ID 4 +#define IFH_WID_ACL_HIT 1 +#define IFH_WID_ACL_IDX 6 +#define IFH_WID_ISDX 8 +#define IFH_WID_DSTS 9 +#define IFH_WID_FLOOD 2 +#define IFH_WID_SEQ_OP 2 +#define IFH_WID_IPV 3 +#define IFH_WID_AFI 1 +#define IFH_WID_AGED 2 +#define IFH_WID_RTP_ID 10 +#define IFH_WID_RTP_SUBID 1 +#define IFH_WID_PN_DATA_STATUS 8 +#define IFH_WID_PN_TRANSF_STATUS_ZERO 1 +#define IFH_WID_PN_CC 16 + +#endif /* __LAN966X_IFH_H__ */ diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 2984f510ae27..cf147d44b345 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -3,13 +3,25 @@ #include #include #include +#include #include #include #include +#include #include #include "lan966x_main.h" +#define XTR_EOF_0 0x00000080U +#define XTR_EOF_1 0x01000080U +#define XTR_EOF_2 0x02000080U +#define XTR_EOF_3 0x03000080U +#define XTR_PRUNED 0x04000080U +#define XTR_ABORT 0x05000080U +#define XTR_ESCAPE 0x06000080U +#define XTR_NOT_READY 0x07000080U +#define XTR_VALID_BYTES(x) (4 - (((x) >> 24) & 3)) + #define READL_SLEEP_US 10 #define READL_TIMEOUT_US 100000000 @@ -82,23 +94,450 @@ static int lan966x_create_targets(struct platform_device *pdev, return 0; } +static int lan966x_port_get_phys_port_name(struct net_device *dev, + char *buf, size_t len) +{ + struct lan966x_port *port = netdev_priv(dev); + int ret; + + ret = snprintf(buf, len, "p%d", port->chip_port); + if (ret >= len) + return -EINVAL; + + return 0; +} + +static int lan966x_port_open(struct net_device *dev) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + int err; + + if (port->serdes) { + err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, + port->config.phy_mode); + if (err) { + netdev_err(dev, "Could not set mode of SerDes\n"); + return err; + } + } + + /* Enable receiving frames on the port, and activate auto-learning of + * MAC addresses. + */ + lan_wr(ANA_PORT_CFG_LEARNAUTO_SET(1) | + ANA_PORT_CFG_RECV_ENA_SET(1) | + ANA_PORT_CFG_PORTID_VAL_SET(port->chip_port), + lan966x, ANA_PORT_CFG(port->chip_port)); + + err = phylink_of_phy_connect(port->phylink, to_of_node(port->fwnode), 0); + if (err) { + netdev_err(dev, "Could not attach to PHY\n"); + return err; + } + + phylink_start(port->phylink); + + return 0; +} + +static int lan966x_port_stop(struct net_device *dev) +{ + struct lan966x_port *port = netdev_priv(dev); + + lan966x_port_config_down(port); + phylink_stop(port->phylink); + phylink_disconnect_phy(port->phylink); + + return 0; +} + +static void lan966x_ifh_inject(u32 *ifh, size_t val, size_t pos, size_t length) +{ + int i; + + for (i = pos; i < pos + length; ++i) { + if (val & BIT(i - pos)) + ifh[IFH_LEN - i / 32 - 1] |= BIT(i % 32); + else + ifh[IFH_LEN - i / 32 - 1] &= ~(BIT(i % 32)); + } +} + +static void lan966x_gen_ifh(u32 *ifh, struct lan966x_frame_info *info, + struct lan966x *lan966x) +{ + lan966x_ifh_inject(ifh, 1, IFH_POS_BYPASS, 1); + lan966x_ifh_inject(ifh, info->port, IFH_POS_DSTS, IFH_WID_DSTS); + lan966x_ifh_inject(ifh, info->qos_class, IFH_POS_QOS_CLASS, + IFH_WID_QOS_CLASS); + lan966x_ifh_inject(ifh, info->ipv, IFH_POS_IPV, IFH_WID_IPV); +} + +static int lan966x_port_ifh_xmit(struct sk_buff *skb, + struct lan966x_frame_info *info, + struct net_device *dev) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + u32 i, count, last; + u32 ifh[IFH_LEN]; + u8 grp = 0; + u32 val; + + val = lan_rd(lan966x, QS_INJ_STATUS); + if (!(QS_INJ_STATUS_FIFO_RDY_GET(val) & BIT(grp)) || + (QS_INJ_STATUS_WMARK_REACHED_GET(val) & BIT(grp))) + return NETDEV_TX_BUSY; + + /* Write start of frame */ + lan_wr(QS_INJ_CTRL_GAP_SIZE_SET(1) | + QS_INJ_CTRL_SOF_SET(1), + lan966x, QS_INJ_CTRL(grp)); + + memset(ifh, 0x0, sizeof(u32) * IFH_LEN); + lan966x_gen_ifh(ifh, info, lan966x); + + /* Write IFH header */ + for (i = 0; i < IFH_LEN; ++i) { + /* Wait until the fifo is ready */ + while (!(QS_INJ_STATUS_FIFO_RDY_GET(lan_rd(lan966x, QS_INJ_STATUS)) & + BIT(grp))) + ; + + lan_wr((__force u32)cpu_to_be32(ifh[i]), lan966x, + QS_INJ_WR(grp)); + } + + /* Write frame */ + count = DIV_ROUND_UP(skb->len, 4); + last = skb->len % 4; + for (i = 0; i < count; ++i) { + /* Wait until the fifo is ready */ + while (!(QS_INJ_STATUS_FIFO_RDY_GET(lan_rd(lan966x, QS_INJ_STATUS)) & + BIT(grp))) + ; + + lan_wr(((u32 *)skb->data)[i], lan966x, QS_INJ_WR(grp)); + } + + /* Add padding */ + while (i < (LAN966X_BUFFER_MIN_SZ / 4)) { + /* Wait until the fifo is ready */ + while (!(QS_INJ_STATUS_FIFO_RDY_GET(lan_rd(lan966x, QS_INJ_STATUS)) & + BIT(grp))) + ; + + lan_wr(0, lan966x, QS_INJ_WR(grp)); + ++i; + } + + /* Inidcate EOF and valid bytes in the last word */ + lan_wr(QS_INJ_CTRL_GAP_SIZE_SET(1) | + QS_INJ_CTRL_VLD_BYTES_SET(skb->len < LAN966X_BUFFER_MIN_SZ ? + 0 : last) | + QS_INJ_CTRL_EOF_SET(1), + lan966x, QS_INJ_CTRL(grp)); + + /* Add dummy CRC */ + lan_wr(0, lan966x, QS_INJ_WR(grp)); + skb_tx_timestamp(skb); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static int lan966x_port_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x_frame_info info; + + memset(&info, 0, sizeof(info)); + + info.port = BIT(port->chip_port); + info.vid = skb_vlan_tag_get(skb); + + /* Adjust frame priority to priority queue */ + info.qos_class = skb->priority >= 0x7 ? 0x7 : skb->priority; + info.ipv = info.qos_class; + + return lan966x_port_ifh_xmit(skb, &info, dev); +} + +static void lan966x_set_promisc(struct lan966x_port *port, bool enable) +{ + struct lan966x *lan966x = port->lan966x; + + lan_rmw(ANA_CPU_FWD_CFG_SRC_COPY_ENA_SET(enable), + ANA_CPU_FWD_CFG_SRC_COPY_ENA, + lan966x, ANA_CPU_FWD_CFG(port->chip_port)); +} + +static void lan966x_change_rx_flags(struct net_device *dev, int flags) +{ + struct lan966x_port *port = netdev_priv(dev); + + if (!(flags & IFF_PROMISC)) + return; + + if (dev->flags & IFF_PROMISC) + lan966x_set_promisc(port, true); + else + lan966x_set_promisc(port, false); +} + +static int lan966x_change_mtu(struct net_device *dev, int new_mtu) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + + lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu), + lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); + dev->mtu = new_mtu; + + return 0; +} + +static const struct net_device_ops lan966x_port_netdev_ops = { + .ndo_open = lan966x_port_open, + .ndo_stop = lan966x_port_stop, + .ndo_start_xmit = lan966x_port_xmit, + .ndo_change_rx_flags = lan966x_change_rx_flags, + .ndo_change_mtu = lan966x_change_mtu, + .ndo_get_phys_port_name = lan966x_port_get_phys_port_name, +}; + +static int lan966x_ifh_extract(u32 *ifh, size_t pos, size_t length) +{ + int val = 0; + int i; + + for (i = pos; i < pos + length; ++i) + val |= ((ifh[IFH_LEN - i / 32 - 1] & BIT(i % 32)) >> + (i % 32)) << (i - pos); + + return val; +} + +static int lan966x_parse_ifh(u32 *ifh, struct lan966x_frame_info *info) +{ + int i; + + /* The IFH is in network order, switch to CPU order */ + for (i = 0; i < IFH_LEN; i++) + ifh[i] = ntohl((__force __be32)ifh[i]); + + info->len = lan966x_ifh_extract(ifh, IFH_POS_LEN, IFH_WID_LEN); + info->port = lan966x_ifh_extract(ifh, IFH_POS_SRCPORT, IFH_WID_SRCPORT); + + info->vid = lan966x_ifh_extract(ifh, IFH_POS_TCI, IFH_WID_TCI); + info->timestamp = lan966x_ifh_extract(ifh, IFH_POS_TIMESTAMP, + IFH_WID_TIMESTAMP); + return 0; +} + +static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, bool ifh, + u32 *rval) +{ + u32 bytes_valid; + u32 val; + + val = lan_rd(lan966x, QS_XTR_RD(grp)); + if (val == XTR_NOT_READY) { + if (ifh) + return -EIO; + + do { + val = lan_rd(lan966x, QS_XTR_RD(grp)); + } while (val == XTR_NOT_READY); + } + + switch (val) { + case XTR_ABORT: + return -EIO; + case XTR_EOF_0: + case XTR_EOF_1: + case XTR_EOF_2: + case XTR_EOF_3: + case XTR_PRUNED: + bytes_valid = XTR_VALID_BYTES(val); + val = lan_rd(lan966x, QS_XTR_RD(grp)); + if (val == XTR_ESCAPE) + *rval = lan_rd(lan966x, QS_XTR_RD(grp)); + else + *rval = val; + + return bytes_valid; + case XTR_ESCAPE: + *rval = lan_rd(lan966x, QS_XTR_RD(grp)); + + return 4; + default: + *rval = val; + + return 4; + } +} + +static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) +{ + struct lan966x *lan966x = args; + int i, grp = 0, err = 0; + + if (!(lan_rd(lan966x, QS_XTR_DATA_PRESENT) & BIT(grp))) + return IRQ_NONE; + + do { + u32 ifh[IFH_LEN] = { 0 }; + struct lan966x_frame_info info; + struct net_device *dev; + int sz, len, buf_len; + struct sk_buff *skb; + u32 *buf; + u32 val; + + for (i = 0; i < IFH_LEN; i++) { + err = lan966x_rx_frame_word(lan966x, grp, true, + &ifh[i]); + if (err != 4) + break; + } + + if (err != 4) + break; + + err = 0; + + lan966x_parse_ifh(ifh, &info); + WARN_ON(info.port >= lan966x->num_phys_ports); + + dev = lan966x->ports[info.port]->dev; + skb = netdev_alloc_skb(dev, info.len); + if (unlikely(!skb)) { + netdev_err(dev, "Unable to allocate sk_buff\n"); + err = -ENOMEM; + break; + } + buf_len = info.len - ETH_FCS_LEN; + buf = (u32 *)skb_put(skb, buf_len); + + len = 0; + do { + sz = lan966x_rx_frame_word(lan966x, grp, false, &val); + *buf++ = val; + len += sz; + } while (len < buf_len); + + /* Read the FCS */ + sz = lan966x_rx_frame_word(lan966x, grp, false, &val); + + /* Update the statistics if part of the FCS was read before */ + len -= ETH_FCS_LEN - sz; + + if (unlikely(dev->features & NETIF_F_RXFCS)) { + buf = (u32 *)skb_put(skb, ETH_FCS_LEN); + *buf = val; + } + + if (sz < 0) { + err = sz; + break; + } + + skb->protocol = eth_type_trans(skb, dev); + + netif_rx_ni(skb); + dev->stats.rx_bytes += len; + dev->stats.rx_packets++; + } while (lan_rd(lan966x, QS_XTR_DATA_PRESENT) & BIT(grp)); + + if (err) + while (lan_rd(lan966x, QS_XTR_DATA_PRESENT) & BIT(grp)) + lan_rd(lan966x, QS_XTR_RD(grp)); + + return IRQ_HANDLED; +} + +static void lan966x_cleanup_ports(struct lan966x *lan966x) +{ + struct lan966x_port *port; + int portno; + + for (portno = 0; portno < lan966x->num_phys_ports; portno++) { + port = lan966x->ports[portno]; + if (!port) + continue; + + if (port->phylink) { + rtnl_lock(); + lan966x_port_stop(port->dev); + rtnl_unlock(); + port->phylink = NULL; + } + + if (port->fwnode) + fwnode_handle_put(port->fwnode); + + if (port->dev) + unregister_netdev(port->dev); + } +} + static int lan966x_probe_port(struct lan966x *lan966x, u8 port, phy_interface_t phy_mode) { struct lan966x_port *lan966x_port; + struct phylink *phylink; + struct net_device *dev; + int err; if (port >= lan966x->num_phys_ports) return -EINVAL; - lan966x_port = devm_kzalloc(lan966x->dev, sizeof(*lan966x_port), - GFP_KERNEL); + dev = devm_alloc_etherdev_mqs(lan966x->dev, + sizeof(struct lan966x_port), 8, 1); + if (!dev) + return -ENOMEM; + SET_NETDEV_DEV(dev, lan966x->dev); + lan966x_port = netdev_priv(dev); + lan966x_port->dev = dev; lan966x_port->lan966x = lan966x; lan966x_port->chip_port = port; lan966x_port->pvid = PORT_PVID; lan966x->ports[port] = lan966x_port; + dev->max_mtu = ETH_MAX_MTU; + + dev->netdev_ops = &lan966x_port_netdev_ops; + dev->needed_headroom = IFH_LEN * sizeof(u32); + + err = register_netdev(dev); + if (err) { + dev_err(lan966x->dev, "register_netdev failed\n"); + goto err_register_netdev; + } + + lan966x_port->phylink_config.dev = &lan966x_port->dev->dev; + lan966x_port->phylink_config.type = PHYLINK_NETDEV; + lan966x_port->phylink_config.pcs_poll = true; + + phylink = phylink_create(&lan966x_port->phylink_config, + lan966x_port->fwnode, + phy_mode, + &lan966x_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + lan966x_port->phylink = phylink; + return 0; + +err_register_netdev: + return err; } static void lan966x_init(struct lan966x *lan966x) @@ -306,6 +745,19 @@ static int lan966x_probe(struct platform_device *pdev) /* There QS system has 32KB of memory */ lan966x->shared_queue_sz = LAN966X_BUFFER_MEMORY; + /* set irq */ + lan966x->xtr_irq = platform_get_irq_byname(pdev, "xtr"); + if (lan966x->xtr_irq <= 0) + return -EINVAL; + + err = devm_request_threaded_irq(&pdev->dev, lan966x->xtr_irq, NULL, + lan966x_xtr_irq_handler, IRQF_ONESHOT, + "frame extraction", lan966x); + if (err) { + pr_err("Unable to use xtr irq"); + return -ENODEV; + } + /* init switch */ lan966x_init(lan966x); @@ -321,17 +773,40 @@ static int lan966x_probe(struct platform_device *pdev) phy_mode = fwnode_get_phy_mode(portnp); err = lan966x_probe_port(lan966x, port, phy_mode); if (err) - return err; + goto cleanup_ports; + + /* Read needed configuration */ + lan966x->ports[port]->config.phy_mode = phy_mode; + lan966x->ports[port]->config.portmode = phy_mode; + lan966x->ports[port]->fwnode = portnp; + + serdes = devm_of_phy_get(lan966x->dev, to_of_node(portnp), NULL); + if (!IS_ERR(serdes)) + lan966x->ports[port]->serdes = serdes; + + lan966x_port_init(lan966x->ports[port]); } return 0; +cleanup_ports: + fwnode_handle_put(portnp); + + disable_irq(lan966x->xtr_irq); + lan966x->xtr_irq = -ENXIO; + lan966x_cleanup_ports(lan966x); out: return err; } static int lan966x_remove(struct platform_device *pdev) { + struct lan966x *lan966x = platform_get_drvdata(pdev); + + disable_irq(lan966x->xtr_irq); + lan966x->xtr_irq = -ENXIO; + lan966x_cleanup_ports(lan966x); + return 0; } diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 0c5fa14437a5..9ae1582f5cdb 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -3,7 +3,12 @@ #ifndef __LAN966X_MAIN_H__ #define __LAN966X_MAIN_H__ +#include +#include +#include + #include "lan966x_regs.h" +#include "lan966x_ifh.h" #define LAN966X_BUFFER_CELL_SZ 64 #define LAN966X_BUFFER_MEMORY (160 * 1024) @@ -35,6 +40,15 @@ struct lan966x_port; +struct lan966x_frame_info { + u32 len; + u16 port; /* Bit mask */ + u16 vid; + u32 timestamp; + u8 qos_class; + u8 ipv; +}; + struct lan966x { struct device *dev; @@ -44,17 +58,41 @@ struct lan966x { void __iomem *regs[NUM_TARGETS]; int shared_queue_sz; + + /* interrupts */ + int xtr_irq; +}; + +struct lan966x_port_config { + phy_interface_t portmode; + phy_interface_t phy_mode; + int speed; + int duplex; + u32 pause; }; struct lan966x_port { + struct net_device *dev; struct lan966x *lan966x; u8 chip_port; u16 pvid; + struct phylink_config phylink_config; + struct lan966x_port_config config; + struct phylink *phylink; + struct phy *serdes; + struct fwnode_handle *fwnode; + void __iomem *regs; }; +extern const struct phylink_mac_ops lan966x_phylink_mac_ops; + +void lan966x_port_config_down(struct lan966x_port *port); +void lan966x_port_config_up(struct lan966x_port *port); +void lan966x_port_init(struct lan966x_port *port); + static inline void __iomem *lan_addr(void __iomem *base[], int id, int tinst, int tcnt, int gbase, int ginst, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c new file mode 100644 index 000000000000..23687492869f --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2020 Microchip Technology Inc. */ + +#include +#include +#include +#include +#include + +#include "lan966x_main.h" + +static void lan966x_phylink_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + switch (state->interface) { + case PHY_INTERFACE_MODE_NA: + case PHY_INTERFACE_MODE_GMII: + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + break; + default: + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + return; + } + bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static void lan966x_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) +{ +} + +static void lan966x_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, + phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct lan966x_port *port = netdev_priv(to_net_dev(config->dev)); + struct lan966x_port_config *port_config = &port->config; + + port_config->duplex = duplex; + port_config->speed = speed; + port_config->pause = 0; + port_config->pause |= tx_pause ? MLO_PAUSE_TX : 0; + port_config->pause |= rx_pause ? MLO_PAUSE_RX : 0; + + lan966x_port_config_up(port); +} + +static void lan966x_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) +{ +} + +static void lan966x_phylink_mac_link_state(struct phylink_config *config, + struct phylink_link_state *state) +{ +} + +static void lan966x_phylink_mac_aneg_restart(struct phylink_config *config) +{ +} + +const struct phylink_mac_ops lan966x_phylink_mac_ops = { + .validate = lan966x_phylink_validate, + .mac_pcs_get_state = lan966x_phylink_mac_link_state, + .mac_config = lan966x_phylink_mac_config, + .mac_an_restart = lan966x_phylink_mac_aneg_restart, + .mac_link_down = lan966x_phylink_mac_link_down, + .mac_link_up = lan966x_phylink_mac_link_up, +}; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c new file mode 100644 index 000000000000..7d6a3c968bd3 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#include "lan966x_main.h" + +/* Watermark encode */ +#define MULTIPLIER_BIT BIT(8) +static u32 lan966x_wm_enc(u32 value) +{ + value /= LAN966X_BUFFER_CELL_SZ; + + if (value >= MULTIPLIER_BIT) { + value /= 16; + if (value >= MULTIPLIER_BIT) + value = (MULTIPLIER_BIT - 1); + + value |= MULTIPLIER_BIT; + } + + return value; +} + +static void lan966x_port_link_down(struct lan966x_port *port) +{ + struct lan966x *lan966x = port->lan966x; + u32 val, delay = 0; + + /* 0.5: Disable any AFI */ + lan_rmw(AFI_PORT_CFG_FC_SKIP_TTI_INJ_SET(1) | + AFI_PORT_CFG_FRM_OUT_MAX_SET(0), + AFI_PORT_CFG_FC_SKIP_TTI_INJ | + AFI_PORT_CFG_FRM_OUT_MAX, + lan966x, AFI_PORT_CFG(port->chip_port)); + + /* wait for reg afi_port_frm_out to become 0 for the port */ + while (true) { + val = lan_rd(lan966x, AFI_PORT_FRM_OUT(port->chip_port)); + if (!AFI_PORT_FRM_OUT_FRM_OUT_CNT_GET(val)) + break; + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + delay++; + if (delay == 2000) { + pr_err("AFI timeout chip port %u", port->chip_port); + break; + } + } + + delay = 0; + + /* 1: Reset the PCS Rx clock domain */ + lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(1), + DEV_CLOCK_CFG_PCS_RX_RST, + lan966x, DEV_CLOCK_CFG(port->chip_port)); + + /* 2: Disable MAC frame reception */ + lan_rmw(DEV_MAC_ENA_CFG_RX_ENA_SET(0), + DEV_MAC_ENA_CFG_RX_ENA, + lan966x, DEV_MAC_ENA_CFG(port->chip_port)); + + /* 3: Disable traffic being sent to or from switch port */ + lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(0), + QSYS_SW_PORT_MODE_PORT_ENA, + lan966x, QSYS_SW_PORT_MODE(port->chip_port)); + + /* 4: Disable dequeuing from the egress queues */ + lan_rmw(QSYS_PORT_MODE_DEQUEUE_DIS_SET(1), + QSYS_PORT_MODE_DEQUEUE_DIS, + lan966x, QSYS_PORT_MODE(port->chip_port)); + + /* 5: Disable Flowcontrol */ + lan_rmw(SYS_PAUSE_CFG_PAUSE_ENA_SET(0), + SYS_PAUSE_CFG_PAUSE_ENA, + lan966x, SYS_PAUSE_CFG(port->chip_port)); + + /* 5.1: Disable PFC */ + lan_rmw(QSYS_SW_PORT_MODE_TX_PFC_ENA_SET(0), + QSYS_SW_PORT_MODE_TX_PFC_ENA, + lan966x, QSYS_SW_PORT_MODE(port->chip_port)); + + /* 6: Wait a worst case time 8ms (jumbo/10Mbit) */ + usleep_range(8 * USEC_PER_MSEC, 9 * USEC_PER_MSEC); + + /* 7: Disable HDX backpressure */ + lan_rmw(SYS_FRONT_PORT_MODE_HDX_MODE_SET(0), + SYS_FRONT_PORT_MODE_HDX_MODE, + lan966x, SYS_FRONT_PORT_MODE(port->chip_port)); + + /* 8: Flush the queues accociated with the port */ + lan_rmw(QSYS_SW_PORT_MODE_AGING_MODE_SET(3), + QSYS_SW_PORT_MODE_AGING_MODE, + lan966x, QSYS_SW_PORT_MODE(port->chip_port)); + + /* 9: Enable dequeuing from the egress queues */ + lan_rmw(QSYS_PORT_MODE_DEQUEUE_DIS_SET(0), + QSYS_PORT_MODE_DEQUEUE_DIS, + lan966x, QSYS_PORT_MODE(port->chip_port)); + + /* 10: Wait until flushing is complete */ + while (true) { + val = lan_rd(lan966x, QSYS_SW_STATUS(port->chip_port)); + if (!QSYS_SW_STATUS_EQ_AVAIL_GET(val)) + break; + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + delay++; + if (delay == 2000) { + pr_err("Flush timeout chip port %u", port->chip_port); + break; + } + } + + /* 11: Reset the Port and MAC clock domains */ + lan_rmw(DEV_MAC_ENA_CFG_TX_ENA_SET(0), + DEV_MAC_ENA_CFG_TX_ENA, + lan966x, DEV_MAC_ENA_CFG(port->chip_port)); /* Bugzilla#19076 */ + + lan_rmw(DEV_CLOCK_CFG_PORT_RST_SET(1), + DEV_CLOCK_CFG_PORT_RST, + lan966x, DEV_CLOCK_CFG(port->chip_port)); + + usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC); + + lan_rmw(DEV_CLOCK_CFG_MAC_TX_RST_SET(1) | + DEV_CLOCK_CFG_MAC_RX_RST_SET(1) | + DEV_CLOCK_CFG_PORT_RST_SET(1), + DEV_CLOCK_CFG_MAC_TX_RST | + DEV_CLOCK_CFG_MAC_RX_RST | + DEV_CLOCK_CFG_PORT_RST, + lan966x, DEV_CLOCK_CFG(port->chip_port)); + + /* 12: Clear flushing */ + lan_rmw(QSYS_SW_PORT_MODE_AGING_MODE_SET(2), + QSYS_SW_PORT_MODE_AGING_MODE, + lan966x, QSYS_SW_PORT_MODE(port->chip_port)); + + /* The port is disabled and flushed, now set up the port in the + * new operating mode + */ +} + +static void lan966x_port_link_up(struct lan966x_port *port) +{ + struct lan966x_port_config *config = &port->config; + struct lan966x *lan966x = port->lan966x; + int speed = 0, mode = 0; + int atop_wm = 0; + + switch (config->speed) { + case SPEED_10: + speed = LAN966X_SPEED_10; + break; + case SPEED_100: + speed = LAN966X_SPEED_100; + break; + case SPEED_1000: + speed = LAN966X_SPEED_1000; + mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1); + break; + } + + /* Also the GIGA_MODE_ENA(1) needs to be set regardless of the + * port speed for QSGMII ports. + */ + if (config->phy_mode == PHY_INTERFACE_MODE_QSGMII) + mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1); + + lan_wr(config->duplex | mode, + lan966x, DEV_MAC_MODE_CFG(port->chip_port)); + + lan_rmw(DEV_MAC_IFG_CFG_TX_IFG_SET(5), + DEV_MAC_IFG_CFG_TX_IFG, + lan966x, DEV_MAC_IFG_CFG(port->chip_port)); + + lan_rmw(DEV_MAC_HDX_CFG_SEED_SET(4) | + DEV_MAC_HDX_CFG_SEED_LOAD_SET(1), + DEV_MAC_HDX_CFG_SEED | + DEV_MAC_HDX_CFG_SEED_LOAD, + lan966x, DEV_MAC_HDX_CFG(port->chip_port)); + + if (config->phy_mode != PHY_INTERFACE_MODE_QSGMII) { + if (config->speed == SPEED_1000) + lan_rmw(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_SET(1), + CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA, + lan966x, + CHIP_TOP_CUPHY_PORT_CFG(port->chip_port)); + else + lan_rmw(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_SET(0), + CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA, + lan966x, + CHIP_TOP_CUPHY_PORT_CFG(port->chip_port)); + } + + /* No PFC */ + lan_wr(ANA_PFC_CFG_FC_LINK_SPEED_SET(speed), + lan966x, ANA_PFC_CFG(port->chip_port)); + + if (config->phy_mode == PHY_INTERFACE_MODE_QSGMII) { + lan_rmw(DEV_PCS1G_CFG_PCS_ENA_SET(1), + DEV_PCS1G_CFG_PCS_ENA, + lan966x, DEV_PCS1G_CFG(port->chip_port)); + + lan_rmw(DEV_PCS1G_SD_CFG_SD_ENA_SET(0), + DEV_PCS1G_SD_CFG_SD_ENA, + lan966x, DEV_PCS1G_SD_CFG(port->chip_port)); + } + + lan_rmw(DEV_PCS1G_CFG_PCS_ENA_SET(1), + DEV_PCS1G_CFG_PCS_ENA, + lan966x, DEV_PCS1G_CFG(port->chip_port)); + + lan_rmw(DEV_PCS1G_SD_CFG_SD_ENA_SET(0), + DEV_PCS1G_SD_CFG_SD_ENA, + lan966x, DEV_PCS1G_SD_CFG(port->chip_port)); + + /* Set Pause WM hysteresis, start/stop are in 1518 byte units */ + lan_wr(SYS_PAUSE_CFG_PAUSE_ENA_SET(1) | + SYS_PAUSE_CFG_PAUSE_STOP_SET(lan966x_wm_enc(4 * 1518)) | + SYS_PAUSE_CFG_PAUSE_START_SET(lan966x_wm_enc(6 * 1518)), + lan966x, SYS_PAUSE_CFG(port->chip_port)); + + /* Set SMAC of Pause frame (00:00:00:00:00:00) */ + lan_wr(0, lan966x, DEV_FC_MAC_LOW_CFG(port->chip_port)); + lan_wr(0, lan966x, DEV_FC_MAC_HIGH_CFG(port->chip_port)); + + /* Flow control */ + lan_rmw(SYS_MAC_FC_CFG_FC_LINK_SPEED_SET(speed) | + SYS_MAC_FC_CFG_FC_LATENCY_CFG_SET(7) | + SYS_MAC_FC_CFG_ZERO_PAUSE_ENA_SET(1) | + SYS_MAC_FC_CFG_PAUSE_VAL_CFG_SET(0xffff) | + SYS_MAC_FC_CFG_RX_FC_ENA_SET(config->pause & MLO_PAUSE_RX ? 1 : 0) | + SYS_MAC_FC_CFG_TX_FC_ENA_SET(config->pause & MLO_PAUSE_TX ? 1 : 0), + SYS_MAC_FC_CFG_FC_LINK_SPEED | + SYS_MAC_FC_CFG_FC_LATENCY_CFG | + SYS_MAC_FC_CFG_ZERO_PAUSE_ENA | + SYS_MAC_FC_CFG_PAUSE_VAL_CFG | + SYS_MAC_FC_CFG_RX_FC_ENA | + SYS_MAC_FC_CFG_TX_FC_ENA, + lan966x, SYS_MAC_FC_CFG(port->chip_port)); + + /* Tail dropping watermark */ + atop_wm = lan966x->shared_queue_sz; + + /* The total memory size is diveded by number of front ports plus CPU + * port + */ + lan_wr(lan966x_wm_enc(atop_wm / lan966x->num_phys_ports + 1), lan966x, + SYS_ATOP(port->chip_port)); + lan_wr(lan966x_wm_enc(atop_wm), lan966x, SYS_ATOP_TOT_CFG); + + /* This needs to be at the end */ + /* Enable MAC module */ + lan_wr(DEV_MAC_ENA_CFG_RX_ENA_SET(1) | + DEV_MAC_ENA_CFG_TX_ENA_SET(1), + lan966x, DEV_MAC_ENA_CFG(port->chip_port)); + + /* Take out the clock from reset */ + lan_wr(DEV_CLOCK_CFG_LINK_SPEED_SET(speed), + lan966x, DEV_CLOCK_CFG(port->chip_port)); + + /* Core: Enable port for frame transfer */ + lan_wr(QSYS_SW_PORT_MODE_PORT_ENA_SET(1) | + QSYS_SW_PORT_MODE_SCH_NEXT_CFG_SET(1) | + QSYS_SW_PORT_MODE_INGRESS_DROP_MODE_SET(1), + lan966x, QSYS_SW_PORT_MODE(port->chip_port)); + + lan_rmw(AFI_PORT_CFG_FC_SKIP_TTI_INJ_SET(0) | + AFI_PORT_CFG_FRM_OUT_MAX_SET(16), + AFI_PORT_CFG_FC_SKIP_TTI_INJ | + AFI_PORT_CFG_FRM_OUT_MAX, + lan966x, AFI_PORT_CFG(port->chip_port)); +} + +void lan966x_port_config_down(struct lan966x_port *port) +{ + lan966x_port_link_down(port); +} + +void lan966x_port_config_up(struct lan966x_port *port) +{ + lan966x_port_link_down(port); + lan966x_port_link_up(port); +} + +void lan966x_port_init(struct lan966x_port *port) +{ + struct lan966x_port_config *config = &port->config; + struct lan966x *lan966x = port->lan966x; + + if (config->phy_mode != PHY_INTERFACE_MODE_QSGMII) + return; + + lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) | + DEV_CLOCK_CFG_PCS_TX_RST_SET(0) | + DEV_CLOCK_CFG_LINK_SPEED_SET(LAN966X_SPEED_1000), + DEV_CLOCK_CFG_PCS_RX_RST | + DEV_CLOCK_CFG_PCS_TX_RST | + DEV_CLOCK_CFG_LINK_SPEED, + lan966x, DEV_CLOCK_CFG(port->chip_port)); +} From patchwork Mon Sep 20 09:52:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505017 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B42AC43219 for ; Mon, 20 Sep 2021 09:52:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6BAF560F9D for ; Mon, 20 Sep 2021 09:52:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236781AbhITJyW (ORCPT ); Mon, 20 Sep 2021 05:54:22 -0400 Received: from esa.microchip.iphmx.com ([68.232.153.233]:10199 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236833AbhITJxZ (ORCPT ); Mon, 20 Sep 2021 05:53:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131519; x=1663667519; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7zh46xW6WIb46nT5IfMdGF3myb9A5ac3uBD7/y5IlH4=; b=f+IM3Ic63/SQXRQl2wGTdT7jDjhXSm4/MXzvKa6OLATrnyZnrB1tNUBW xePmOJxfkdN752/m1kJ2i/c7Pw1w7c4yAWIXoOoEXBCx4UuNxqX1CKfGH lqXy8zhqEwlYFiehyQ7A+b8z1RFoWKGrpa6UeLaxjVRMfPGZKH8T/VE8K Z3yDvZt8ddFF++eop4Jnvu2cS27pJhWKfyv/n8MJz2/lmIlY/xcpqmJVY uEC25SPCmGAzUf4M2DNfOK2uq4rZb0+U0wT7kKaBGoV9LBGZ8KF7MtkI3 Pm/dgGcLZj8OLOMR9EKnAj4wpqekQE60IKhxDVL3U3Nvf+41r+SaOiEJb Q==; IronPort-SDR: /pUNJDZ9u8EHp+VhzW2N8v/Nu8i8VKaCYZ/fMzGmvQ4hF0QCRyuHyORUNZaJpbZjgzHK0bhHH4 aX/hs8/8SKG0obkT5wohcQ9rtLu4P1oHH6ehJj/MQTwuzxYh8tTo4d/b4zaFd5zE9MnDWuai2L Yhk6gl5Kh0/g2a8LrgUa4nbhSqe4y06zzMchWvsq5SiEfpsyxqCFmQls5nO9CTSABB/g/DZIkj bI2jEuA7X94P+2FzCvFifBaQGO/gQcews+ngTV6epC4XQsGz0x+/NXYweia8vQNZIvmgVONK/R +kE1cBCuskP1NvaBZFlEQ5wb X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="137192411" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:48 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:47 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:45 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 11/12] net: lan966x: add mactable support Date: Mon, 20 Sep 2021 11:52:17 +0200 Message-ID: <20210920095218.1108151-12-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This patch adds support for MAC table operations like add and forget. Also add the functionality to read the MAC address from DT, if there is no MAC set in DT it would use a random one. Signed-off-by: Horatiu Vultur --- .../ethernet/microchip/lan966x/lan966x_main.c | 158 ++++++++++++++++++ .../ethernet/microchip/lan966x/lan966x_main.h | 29 ++++ 2 files changed, 187 insertions(+) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index cf147d44b345..53b88bb5b718 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -24,6 +24,8 @@ #define READL_SLEEP_US 10 #define READL_TIMEOUT_US 100000000 +#define TABLE_UPDATE_SLEEP_US 10 +#define TABLE_UPDATE_TIMEOUT_US 100000 #define IO_RANGES 2 @@ -94,6 +96,107 @@ static int lan966x_create_targets(struct platform_device *pdev, return 0; } +static int lan966x_mact_get_status(struct lan966x *lan966x) +{ + return lan_rd(lan966x, ANA_MACACCESS); +} + +static int lan966x_mact_wait_for_completion(struct lan966x *lan966x) +{ + u32 val; + + return readx_poll_timeout(lan966x_mact_get_status, + lan966x, val, + (ANA_MACACCESS_MAC_TABLE_CMD_GET(val)) == + MACACCESS_CMD_IDLE, + TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US); +} + +static void lan966x_mact_select(struct lan966x *lan966x, + const unsigned char mac[ETH_ALEN], + unsigned int vid) +{ + u32 macl = 0, mach = 0; + + /* Set the MAC address to handle and the vlan associated in a format + * understood by the hardware. + */ + mach |= vid << 16; + mach |= mac[0] << 8; + mach |= mac[1] << 0; + macl |= mac[2] << 24; + macl |= mac[3] << 16; + macl |= mac[4] << 8; + macl |= mac[5] << 0; + + lan_wr(macl, lan966x, ANA_MACLDATA); + lan_wr(mach, lan966x, ANA_MACHDATA); +} + +static int lan966x_mact_learn(struct lan966x *lan966x, int port, + const unsigned char mac[ETH_ALEN], + unsigned int vid, + enum macaccess_entry_type type) +{ + lan966x_mact_select(lan966x, mac, vid); + + /* Issue a write command */ + lan_wr(ANA_MACACCESS_VALID_SET(1) | + ANA_MACACCESS_CHANGE2SW_SET(0) | + ANA_MACACCESS_DEST_IDX_SET(port) | + ANA_MACACCESS_ENTRYTYPE_SET(type) | + ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_LEARN), + lan966x, ANA_MACACCESS); + + return lan966x_mact_wait_for_completion(lan966x); +} + +static int lan966x_mact_forget(struct lan966x *lan966x, + const unsigned char mac[ETH_ALEN], + unsigned int vid, + enum macaccess_entry_type type) +{ + lan966x_mact_select(lan966x, mac, vid); + + /* Issue a forget command */ + lan_wr(ANA_MACACCESS_ENTRYTYPE_SET(type) | + ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_FORGET), + lan966x, ANA_MACACCESS); + + return lan966x_mact_wait_for_completion(lan966x); +} + +static void lan966x_mact_init(struct lan966x *lan966x) +{ + /* Clear the MAC table */ + lan_wr(MACACCESS_CMD_INIT, + lan966x, ANA_MACACCESS); + lan966x_mact_wait_for_completion(lan966x); +} + +static int lan966x_port_set_mac_address(struct net_device *dev, void *p) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + const struct sockaddr *addr = p; + int ret; + + /* Learn the new net device MAC address in the mac table. */ + ret = lan966x_mact_learn(lan966x, PGID_CPU, addr->sa_data, port->pvid, + ENTRYTYPE_LOCKED); + if (ret) + return ret; + + /* Then forget the previous one. */ + ret = lan966x_mact_forget(lan966x, dev->dev_addr, port->pvid, + ENTRYTYPE_LOCKED); + if (ret) + return ret; + + ether_addr_copy(dev->dev_addr, addr->sa_data); + return ret; +} + static int lan966x_port_get_phys_port_name(struct net_device *dev, char *buf, size_t len) { @@ -301,13 +404,50 @@ static int lan966x_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static int lan966x_mc_unsync(struct net_device *dev, const unsigned char *addr) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + + return lan966x_mact_forget(lan966x, addr, port->pvid, ENTRYTYPE_LOCKED); +} + +static int lan966x_mc_sync(struct net_device *dev, const unsigned char *addr) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + + return lan966x_mact_learn(lan966x, PGID_CPU, addr, port->pvid, + ENTRYTYPE_LOCKED); +} + +static void lan966x_set_rx_mode(struct net_device *dev) +{ + __dev_mc_sync(dev, lan966x_mc_sync, lan966x_mc_unsync); +} + +static int lan966x_port_get_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct lan966x_port *lan966x_port = netdev_priv(dev); + struct lan966x *lan966x = lan966x_port->lan966x; + + ppid->id_len = sizeof(lan966x->base_mac); + memcpy(&ppid->id, &lan966x->base_mac, ppid->id_len); + + return 0; +} + static const struct net_device_ops lan966x_port_netdev_ops = { .ndo_open = lan966x_port_open, .ndo_stop = lan966x_port_stop, .ndo_start_xmit = lan966x_port_xmit, .ndo_change_rx_flags = lan966x_change_rx_flags, .ndo_change_mtu = lan966x_change_mtu, + .ndo_set_rx_mode = lan966x_set_rx_mode, .ndo_get_phys_port_name = lan966x_port_get_phys_port_name, + .ndo_set_mac_address = lan966x_port_set_mac_address, + .ndo_get_port_parent_id = lan966x_port_get_parent_id, }; static int lan966x_ifh_extract(u32 *ifh, size_t pos, size_t length) @@ -515,6 +655,12 @@ static int lan966x_probe_port(struct lan966x *lan966x, u8 port, dev->netdev_ops = &lan966x_port_netdev_ops; dev->needed_headroom = IFH_LEN * sizeof(u32); + ether_addr_copy(dev->dev_addr, lan966x->base_mac); + dev->dev_addr[ETH_ALEN - 1] += port + 1; + + lan966x_mact_learn(lan966x, PGID_CPU, dev->dev_addr, lan966x_port->pvid, + ENTRYTYPE_LOCKED); + err = register_netdev(dev); if (err) { dev_err(lan966x->dev, "register_netdev failed\n"); @@ -544,6 +690,9 @@ static void lan966x_init(struct lan966x *lan966x) { u32 port, i; + /* MAC table initialization */ + lan966x_mact_init(lan966x); + /* Flush queues */ lan_wr(lan_rd(lan966x, QS_XTR_FLUSH) | GENMASK(1, 0), @@ -708,6 +857,7 @@ static int lan966x_probe(struct platform_device *pdev) { struct fwnode_handle *ports, *portnp; struct lan966x *lan966x; + u8 mac_addr[ETH_ALEN]; int err, i; lan966x = devm_kzalloc(&pdev->dev, sizeof(*lan966x), GFP_KERNEL); @@ -717,6 +867,14 @@ static int lan966x_probe(struct platform_device *pdev) platform_set_drvdata(pdev, lan966x); lan966x->dev = &pdev->dev; + if (device_get_mac_address(&pdev->dev, mac_addr, sizeof(mac_addr))) { + ether_addr_copy(lan966x->base_mac, mac_addr); + } else { + pr_info("MAC addr was not set, use random MAC\n"); + eth_random_addr(lan966x->base_mac); + lan966x->base_mac[5] &= 0xf0; + } + ports = device_get_named_child_node(&pdev->dev, "ethernet-ports"); if (!ports) { dev_err(&pdev->dev, "no ethernet-ports child not found\n"); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 9ae1582f5cdb..d499f654e316 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -4,6 +4,9 @@ #define __LAN966X_MAIN_H__ #include +#include "linux/ethtool.h" +#include +#include #include #include @@ -38,6 +41,30 @@ #define CPU_PORT 8 +#define LAN966X_MACT_COLUMNS 4 +#define MACACCESS_CMD_IDLE 0 +#define MACACCESS_CMD_LEARN 1 +#define MACACCESS_CMD_FORGET 2 +#define MACACCESS_CMD_AGE 3 +#define MACACCESS_CMD_GET_NEXT 4 +#define MACACCESS_CMD_INIT 5 +#define MACACCESS_CMD_READ 6 +#define MACACCESS_CMD_WRITE 7 +#define MACACCESS_CMD_SYNC_GET_NEXT 8 + +/* MAC table entry types. + * ENTRYTYPE_NORMAL is subject to aging. + * ENTRYTYPE_LOCKED is not subject to aging. + * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast. + * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast. + */ +enum macaccess_entry_type { + ENTRYTYPE_NORMAL = 0, + ENTRYTYPE_LOCKED, + ENTRYTYPE_MACV4, + ENTRYTYPE_MACV6, +}; + struct lan966x_port; struct lan966x_frame_info { @@ -59,6 +86,8 @@ struct lan966x { int shared_queue_sz; + u8 base_mac[ETH_ALEN]; + /* interrupts */ int xtr_irq; }; From patchwork Mon Sep 20 09:52:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 12505019 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45F38C433FE for ; Mon, 20 Sep 2021 09:52:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 31C7160F9D for ; Mon, 20 Sep 2021 09:52:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237474AbhITJyL (ORCPT ); Mon, 20 Sep 2021 05:54:11 -0400 Received: from esa.microchip.iphmx.com ([68.232.154.123]:37479 "EHLO esa.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236781AbhITJxT (ORCPT ); Mon, 20 Sep 2021 05:53:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1632131512; x=1663667512; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pwJwGbEIIjCN1Dfp1IEqlyndVqIkbVlMlcttoC0S3q0=; b=v+DoRXdZITzMr6SMWrm8tUQampRQEuGsOnbcqgpXCbfwSBo3b1N3vOMQ W4dUwnArnmqjtp7SmpR2K2TwF3YpHUvn6FWYpUtIK+KDo+fO9P1v0rG+m ZvIeLw2jf5xf+Ve5r7BJjZPBwzUacP/r2pdFAcBKVBW8DOlcLlsj83TUn gczyGzABFxLKE9yQMJHsNORKNhBvU6IwR3DuNdUFilU6cS1vv9fRGsBhb v8drt2DKDkhqVMs0Hrbvg0m7XfvIShRzjEgHWbaBbAOWP9tmUnvZxfUK2 ByV9yWSRvmZmznDoXfxFFySAnuZ+uVRDr55XMUutuXw3MuoRo30NtW2B7 Q==; IronPort-SDR: bkiwZXYrLbkBuN1tHpOJcwCmG4G6pLj0DOwz5wSHp1hXYYuGexBXGanP0WE+iZi8shZRgZ551Z ggbxf1ZgFbJuhqAicb3cgVMGRHQcw5rtpXAc6EUh+HHRNc+GjqfGp1BFcDi63WfIzDDz1e0hEM SuM7C5+HtDZDRY7MEd05up25KDvtfAOQqonxIpsqwqGhfQxkotdLcL1uUs/GC5Gu1l6V+wDq4Z kXbZMtbpVhIqZgdjF6Gc0QzLkplQzL3Rvxxz0Mr0y0uxfqLMHFkfCcsZbnCShtv5boECzlv8Hd OzP+87rmHjYRizVOUJDq+6Re X-IronPort-AV: E=Sophos;i="5.85,308,1624345200"; d="scan'208";a="129913612" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 20 Sep 2021 02:51:51 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Mon, 20 Sep 2021 02:51:51 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Mon, 20 Sep 2021 02:51:48 -0700 From: Horatiu Vultur To: , , , , , , , , , , , , , CC: Horatiu Vultur Subject: [RFC PATCH net-next 12/12] net: lan966x: add ethtool configuration and statistics Date: Mon, 20 Sep 2021 11:52:18 +0200 Message-ID: <20210920095218.1108151-13-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920095218.1108151-1-horatiu.vultur@microchip.com> References: <20210920095218.1108151-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC This patch adds support for statistics counters for the network interfaces. Also adds support for configuring the network interface via ethtool like: speed, duplex etc. Signed-off-by: Horatiu Vultur --- .../net/ethernet/microchip/lan966x/Makefile | 3 +- .../microchip/lan966x/lan966x_ethtool.c | 578 ++++++++++++++++++ .../ethernet/microchip/lan966x/lan966x_main.c | 11 + .../ethernet/microchip/lan966x/lan966x_main.h | 20 + 4 files changed, 611 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile index e18c9b2d0bb7..445a2abc47ff 100644 --- a/drivers/net/ethernet/microchip/lan966x/Makefile +++ b/drivers/net/ethernet/microchip/lan966x/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o -lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o +lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \ + lan966x_ethtool.o diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c new file mode 100644 index 000000000000..90fe2d872afa --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2019 Microchip Technology Inc. */ + +#include + +#include "lan966x_main.h" + +/* Number of traffic classes */ +#define LAN966X_NUM_TC 8 +#define LAN966X_STATS_CHECK_DELAY (2 * HZ) + +static const struct lan966x_stat_layout lan966x_stats_layout[] = { + { .name = "rx_octets", .offset = 0x00, }, + { .name = "rx_unicast", .offset = 0x01, }, + { .name = "rx_multicast", .offset = 0x02 }, + { .name = "rx_broadcast", .offset = 0x03 }, + { .name = "rx_short", .offset = 0x04 }, + { .name = "rx_frag", .offset = 0x05 }, + { .name = "rx_jabber", .offset = 0x06 }, + { .name = "rx_crc", .offset = 0x07 }, + { .name = "rx_symbol_err", .offset = 0x08 }, + { .name = "rx_sz_64", .offset = 0x09 }, + { .name = "rx_sz_65_127", .offset = 0x0a}, + { .name = "rx_sz_128_255", .offset = 0x0b}, + { .name = "rx_sz_256_511", .offset = 0x0c }, + { .name = "rx_sz_512_1023", .offset = 0x0d }, + { .name = "rx_sz_1024_1526", .offset = 0x0e }, + { .name = "rx_sz_jumbo", .offset = 0x0f }, + { .name = "rx_pause", .offset = 0x10 }, + { .name = "rx_control", .offset = 0x11 }, + { .name = "rx_long", .offset = 0x12 }, + { .name = "rx_cat_drop", .offset = 0x13 }, + { .name = "rx_red_prio_0", .offset = 0x14 }, + { .name = "rx_red_prio_1", .offset = 0x15 }, + { .name = "rx_red_prio_2", .offset = 0x16 }, + { .name = "rx_red_prio_3", .offset = 0x17 }, + { .name = "rx_red_prio_4", .offset = 0x18 }, + { .name = "rx_red_prio_5", .offset = 0x19 }, + { .name = "rx_red_prio_6", .offset = 0x1a }, + { .name = "rx_red_prio_7", .offset = 0x1b }, + { .name = "rx_yellow_prio_0", .offset = 0x1c }, + { .name = "rx_yellow_prio_1", .offset = 0x1d }, + { .name = "rx_yellow_prio_2", .offset = 0x1e }, + { .name = "rx_yellow_prio_3", .offset = 0x1f }, + { .name = "rx_yellow_prio_4", .offset = 0x20 }, + { .name = "rx_yellow_prio_5", .offset = 0x21 }, + { .name = "rx_yellow_prio_6", .offset = 0x22 }, + { .name = "rx_yellow_prio_7", .offset = 0x23 }, + { .name = "rx_green_prio_0", .offset = 0x24 }, + { .name = "rx_green_prio_1", .offset = 0x25 }, + { .name = "rx_green_prio_2", .offset = 0x26 }, + { .name = "rx_green_prio_3", .offset = 0x27 }, + { .name = "rx_green_prio_4", .offset = 0x28 }, + { .name = "rx_green_prio_5", .offset = 0x29 }, + { .name = "rx_green_prio_6", .offset = 0x2a }, + { .name = "rx_green_prio_7", .offset = 0x2b }, + { .name = "rx_assembly_err", .offset = 0x2c }, + { .name = "rx_smd_err", .offset = 0x2d }, + { .name = "rx_assembly_ok", .offset = 0x2e }, + { .name = "rx_merge_frag", .offset = 0x2f }, + { .name = "rx_pmac_octets", .offset = 0x30, }, + { .name = "rx_pmac_unicast", .offset = 0x31, }, + { .name = "rx_pmac_multicast", .offset = 0x32 }, + { .name = "rx_pmac_broadcast", .offset = 0x33 }, + { .name = "rx_pmac_short", .offset = 0x34 }, + { .name = "rx_pmac_frag", .offset = 0x35 }, + { .name = "rx_pmac_jabber", .offset = 0x36 }, + { .name = "rx_pmac_crc", .offset = 0x37 }, + { .name = "rx_pmac_symbol_err", .offset = 0x38 }, + { .name = "rx_pmac_sz_64", .offset = 0x39 }, + { .name = "rx_pmac_sz_65_127", .offset = 0x3a }, + { .name = "rx_pmac_sz_128_255", .offset = 0x3b }, + { .name = "rx_pmac_sz_256_511", .offset = 0x3c }, + { .name = "rx_pmac_sz_512_1023", .offset = 0x3d }, + { .name = "rx_pmac_sz_1024_1526", .offset = 0x3e }, + { .name = "rx_pmac_sz_jumbo", .offset = 0x3f }, + { .name = "rx_pmac_pause", .offset = 0x40 }, + { .name = "rx_pmac_control", .offset = 0x41 }, + { .name = "rx_pmac_long", .offset = 0x42 }, + + { .name = "tx_octets", .offset = 0x80, }, + { .name = "tx_unicast", .offset = 0x81, }, + { .name = "tx_multicast", .offset = 0x82 }, + { .name = "tx_broadcast", .offset = 0x83 }, + { .name = "tx_col", .offset = 0x84 }, + { .name = "tx_drop", .offset = 0x85 }, + { .name = "tx_pause", .offset = 0x86 }, + { .name = "tx_sz_64", .offset = 0x87 }, + { .name = "tx_sz_65_127", .offset = 0x88 }, + { .name = "tx_sz_128_255", .offset = 0x89 }, + { .name = "tx_sz_256_511", .offset = 0x8a }, + { .name = "tx_sz_512_1023", .offset = 0x8b }, + { .name = "tx_sz_1024_1526", .offset = 0x8c }, + { .name = "tx_sz_jumbo", .offset = 0x8d }, + { .name = "tx_yellow_prio_0", .offset = 0x8e }, + { .name = "tx_yellow_prio_1", .offset = 0x8f }, + { .name = "tx_yellow_prio_2", .offset = 0x90 }, + { .name = "tx_yellow_prio_3", .offset = 0x91 }, + { .name = "tx_yellow_prio_4", .offset = 0x92 }, + { .name = "tx_yellow_prio_5", .offset = 0x93 }, + { .name = "tx_yellow_prio_6", .offset = 0x94 }, + { .name = "tx_yellow_prio_7", .offset = 0x95 }, + { .name = "tx_green_prio_0", .offset = 0x96 }, + { .name = "tx_green_prio_1", .offset = 0x97 }, + { .name = "tx_green_prio_2", .offset = 0x98 }, + { .name = "tx_green_prio_3", .offset = 0x99 }, + { .name = "tx_green_prio_4", .offset = 0x9a }, + { .name = "tx_green_prio_5", .offset = 0x9b }, + { .name = "tx_green_prio_6", .offset = 0x9c }, + { .name = "tx_green_prio_7", .offset = 0x9d }, + { .name = "tx_aged", .offset = 0x9e }, + { .name = "tx_llct", .offset = 0x9f }, + { .name = "tx_ct", .offset = 0xa0 }, + { .name = "tx_mm_hold", .offset = 0xa1 }, + { .name = "tx_merge_frag", .offset = 0xa2 }, + { .name = "tx_pmac_octets", .offset = 0xa3, }, + { .name = "tx_pmac_unicast", .offset = 0xa4, }, + { .name = "tx_pmac_multicast", .offset = 0xa5 }, + { .name = "tx_pmac_broadcast", .offset = 0xa6 }, + { .name = "tx_pmac_pause", .offset = 0xa7 }, + { .name = "tx_pmac_sz_64", .offset = 0xa8 }, + { .name = "tx_pmac_sz_65_127", .offset = 0xa9 }, + { .name = "tx_pmac_sz_128_255", .offset = 0xaa }, + { .name = "tx_pmac_sz_256_511", .offset = 0xab }, + { .name = "tx_pmac_sz_512_1023", .offset = 0xac }, + { .name = "tx_pmac_sz_1024_1526", .offset = 0xad }, + { .name = "tx_pmac_sz_jumbo", .offset = 0xae }, + + { .name = "dr_local", .offset = 0x100 }, + { .name = "dr_tail", .offset = 0x101 }, + { .name = "dr_yellow_prio_0", .offset = 0x102 }, + { .name = "dr_yellow_prio_1", .offset = 0x103 }, + { .name = "dr_yellow_prio_2", .offset = 0x104 }, + { .name = "dr_yellow_prio_3", .offset = 0x105 }, + { .name = "dr_yellow_prio_4", .offset = 0x106 }, + { .name = "dr_yellow_prio_5", .offset = 0x107 }, + { .name = "dr_yellow_prio_6", .offset = 0x108 }, + { .name = "dr_yellow_prio_7", .offset = 0x109 }, + { .name = "dr_green_prio_0", .offset = 0x10a }, + { .name = "dr_green_prio_1", .offset = 0x10b }, + { .name = "dr_green_prio_2", .offset = 0x10c }, + { .name = "dr_green_prio_3", .offset = 0x10d }, + { .name = "dr_green_prio_4", .offset = 0x10e }, + { .name = "dr_green_prio_5", .offset = 0x10f }, + { .name = "dr_green_prio_6", .offset = 0x110 }, + { .name = "dr_green_prio_7", .offset = 0x111 }, +}; + +/* The following numbers are indexes into lan966x_stats_layout[] */ +#define SYS_COUNT_RX_OCT 0 +#define SYS_COUNT_RX_UC 1 +#define SYS_COUNT_RX_MC 2 +#define SYS_COUNT_RX_BC 3 +#define SYS_COUNT_RX_SHORT 4 +#define SYS_COUNT_RX_FRAG 5 +#define SYS_COUNT_RX_JABBER 6 +#define SYS_COUNT_RX_CRC 7 +#define SYS_COUNT_RX_SYMBOL_ERR 8 +#define SYS_COUNT_RX_SZ_64 9 +#define SYS_COUNT_RX_SZ_65_127 10 +#define SYS_COUNT_RX_SZ_128_255 11 +#define SYS_COUNT_RX_SZ_256_511 12 +#define SYS_COUNT_RX_SZ_512_1023 13 +#define SYS_COUNT_RX_SZ_1024_1526 14 +#define SYS_COUNT_RX_SZ_JUMBO 15 +#define SYS_COUNT_RX_PAUSE 16 +#define SYS_COUNT_RX_CONTROL 17 +#define SYS_COUNT_RX_LONG 18 +#define SYS_COUNT_RX_CAT_DROP 19 +#define SYS_COUNT_RX_RED_PRIO_0 20 +#define SYS_COUNT_RX_RED_PRIO_1 21 +#define SYS_COUNT_RX_RED_PRIO_2 22 +#define SYS_COUNT_RX_RED_PRIO_3 23 +#define SYS_COUNT_RX_RED_PRIO_4 24 +#define SYS_COUNT_RX_RED_PRIO_5 25 +#define SYS_COUNT_RX_RED_PRIO_6 26 +#define SYS_COUNT_RX_RED_PRIO_7 27 +#define SYS_COUNT_RX_YELLOW_PRIO_0 28 +#define SYS_COUNT_RX_YELLOW_PRIO_1 29 +#define SYS_COUNT_RX_YELLOW_PRIO_2 30 +#define SYS_COUNT_RX_YELLOW_PRIO_3 31 +#define SYS_COUNT_RX_YELLOW_PRIO_4 32 +#define SYS_COUNT_RX_YELLOW_PRIO_5 33 +#define SYS_COUNT_RX_YELLOW_PRIO_6 34 +#define SYS_COUNT_RX_YELLOW_PRIO_7 35 +#define SYS_COUNT_RX_GREEN_PRIO_0 36 +#define SYS_COUNT_RX_GREEN_PRIO_1 37 +#define SYS_COUNT_RX_GREEN_PRIO_2 38 +#define SYS_COUNT_RX_GREEN_PRIO_3 39 +#define SYS_COUNT_RX_GREEN_PRIO_4 40 +#define SYS_COUNT_RX_GREEN_PRIO_5 41 +#define SYS_COUNT_RX_GREEN_PRIO_6 42 +#define SYS_COUNT_RX_GREEN_PRIO_7 43 +#define SYS_COUNT_RX_ASSEMBLY_ERR 44 +#define SYS_COUNT_RX_SMD_ERR 45 +#define SYS_COUNT_RX_ASSEMBLY_OK 46 +#define SYS_COUNT_RX_MERGE_FRAG 47 +#define SYS_COUNT_RX_PMAC_OCT 48 +#define SYS_COUNT_RX_PMAC_UC 49 +#define SYS_COUNT_RX_PMAC_MC 50 +#define SYS_COUNT_RX_PMAC_BC 51 +#define SYS_COUNT_RX_PMAC_SHORT 52 +#define SYS_COUNT_RX_PMAC_FRAG 53 +#define SYS_COUNT_RX_PMAC_JABBER 54 +#define SYS_COUNT_RX_PMAC_CRC 55 +#define SYS_COUNT_RX_PMAC_SYMBOL_ERR 56 +#define SYS_COUNT_RX_PMAC_SZ_64 57 +#define SYS_COUNT_RX_PMAC_SZ_65_127 58 +#define SYS_COUNT_RX_PMAC_SZ_128_255 59 +#define SYS_COUNT_RX_PMAC_SZ_256_511 60 +#define SYS_COUNT_RX_PMAC_SZ_512_1023 61 +#define SYS_COUNT_RX_PMAC_SZ_1024_1526 62 +#define SYS_COUNT_RX_PMAC_SZ_JUMBO 63 +#define SYS_COUNT_RX_PMAC_PAUSE 64 +#define SYS_COUNT_RX_PMAC_CONTROL 65 +#define SYS_COUNT_RX_PMAC_LONG 66 + +#define SYS_COUNT_TX_OCT 67 +#define SYS_COUNT_TX_UC 68 +#define SYS_COUNT_TX_MC 69 +#define SYS_COUNT_TX_BC 70 +#define SYS_COUNT_TX_COL 71 +#define SYS_COUNT_TX_DROP 72 +#define SYS_COUNT_TX_PAUSE 73 +#define SYS_COUNT_TX_SZ_64 74 +#define SYS_COUNT_TX_SZ_65_127 75 +#define SYS_COUNT_TX_SZ_128_255 76 +#define SYS_COUNT_TX_SZ_256_511 77 +#define SYS_COUNT_TX_SZ_512_1023 78 +#define SYS_COUNT_TX_SZ_1024_1526 79 +#define SYS_COUNT_TX_SZ_JUMBO 80 +#define SYS_COUNT_TX_YELLOW_PRIO_0 81 +#define SYS_COUNT_TX_YELLOW_PRIO_1 82 +#define SYS_COUNT_TX_YELLOW_PRIO_2 83 +#define SYS_COUNT_TX_YELLOW_PRIO_3 84 +#define SYS_COUNT_TX_YELLOW_PRIO_4 85 +#define SYS_COUNT_TX_YELLOW_PRIO_5 86 +#define SYS_COUNT_TX_YELLOW_PRIO_6 87 +#define SYS_COUNT_TX_YELLOW_PRIO_7 88 +#define SYS_COUNT_TX_GREEN_PRIO_0 89 +#define SYS_COUNT_TX_GREEN_PRIO_1 90 +#define SYS_COUNT_TX_GREEN_PRIO_2 91 +#define SYS_COUNT_TX_GREEN_PRIO_3 92 +#define SYS_COUNT_TX_GREEN_PRIO_4 93 +#define SYS_COUNT_TX_GREEN_PRIO_5 94 +#define SYS_COUNT_TX_GREEN_PRIO_6 95 +#define SYS_COUNT_TX_GREEN_PRIO_7 96 +#define SYS_COUNT_TX_AGED 97 +#define SYS_COUNT_TX_LLCT 98 +#define SYS_COUNT_TX_CT 99 +#define SYS_COUNT_TX_MM_HOLD 100 +#define SYS_COUNT_TX_MERGE_FRAG 101 +#define SYS_COUNT_TX_PMAC_OCT 102 +#define SYS_COUNT_TX_PMAC_UC 103 +#define SYS_COUNT_TX_PMAC_MC 104 +#define SYS_COUNT_TX_PMAC_BC 105 +#define SYS_COUNT_TX_PMAC_PAUSE 106 +#define SYS_COUNT_TX_PMAC_SZ_64 107 +#define SYS_COUNT_TX_PMAC_SZ_65_127 108 +#define SYS_COUNT_TX_PMAC_SZ_128_255 109 +#define SYS_COUNT_TX_PMAC_SZ_256_511 110 +#define SYS_COUNT_TX_PMAC_SZ_512_1023 111 +#define SYS_COUNT_TX_PMAC_SZ_1024_1526 112 +#define SYS_COUNT_TX_PMAC_SZ_JUMBO 113 + +#define SYS_COUNT_DR_LOCAL 114 +#define SYS_COUNT_DR_TAIL 115 +#define SYS_COUNT_DR_YELLOW_PRIO_0 116 +#define SYS_COUNT_DR_YELLOW_PRIO_1 117 +#define SYS_COUNT_DR_YELLOW_PRIO_2 118 +#define SYS_COUNT_DR_YELLOW_PRIO_3 119 +#define SYS_COUNT_DR_YELLOW_PRIO_4 120 +#define SYS_COUNT_DR_YELLOW_PRIO_5 121 +#define SYS_COUNT_DR_YELLOW_PRIO_6 122 +#define SYS_COUNT_DR_YELLOW_PRIO_7 123 +#define SYS_COUNT_DR_GREEN_PRIO_0 124 +#define SYS_COUNT_DR_GREEN_PRIO_1 125 +#define SYS_COUNT_DR_GREEN_PRIO_2 126 +#define SYS_COUNT_DR_GREEN_PRIO_3 127 +#define SYS_COUNT_DR_GREEN_PRIO_4 128 +#define SYS_COUNT_DR_GREEN_PRIO_5 129 +#define SYS_COUNT_DR_GREEN_PRIO_6 130 +#define SYS_COUNT_DR_GREEN_PRIO_7 131 + +/* Add a possibly wrapping 32 bit value to a 64 bit counter */ +static void lan966x_add_cnt(u64 *cnt, u32 val) +{ + if (val < (*cnt & U32_MAX)) + *cnt += (u64)1 << 32; /* value has wrapped */ + + *cnt = (*cnt & ~(u64)U32_MAX) + val; +} + +static void lan966x_stats_update(struct lan966x *lan966x) +{ + int i, j; + + mutex_lock(&lan966x->stats_lock); + + for (i = 0; i < lan966x->num_phys_ports; i++) { + uint idx = i * lan966x->num_stats; + + lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i), + lan966x, SYS_STAT_CFG); + + for (j = 0; j < lan966x->num_stats; j++) { + u32 offset = lan966x->stats_layout[j].offset; + + lan966x_add_cnt(&lan966x->stats[idx++], + lan_rd(lan966x, SYS_CNT(offset))); + } + } + + mutex_unlock(&lan966x->stats_lock); +} + +static int lan966x_get_sset_count(struct net_device *dev, int sset) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + + if (sset != ETH_SS_STATS) + return -EOPNOTSUPP; + + return lan966x->num_stats; +} + +static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data) +{ + struct lan966x_port *port = netdev_priv(netdev); + struct lan966x *lan966x = port->lan966x; + int i; + + if (sset != ETH_SS_STATS) + return; + + for (i = 0; i < lan966x->num_stats; i++) + memcpy(data + i * ETH_GSTRING_LEN, + lan966x->stats_layout[i].name, ETH_GSTRING_LEN); +} + +static void lan966x_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + int i; + + /* check and update now */ + lan966x_stats_update(lan966x); + + /* Copy all counters */ + for (i = 0; i < lan966x->num_stats; i++) + *data++ = lan966x->stats[port->chip_port * + lan966x->num_stats + i]; +} + +static void lan966x_get_eth_mac_stats(struct net_device *dev, + struct ethtool_eth_mac_stats *mac_stats) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + u32 idx; + + lan966x_stats_update(lan966x); + + idx = port->chip_port * lan966x->num_stats; + + mutex_lock(&lan966x->stats_lock); + + mac_stats->FramesTransmittedOK = + lan966x->stats[idx + SYS_COUNT_TX_UC] + + lan966x->stats[idx + SYS_COUNT_TX_MC] + + lan966x->stats[idx + SYS_COUNT_TX_BC] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC]; + mac_stats->SingleCollisionFrames = + lan966x->stats[idx + SYS_COUNT_TX_COL]; + mac_stats->MultipleCollisionFrames = 0; + mac_stats->FramesReceivedOK = + lan966x->stats[idx + SYS_COUNT_RX_UC] + + lan966x->stats[idx + SYS_COUNT_RX_MC] + + lan966x->stats[idx + SYS_COUNT_RX_BC]; + mac_stats->FrameCheckSequenceErrors = + lan966x->stats[idx + SYS_COUNT_RX_CRC] + + lan966x->stats[idx + SYS_COUNT_RX_CRC]; + mac_stats->AlignmentErrors = 0; + mac_stats->OctetsTransmittedOK = + lan966x->stats[idx + SYS_COUNT_TX_OCT] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT]; + mac_stats->FramesWithDeferredXmissions = + lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD]; + mac_stats->LateCollisions = 0; + mac_stats->FramesAbortedDueToXSColls = 0; + mac_stats->FramesLostDueToIntMACXmitError = 0; + mac_stats->CarrierSenseErrors = 0; + mac_stats->OctetsReceivedOK = + lan966x->stats[idx + SYS_COUNT_RX_OCT]; + mac_stats->FramesLostDueToIntMACRcvError = 0; + mac_stats->MulticastFramesXmittedOK = + lan966x->stats[idx + SYS_COUNT_TX_MC] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC]; + mac_stats->BroadcastFramesXmittedOK = + lan966x->stats[idx + SYS_COUNT_TX_BC] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC]; + mac_stats->FramesWithExcessiveDeferral = 0; + mac_stats->MulticastFramesReceivedOK = + lan966x->stats[idx + SYS_COUNT_RX_MC]; + mac_stats->BroadcastFramesReceivedOK = + lan966x->stats[idx + SYS_COUNT_RX_BC]; + mac_stats->InRangeLengthErrors = + lan966x->stats[idx + SYS_COUNT_RX_FRAG] + + lan966x->stats[idx + SYS_COUNT_RX_JABBER] + + lan966x->stats[idx + SYS_COUNT_RX_CRC] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC]; + mac_stats->OutOfRangeLengthField = + lan966x->stats[idx + SYS_COUNT_RX_SHORT] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] + + lan966x->stats[idx + SYS_COUNT_RX_LONG] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG]; + mac_stats->FrameTooLongErrors = + lan966x->stats[idx + SYS_COUNT_RX_LONG] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG]; + + mutex_unlock(&lan966x->stats_lock); +} + +static int lan966x_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) +{ + struct lan966x_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_get(port->phylink, cmd); +} + +static int lan966x_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) +{ + struct lan966x_port *port = netdev_priv(ndev); + + return phylink_ethtool_ksettings_set(port->phylink, cmd); +} + +const struct ethtool_ops lan966x_ethtool_ops = { + .get_link_ksettings = lan966x_get_link_ksettings, + .set_link_ksettings = lan966x_set_link_ksettings, + .get_sset_count = lan966x_get_sset_count, + .get_strings = lan966x_get_strings, + .get_ethtool_stats = lan966x_get_ethtool_stats, + .get_eth_mac_stats = lan966x_get_eth_mac_stats, + .get_link = ethtool_op_get_link, +}; + +static void lan966x_check_stats_work(struct work_struct *work) +{ + struct delayed_work *del_work = to_delayed_work(work); + struct lan966x *lan966x = container_of(del_work, struct lan966x, + stats_work); + + lan966x_stats_update(lan966x); + + queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work, + LAN966X_STATS_CHECK_DELAY); +} + +void lan966x_stats_get(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + u32 idx; + int i; + + idx = port->chip_port * lan966x->num_stats; + + mutex_lock(&lan966x->stats_lock); + + stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT]; + + stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] + + lan966x->stats[idx + SYS_COUNT_RX_FRAG] + + lan966x->stats[idx + SYS_COUNT_RX_JABBER] + + lan966x->stats[idx + SYS_COUNT_RX_CRC] + + lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_64] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] + + lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] + + lan966x->stats[idx + SYS_COUNT_RX_LONG] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO]; + + stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] + + lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC]; + + stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] + + lan966x->stats[idx + SYS_COUNT_RX_FRAG] + + lan966x->stats[idx + SYS_COUNT_RX_JABBER] + + lan966x->stats[idx + SYS_COUNT_RX_CRC] + + lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] + + lan966x->stats[idx + SYS_COUNT_RX_LONG]; + + stats->rx_dropped = dev->stats.rx_dropped + + lan966x->stats[idx + SYS_COUNT_RX_LONG] + + lan966x->stats[idx + SYS_COUNT_DR_LOCAL] + + lan966x->stats[idx + SYS_COUNT_DR_TAIL]; + + for (i = 0; i < LAN966X_NUM_TC; i++) { + stats->rx_dropped += + (lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] + + lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]); + } + + /* Get Tx stats */ + stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT]; + + stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] + + lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] + + lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO]; + + stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] + + lan966x->stats[idx + SYS_COUNT_TX_AGED]; + + stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL]; + + mutex_unlock(&lan966x->stats_lock); +} + +int lan966x_stats_init(struct lan966x *lan966x) +{ + char queue_name[32]; + + lan966x->stats_layout = lan966x_stats_layout; + lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout); + lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports * + lan966x->num_stats, + sizeof(u64), GFP_KERNEL); + if (!lan966x->stats) + return -ENOMEM; + + /* Init stats worker */ + mutex_init(&lan966x->stats_lock); + snprintf(queue_name, sizeof(queue_name), "%s-stats", + dev_name(lan966x->dev)); + lan966x->stats_queue = create_singlethread_workqueue(queue_name); + INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work); + queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work, + LAN966X_STATS_CHECK_DELAY); + + return 0; +} diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 53b88bb5b718..7448d414c6cc 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -446,6 +446,7 @@ static const struct net_device_ops lan966x_port_netdev_ops = { .ndo_change_mtu = lan966x_change_mtu, .ndo_set_rx_mode = lan966x_set_rx_mode, .ndo_get_phys_port_name = lan966x_port_get_phys_port_name, + .ndo_get_stats64 = lan966x_stats_get, .ndo_set_mac_address = lan966x_port_set_mac_address, .ndo_get_port_parent_id = lan966x_port_get_parent_id, }; @@ -653,6 +654,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u8 port, dev->max_mtu = ETH_MAX_MTU; dev->netdev_ops = &lan966x_port_netdev_ops; + dev->ethtool_ops = &lan966x_ethtool_ops; dev->needed_headroom = IFH_LEN * sizeof(u32); ether_addr_copy(dev->dev_addr, lan966x->base_mac); @@ -918,6 +920,7 @@ static int lan966x_probe(struct platform_device *pdev) /* init switch */ lan966x_init(lan966x); + lan966x_stats_init(lan966x); /* go over the child nodes */ fwnode_for_each_available_child_node(ports, portnp) { @@ -950,6 +953,10 @@ static int lan966x_probe(struct platform_device *pdev) cleanup_ports: fwnode_handle_put(portnp); + cancel_delayed_work_sync(&lan966x->stats_work); + destroy_workqueue(lan966x->stats_queue); + mutex_destroy(&lan966x->stats_lock); + disable_irq(lan966x->xtr_irq); lan966x->xtr_irq = -ENXIO; lan966x_cleanup_ports(lan966x); @@ -961,6 +968,10 @@ static int lan966x_remove(struct platform_device *pdev) { struct lan966x *lan966x = platform_get_drvdata(pdev); + cancel_delayed_work_sync(&lan966x->stats_work); + destroy_workqueue(lan966x->stats_queue); + mutex_destroy(&lan966x->stats_lock); + disable_irq(lan966x->xtr_irq); lan966x->xtr_irq = -ENXIO; lan966x_cleanup_ports(lan966x); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index d499f654e316..fa484226656e 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -76,6 +76,11 @@ struct lan966x_frame_info { u8 ipv; }; +struct lan966x_stat_layout { + u32 offset; + char name[ETH_GSTRING_LEN]; +}; + struct lan966x { struct device *dev; @@ -88,6 +93,16 @@ struct lan966x { u8 base_mac[ETH_ALEN]; + /* stats */ + const struct lan966x_stat_layout *stats_layout; + u32 num_stats; + + /* workqueue for reading stats */ + struct mutex stats_lock; + u64 *stats; + struct delayed_work stats_work; + struct workqueue_struct *stats_queue; + /* interrupts */ int xtr_irq; }; @@ -117,6 +132,11 @@ struct lan966x_port { }; extern const struct phylink_mac_ops lan966x_phylink_mac_ops; +extern const struct ethtool_ops lan966x_ethtool_ops; + +void lan966x_stats_get(struct net_device *dev, + struct rtnl_link_stats64 *stats); +int lan966x_stats_init(struct lan966x *lan966x); void lan966x_port_config_down(struct lan966x_port *port); void lan966x_port_config_up(struct lan966x_port *port);