From patchwork Wed Nov 9 22:47:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Thompson X-Patchwork-Id: 13038136 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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B30BC4332F for ; Wed, 9 Nov 2022 22:48:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231355AbiKIWso (ORCPT ); Wed, 9 Nov 2022 17:48:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231283AbiKIWsV (ORCPT ); Wed, 9 Nov 2022 17:48:21 -0500 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2051.outbound.protection.outlook.com [40.107.237.51]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 137332C10A for ; Wed, 9 Nov 2022 14:48:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NanlpN16jMgRA5As1h28LnSahoprYnfeQRnJDnUoN+svZfMPBIH/cr5/qzb0z6YlfGPv1aptLuRMOiWZDFWS+Sg1Chw5OWbMeznrcWg804Laj8YzSRVPuFg7DMpbvmAdTqzCA9FbyceC6neHEfBLTnExxCTJUsAb5WxMDC0qum9bcUL55Ctjdbxqohq0nXo3MlVQ8ZfytP0DtS8x8ItX3BfjRbYVjepmzaAUghpEwBCsp9XpIQ9JF57Oq+w0/xqpjg9U+4tw5NxOYrna9YmZwvG9YGj7qq1h/uKYUw5OcifdYobMATgcRsjrBZVwS0VuwFoCUaY4X09TxbtffhDk7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=uv9uvaGDzCtPKxpbNiDstktyX8+MvEXHpVZaheWBq8w=; b=DExF8aKZTeJAykQv0V0MZU+QNna6M8jS/P6v9sIPUEjDL73KzUEwat4q4XWhynWGb+pkHeBozoIgL6JOmuEi3eReERhVAQpG002dyE8ovvB1kbgMf46xm+zjDatsME2Q1V2pM74/H9aRw8Y8xzegrzdsDIysWp/Y9hkI297jY6MCbzR0Oo2wQb1iisaRaM2K26oqn55wms768qdxjGJV5cDAQ5LO8XAYjpYYC+sqCzo2t8V7bIiY3wdnw84ni2W46IFjio7OS5MCPIWoe1qTwtF2TS4DehHRnwYt1npfHeLwgL36zIKrdZ8y5/1KPnTCSrvV0clKQ/bi4+BjXzHUPw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=davemloft.net smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=uv9uvaGDzCtPKxpbNiDstktyX8+MvEXHpVZaheWBq8w=; b=PoZrAOuwYZoxcvaVi9ySVL7PNuw5XBsEtyOLT+zasAVangH9Cd1GSk/B/bXrsa+yNIuSCvK8RJ74fwRfptFsqzMXd2trzVX8y5Q7yARMr9x5kjZdBx/hLLTS5A4oc5p6wJikv6g+mdsvP5N4+JZmzyuqctSpMzgjKCx0j4ILrcffsGhSLkfzOozhH18LkMPFPlLn0YpRbGsXyyvu/u1Ip//6IVRG+mVPHpE5dsh2xYq9M+zuNVv6hekl1JpFSNVtVeku7j0Cn76IF2vBl+xifrypi0tCXQ24bTdJc1Ut/Rl8K5H/j9p8ycjjzoo8+OFHMf8fIS3ngNNaGotAHMwJdQ== Received: from DS7PR06CA0049.namprd06.prod.outlook.com (2603:10b6:8:54::35) by SA1PR12MB7149.namprd12.prod.outlook.com (2603:10b6:806:29c::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5791.27; Wed, 9 Nov 2022 22:48:12 +0000 Received: from DM6NAM11FT027.eop-nam11.prod.protection.outlook.com (2603:10b6:8:54:cafe::46) by DS7PR06CA0049.outlook.office365.com (2603:10b6:8:54::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5813.12 via Frontend Transport; Wed, 9 Nov 2022 22:48:12 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by DM6NAM11FT027.mail.protection.outlook.com (10.13.172.205) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5813.12 via Frontend Transport; Wed, 9 Nov 2022 22:48:11 +0000 Received: from drhqmail203.nvidia.com (10.126.190.182) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.26; Wed, 9 Nov 2022 14:48:05 -0800 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail203.nvidia.com (10.126.190.182) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 9 Nov 2022 14:48:05 -0800 Received: from vdi.nvidia.com (10.127.8.14) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.986.36 via Frontend Transport; Wed, 9 Nov 2022 14:48:03 -0800 From: David Thompson To: , , , CC: , , , , , , David Thompson , "Asmaa Mnebhi" Subject: [PATCH net-next v2 3/4] mlxbf_gige: add BlueField-3 Serdes configuration Date: Wed, 9 Nov 2022 17:47:51 -0500 Message-ID: <20221109224752.17664-4-davthompson@nvidia.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20221109224752.17664-1-davthompson@nvidia.com> References: <20221109224752.17664-1-davthompson@nvidia.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM6NAM11FT027:EE_|SA1PR12MB7149:EE_ X-MS-Office365-Filtering-Correlation-Id: 43d9954a-c5f5-41a0-d4bb-08dac2a47af1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HzUBiJsCpFvimZR0OvhETxTpTRWmiQBH2Y4WBFxstALTOoRhMtE/V+iwXx6rU2FoqH/f9ylSzgCTI3rP6j8sqlJ6t5D4odw0ieLG3m9EgTt/WufVzD20Iere2cHi41LBJvT+njPv7XOc6pLCxvmneyvSvr+Ngk94oN0oSiREjhpkO/6DsoI8xCpGfIHGfiyn8OUd018GBgUnuVYpIRT2uIjH8oaxx1dSMr2DhqEFdYRzH9JkLqsFxFnq+Hsduov3QzcHMOYoofHBkUHqsUNU/u2etIVKPWFDV9I5EzemDmN/dMix6WyJfkKxyIb1ElYTKCjok2KZucT6EmMZPEdDYftu550MWv/hHihUT3uiYw6vPFa2BgPSVsBS75R2/WO62dGQjTUO0shabKURBcWX8E40V0fXYbuzlv6kGr5sDMjP67wDF9OdRiICqxlPK7bif1CDpGKps0om5FR5x4iIn5x4HUM35KKGUqcKax64L/bxvoPlsczeet9L31ZtiST04s4n2RtiiGtOj12trmjBoPBZE63zoQarOnj5NGyxLfLr6W8pzMMNybCMKF0y9M3vi23F/VpLN8DhAHCHv/ILqIPbIqAKylbZgyiTaGiaQo9JvYrCkOlyx9Rt6gAshN8GI/pVdV/eOuv8Mz+rUr9wrUaa5kkYS/Yxf/LQ0iZKVwCX2IAezYPP6gTVL6UQ+gbxgDWyHLmFmLglzmAVbKQwenWLDZN92dxL9QE5lhYi2yu1h2vIqebT9A9cSELEAeXWoMxs2S4jk2q/YiPzzZmy2n1Qgub0fF3pUDQPm/AKGjf61uZHQnamt2rhNlmurJkbADL/N1gUDDMA/eCq9w+fpg== X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230022)(4636009)(346002)(136003)(396003)(39860400002)(376002)(451199015)(40470700004)(36840700001)(46966006)(82310400005)(2906002)(41300700001)(86362001)(40480700001)(83380400001)(426003)(186003)(40460700003)(47076005)(70586007)(70206006)(8936002)(7636003)(30864003)(5660300002)(356005)(336012)(36756003)(36860700001)(1076003)(2616005)(26005)(7696005)(107886003)(8676002)(4326008)(478600001)(316002)(110136005)(6666004)(54906003)(82740400003)(559001)(579004)(473944003)(414714003);DIR:OUT;SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Nov 2022 22:48:11.7878 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 43d9954a-c5f5-41a0-d4bb-08dac2a47af1 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: DM6NAM11FT027.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA1PR12MB7149 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The BlueField-3 out-of-band Ethernet interface requires SerDes configuration. There are two aspects to this: Configuration of PLL: 1) Initialize UPHY registers to values dependent on p1clk clock 2) Load PLL best known values via the gateway register 3) Set the fuses to tune up the SerDes voltage 4) Lock the PLL 5) Get the lanes out of functional reset. 6) Configure the UPHY microcontroller via gateway reads/writes Configuration of lanes: 1) Configure and open TX lanes 2) Configure and open RX lanes Signed-off-by: David Thompson Signed-off-by: Asmaa Mnebhi --- .../net/ethernet/mellanox/mlxbf_gige/Makefile | 3 +- .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 4 +- .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 57 +- .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c | 37 - .../mellanox/mlxbf_gige/mlxbf_gige_uphy.c | 1173 +++++++++++++++++ .../mellanox/mlxbf_gige/mlxbf_gige_uphy.h | 398 ++++++ 6 files changed, 1628 insertions(+), 44 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile index a97c2bef846b..524af17cad9c 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile @@ -7,4 +7,5 @@ mlxbf_gige-y := mlxbf_gige_ethtool.o \ mlxbf_gige_main.o \ mlxbf_gige_mdio.o \ mlxbf_gige_rx.o \ - mlxbf_gige_tx.o + mlxbf_gige_tx.o \ + mlxbf_gige_uphy.o diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h index a453b9cd9033..e9bd09ee0b1f 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h @@ -100,6 +100,7 @@ struct mlxbf_gige { struct platform_device *pdev; void __iomem *mdio_io; void __iomem *clk_io; + void __iomem *fuse_gw_io; struct mii_bus *mdiobus; spinlock_t lock; /* for packet processing indices */ u16 rx_q_entries; @@ -166,7 +167,8 @@ enum mlxbf_gige_res { MLXBF_GIGE_RES_GPIO0, MLXBF_GIGE_RES_LLU, MLXBF_GIGE_RES_PLU, - MLXBF_GIGE_RES_CLK + MLXBF_GIGE_RES_CLK, + MLXBF_GIGE_RES_FUSE_GW }; /* Version of register data returned by mlxbf_gige_get_regs() */ diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index 32d7030eb2cf..80060a54ba95 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -18,6 +18,25 @@ #include "mlxbf_gige.h" #include "mlxbf_gige_regs.h" +#include "mlxbf_gige_uphy.h" + +#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 +#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c +#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824 +#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000020 + +static struct resource corepll_params[] = { + [MLXBF_GIGE_VERSION_BF2] = { + .start = MLXBF_GIGE_BF2_COREPLL_ADDR, + .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, + .name = "COREPLL_RES" + }, + [MLXBF_GIGE_VERSION_BF3] = { + .start = MLXBF_GIGE_BF3_COREPLL_ADDR, + .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1, + .name = "COREPLL_RES" + } +}; /* Allocate SKB whose payload pointer aligns with the Bluefield * hardware DMA limitation, i.e. DMA operation can't cross @@ -360,11 +379,14 @@ static int mlxbf_gige_probe(struct platform_device *pdev) { struct phy_device *phydev; struct net_device *netdev; + struct resource *clk_res; struct mlxbf_gige *priv; void __iomem *llu_base; void __iomem *plu_base; + void __iomem *clk_io; void __iomem *base; int addr, phy_irq; + u64 soc_version; u64 control; int err; @@ -372,6 +394,25 @@ static int mlxbf_gige_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); + soc_version = readq(base + MLXBF_GIGE_VERSION); + if (soc_version > MLXBF_GIGE_VERSION_BF3) + return -ENODEV; + + /* clk resource shared with other drivers so cannot use + * devm_platform_ioremap_resource + */ + clk_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK); + if (!clk_res) { + /* For backward compatibility with older ACPI tables, also keep + * CLK resource internal to the driver. + */ + clk_res = &corepll_params[soc_version]; + } + + clk_io = devm_ioremap(&pdev->dev, clk_res->start, resource_size(clk_res)); + if (!clk_io) + return -ENOMEM; + llu_base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_LLU); if (IS_ERR(llu_base)) return PTR_ERR(llu_base); @@ -401,17 +442,23 @@ static int mlxbf_gige_probe(struct platform_device *pdev) spin_lock_init(&priv->lock); - priv->hw_version = readq(base + MLXBF_GIGE_VERSION); + priv->clk_io = clk_io; + priv->base = base; + priv->llu_base = llu_base; + priv->plu_base = plu_base; + priv->hw_version = soc_version; + + if (priv->hw_version == MLXBF_GIGE_VERSION_BF3) { + err = mlxbf_gige_config_uphy(priv); + if (err) + return err; + } /* Attach MDIO device */ err = mlxbf_gige_mdio_probe(pdev, priv); if (err) return err; - priv->base = base; - priv->llu_base = llu_base; - priv->plu_base = plu_base; - priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ; priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ; diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c index 7ac06fd31011..043edf57e36b 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c @@ -113,24 +113,6 @@ static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t[] = { /* Busy bit is set by software and cleared by hardware */ #define MLXBF_GIGE_MDIO_SET_BUSY 0x1 -#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30 -#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c -#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824 -#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010 - -static struct resource corepll_params[] = { - [MLXBF_GIGE_VERSION_BF2] = { - .start = MLXBF_GIGE_BF2_COREPLL_ADDR, - .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1, - .name = "COREPLL_RES" - }, - [MLXBF_GIGE_VERSION_BF3] = { - .start = MLXBF_GIGE_BF3_COREPLL_ADDR, - .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1, - .name = "COREPLL_RES" - } -}; - /* Returns core clock i1clk in Hz */ static u64 calculate_i1clk(struct mlxbf_gige *priv) { @@ -294,31 +276,12 @@ static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv) int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv) { struct device *dev = &pdev->dev; - struct resource *res; int ret; - if (priv->hw_version > MLXBF_GIGE_VERSION_BF3) - return -ENODEV; - priv->mdio_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MDIO9); if (IS_ERR(priv->mdio_io)) return PTR_ERR(priv->mdio_io); - /* clk resource shared with other drivers so cannot use - * devm_platform_ioremap_resource - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK); - if (!res) { - /* For backward compatibility with older ACPI tables, also keep - * CLK resource internal to the driver. - */ - res = &corepll_params[priv->hw_version]; - } - - priv->clk_io = devm_ioremap(dev, res->start, resource_size(res)); - if (!priv->clk_io) - return -ENOMEM; - priv->mdio_gw = &mlxbf_gige_mdio_gw_t[priv->hw_version]; mlxbf_gige_mdio_cfg(priv); diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c new file mode 100644 index 000000000000..eb8c55b135a9 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c @@ -0,0 +1,1173 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause + +/* UPHY support for Nvidia Gigabit Ethernet driver + * + * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES + */ + +#include +#include +#include + +#include "mlxbf_gige.h" +#include "mlxbf_gige_uphy.h" + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_clm_init[] = { + {.addr = 0x001, .wdata = 0x0105}, + {.addr = 0x008, .wdata = 0x0001}, + {.addr = 0x00B, .wdata = 0x8420}, + {.addr = 0x00E, .wdata = 0x0110}, + {.addr = 0x010, .wdata = 0x3010}, + {.addr = 0x027, .wdata = 0x0104}, + {.addr = 0x02F, .wdata = 0x09EA}, + {.addr = 0x055, .wdata = 0x0008}, + {.addr = 0x058, .wdata = 0x0088}, + {.addr = 0x072, .wdata = 0x3222}, + {.addr = 0x073, .wdata = 0x7654}, + {.addr = 0x074, .wdata = 0xBA98}, + {.addr = 0x075, .wdata = 0xDDDC} +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_imem_init[] = { + {.addr = 0x39C, .wdata = 0x0000}, + {.addr = 0x39D, .wdata = 0x0095}, + {.addr = 0x3BF, .wdata = 0x9027}, + {.addr = 0x39E, .wdata = 0xA8F6}, + {.addr = 0x39F, .wdata = 0xAA10}, + {.addr = 0x3A0, .wdata = 0xA8D4}, + {.addr = 0x3A1, .wdata = 0xA7AE}, + {.addr = 0x3A2, .wdata = 0xA7CC}, + {.addr = 0x3A3, .wdata = 0x9BE4}, + {.addr = 0x3A4, .wdata = 0xB2D2}, + {.addr = 0x3A5, .wdata = 0xB1F2}, + {.addr = 0x3AE, .wdata = 0x7C38}, + {.addr = 0x3AF, .wdata = 0x7C4A}, + {.addr = 0x3B0, .wdata = 0x7C25}, + {.addr = 0x3B1, .wdata = 0x7C74}, + {.addr = 0x3B2, .wdata = 0x3C00}, + {.addr = 0x3B3, .wdata = 0x3C11}, + {.addr = 0x3B4, .wdata = 0x3C5D}, + {.addr = 0x3B5, .wdata = 0x3C5D} +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_seq_imem_wr_en_init = { + .addr = 0x39A, .wdata = 0x0001 +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_seq_imem_wr_dis_init = { + .addr = 0x39A, .wdata = 0x0000 +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_imem_data[] = { + { /* .iaddr = 0x0000 */ .wdata = 0x02DF}, + { /* .iaddr = 0x0001 */ .wdata = 0xEEC0}, + { /* .iaddr = 0x0002 */ .wdata = 0xD508}, + { /* .iaddr = 0x0003 */ .wdata = 0x022F}, + { /* .iaddr = 0x0004 */ .wdata = 0xC401}, + { /* .iaddr = 0x0005 */ .wdata = 0xD341}, + { /* .iaddr = 0x0006 */ .wdata = 0xC402}, + { /* .iaddr = 0x0007 */ .wdata = 0xD342}, + { /* .iaddr = 0x0008 */ .wdata = 0xC403}, + { /* .iaddr = 0x0009 */ .wdata = 0xD343}, + { /* .iaddr = 0x000A */ .wdata = 0xC404}, + { /* .iaddr = 0x000B */ .wdata = 0xD344}, + { /* .iaddr = 0x000C */ .wdata = 0xC417}, + { /* .iaddr = 0x000D */ .wdata = 0xD355}, + { /* .iaddr = 0x000E */ .wdata = 0xC418}, + { /* .iaddr = 0x000F */ .wdata = 0xD356}, + { /* .iaddr = 0x0010 */ .wdata = 0xF021}, + { /* .iaddr = 0x0011 */ .wdata = 0xF003}, + { /* .iaddr = 0x0012 */ .wdata = 0xE224}, + { /* .iaddr = 0x0013 */ .wdata = 0x0DA9}, + { /* .iaddr = 0x0014 */ .wdata = 0xF003}, + { /* .iaddr = 0x0015 */ .wdata = 0xE21C}, + { /* .iaddr = 0x0016 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0017 */ .wdata = 0x0D87}, + { /* .iaddr = 0x0018 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0019 */ .wdata = 0xE806}, + { /* .iaddr = 0x001A */ .wdata = 0xC3C5}, + { /* .iaddr = 0x001B */ .wdata = 0xD306}, + { /* .iaddr = 0x001C */ .wdata = 0xEEDF}, + { /* .iaddr = 0x001D */ .wdata = 0xE806}, + { /* .iaddr = 0x001E */ .wdata = 0xC3C6}, + { /* .iaddr = 0x001F */ .wdata = 0xD306}, + { /* .iaddr = 0x0020 */ .wdata = 0xF002}, + { /* .iaddr = 0x0021 */ .wdata = 0xC3C8}, + { /* .iaddr = 0x0022 */ .wdata = 0x409A}, + { /* .iaddr = 0x0023 */ .wdata = 0xF021}, + { /* .iaddr = 0x0024 */ .wdata = 0xEEE0}, + { /* .iaddr = 0x0025 */ .wdata = 0xEEC0}, + { /* .iaddr = 0x0026 */ .wdata = 0xD70D}, + { /* .iaddr = 0x0027 */ .wdata = 0xC305}, + { /* .iaddr = 0x0028 */ .wdata = 0xD328}, + { /* .iaddr = 0x0029 */ .wdata = 0xC300}, + { /* .iaddr = 0x002A */ .wdata = 0xD314}, + { /* .iaddr = 0x002B */ .wdata = 0xC301}, + { /* .iaddr = 0x002C */ .wdata = 0xD318}, + { /* .iaddr = 0x002D */ .wdata = 0xC303}, + { /* .iaddr = 0x002E */ .wdata = 0xD320}, + { /* .iaddr = 0x002F */ .wdata = 0xC302}, + { /* .iaddr = 0x0030 */ .wdata = 0xD31C}, + { /* .iaddr = 0x0031 */ .wdata = 0xC304}, + { /* .iaddr = 0x0032 */ .wdata = 0xD324}, + { /* .iaddr = 0x0033 */ .wdata = 0xC358}, + { /* .iaddr = 0x0034 */ .wdata = 0xD330}, + { /* .iaddr = 0x0035 */ .wdata = 0xC307}, + { /* .iaddr = 0x0036 */ .wdata = 0xD115}, + { /* .iaddr = 0x0037 */ .wdata = 0xF021}, + { /* .iaddr = 0x0038 */ .wdata = 0xD70D}, + { /* .iaddr = 0x0039 */ .wdata = 0xC305}, + { /* .iaddr = 0x003A */ .wdata = 0xD328}, + { /* .iaddr = 0x003B */ .wdata = 0xC300}, + { /* .iaddr = 0x003C */ .wdata = 0xD314}, + { /* .iaddr = 0x003D */ .wdata = 0xC301}, + { /* .iaddr = 0x003E */ .wdata = 0xD318}, + { /* .iaddr = 0x003F */ .wdata = 0xC303}, + { /* .iaddr = 0x0040 */ .wdata = 0xD320}, + { /* .iaddr = 0x0041 */ .wdata = 0xC302}, + { /* .iaddr = 0x0042 */ .wdata = 0xD31C}, + { /* .iaddr = 0x0043 */ .wdata = 0xC304}, + { /* .iaddr = 0x0044 */ .wdata = 0xD324}, + { /* .iaddr = 0x0045 */ .wdata = 0xC358}, + { /* .iaddr = 0x0046 */ .wdata = 0xD330}, + { /* .iaddr = 0x0047 */ .wdata = 0xC307}, + { /* .iaddr = 0x0048 */ .wdata = 0xD115}, + { /* .iaddr = 0x0049 */ .wdata = 0xF021}, + { /* .iaddr = 0x004A */ .wdata = 0xC70D}, + { /* .iaddr = 0x004B */ .wdata = 0xD70F}, + { /* .iaddr = 0x004C */ .wdata = 0xC328}, + { /* .iaddr = 0x004D */ .wdata = 0xD305}, + { /* .iaddr = 0x004E */ .wdata = 0xC314}, + { /* .iaddr = 0x004F */ .wdata = 0xD300}, + { /* .iaddr = 0x0050 */ .wdata = 0xC318}, + { /* .iaddr = 0x0051 */ .wdata = 0xD301}, + { /* .iaddr = 0x0052 */ .wdata = 0xC320}, + { /* .iaddr = 0x0053 */ .wdata = 0xD303}, + { /* .iaddr = 0x0054 */ .wdata = 0xC31C}, + { /* .iaddr = 0x0055 */ .wdata = 0xD302}, + { /* .iaddr = 0x0056 */ .wdata = 0xC324}, + { /* .iaddr = 0x0057 */ .wdata = 0xD304}, + { /* .iaddr = 0x0058 */ .wdata = 0xC330}, + { /* .iaddr = 0x0059 */ .wdata = 0xD358}, + { /* .iaddr = 0x005A */ .wdata = 0xC115}, + { /* .iaddr = 0x005B */ .wdata = 0xD307}, + { /* .iaddr = 0x005C */ .wdata = 0xF021}, + { /* .iaddr = 0x005D */ .wdata = 0x0249}, + { /* .iaddr = 0x005E */ .wdata = 0x0362}, + { /* .iaddr = 0x005F */ .wdata = 0x023D}, + { /* .iaddr = 0x0060 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0061 */ .wdata = 0x0369}, + { /* .iaddr = 0x0062 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0063 */ .wdata = 0x0CEA}, + { /* .iaddr = 0x0064 */ .wdata = 0xEEC2}, + { /* .iaddr = 0x0065 */ .wdata = 0xD701}, + { /* .iaddr = 0x0066 */ .wdata = 0x02C8}, + { /* .iaddr = 0x0067 */ .wdata = 0xC3C3}, + { /* .iaddr = 0x0068 */ .wdata = 0xD306}, + { /* .iaddr = 0x0069 */ .wdata = 0xC3C8}, + { /* .iaddr = 0x006A */ .wdata = 0x009A}, + { /* .iaddr = 0x006B */ .wdata = 0xC3D1}, + { /* .iaddr = 0x006C */ .wdata = 0xD309}, + { /* .iaddr = 0x006D */ .wdata = 0x0C46}, + { /* .iaddr = 0x006E */ .wdata = 0x0DE7}, + { /* .iaddr = 0x006F */ .wdata = 0xEEC0}, + { /* .iaddr = 0x0070 */ .wdata = 0xC3D9}, + { /* .iaddr = 0x0071 */ .wdata = 0x0DDE}, + { /* .iaddr = 0x0072 */ .wdata = 0x02D7}, + { /* .iaddr = 0x0073 */ .wdata = 0xF021}, + { /* .iaddr = 0x0074 */ .wdata = 0x1441}, + { /* .iaddr = 0x0075 */ .wdata = 0xF003}, + { /* .iaddr = 0x0076 */ .wdata = 0xC03F}, + { /* .iaddr = 0x0077 */ .wdata = 0xF704}, + { /* .iaddr = 0x0078 */ .wdata = 0xF009}, + { /* .iaddr = 0x0079 */ .wdata = 0xE21A}, + { /* .iaddr = 0x007A */ .wdata = 0xF002}, + { /* .iaddr = 0x007B */ .wdata = 0x0C52}, + { /* .iaddr = 0x007C */ .wdata = 0xE206}, + { /* .iaddr = 0x007D */ .wdata = 0xEEC1}, + { /* .iaddr = 0x007E */ .wdata = 0xD01A}, + { /* .iaddr = 0x007F */ .wdata = 0x3C5D}, + { /* .iaddr = 0x0080 */ .wdata = 0xEEC0}, + { /* .iaddr = 0x0081 */ .wdata = 0xD01A}, + { /* .iaddr = 0x0082 */ .wdata = 0x0E12}, + { /* .iaddr = 0x0083 */ .wdata = 0xEEC0}, + { /* .iaddr = 0x0084 */ .wdata = 0x13E1}, + { /* .iaddr = 0x0085 */ .wdata = 0x1441}, + { /* .iaddr = 0x0086 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0087 */ .wdata = 0xD70E}, + { /* .iaddr = 0x0088 */ .wdata = 0xD70F}, + { /* .iaddr = 0x0089 */ .wdata = 0xEEC0}, + { /* .iaddr = 0x008A */ .wdata = 0xD70E}, + { /* .iaddr = 0x008B */ .wdata = 0xC458}, + { /* .iaddr = 0x008C */ .wdata = 0x13BE}, + { /* .iaddr = 0x008D */ .wdata = 0xEEC0}, + { /* .iaddr = 0x008E */ .wdata = 0xF29B}, + { /* .iaddr = 0x008F */ .wdata = 0xE20A}, + { /* .iaddr = 0x0090 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0091 */ .wdata = 0xD01D}, + { /* .iaddr = 0x0092 */ .wdata = 0xEEC1}, + { /* .iaddr = 0x0093 */ .wdata = 0xD3FD}, + { /* .iaddr = 0x0094 */ .wdata = 0xF021} +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_seq_imem_csum_en = { + .addr = 0x39A, .wdata = 0x0004 +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_seq_imem_csum_dis = { + .addr = 0x39A, .wdata = 0x0000 +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_seq_imem_bmap_clr[] = { + {.addr = 0x39E, .wdata = 0x0000}, + {.addr = 0x39F, .wdata = 0x0000}, + {.addr = 0x3A0, .wdata = 0x0000}, + {.addr = 0x3A1, .wdata = 0x0000}, + {.addr = 0x3A2, .wdata = 0x0000}, + {.addr = 0x3A3, .wdata = 0x0000}, + {.addr = 0x3A4, .wdata = 0x0000}, + {.addr = 0x3A5, .wdata = 0x0000}, + {.addr = 0x3A6, .wdata = 0x0000}, + {.addr = 0x3A7, .wdata = 0x0000}, + {.addr = 0x3A8, .wdata = 0x0000}, + {.addr = 0x3A9, .wdata = 0x0000}, + {.addr = 0x3AA, .wdata = 0x0000}, + {.addr = 0x3AB, .wdata = 0x0000}, + {.addr = 0x3AC, .wdata = 0x0000}, + {.addr = 0x3AD, .wdata = 0x0000}, + {.addr = 0x3AE, .wdata = 0x0000}, + {.addr = 0x3AF, .wdata = 0x0000}, + {.addr = 0x3B0, .wdata = 0x0000}, + {.addr = 0x3B1, .wdata = 0x0000}, + {.addr = 0x3B2, .wdata = 0x0000}, + {.addr = 0x3B3, .wdata = 0x0000}, + {.addr = 0x3B4, .wdata = 0x0000}, + {.addr = 0x3B5, .wdata = 0x0000}, + {.addr = 0x3B6, .wdata = 0x0000}, + {.addr = 0x3B7, .wdata = 0x0000}, + {.addr = 0x3B8, .wdata = 0x0000}, + {.addr = 0x3B9, .wdata = 0x0000}, + {.addr = 0x3BA, .wdata = 0x0000}, + {.addr = 0x3BB, .wdata = 0x0000}, + {.addr = 0x3BC, .wdata = 0x0000}, + {.addr = 0x3BD, .wdata = 0x0000} +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_tx_init[] = { + {.addr = 0x002, .wdata = 0x5125}, + {.addr = 0x01C, .wdata = 0x0018}, + {.addr = 0x01E, .wdata = 0x0E00}, + {.addr = 0x01F, .wdata = 0xC200}, + {.addr = 0x023, .wdata = 0x0277}, + {.addr = 0x024, .wdata = 0x026B}, + {.addr = 0x053, .wdata = 0x0700}, + {.addr = 0x059, .wdata = 0x1011}, + {.addr = 0x060, .wdata = 0x0000}, + {.addr = 0x062, .wdata = 0x0135}, + {.addr = 0x063, .wdata = 0x0443}, + {.addr = 0x064, .wdata = 0x0000}, + {.addr = 0x066, .wdata = 0x0061}, + {.addr = 0x067, .wdata = 0x0042}, + {.addr = 0x06A, .wdata = 0x1212}, + {.addr = 0x06B, .wdata = 0x1515}, + {.addr = 0x06C, .wdata = 0x011A}, + {.addr = 0x06D, .wdata = 0x0132}, + {.addr = 0x06E, .wdata = 0x0632}, + {.addr = 0x06F, .wdata = 0x0643}, + {.addr = 0x070, .wdata = 0x0233}, + {.addr = 0x071, .wdata = 0x0433}, + {.addr = 0x07E, .wdata = 0x6A08}, + {.addr = 0x08D, .wdata = 0x2101}, + {.addr = 0x093, .wdata = 0x0015}, + {.addr = 0x096, .wdata = 0x7555}, + {.addr = 0x0A9, .wdata = 0xE754}, + {.addr = 0x0AA, .wdata = 0x7ED1}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000} +}; + +static const struct mlxbf_gige_uphy_cfg_reg +mlxbf_gige_dlm_rx_init[] = { + {.addr = 0x003, .wdata = 0x5125}, + {.addr = 0x01D, .wdata = 0x0004}, + {.addr = 0x028, .wdata = 0x1000}, + {.addr = 0x029, .wdata = 0x1001}, + {.addr = 0x02E, .wdata = 0x0004}, + {.addr = 0x053, .wdata = 0x0700}, + {.addr = 0x057, .wdata = 0x5044}, + {.addr = 0x05B, .wdata = 0x1011}, + {.addr = 0x0D2, .wdata = 0x0002}, + {.addr = 0x0D9, .wdata = 0x0000}, + {.addr = 0x0DA, .wdata = 0x0000}, + {.addr = 0x0DB, .wdata = 0x0000}, + {.addr = 0x0E2, .wdata = 0x0000}, + {.addr = 0x0E7, .wdata = 0xBB10}, + {.addr = 0x0E8, .wdata = 0xBB10}, + {.addr = 0x0EC, .wdata = 0x0111}, + {.addr = 0x0ED, .wdata = 0x1C00}, + {.addr = 0x0F5, .wdata = 0x0000}, + {.addr = 0x102, .wdata = 0x0CA6}, + {.addr = 0x107, .wdata = 0x0020}, + {.addr = 0x10C, .wdata = 0x1E31}, + {.addr = 0x10D, .wdata = 0x1D29}, + {.addr = 0x111, .wdata = 0x00E7}, + {.addr = 0x112, .wdata = 0x5202}, + {.addr = 0x117, .wdata = 0x0493}, + {.addr = 0x11B, .wdata = 0x0148}, + {.addr = 0x120, .wdata = 0x23DE}, + {.addr = 0x121, .wdata = 0x2294}, + {.addr = 0x125, .wdata = 0x03FF}, + {.addr = 0x126, .wdata = 0x25F0}, + {.addr = 0x12B, .wdata = 0xC633}, + {.addr = 0x136, .wdata = 0x0F6A}, + {.addr = 0x143, .wdata = 0x0000}, + {.addr = 0x148, .wdata = 0x0001}, + {.addr = 0x14E, .wdata = 0x0000}, + {.addr = 0x155, .wdata = 0x2003}, + {.addr = 0x15C, .wdata = 0x099B}, + {.addr = 0x161, .wdata = 0x0088}, + {.addr = 0x16B, .wdata = 0x0433}, + {.addr = 0x172, .wdata = 0x099B}, + {.addr = 0x17C, .wdata = 0x045D}, + {.addr = 0x17D, .wdata = 0x006A}, + {.addr = 0x181, .wdata = 0x0000}, + {.addr = 0x189, .wdata = 0x1590}, + {.addr = 0x18E, .wdata = 0x0080}, + {.addr = 0x18F, .wdata = 0x90EC}, + {.addr = 0x191, .wdata = 0x79F8}, + {.addr = 0x194, .wdata = 0x000A}, + {.addr = 0x195, .wdata = 0x000A}, + {.addr = 0x1EB, .wdata = 0x0133}, + {.addr = 0x1F0, .wdata = 0x0030}, + {.addr = 0x1F1, .wdata = 0x0030}, + {.addr = 0x1F5, .wdata = 0x3737}, + {.addr = 0x1F6, .wdata = 0x3737}, + {.addr = 0x1FA, .wdata = 0x2C00}, + {.addr = 0x1FF, .wdata = 0x0516}, + {.addr = 0x200, .wdata = 0x0516}, + {.addr = 0x204, .wdata = 0x3010}, + {.addr = 0x209, .wdata = 0x0429}, + {.addr = 0x20E, .wdata = 0x0010}, + {.addr = 0x213, .wdata = 0x005A}, + {.addr = 0x214, .wdata = 0x0000}, + {.addr = 0x216, .wdata = 0x0000}, + {.addr = 0x218, .wdata = 0x0000}, + {.addr = 0x225, .wdata = 0x0000}, + {.addr = 0x22A, .wdata = 0x0000}, + {.addr = 0x22B, .wdata = 0x0000}, + {.addr = 0x231, .wdata = 0x0000}, + {.addr = 0x232, .wdata = 0x0000}, + {.addr = 0x233, .wdata = 0x0000}, + {.addr = 0x245, .wdata = 0x0300}, + {.addr = 0x24A, .wdata = 0x0000}, + {.addr = 0x24F, .wdata = 0xFFF3}, + {.addr = 0x254, .wdata = 0x0000}, + {.addr = 0x259, .wdata = 0x0000}, + {.addr = 0x25E, .wdata = 0x0000}, + {.addr = 0x265, .wdata = 0x0009}, + {.addr = 0x267, .wdata = 0x0174}, + {.addr = 0x271, .wdata = 0x01F0}, + {.addr = 0x273, .wdata = 0x0170}, + {.addr = 0x275, .wdata = 0x7828}, + {.addr = 0x279, .wdata = 0x3E3A}, + {.addr = 0x27D, .wdata = 0x8468}, + {.addr = 0x283, .wdata = 0x000C}, + {.addr = 0x285, .wdata = 0x7777}, + {.addr = 0x288, .wdata = 0x5503}, + {.addr = 0x28C, .wdata = 0x0030}, + {.addr = 0x28E, .wdata = 0xBBBB}, + {.addr = 0x290, .wdata = 0xBBBB}, + {.addr = 0x293, .wdata = 0x0021}, + {.addr = 0x2FA, .wdata = 0x3B40}, + {.addr = 0x2FB, .wdata = 0x7777}, + {.addr = 0x30A, .wdata = 0x8022}, + {.addr = 0x319, .wdata = 0x205E}, + {.addr = 0x31B, .wdata = 0x0000}, + {.addr = 0x31D, .wdata = 0x6004}, + {.addr = 0x320, .wdata = 0x3014}, + {.addr = 0x322, .wdata = 0x6004}, + {.addr = 0x326, .wdata = 0x6004}, + {.addr = 0x32A, .wdata = 0x5000}, + {.addr = 0x32E, .wdata = 0x5000}, + {.addr = 0x332, .wdata = 0x6004}, + {.addr = 0x336, .wdata = 0x6063}, + {.addr = 0x389, .wdata = 0x0310}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000}, + {.addr = 0x3FF, .wdata = 0x0000} +}; + +/* returns plu clock p1clk in Hz */ +static u64 mlxbf_gige_calculate_p1clk(struct mlxbf_gige *priv) +{ + u8 core_od, core_r; + u64 freq_output; + u32 reg1, reg2; + u32 core_f; + + reg1 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG1); + reg2 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG2); + + core_f = (reg1 & MLXBF_GIGE_P1_CORE_F_MASK) >> + MLXBF_GIGE_P1_CORE_F_SHIFT; + core_r = (reg1 & MLXBF_GIGE_P1_CORE_R_MASK) >> + MLXBF_GIGE_P1_CORE_R_SHIFT; + core_od = (reg2 & MLXBF_GIGE_P1_CORE_OD_MASK) >> + MLXBF_GIGE_P1_CORE_OD_SHIFT; + + /* Compute PLL output frequency as follow: + * + * CORE_F / 16384 + * freq_output = freq_reference * ---------------------------- + * (CORE_R + 1) * (CORE_OD + 1) + */ + freq_output = div_u64(MLXBF_GIGE_P1_FREQ_REFERENCE * core_f, + MLXBF_GIGE_P1_CLK_CONST); + freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1)); + + return freq_output; +} + +static void mlxbf_gige_ugl_static_config(struct mlxbf_gige *priv) +{ + u32 val, p1clk_mhz; + u32 const_factor; + u64 p1clk; + + /* p1clk is the PLU clock in Hz */ + p1clk = mlxbf_gige_calculate_p1clk(priv); + + /* get p1clk in MHz */ + p1clk_mhz = div_u64(p1clk, 1000000); + + /* Multiply the p1clk clock by 12 according to HW requirements */ + const_factor = p1clk_mhz * MLXBF_GIGE_P1CLK_MULT_FACTOR; + + /* ugl_cr_bridge_desc */ + val = readl(priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC); + val &= ~MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK; + val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK, + MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor)); + val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK, + MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor)); + val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK, + MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC); + + /* pll1x_fsm_counters */ + val = MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES); + + val = MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES); + + val = MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES); + + val = MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES); + + val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES); + val &= ~MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK; + val |= FIELD_PREP(MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK, + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES); + + /* tx_fsm_counters */ + val = MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES); + + val = MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_SLEEP_CYCLES); + + val = MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_POWERUP_CYCLES); + + val = MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES); + + val = readl(priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES); + val &= ~MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK; + val |= FIELD_PREP(MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK, + MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES); + + /* rx_fsm_counters */ + val = MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES); + + val = MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_SLEEP_CYCLES); + + val = MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_POWERUP_CYCLES); + + val = MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_TERM_CYCLES); + + val = MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES); + + val = MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES); + + val = MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES); + + val = MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES); + + val = MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES); + + val = readl(priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES); + val &= ~MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK; + val |= FIELD_PREP(MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK, + MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES); + + /* periodic_flows_timer_max_value */ + val = readl(priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX); + val &= ~MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK; + val |= FIELD_PREP(MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK, + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX); + + /* plltop.center.iddq_cycles */ + val = readl(priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES); + val &= ~MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK; + val |= FIELD_PREP(MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK, + MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES); + + /* lanetop.center.iddq_cycles */ + val = readl(priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES); + val &= ~MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK; + val |= FIELD_PREP(MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK, + MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES); + + /* lanetop.center.power_governor0 */ + val = FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK, + MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor)); + val |= FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK, + MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor)); + writel(val, priv->plu_base + MLXBF_GIGE_LANE_PWR_GOV0); +} + +static int mlxbf_gige_uphy_gw_write(struct mlxbf_gige *priv, u16 addr, + u16 data, bool is_pll) +{ + u32 cmd, val; + int ret; + + cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, 0, is_pll); + + /* Send PLL or lane GW write request */ + writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll)); + + /* If the poll times out, drop the request */ + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_UPHY_GW(is_pll), + val, + !(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)), + 5, 1000000); + if (ret) + dev_dbg(priv->dev, "Failed to send GW write request\n"); + + return ret; +} + +static int mlxbf_gige_uphy_gw_read(struct mlxbf_gige *priv, u16 addr, + bool is_pll) +{ + u32 cmd, val; + int ret; + + cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, 0, 1, is_pll); + + /* Send PLL or lane GW read request */ + writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll)); + + /* If the poll times out, drop the request */ + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_UPHY_GW(is_pll), + val, + !(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Failed to send GW read request\n"); + return ret; + } + + val = readl(priv->plu_base + MLXBF_GIGE_UPHY_GW_DESC0(is_pll)); + val &= MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll); + + return val; +} + +static int mlxbf_gige_load_uphy_clm_init_pkg(struct mlxbf_gige *priv) +{ + int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_clm_init); i++) { + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_clm_init[i].addr, + mlxbf_gige_clm_init[i].wdata, + true); + if (ret) { + dev_dbg(priv->dev, "Failed to load clm init pkg\n"); + return ret; + } + } + + return ret; +} + +static int mlxbf_gige_load_clm_production_fuses(struct mlxbf_gige *priv) +{ + u8 bg_trim_room; + u8 cvb_trim_room; + u8 speedo_room; + int ret; + u32 val; + + val = readl(priv->fuse_gw_io); + bg_trim_room = (val & MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK) >> + MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT; + cvb_trim_room = (val & MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK) >> + MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT; + speedo_room = (val & MLXBF_GIGE_YU_SPEEDO_ROOM_MASK) >> + MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT; + + val = ((bg_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT); + val |= ((cvb_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT); + val |= ((speedo_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT); + val |= ((bg_trim_room & MLXBF_GIGE_YU_FUSE_MASK) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT); + val |= ((cvb_trim_room & MLXBF_GIGE_YU_FUSE_MASK) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT); + val |= ((speedo_room & MLXBF_GIGE_YU_FUSE_MASK) << + MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT); + + ret = mlxbf_gige_uphy_gw_write(priv, MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR, val, true); + if (ret) + dev_dbg(priv->dev, "Failed to load clm production fuses\n"); + + return ret; +} + +static int mlxbf_gige_init_pll(struct mlxbf_gige *priv) +{ + int ret; + + ret = mlxbf_gige_load_uphy_clm_init_pkg(priv); + if (ret) + return ret; + + ret = mlxbf_gige_load_clm_production_fuses(priv); + + return ret; +} + +static int mlxbf_gige_lock_pll(struct mlxbf_gige *priv) +{ + int ret; + u32 val; + + /* plltop.center.uphy_pll_rst_reg_ */ + val = readl(priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG); + val |= MLXBF_GIGE_UPHY_PLL_RST_REG_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG); + + /* cause_or.clrcause.bulk */ + val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK); + val |= MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK); + + writel(0, priv->plu_base + MLXBF_GIGE_PLL_CAL); + + /* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_SLEEP */ + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_PLL_FSM_CTRL, + val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Polling timeout on fsm state sleep\n"); + return ret; + } + + udelay(MLXBF_GIGE_PLL_STAB_TIME); + + val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); + val |= MLXBF_GIGE_PLL_SLEEP_FW_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); + + udelay(MLXBF_GIGE_PLL_STAB_TIME); + writel(MLXBF_GIGE_PLL_RCAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_RCAL); + + /* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_IDLE */ + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_PLL_FSM_CTRL, + val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Polling timeout on fsm state idle\n"); + return ret; + } + + val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); + val &= ~MLXBF_GIGE_PLL_SLEEP_FW_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW); + + writel(MLXBF_GIGE_PLL_CAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_CAL); + + /* Stop polling when cal_valid is different from 0 */ + ret = readl_poll_timeout_atomic(priv->plu_base + MLXBF_GIGE_PLL_CAL_VLD, + val, !!(val & MLXBF_GIGE_PLL_CAL_VLD_MASK), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Polling timeout on cal_valid\n"); + return ret; + } + + /* pll_enable */ + val = readl(priv->plu_base + MLXBF_GIGE_PLL_ENABLE); + val |= MLXBF_GIGE_PLL_ENABLE_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLL_ENABLE); + + return ret; +} + +static void mlxbf_gige_get_lane_out_of_rst(struct mlxbf_gige *priv) +{ + u32 val; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RST_REG); + val |= MLXBF_GIGE_LANE_RST_REG_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RST_REG); +} + +static int mlxbf_gige_load_imem(struct mlxbf_gige *priv) +{ + u16 csum_status; + int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_imem_init); i++) { + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_imem_init[i].addr, + mlxbf_gige_dlm_imem_init[i].wdata, + false); + if (ret) + return ret; + } + + /* Resets the internal counter for MLXBF_GIGE_DLM_IMEM_DATA_ADDR to base address */ + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_seq_imem_wr_en_init.addr, + mlxbf_gige_dlm_seq_imem_wr_en_init.wdata, + false); + if (ret) + return ret; + + /* HW increments the address MLXBF_GIGE_DLM_IMEM_DATA_ADDR internally. */ + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_imem_data); i++) { + ret = mlxbf_gige_uphy_gw_write(priv, + MLXBF_GIGE_LANE_IMEM_DATA_ADDR, + mlxbf_gige_dlm_imem_data[i].wdata, + false); + if (ret) + return ret; + } + + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_seq_imem_wr_dis_init.addr, + mlxbf_gige_dlm_seq_imem_wr_dis_init.wdata, + false); + if (ret) + return ret; + + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_seq_imem_csum_en.addr, + mlxbf_gige_dlm_seq_imem_csum_en.wdata, + false); + if (ret) + return ret; + + udelay(MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT); + + ret = mlxbf_gige_uphy_gw_read(priv, MLXBF_GIGE_LANE_CSUM_STS_ADDR, false); + if (ret < 0) + return ret; + + csum_status = ((ret & MLXBF_GIGE_IMEM_CSUM_STATUS_MASK) >> + MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT); + + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_seq_imem_csum_dis.addr, + mlxbf_gige_dlm_seq_imem_csum_dis.wdata, + false); + if (ret) + return ret; + + if (csum_status != MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID) { + dev_err(priv->dev, "%s: invalid checksum\n", __func__); + + /* recovery flow */ + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_seq_imem_bmap_clr); i++) { + mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_seq_imem_bmap_clr[i].addr, + mlxbf_gige_dlm_seq_imem_bmap_clr[i].wdata, + false); + } + + return MLXBF_GIGE_INVALID_IMEM_CSUM; + } + + return ret; +} + +static int mlxbf_gige_plu_tx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on) +{ + int ret = 0; + u32 val; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); + val &= ~MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); + + if (is_pwr_on) { + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + val &= ~MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + + val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + val |= MLXBF_GIGE_PLU_TX_POWERUP_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + } else { + val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + val &= ~MLXBF_GIGE_PLU_TX_POWERUP_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + val |= MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_LANE_TX_FSM_CTRL, val, + ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_FSM_IDDQ), + 5, 1000000); + if (ret) + dev_dbg(priv->dev, "Polling timeout on tx fsm iddq state\n"); + } + + return ret; +} + +static int mlxbf_gige_dlm_tx_init_pkg(struct mlxbf_gige *priv) +{ + int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_tx_init); i++) { + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_tx_init[i].addr, + mlxbf_gige_dlm_tx_init[i].wdata, + false); + if (ret) { + dev_dbg(priv->dev, "Failed to load dlm tx init pkg\n"); + return ret; + } + } + + return ret; +} + +static int mlxbf_gige_tx_lane_open(struct mlxbf_gige *priv) +{ + u32 val; + int ret; + + /* Prepare the TX lane before opening it */ + + ret = mlxbf_gige_plu_tx_power_ctrl(priv, false); + if (ret) + return ret; + + /* Calibration of TX elastic buffer */ + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK; + val |= MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + val |= MLXBF_GIGE_LANE_TX_DATA_EN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + + writel(MLXBF_GIGE_LANE_TX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_TX_CAL); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + val &= ~MLXBF_GIGE_LANE_TX_RATE_ID_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); + val &= ~MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED); + + /* Loading the DLM tx init package should be done before lane power on */ + ret = mlxbf_gige_dlm_tx_init_pkg(priv); + if (ret) + return ret; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + val &= ~MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + + ret = mlxbf_gige_plu_tx_power_ctrl(priv, true); + if (ret) + return ret; + + /* After preparing the TX lane, open it for data transmission */ + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP); + + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_LANE_TX_FSM_CTRL, val, + ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_DATA_EN), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Polling timeout on fsm tx data enable state\n"); + return ret; + } + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + val |= MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN); + + return ret; +} + +static int mlxbf_gige_dlm_rx_init_pkg(struct mlxbf_gige *priv) +{ + int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_rx_init); i++) { + ret = mlxbf_gige_uphy_gw_write(priv, + mlxbf_gige_dlm_rx_init[i].addr, + mlxbf_gige_dlm_rx_init[i].wdata, + false); + if (ret) { + dev_dbg(priv->dev, "Failed to load dlm rx init pkg\n"); + return ret; + } + } + + return ret; +} + +static int mlxbf_gige_plu_rx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on) +{ + int ret = 0; + u32 val; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + val &= ~MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + + if (is_pwr_on) { + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + val &= ~MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + + val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + val |= MLXBF_GIGE_PLU_RX_POWERUP_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + } else { + /* Enable HW watchdogs. */ + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); + val |= MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK; + val |= MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); + + val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + val &= ~MLXBF_GIGE_PLU_RX_POWERUP_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + val |= MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_LANE_RX_FSM_CTRL, val, + ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_IDDQ), + 5, 1000000); + if (ret) { + dev_dbg(priv->dev, "Polling timeout on rx fsm iddq state\n"); + return ret; + } + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); + val &= ~MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK; + val &= ~MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN); + } + + return ret; +} + +static int mlxbf_gige_rx_lane_open(struct mlxbf_gige *priv) +{ + u32 val; + int ret; + + ret = mlxbf_gige_plu_rx_power_ctrl(priv, false); + if (ret) + return ret; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + val &= ~MLXBF_GIGE_LANE_RX_RATE_ID_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); + val &= ~MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK; + val &= ~MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + val &= ~MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID); + + ret = mlxbf_gige_dlm_rx_init_pkg(priv); + if (ret) + return ret; + + writel(MLXBF_GIGE_LANE_RX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_RX_CAL); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); + val &= ~MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK; + val |= MLXBF_GIGE_LANE_RX_CDR_EN_MASK; + val |= MLXBF_GIGE_LANE_RX_DATA_EN_MASK; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP); + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN); + val &= ~MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK; + val |= MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL; + writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN); + + ret = mlxbf_gige_plu_rx_power_ctrl(priv, true); + if (ret) + return ret; + + ret = readl_poll_timeout_atomic(priv->plu_base + + MLXBF_GIGE_LANE_RX_FSM_CTRL, val, + ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_ACTIVE), + 5, 1000000); + if (ret) + dev_dbg(priv->dev, "Polling timeout on rx fsm active state\n"); + + return ret; +} + +static bool mlxbf_gige_is_uphy_ready(struct mlxbf_gige *priv) +{ + u32 val; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_FSM_CTRL); + if ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) != MLXBF_GIGE_TX_DATA_EN) + return false; + + val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_FSM_CTRL); + if ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) != MLXBF_GIGE_RX_FSM_ACTIVE) + return false; + + return true; +} + +int mlxbf_gige_config_uphy(struct mlxbf_gige *priv) +{ + struct platform_device *pdev = priv->pdev; + struct device *dev = &pdev->dev; + int ret = 0; + + priv->fuse_gw_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_FUSE_GW); + if (IS_ERR(priv->fuse_gw_io)) + return PTR_ERR(priv->fuse_gw_io); + + if (mlxbf_gige_is_uphy_ready(priv)) + return 0; + + mlxbf_gige_ugl_static_config(priv); + ret = mlxbf_gige_init_pll(priv); + if (ret) { + dev_err(dev, "%s: Failed to initialize PLL\n", __func__); + return ret; + } + + ret = mlxbf_gige_lock_pll(priv); + if (ret) { + dev_err(dev, "%s: Failed to lock PLL\n", __func__); + return ret; + } + + /* Due to hardware design issue, we need to get the lanes out of reset + * before configuring the imem. + */ + mlxbf_gige_get_lane_out_of_rst(priv); + ret = mlxbf_gige_load_imem(priv); + if (ret) { + dev_err(dev, "%s: Failed to load imem\n", __func__); + return ret; + } + + ret = mlxbf_gige_tx_lane_open(priv); + if (ret) { + dev_err(dev, "%s: Failed to open tx lane\n", __func__); + return ret; + } + + ret = mlxbf_gige_rx_lane_open(priv); + if (ret) + dev_err(dev, "%s: Failed to open rx lane\n", __func__); + + return ret; +} diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h new file mode 100644 index 000000000000..914e627c302a --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h @@ -0,0 +1,398 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ + +/* UPHY support for Mellanox Gigabit Ethernet driver + * + * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES + */ + +#ifndef __MLXBF_GIGE_UPHY_H__ +#define __MLXBF_GIGE_UPHY_H__ + +#include + +/* Some registers' values depend on the p1clk clock. The following + * formula applies: + * ((time_in_ns*const_factor)/MLXBF_GIGE_TIME_FACTOR_TO_USEC) + */ +#define MLXBF_GIGE_TIME_FACTOR_TO_USEC 10000 + +/* All addresses represent the offset from the base PLU address */ + +#define MLXBF_GIGE_PLU_POWERUP 0x488 +#define MLXBF_GIGE_PLU_TX_POWERUP_MASK GENMASK(28, 28) +#define MLXBF_GIGE_PLU_RX_POWERUP_MASK GENMASK(27, 27) + +#define MLXBF_GIGE_LANE_CFG_FLAT0_BASE 0x23000 +#define MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA 0x23ef8 +#define MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS 0x23f00 +#define MLXBF_GIGE_IMEM_CSUM_STATUS_MASK GENMASK(6, 5) +#define MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT 5 + +#define MLXBF_GIGE_PLL_CFG_FLAT0_BASE 0x25000 +#define MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL 0x251d8 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT 0 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT 4 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT 8 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT 12 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT 13 +#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT 14 + +#define MLXBF_GIGE_LANE_TX_FSM_CTRL 0x26000 +#define MLXBF_GIGE_LANE_TX_FSM_PS_MASK GENMASK(3, 0) + +#define MLXBF_GIGE_LANE_TX_BITS_SWAP 0x2600c +#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK GENMASK(20, 16) +#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL \ + FIELD_PREP(MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK, 0x3) +#define MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK GENMASK(0, 0) + +#define MLXBF_GIGE_LANE_TX_DATA_EN 0x26010 +#define MLXBF_GIGE_LANE_TX_RATE_ID_MASK GENMASK(30, 28) +#define MLXBF_GIGE_LANE_TX_DATA_EN_MASK GENMASK(23, 23) +#define MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK GENMASK(21, 21) +#define MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK GENMASK(17, 17) + +#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED 0x26014 +#define MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK GENMASK(9, 8) +#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK GENMASK(2, 0) + +#define MLXBF_GIGE_LANE_TX_CAL 0x26018 +#define MLXBF_GIGE_LANE_TX_CAL_MASK GENMASK(0, 0) + +#define MLXBF_GIGE_LANE_RX_FSM_CTRL 0x26040 +#define MLXBF_GIGE_LANE_RX_FSM_PS_MASK GENMASK(3, 0) + +#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN 0x26054 +#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK GENMASK(31, 31) +#define MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK GENMASK(30, 30) + +#define MLXBF_GIGE_LANE_RX_RATE_ID 0x26058 +#define MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK GENMASK(18, 16) +#define MLXBF_GIGE_LANE_RX_RATE_ID_MASK GENMASK(14, 12) +#define MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK GENMASK(7, 6) +#define MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK GENMASK(4, 4) + +#define MLXBF_GIGE_LANE_RX_CAL 0x2605c +#define MLXBF_GIGE_LANE_RX_CAL_MASK GENMASK(0, 0) + +#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP 0x26060 +#define MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK GENMASK(5, 5) +#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK GENMASK(4, 4) +#define MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK GENMASK(3, 3) +#define MLXBF_GIGE_LANE_RX_CDR_EN_MASK GENMASK(2, 2) +#define MLXBF_GIGE_LANE_RX_DATA_EN_MASK GENMASK(1, 1) + +#define MLXBF_GIGE_LANE_RX_EQ_TRAIN 0x26064 +#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK GENMASK(2, 0) +#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL \ + FIELD_PREP(MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK, 0x3) + +#define MLXBF_GIGE_LANE_GW 0x26100 +#define MLXBF_GIGE_LANE_GW_ADDR_MASK GENMASK(10, 1) +#define MLXBF_GIGE_LANE_GW_RW_MASK GENMASK(11, 11) +#define MLXBF_GIGE_LANE_GW_DATA_MASK GENMASK(27, 12) +#define MLXBF_GIGE_LANE_GW_DATA_EN_MASK GENMASK(28, 28) +#define MLXBF_GIGE_LANE_GW_BUSY_MASK GENMASK(30, 30) +#define MLXBF_GIGE_LANE_GW_ADDR_SHIFT 1 +#define MLXBF_GIGE_LANE_GW_DESC0 0x2610c +#define MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK GENMASK(15, 0) + +#define MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES 0x26600 +#define MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor) \ + ((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_TX_FSM_SLEEP_CYCLES 0x26604 +#define MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor) \ + ((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_TX_FSM_POWERUP_CYCLES 0x26608 +#define MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor) \ + ((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES 0x2660c +#define MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor) \ + ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES 0x26610 +#define MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor) \ + ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK GENMASK(18, 0) + +#define MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES 0x26614 +#define MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor) \ + ((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_SLEEP_CYCLES 0x26618 +#define MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor) \ + ((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_POWERUP_CYCLES 0x2661c +#define MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor) \ + ((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_TERM_CYCLES 0x26620 +#define MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor) \ + ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES 0x26624 +#define MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor) \ + ((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES 0x26628 +#define MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor) \ + ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES 0x2662c +#define MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor) \ + ((48000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor)) + +#define MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES 0x26630 +#define MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor) \ + ((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES 0x26634 +#define MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor) \ + ((4000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor)) + +#define MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES 0x26638 +#define MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor) \ + ((30000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK GENMASK(20, 0) + +#define MLXBF_GIGE_LANE_PWR_GOV0 0x26650 +#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor) \ + ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK GENMASK(31, 16) +#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor) \ + ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK GENMASK(15, 0) + +#define MLXBF_GIGE_LANE_IDDQ_CYCLES 0x26660 +#define MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor) \ + ((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK GENMASK(28, 16) + +#define MLXBF_GIGE_LANE_RST_REG 0x26660 +#define MLXBF_GIGE_LANE_RST_REG_MASK GENMASK(7, 6) + +#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX 0x26668 +#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor) \ + ((2500000 / (MLXBF_GIGE_TIME_FACTOR_TO_USEC * 8)) * (const_factor)) +#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK GENMASK(22, 0) + +#define MLXBF_GIGE_PLL_FSM_CTRL 0x26800 +#define MLXBF_GIGE_PLL_FSM_PS_MASK GENMASK(3, 0) + +#define MLXBF_GIGE_PLL_GW 0x26810 +#define MLXBF_GIGE_PLL_GW_ADDR_MASK GENMASK(10, 1) +#define MLXBF_GIGE_PLL_GW_RW_MASK GENMASK(11, 11) +#define MLXBF_GIGE_PLL_GW_DATA_MASK GENMASK(27, 12) +#define MLXBF_GIGE_PLL_GW_DATA_EN_MASK GENMASK(28, 28) +#define MLXBF_GIGE_PLL_GW_BUSY_MASK GENMASK(30, 30) +#define MLXBF_GIGE_PLL_GW_ADDR_SHIFT 1 +#define MLXBF_GIGE_PLL_GW_DESC0 0x2681c +#define MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK GENMASK(15, 0) + +#define MLXBF_GIGE_PLL_SLEEP_FW 0x26820 +#define MLXBF_GIGE_PLL_SLEEP_FW_MASK GENMASK(14, 14) + +#define MLXBF_GIGE_PLL_ENABLE 0x26820 +#define MLXBF_GIGE_PLL_ENABLE_MASK GENMASK(1, 1) + +#define MLXBF_GIGE_PLL_RCAL 0x26828 +#define MLXBF_GIGE_PLL_RCAL_MASK GENMASK(0, 0) + +#define MLXBF_GIGE_PLL_CAL_VLD 0x2682c +#define MLXBF_GIGE_PLL_CAL_VLD_MASK GENMASK(1, 0) + +#define MLXBF_GIGE_PLL_CAL 0x26830 +#define MLXBF_GIGE_PLL_CAL_MASK GENMASK(0, 0) + +#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK 0x26878 +#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK GENMASK(16, 0) + +#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES 0x26900 +#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor) \ + ((250 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES 0x26904 +#define MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor) \ + ((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES 0x26908 +#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor) \ + ((40000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES 0x2690c +#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor) \ + ((300000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES 0x26910 +#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor) \ + ((100000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK GENMASK(18, 0) + +#define MLXBF_GIGE_PLL_IDDQ_CYCLES 0x26914 +#define MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor) \ + ((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK GENMASK(28, 16) + +#define MLXBF_GIGE_UPHY_PLL_RST_REG 0x26914 +#define MLXBF_GIGE_UPHY_PLL_RST_REG_MASK GENMASK(2, 2) + +#define MLXBF_GIGE_UGL_CR_BRIDGE_DESC 0x26a90 +#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK GENMASK(5, 0) +#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK GENMASK(13, 8) +#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK GENMASK(21, 16) +#define MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK \ + (MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK | \ + MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK | \ + MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK) + +#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor) \ + ((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor) \ + ((30 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) +#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor) \ + ((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC) + +/* rw = 0 for write and 1 for read. + * data_en should be set to 1 only for a write transaction. + */ +#define MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) \ + ((((addr) << MLXBF_GIGE_PLL_GW_ADDR_SHIFT) & MLXBF_GIGE_PLL_GW_ADDR_MASK) | \ + FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_MASK, data) | \ + FIELD_PREP(MLXBF_GIGE_PLL_GW_BUSY_MASK, 1) | \ + (rw ? FIELD_PREP(MLXBF_GIGE_PLL_GW_RW_MASK, 1) : \ + FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_EN_MASK, 1))) + +#define MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw) \ + ((((addr) << MLXBF_GIGE_LANE_GW_ADDR_SHIFT) & MLXBF_GIGE_LANE_GW_ADDR_MASK) | \ + FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_MASK, data) | \ + FIELD_PREP(MLXBF_GIGE_LANE_GW_BUSY_MASK, 1) | \ + (rw ? FIELD_PREP(MLXBF_GIGE_LANE_GW_RW_MASK, 1) : \ + FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_EN_MASK, 1))) + +#define MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, rw, is_pll) \ + ((is_pll) ? MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) : \ + MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw)) + +#define MLXBF_GIGE_UPHY_GW(is_pll) \ + ((is_pll) ? MLXBF_GIGE_PLL_GW : MLXBF_GIGE_LANE_GW) + +#define MLXBF_GIGE_UPHY_GW_DESC0(is_pll) \ + ((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0 : MLXBF_GIGE_LANE_GW_DESC0) + +#define MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll) \ + ((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK : \ + MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK) + +#define MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll) \ + ((is_pll) ? MLXBF_GIGE_PLL_GW_BUSY_MASK : \ + MLXBF_GIGE_LANE_GW_BUSY_MASK) + +/* bootrecord p1clk */ +#define MLXBF_GIGE_P1CLK_REG1 0x14 +#define MLXBF_GIGE_P1CLK_REG2 0x18 +#define MLXBF_GIGE_P1_CORE_F_SHIFT 0 +#define MLXBF_GIGE_P1_CORE_F_MASK GENMASK(25, 0) +#define MLXBF_GIGE_P1_CORE_R_SHIFT 26 +#define MLXBF_GIGE_P1_CORE_R_MASK GENMASK(31, 26) +#define MLXBF_GIGE_P1_CORE_OD_SHIFT 0 +#define MLXBF_GIGE_P1_CORE_OD_MASK GENMASK(3, 0) + +#define MLXBF_GIGE_P1CLK_MULT_FACTOR 12 +#define MLXBF_GIGE_P1_FREQ_REFERENCE 156250000ULL +#define MLXBF_GIGE_P1_CLK_CONST 16384ULL + +/* There is a 32-bit crspace to 16-bit UPHY address encoding. + * The 16-bit address can be accessed via the GW register. + * Subtract the crspace region base address from the actual + * address that needs to be accessed via the gw. + * Then divide it by 4 since crspace registers are 4 bit aligned + */ +#define MLXBF_GIGE_32B_TO_16B_ADDR(addr, base) (((addr) - (base)) >> 2) + +#define MLXBF_GIGE_LANE_CSUM_STS_ADDR \ + MLXBF_GIGE_32B_TO_16B_ADDR( \ + MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS, \ + MLXBF_GIGE_LANE_CFG_FLAT0_BASE) + +#define MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID 0x3 +#define MLXBF_GIGE_INVALID_IMEM_CSUM -1 + +#define MLXBF_GIGE_LANE_IMEM_DATA_ADDR \ + MLXBF_GIGE_32B_TO_16B_ADDR( \ + MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA, \ + MLXBF_GIGE_LANE_CFG_FLAT0_BASE) + +#define MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR \ + MLXBF_GIGE_32B_TO_16B_ADDR( \ + MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL, \ + MLXBF_GIGE_PLL_CFG_FLAT0_BASE) + +#define MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK GENMASK(4, 0) +#define MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT 0 +#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK GENMASK(9, 5) +#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT 5 +#define MLXBF_GIGE_YU_SPEEDO_ROOM_MASK GENMASK(14, 10) +#define MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT 10 +#define MLXBF_GIGE_YU_FUSE_VALID_SHIFT 4 +/* Fuse mask without valid bit */ +#define MLXBF_GIGE_YU_FUSE_MASK 0xf + +enum { + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDDQ, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT1, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT0, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT1, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT0, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_ACTIVE, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_LOCK, + MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SPEED_CHANGE +}; + +enum { + MLXBF_GIGE_TX_FSM_IDDQ, + MLXBF_GIGE_TX_FSM_SLEEP, + MLXBF_GIGE_TX_FSM_SPEED_CHANGE, + MLXBF_GIGE_TX_FSM_POWERUP, + MLXBF_GIGE_TX_UGL_TX_POWERUP, + MLXBF_GIGE_TX_CAL_DONE_WAIT1, + MLXBF_GIGE_TX_CAL_ABORT, + MLXBF_GIGE_TX_CAL_ABORT_DONE_WAIT1, + MLXBF_GIGE_TX_CAL_DONE_WAIT0, + MLXBF_GIGE_TX_CAL_DONE, + MLXBF_GIGE_TX_DATA_READY, + MLXBF_GIGE_TX_DATA_EN_RDY, + MLXBF_GIGE_TX_DATA_EN +}; + +enum { + MLXBF_GIGE_RX_FSM_IDDQ, + MLXBF_GIGE_RX_FSM_SLEEP, + MLXBF_GIGE_RX_FSM_SPEED_CHANGE, + MLXBF_GIGE_RX_FSM_POWERUP, + MLXBF_GIGE_RX_FSM_CAL, + MLXBF_GIGE_RX_FSM_WAIT_TERM, + MLXBF_GIGE_RX_FSM_DATA_EN_RDY, + MLXBF_GIGE_RX_FSM_DATA_EN, + MLXBF_GIGE_RX_FSM_CDR_EN, + MLXBF_GIGE_RX_FSM_ACTIVE, + MLXBF_GIGE_RX_FSM_EQ, + MLXBF_GIGE_RX_FSM_EOM +}; + +#define MLXBF_GIGE_PLL_STAB_TIME 6 /* us */ +#define MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT 15 /* us */ + +struct mlxbf_gige_uphy_cfg_reg { + u16 addr; + u16 wdata; +}; + +int mlxbf_gige_config_uphy(struct mlxbf_gige *priv); + +#endif /* __MLXBF_GIGE_UPHY_H__ */