get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1415019/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1415019,
    "url": "http://patchwork.ozlabs.org/api/patches/1415019/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20201211160612.1498780-43-sr@denx.de/",
    "project": {
        "id": 18,
        "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api",
        "name": "U-Boot",
        "link_name": "uboot",
        "list_id": "u-boot.lists.denx.de",
        "list_email": "u-boot@lists.denx.de",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20201211160612.1498780-43-sr@denx.de>",
    "list_archive_url": null,
    "date": "2020-12-11T16:06:04",
    "name": "[v1,42/50] mips: octeon: Add cvmx-qlm.c",
    "commit_ref": "198cffde05976184b7657baadd334d84a08a4d7c",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "deb716ea988f9184329a55a8c064f884982f689e",
    "submitter": {
        "id": 13,
        "url": "http://patchwork.ozlabs.org/api/people/13/?format=api",
        "name": "Stefan Roese",
        "email": "sr@denx.de"
    },
    "delegate": {
        "id": 4307,
        "url": "http://patchwork.ozlabs.org/api/users/4307/?format=api",
        "username": "danielschwierzeck",
        "first_name": "Daniel",
        "last_name": "Schwierzeck",
        "email": "daniel.schwierzeck@googlemail.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20201211160612.1498780-43-sr@denx.de/mbox/",
    "series": [
        {
            "id": 220054,
            "url": "http://patchwork.ozlabs.org/api/series/220054/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=220054",
            "date": "2020-12-11T16:05:23",
            "name": "mips: octeon: Add serdes and device helper support incl. DM PCIe driver",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/220054/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1415019/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1415019/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<u-boot-bounces@lists.denx.de>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=85.214.62.61; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=<UNKNOWN>)",
            "ozlabs.org;\n dmarc=none (p=none dis=none) header.from=denx.de",
            "ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=denx.de header.i=@denx.de header.a=rsa-sha256\n header.s=phobos-20191101 header.b=kRhYnVjs;\n\tdkim-atps=neutral",
            "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=denx.de",
            "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de",
            "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=denx.de",
            "phobos.denx.de; spf=none smtp.mailfrom=sr@denx.de"
        ],
        "Received": [
            "from phobos.denx.de (phobos.denx.de [85.214.62.61])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4CswqP2Jxjz9sSs\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 12 Dec 2020 03:15:13 +1100 (AEDT)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id D4739827E6;\n\tFri, 11 Dec 2020 17:09:32 +0100 (CET)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 04374827C7; Fri, 11 Dec 2020 17:08:48 +0100 (CET)",
            "from mx2.mailbox.org (mx2a.mailbox.org\n [IPv6:2001:67c:2050:104:0:2:25:2])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 4867382761\n for <u-boot@lists.denx.de>; Fri, 11 Dec 2020 17:06:31 +0100 (CET)",
            "from smtp1.mailbox.org (smtp1.mailbox.org\n [IPv6:2001:67c:2050:105:465:1:1:0])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest\n SHA256) (No client certificate requested)\n by mx2.mailbox.org (Postfix) with ESMTPS id DAE7CA0E69;\n Fri, 11 Dec 2020 17:06:30 +0100 (CET)",
            "from smtp1.mailbox.org ([80.241.60.240])\n by spamfilter06.heinlein-hosting.de (spamfilter06.heinlein-hosting.de\n [80.241.56.125]) (amavisd-new, port 10030)\n with ESMTP id Yj9TpgXdmgnR; Fri, 11 Dec 2020 17:06:26 +0100 (CET)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de;\n\ts=phobos-20191101; t=1607702973;\n\tbh=Mfm714tsBed70NUuMqAA8AyvB+Eybd8Ym2/sZY7R8Z4=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t From;\n\tb=kRhYnVjs44rH14xqAQR5+/fm8oMtmoO4paBzMh+uNG94A5hxuePcZUNirZ9FKw0Hw\n\t 5nIbgXFpzuiAMrz7kaTeIqnGtchVf1E5eLr+WdjI0i3IsI8ZUSHzye83b0JDRssf/Y\n\t mxbmdviqAfUpb1ErMceoxborJjKfnr4bdpKMxzHeZlLLSQdnPIlQexFjB/U55vWcJe\n\t qrEwJw99GTJtjiRhBHKYEfZvFk9U4Ydxr7jN/9cmPyZYdR+jAknLu7n5B8VN1ofC79\n\t 6Fiwcz9WoSYUdyWRWiXmd1QrejgNVUZewVMrb840NrypKmcexVrZA84ES5x6x3xDVu\n\t jflB8mkzTzm1w==",
        "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de",
        "X-Spam-Level": "",
        "X-Spam-Status": "No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW,\n SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2",
        "From": "Stefan Roese <sr@denx.de>",
        "To": "u-boot@lists.denx.de",
        "Cc": "daniel.schwierzeck@gmail.com, awilliams@marvell.com, cchavva@marvell.com",
        "Subject": "[PATCH v1 42/50] mips: octeon: Add cvmx-qlm.c",
        "Date": "Fri, 11 Dec 2020 17:06:04 +0100",
        "Message-Id": "<20201211160612.1498780-43-sr@denx.de>",
        "In-Reply-To": "<20201211160612.1498780-1-sr@denx.de>",
        "References": "<20201211160612.1498780-1-sr@denx.de>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-MBO-SPAM-Probability": "*",
        "X-Rspamd-Score": "1.22 / 15.00 / 15.00",
        "X-Rspamd-Queue-Id": "C71741878",
        "X-Rspamd-UID": "3c764e",
        "X-BeenThere": "u-boot@lists.denx.de",
        "X-Mailman-Version": "2.1.34",
        "Precedence": "list",
        "List-Id": "U-Boot discussion <u-boot.lists.denx.de>",
        "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>",
        "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>",
        "List-Post": "<mailto:u-boot@lists.denx.de>",
        "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>",
        "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>",
        "Errors-To": "u-boot-bounces@lists.denx.de",
        "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>",
        "X-Virus-Scanned": "clamav-milter 0.102.3 at phobos.denx.de",
        "X-Virus-Status": "Clean"
    },
    "content": "From: Aaron Williams <awilliams@marvell.com>\n\nImport cvmx-qlm.c from 2013 U-Boot. It will be used by the later\nadded drivers to support PCIe and networking on the MIPS Octeon II / III\nplatforms.\n\nSigned-off-by: Aaron Williams <awilliams@marvell.com>\nSigned-off-by: Stefan Roese <sr@denx.de>\n---\n\n arch/mips/mach-octeon/cvmx-qlm.c | 2350 ++++++++++++++++++++++++++++++\n 1 file changed, 2350 insertions(+)\n create mode 100644 arch/mips/mach-octeon/cvmx-qlm.c",
    "diff": "diff --git a/arch/mips/mach-octeon/cvmx-qlm.c b/arch/mips/mach-octeon/cvmx-qlm.c\nnew file mode 100644\nindex 0000000000..970e34aaff\n--- /dev/null\n+++ b/arch/mips/mach-octeon/cvmx-qlm.c\n@@ -0,0 +1,2350 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2020 Marvell International Ltd.\n+ *\n+ * Helper utilities for qlm.\n+ */\n+\n+#include <log.h>\n+#include <time.h>\n+#include <asm/global_data.h>\n+#include <linux/delay.h>\n+\n+#include <mach/cvmx-regs.h>\n+#include <mach/octeon-model.h>\n+#include <mach/cvmx-fuse.h>\n+#include <mach/octeon-feature.h>\n+#include <mach/cvmx-qlm.h>\n+#include <mach/octeon_qlm.h>\n+#include <mach/cvmx-pcie.h>\n+#include <mach/cvmx-helper.h>\n+#include <mach/cvmx-helper-util.h>\n+#include <mach/cvmx-bgxx-defs.h>\n+#include <mach/cvmx-ciu-defs.h>\n+#include <mach/cvmx-gmxx-defs.h>\n+#include <mach/cvmx-gserx-defs.h>\n+#include <mach/cvmx-mio-defs.h>\n+#include <mach/cvmx-pciercx-defs.h>\n+#include <mach/cvmx-pemx-defs.h>\n+#include <mach/cvmx-pexp-defs.h>\n+#include <mach/cvmx-rst-defs.h>\n+#include <mach/cvmx-sata-defs.h>\n+#include <mach/cvmx-sli-defs.h>\n+#include <mach/cvmx-sriomaintx-defs.h>\n+#include <mach/cvmx-sriox-defs.h>\n+\n+#include <mach/cvmx-helper.h>\n+#include <mach/cvmx-helper-jtag.h>\n+\n+DECLARE_GLOBAL_DATA_PTR;\n+\n+/*\n+ * Their is a copy of this in bootloader qlm configuration, make sure\n+ * to update both the places till i figure out\n+ */\n+#define R_25G_REFCLK100\t\t 0x0\n+#define R_5G_REFCLK100\t\t 0x1\n+#define R_8G_REFCLK100\t\t 0x2\n+#define R_125G_REFCLK15625_KX\t 0x3\n+#define R_3125G_REFCLK15625_XAUI 0x4\n+#define R_103125G_REFCLK15625_KR 0x5\n+#define R_125G_REFCLK15625_SGMII 0x6\n+#define R_5G_REFCLK15625_QSGMII\t 0x7\n+#define R_625G_REFCLK15625_RXAUI 0x8\n+#define R_25G_REFCLK125\t\t 0x9\n+#define R_5G_REFCLK125\t\t 0xa\n+#define R_8G_REFCLK125\t\t 0xb\n+\n+static const int REF_100MHZ = 100000000;\n+static const int REF_125MHZ = 125000000;\n+static const int REF_156MHZ = 156250000;\n+\n+static qlm_jtag_uint32_t *__cvmx_qlm_jtag_xor_ref;\n+\n+/**\n+ * Return the number of QLMs supported by the chip\n+ *\n+ * @return  Number of QLMs\n+ */\n+int cvmx_qlm_get_num(void)\n+{\n+\tif (OCTEON_IS_MODEL(OCTEON_CN68XX))\n+\t\treturn 5;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN66XX))\n+\t\treturn 3;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN63XX))\n+\t\treturn 3;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN61XX))\n+\t\treturn 3;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF71XX))\n+\t\treturn 2;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN78XX))\n+\t\treturn 8;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\treturn 7;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX))\n+\t\treturn 9;\n+\treturn 0;\n+}\n+\n+/**\n+ * Return the qlm number based on the interface\n+ *\n+ * @param xiface  interface to look up\n+ *\n+ * @return the qlm number based on the xiface\n+ */\n+int cvmx_qlm_interface(int xiface)\n+{\n+\tstruct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN61XX)) {\n+\t\treturn (xi.interface == 0) ? 2 : 0;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) {\n+\t\treturn 2 - xi.interface;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {\n+\t\tif (xi.interface == 0)\n+\t\t\treturn 0;\n+\n+\t\tdebug(\"Warning: %s: Invalid interface %d\\n\",\n+\t\t      __func__, xi.interface);\n+\t} else if (octeon_has_feature(OCTEON_FEATURE_BGX)) {\n+\t\tdebug(\"Warning: not supported\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* Must be cn68XX */\n+\tswitch (xi.interface) {\n+\tcase 1:\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn xi.interface;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/**\n+ * Return the qlm number based for a port in the interface\n+ *\n+ * @param xiface  interface to look up\n+ * @param index  index in an interface\n+ *\n+ * @return the qlm number based on the xiface\n+ */\n+int cvmx_qlm_lmac(int xiface, int index)\n+{\n+\tstruct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX)) {\n+\t\tcvmx_bgxx_cmr_global_config_t gconfig;\n+\t\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\t\tcvmx_gserx_cfg_t gserx_cfg;\n+\t\tint qlm;\n+\n+\t\tif (xi.interface < 6) {\n+\t\t\tif (xi.interface < 2) {\n+\t\t\t\tgconfig.u64 =\n+\t\t\t\t\tcsr_rd_node(xi.node,\n+\t\t\t\t\t\t    CVMX_BGXX_CMR_GLOBAL_CONFIG(xi.interface));\n+\t\t\t\tif (gconfig.s.pmux_sds_sel)\n+\t\t\t\t\tqlm = xi.interface + 2; /* QLM 2 or 3 */\n+\t\t\t\telse\n+\t\t\t\t\tqlm = xi.interface; /* QLM 0 or 1 */\n+\t\t\t} else {\n+\t\t\t\tqlm = xi.interface + 2; /* QLM 4-7 */\n+\t\t\t}\n+\n+\t\t\t/* make sure the QLM is powered up and out of reset */\n+\t\t\tphy_ctl.u64 = csr_rd_node(xi.node, CVMX_GSERX_PHY_CTL(qlm));\n+\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\treturn -1;\n+\t\t\tgserx_cfg.u64 = csr_rd_node(xi.node, CVMX_GSERX_CFG(qlm));\n+\t\t\tif (gserx_cfg.s.bgx)\n+\t\t\t\treturn qlm;\n+\t\t\telse\n+\t\t\t\treturn -1;\n+\t\t} else if (xi.interface <= 7) { /* ILK */\n+\t\t\tint qlm;\n+\n+\t\t\tfor (qlm = 4; qlm < 8; qlm++) {\n+\t\t\t\t/* Make sure the QLM is powered and out of reset */\n+\t\t\t\tphy_ctl.u64 = csr_rd_node(xi.node, CVMX_GSERX_PHY_CTL(qlm));\n+\t\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\t\tcontinue;\n+\t\t\t\t/* Make sure the QLM is in ILK mode */\n+\t\t\t\tgserx_cfg.u64 = csr_rd_node(xi.node, CVMX_GSERX_CFG(qlm));\n+\t\t\t\tif (gserx_cfg.s.ila)\n+\t\t\t\t\treturn qlm;\n+\t\t\t}\n+\t\t}\n+\t\treturn -1;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN73XX)) {\n+\t\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\t\tcvmx_gserx_cfg_t gserx_cfg;\n+\t\tint qlm;\n+\n+\t\t/* (interface)0->QLM2, 1->QLM3, 2->DLM5/3->DLM6 */\n+\t\tif (xi.interface < 2) {\n+\t\t\tqlm = xi.interface + 2; /* (0,1)->ret(2,3) */\n+\n+\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\treturn -1;\n+\n+\t\t\tgserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\t\t\tif (gserx_cfg.s.bgx)\n+\t\t\t\treturn qlm;\n+\t\t\telse\n+\t\t\t\treturn -1;\n+\t\t} else if (xi.interface == 2) {\n+\t\t\tcvmx_gserx_cfg_t g1, g2;\n+\n+\t\t\tg1.u64 = csr_rd(CVMX_GSERX_CFG(5));\n+\t\t\tg2.u64 = csr_rd(CVMX_GSERX_CFG(6));\n+\t\t\t/* Check if both QLM5 & QLM6 are BGX2 */\n+\t\t\tif (g2.s.bgx) {\n+\t\t\t\tif (g1.s.bgx) {\n+\t\t\t\t\tcvmx_gserx_phy_ctl_t phy_ctl1;\n+\n+\t\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));\n+\t\t\t\t\tphy_ctl1.u64 = csr_rd(CVMX_GSERX_PHY_CTL(6));\n+\t\t\t\t\tif ((phy_ctl.s.phy_pd || phy_ctl.s.phy_reset) &&\n+\t\t\t\t\t    (phy_ctl1.s.phy_pd || phy_ctl1.s.phy_reset))\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t\tif (index >= 2)\n+\t\t\t\t\t\treturn 6;\n+\t\t\t\t\treturn 5;\n+\t\t\t\t} else { /* QLM6 is BGX2 */\n+\t\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(6));\n+\t\t\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t\treturn 6;\n+\t\t\t\t}\n+\t\t\t} else if (g1.s.bgx) {\n+\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));\n+\t\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\t\treturn -1;\n+\t\t\t\treturn 5;\n+\t\t\t}\n+\t\t}\n+\t\treturn -1;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CNF75XX)) {\n+\t\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\t\tcvmx_gserx_cfg_t gserx_cfg;\n+\t\tint qlm;\n+\n+\t\tif (xi.interface == 0) {\n+\t\t\tcvmx_gserx_cfg_t g1, g2;\n+\n+\t\t\tg1.u64 = csr_rd(CVMX_GSERX_CFG(4));\n+\t\t\tg2.u64 = csr_rd(CVMX_GSERX_CFG(5));\n+\t\t\t/* Check if both QLM4 & QLM5 are BGX0 */\n+\t\t\tif (g2.s.bgx) {\n+\t\t\t\tif (g1.s.bgx) {\n+\t\t\t\t\tcvmx_gserx_phy_ctl_t phy_ctl1;\n+\n+\t\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(4));\n+\t\t\t\t\tphy_ctl1.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));\n+\t\t\t\t\tif ((phy_ctl.s.phy_pd || phy_ctl.s.phy_reset) &&\n+\t\t\t\t\t    (phy_ctl1.s.phy_pd || phy_ctl1.s.phy_reset))\n+\t\t\t\t\t\treturn -1;\n+\t\t\t\t\tif (index >= 2)\n+\t\t\t\t\t\treturn 5;\n+\t\t\t\t\treturn 4;\n+\t\t\t\t}\n+\n+\t\t\t\t/* QLM5 is BGX0 */\n+\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));\n+\t\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\t\treturn -1;\n+\t\t\t\treturn 5;\n+\t\t\t} else if (g1.s.bgx) {\n+\t\t\t\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(4));\n+\t\t\t\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\t\t\t\treturn -1;\n+\t\t\t\treturn 4;\n+\t\t\t}\n+\t\t} else if (xi.interface < 2) {\n+\t\t\tqlm = (xi.interface == 1) ? 2 : 3;\n+\t\t\tgserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\t\t\tif (gserx_cfg.s.srio)\n+\t\t\t\treturn qlm;\n+\t\t}\n+\t\treturn -1;\n+\t}\n+\treturn -1;\n+}\n+\n+/**\n+ * Return if only DLM5/DLM6/DLM5+DLM6 is used by BGX\n+ *\n+ * @param BGX  BGX to search for.\n+ *\n+ * @return muxes used 0 = DLM5+DLM6, 1 = DLM5, 2 = DLM6.\n+ */\n+int cvmx_qlm_mux_interface(int bgx)\n+{\n+\tint mux = 0;\n+\tcvmx_gserx_cfg_t gser1, gser2;\n+\tint qlm1, qlm2;\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN73XX) && bgx != 2)\n+\t\treturn -1;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX) && bgx != 0)\n+\t\treturn -1;\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN73XX)) {\n+\t\tqlm1 = 5;\n+\t\tqlm2 = 6;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CNF75XX)) {\n+\t\tqlm1 = 4;\n+\t\tqlm2 = 5;\n+\t} else {\n+\t\treturn -1;\n+\t}\n+\n+\tgser1.u64 = csr_rd(CVMX_GSERX_CFG(qlm1));\n+\tgser2.u64 = csr_rd(CVMX_GSERX_CFG(qlm2));\n+\n+\tif (gser1.s.bgx && gser2.s.bgx)\n+\t\tmux = 0;\n+\telse if (gser1.s.bgx)\n+\t\tmux = 1; // BGX2 is using DLM5 only\n+\telse if (gser2.s.bgx)\n+\t\tmux = 2; // BGX2 is using DLM6 only\n+\n+\treturn mux;\n+}\n+\n+/**\n+ * Return number of lanes for a given qlm\n+ *\n+ * @param qlm    QLM to examine\n+ *\n+ * @return  Number of lanes\n+ */\n+int cvmx_qlm_get_lanes(int qlm)\n+{\n+\tif (OCTEON_IS_MODEL(OCTEON_CN61XX) && qlm == 1)\n+\t\treturn 2;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF71XX))\n+\t\treturn 2;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\treturn (qlm < 4) ? 4 /*QLM0,1,2,3*/ : 2 /*DLM4,5,6*/;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX))\n+\t\treturn (qlm == 2 || qlm == 3) ? 4 /*QLM2,3*/ : 2 /*DLM0,1,4,5*/;\n+\treturn 4;\n+}\n+\n+/**\n+ * Get the QLM JTAG fields based on Octeon model on the supported chips.\n+ *\n+ * @return  qlm_jtag_field_t structure\n+ */\n+const __cvmx_qlm_jtag_field_t *cvmx_qlm_jtag_get_field(void)\n+{\n+\t/* Figure out which JTAG chain description we're using */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN68XX)) {\n+\t\treturn __cvmx_qlm_jtag_field_cn68xx;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN66XX) || OCTEON_IS_MODEL(OCTEON_CN61XX) ||\n+\t\t   OCTEON_IS_MODEL(OCTEON_CNF71XX)) {\n+\t\treturn __cvmx_qlm_jtag_field_cn66xx;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {\n+\t\treturn __cvmx_qlm_jtag_field_cn63xx;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+/**\n+ * Get the QLM JTAG length by going through qlm_jtag_field for each\n+ * Octeon model that is supported\n+ *\n+ * @return return the length.\n+ */\n+int cvmx_qlm_jtag_get_length(void)\n+{\n+\tconst __cvmx_qlm_jtag_field_t *qlm_ptr = cvmx_qlm_jtag_get_field();\n+\tint length = 0;\n+\n+\t/* Figure out how many bits are in the JTAG chain */\n+\twhile (qlm_ptr && qlm_ptr->name) {\n+\t\tif (qlm_ptr->stop_bit > length)\n+\t\t\tlength = qlm_ptr->stop_bit + 1;\n+\t\tqlm_ptr++;\n+\t}\n+\treturn length;\n+}\n+\n+/**\n+ * Initialize the QLM layer\n+ */\n+void cvmx_qlm_init(void)\n+{\n+\tif (OCTEON_IS_OCTEON3())\n+\t\treturn;\n+\n+\t/* ToDo: No support for non-Octeon 3 yet */\n+\tprintf(\"Please add support for unsupported Octeon SoC\\n\");\n+}\n+\n+/**\n+ * Lookup the bit information for a JTAG field name\n+ *\n+ * @param name   Name to lookup\n+ *\n+ * @return Field info, or NULL on failure\n+ */\n+static const __cvmx_qlm_jtag_field_t *__cvmx_qlm_lookup_field(const char *name)\n+{\n+\tconst __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field();\n+\n+\twhile (ptr->name) {\n+\t\tif (strcmp(name, ptr->name) == 0)\n+\t\t\treturn ptr;\n+\t\tptr++;\n+\t}\n+\n+\tdebug(\"%s: Illegal field name %s\\n\", __func__, name);\n+\treturn NULL;\n+}\n+\n+/**\n+ * Get a field in a QLM JTAG chain\n+ *\n+ * @param qlm    QLM to get\n+ * @param lane   Lane in QLM to get\n+ * @param name   String name of field\n+ *\n+ * @return JTAG field value\n+ */\n+uint64_t cvmx_qlm_jtag_get(int qlm, int lane, const char *name)\n+{\n+\tconst __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);\n+\tint qlm_jtag_length = cvmx_qlm_jtag_get_length();\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\n+\tif (!field)\n+\t\treturn 0;\n+\n+\t/* Capture the current settings */\n+\tcvmx_helper_qlm_jtag_capture(qlm);\n+\t/*\n+\t * Shift past lanes we don't care about. CN6XXX/7XXX shifts lane 0 first,\n+\t * CN3XXX/5XXX shifts lane 3 first\n+\t */\n+\t/* Shift to the start of the field */\n+\tcvmx_helper_qlm_jtag_shift_zeros(qlm,\n+\t\t\t\t\t qlm_jtag_length * (num_lanes - 1 - lane));\n+\tcvmx_helper_qlm_jtag_shift_zeros(qlm, field->start_bit);\n+\t/* Shift out the value and return it */\n+\treturn cvmx_helper_qlm_jtag_shift(qlm, field->stop_bit - field->start_bit + 1, 0);\n+}\n+\n+/**\n+ * Set a field in a QLM JTAG chain\n+ *\n+ * @param qlm    QLM to set\n+ * @param lane   Lane in QLM to set, or -1 for all lanes\n+ * @param name   String name of field\n+ * @param value  Value of the field\n+ */\n+void cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value)\n+{\n+\tint i, l;\n+\tu32 shift_values[CVMX_QLM_JTAG_UINT32];\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\tconst __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);\n+\tint qlm_jtag_length = cvmx_qlm_jtag_get_length();\n+\tint total_length = qlm_jtag_length * num_lanes;\n+\tint bits = 0;\n+\n+\tif (!field)\n+\t\treturn;\n+\n+\t/* Get the current state */\n+\tcvmx_helper_qlm_jtag_capture(qlm);\n+\tfor (i = 0; i < CVMX_QLM_JTAG_UINT32; i++)\n+\t\tshift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0);\n+\n+\t/* Put new data in our local array */\n+\tfor (l = 0; l < num_lanes; l++) {\n+\t\tu64 new_value = value;\n+\t\tint bits;\n+\t\tint adj_lanes;\n+\n+\t\tif (l != lane && lane != -1)\n+\t\t\tcontinue;\n+\n+\t\tadj_lanes = (num_lanes - 1 - l) * qlm_jtag_length;\n+\n+\t\tfor (bits = field->start_bit + adj_lanes; bits <= field->stop_bit + adj_lanes;\n+\t\t     bits++) {\n+\t\t\tif (new_value & 1)\n+\t\t\t\tshift_values[bits / 32] |= 1 << (bits & 31);\n+\t\t\telse\n+\t\t\t\tshift_values[bits / 32] &= ~(1 << (bits & 31));\n+\t\t\tnew_value >>= 1;\n+\t\t}\n+\t}\n+\n+\t/* Shift out data and xor with reference */\n+\twhile (bits < total_length) {\n+\t\tu32 shift = shift_values[bits / 32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits / 32];\n+\t\tint width = total_length - bits;\n+\n+\t\tif (width > 32)\n+\t\t\twidth = 32;\n+\t\tcvmx_helper_qlm_jtag_shift(qlm, width, shift);\n+\t\tbits += 32;\n+\t}\n+\n+\t/* Update the new data */\n+\tcvmx_helper_qlm_jtag_update(qlm);\n+\n+\t/*\n+\t * Always give the QLM 1ms to settle after every update. This may not\n+\t * always be needed, but some of the options make significant\n+\t * electrical changes\n+\t */\n+\tudelay(1000);\n+}\n+\n+/**\n+ * Errata G-16094: QLM Gen2 Equalizer Default Setting Change.\n+ * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the\n+ * JTAG setting for a QLMs to run better at 5 and 6.25Ghz.\n+ */\n+void __cvmx_qlm_speed_tweak(void)\n+{\n+\tcvmx_mio_qlmx_cfg_t qlm_cfg;\n+\tint num_qlms = cvmx_qlm_get_num();\n+\tint qlm;\n+\n+\t/* Workaround for Errata (G-16467) */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X)) {\n+\t\tfor (qlm = 0; qlm < num_qlms; qlm++) {\n+\t\t\tint ir50dac;\n+\n+\t\t\t/*\n+\t\t\t * This workaround only applies to QLMs running at\n+\t\t\t * 6.25Ghz\n+\t\t\t */\n+\t\t\tif (cvmx_qlm_get_gbaud_mhz(qlm) == 6250) {\n+#ifdef CVMX_QLM_DUMP_STATE\n+\t\t\t\tdebug(\"%s:%d: QLM%d: Applying workaround for Errata G-16467\\n\",\n+\t\t\t\t      __func__, __LINE__, qlm);\n+\t\t\t\tcvmx_qlm_display_registers(qlm);\n+\t\t\t\tdebug(\"\\n\");\n+#endif\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"cfg_cdr_trunc\", 0);\n+\t\t\t\t/* Hold the QLM in reset */\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"cfg_rst_n_set\", 0);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"cfg_rst_n_clr\", 1);\n+\t\t\t\t/* Forcfe TX to be idle */\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"cfg_tx_idle_clr\", 0);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"cfg_tx_idle_set\", 1);\n+\t\t\t\tif (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_0)) {\n+\t\t\t\t\tir50dac = cvmx_qlm_jtag_get(qlm, 0, \"ir50dac\");\n+\t\t\t\t\twhile (++ir50dac <= 31)\n+\t\t\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"ir50dac\", ir50dac);\n+\t\t\t\t}\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"div4_byp\", 0);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"clkf_byp\", 16);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"serdes_pll_byp\", 1);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"spdsel_byp\", 1);\n+#ifdef CVMX_QLM_DUMP_STATE\n+\t\t\t\tdebug(\"%s:%d: QLM%d: Done applying workaround for Errata G-16467\\n\",\n+\t\t\t\t      __func__, __LINE__, qlm);\n+\t\t\t\tcvmx_qlm_display_registers(qlm);\n+\t\t\t\tdebug(\"\\n\\n\");\n+#endif\n+\t\t\t\t/*\n+\t\t\t\t * The QLM will be taken out of reset later\n+\t\t\t\t * when ILK/XAUI are initialized.\n+\t\t\t\t */\n+\t\t\t}\n+\t\t}\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) ||\n+\t\t   OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) {\n+\t\t/* Loop through the QLMs */\n+\t\tfor (qlm = 0; qlm < num_qlms; qlm++) {\n+\t\t\t/* Read the QLM speed */\n+\t\t\tqlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\n+\t\t\t/* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */\n+\t\t\tif (qlm_cfg.s.qlm_spd == 5 || qlm_cfg.s.qlm_spd == 12 ||\n+\t\t\t    qlm_cfg.s.qlm_spd == 0 || qlm_cfg.s.qlm_spd == 6 ||\n+\t\t\t    qlm_cfg.s.qlm_spd == 11) {\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"rx_cap_gen2\", 0x1);\n+\t\t\t\tcvmx_qlm_jtag_set(qlm, -1, \"rx_eq_gen2\", 0x8);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * Errata G-16174: QLM Gen2 PCIe IDLE DAC change.\n+ * CN68XX pass 1.x, CN66XX pass 1.x and CN63XX pass 1.0-2.2 QLM tweak.\n+ * This function tweaks the JTAG setting for a QLMs for PCIe to run better.\n+ */\n+void __cvmx_qlm_pcie_idle_dac_tweak(void)\n+{\n+\tint num_qlms = 0;\n+\tint qlm;\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X))\n+\t\tnum_qlms = 5;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X))\n+\t\tnum_qlms = 3;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN63XX))\n+\t\tnum_qlms = 3;\n+\telse\n+\t\treturn;\n+\n+\t/* Loop through the QLMs */\n+\tfor (qlm = 0; qlm < num_qlms; qlm++)\n+\t\tcvmx_qlm_jtag_set(qlm, -1, \"idle_dac\", 0x2);\n+}\n+\n+void __cvmx_qlm_pcie_cfg_rxd_set_tweak(int qlm, int lane)\n+{\n+\tif (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))\n+\t\tcvmx_qlm_jtag_set(qlm, lane, \"cfg_rxd_set\", 0x1);\n+}\n+\n+/**\n+ * Get the speed (Gbaud) of the QLM in Mhz for a given node.\n+ *\n+ * @param node   node of the QLM\n+ * @param qlm    QLM to examine\n+ *\n+ * @return Speed in Mhz\n+ */\n+int cvmx_qlm_get_gbaud_mhz_node(int node, int qlm)\n+{\n+\tcvmx_gserx_lane_mode_t lane_mode;\n+\tcvmx_gserx_cfg_t cfg;\n+\n+\tif (!octeon_has_feature(OCTEON_FEATURE_MULTINODE))\n+\t\treturn 0;\n+\n+\tif (qlm >= 8)\n+\t\treturn -1; /* FIXME for OCI */\n+\t/* Check if QLM is configured */\n+\tcfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\tif (cfg.u64 == 0)\n+\t\treturn -1;\n+\tif (cfg.s.pcie) {\n+\t\tint pem = 0;\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either PEM0 x4 of PEM0 x8 */\n+\t\t\tpem = 0;\n+\t\t\tbreak;\n+\t\tcase 1: /* Either PEM0 x4 of PEM1 x4 */\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8)\n+\t\t\t\tpem = 0;\n+\t\t\telse\n+\t\t\t\tpem = 1;\n+\t\t\tbreak;\n+\t\tcase 2: /* Either PEM2 x4 of PEM2 x8 */\n+\t\t\tpem = 2;\n+\t\t\tbreak;\n+\t\tcase 3: /* Either PEM2 x8 of PEM3 x4 or x8 */\n+\t\t\t/* Can be last 4 lanes of PEM2 */\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\tpem = 2;\n+\t\t\t} else {\n+\t\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\t\t\tif (pemx_cfg.cn78xx.lanes8)\n+\t\t\t\t\tpem = 3;\n+\t\t\t\telse\n+\t\t\t\t\tpem = 2;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 4: /* Either PEM3 x8 of PEM3 x4 */\n+\t\t\tpem = 3;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tdebug(\"QLM%d: Should be in PCIe mode\\n\", qlm);\n+\t\t\tbreak;\n+\t\t}\n+\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));\n+\t\tswitch (pemx_cfg.s.md) {\n+\t\tcase 0: /* Gen1 */\n+\t\t\treturn 2500;\n+\t\tcase 1: /* Gen2 */\n+\t\t\treturn 5000;\n+\t\tcase 2: /* Gen3 */\n+\t\t\treturn 8000;\n+\t\tdefault:\n+\t\t\treturn 0;\n+\t\t}\n+\t} else {\n+\t\tlane_mode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));\n+\t\tswitch (lane_mode.s.lmode) {\n+\t\tcase R_25G_REFCLK100:\n+\t\t\treturn 2500;\n+\t\tcase R_5G_REFCLK100:\n+\t\t\treturn 5000;\n+\t\tcase R_8G_REFCLK100:\n+\t\t\treturn 8000;\n+\t\tcase R_125G_REFCLK15625_KX:\n+\t\t\treturn 1250;\n+\t\tcase R_3125G_REFCLK15625_XAUI:\n+\t\t\treturn 3125;\n+\t\tcase R_103125G_REFCLK15625_KR:\n+\t\t\treturn 10312;\n+\t\tcase R_125G_REFCLK15625_SGMII:\n+\t\t\treturn 1250;\n+\t\tcase R_5G_REFCLK15625_QSGMII:\n+\t\t\treturn 5000;\n+\t\tcase R_625G_REFCLK15625_RXAUI:\n+\t\t\treturn 6250;\n+\t\tcase R_25G_REFCLK125:\n+\t\t\treturn 2500;\n+\t\tcase R_5G_REFCLK125:\n+\t\t\treturn 5000;\n+\t\tcase R_8G_REFCLK125:\n+\t\t\treturn 8000;\n+\t\tdefault:\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * Get the speed (Gbaud) of the QLM in Mhz.\n+ *\n+ * @param qlm    QLM to examine\n+ *\n+ * @return Speed in Mhz\n+ */\n+int cvmx_qlm_get_gbaud_mhz(int qlm)\n+{\n+\tif (OCTEON_IS_MODEL(OCTEON_CN63XX)) {\n+\t\tif (qlm == 2) {\n+\t\t\tcvmx_gmxx_inf_mode_t inf_mode;\n+\n+\t\t\tinf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\t\t\tswitch (inf_mode.s.speed) {\n+\t\t\tcase 0:\n+\t\t\t\treturn 5000; /* 5     Gbaud */\n+\t\t\tcase 1:\n+\t\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\t\tcase 2:\n+\t\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\t\tcase 3:\n+\t\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\t\tcase 4:\n+\t\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\t\tcase 5:\n+\t\t\t\treturn 6250; /* 6.25  Gbaud */\n+\t\t\tcase 6:\n+\t\t\t\treturn 5000; /* 5     Gbaud */\n+\t\t\tcase 7:\n+\t\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\t\tcase 8:\n+\t\t\t\treturn 3125; /* 3.125 Gbaud */\n+\t\t\tcase 9:\n+\t\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\t\tcase 10:\n+\t\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\t\tcase 11:\n+\t\t\t\treturn 5000; /* 5     Gbaud */\n+\t\t\tcase 12:\n+\t\t\t\treturn 6250; /* 6.25  Gbaud */\n+\t\t\tcase 13:\n+\t\t\t\treturn 3750; /* 3.75  Gbaud */\n+\t\t\tcase 14:\n+\t\t\t\treturn 3125; /* 3.125 Gbaud */\n+\t\t\tdefault:\n+\t\t\t\treturn 0; /* Disabled */\n+\t\t\t}\n+\t\t} else {\n+\t\t\tcvmx_sriox_status_reg_t status_reg;\n+\n+\t\t\tstatus_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(qlm));\n+\t\t\tif (status_reg.s.srio) {\n+\t\t\t\tcvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;\n+\n+\t\t\t\tsriomaintx_port_0_ctl2.u32 =\n+\t\t\t\t\tcsr_rd(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm));\n+\t\t\t\tswitch (sriomaintx_port_0_ctl2.s.sel_baud) {\n+\t\t\t\tcase 1:\n+\t\t\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\t\t\tcase 2:\n+\t\t\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\t\t\tcase 3:\n+\t\t\t\t\treturn 3125; /* 3.125 Gbaud */\n+\t\t\t\tcase 4:\n+\t\t\t\t\treturn 5000; /* 5     Gbaud */\n+\t\t\t\tcase 5:\n+\t\t\t\t\treturn 6250; /* 6.250 Gbaud */\n+\t\t\t\tdefault:\n+\t\t\t\t\treturn 0; /* Disabled */\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tcvmx_pciercx_cfg032_t pciercx_cfg032;\n+\n+\t\t\t\tpciercx_cfg032.u32 = csr_rd(CVMX_PCIERCX_CFG032(qlm));\n+\t\t\t\tswitch (pciercx_cfg032.s.ls) {\n+\t\t\t\tcase 1:\n+\t\t\t\t\treturn 2500;\n+\t\t\t\tcase 2:\n+\t\t\t\t\treturn 5000;\n+\t\t\t\tcase 4:\n+\t\t\t\t\treturn 8000;\n+\t\t\t\tdefault: {\n+\t\t\t\t\tcvmx_mio_rst_boot_t mio_rst_boot;\n+\n+\t\t\t\t\tmio_rst_boot.u64 = csr_rd(CVMX_MIO_RST_BOOT);\n+\t\t\t\t\tif (qlm == 0 && mio_rst_boot.s.qlm0_spd == 0xf)\n+\t\t\t\t\t\treturn 0;\n+\n+\t\t\t\t\tif (qlm == 1 && mio_rst_boot.s.qlm1_spd == 0xf)\n+\t\t\t\t\t\treturn 0;\n+\n+\t\t\t\t\t/* Best guess I can make */\n+\t\t\t\t\treturn 5000;\n+\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t} else if (OCTEON_IS_OCTEON2()) {\n+\t\tcvmx_mio_qlmx_cfg_t qlm_cfg;\n+\n+\t\tqlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t\tswitch (qlm_cfg.s.qlm_spd) {\n+\t\tcase 0:\n+\t\t\treturn 5000; /* 5     Gbaud */\n+\t\tcase 1:\n+\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\tcase 2:\n+\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\tcase 3:\n+\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\tcase 4:\n+\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\tcase 5:\n+\t\t\treturn 6250; /* 6.25  Gbaud */\n+\t\tcase 6:\n+\t\t\treturn 5000; /* 5     Gbaud */\n+\t\tcase 7:\n+\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\tcase 8:\n+\t\t\treturn 3125; /* 3.125 Gbaud */\n+\t\tcase 9:\n+\t\t\treturn 2500; /* 2.5   Gbaud */\n+\t\tcase 10:\n+\t\t\treturn 1250; /* 1.25  Gbaud */\n+\t\tcase 11:\n+\t\t\treturn 5000; /* 5     Gbaud */\n+\t\tcase 12:\n+\t\t\treturn 6250; /* 6.25  Gbaud */\n+\t\tcase 13:\n+\t\t\treturn 3750; /* 3.75  Gbaud */\n+\t\tcase 14:\n+\t\t\treturn 3125; /* 3.125 Gbaud */\n+\t\tdefault:\n+\t\t\treturn 0; /* Disabled */\n+\t\t}\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {\n+\t\tcvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;\n+\t\tu64 meas_refclock;\n+\t\tu64 freq;\n+\n+\t\t/* Measure the reference clock */\n+\t\tmeas_refclock = cvmx_qlm_measure_clock(qlm);\n+\t\t/* Multiply to get the final frequency */\n+\t\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\t\tfreq = meas_refclock * mpll_multiplier.s.mpll_multiplier;\n+\t\tfreq = (freq + 500000) / 1000000;\n+\n+\t\treturn freq;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {\n+\t\treturn cvmx_qlm_get_gbaud_mhz_node(cvmx_get_node_num(), qlm);\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN73XX) || OCTEON_IS_MODEL(OCTEON_CNF75XX)) {\n+\t\tcvmx_gserx_lane_mode_t lane_mode;\n+\n+\t\tlane_mode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));\n+\t\tswitch (lane_mode.s.lmode) {\n+\t\tcase R_25G_REFCLK100:\n+\t\t\treturn 2500;\n+\t\tcase R_5G_REFCLK100:\n+\t\t\treturn 5000;\n+\t\tcase R_8G_REFCLK100:\n+\t\t\treturn 8000;\n+\t\tcase R_125G_REFCLK15625_KX:\n+\t\t\treturn 1250;\n+\t\tcase R_3125G_REFCLK15625_XAUI:\n+\t\t\treturn 3125;\n+\t\tcase R_103125G_REFCLK15625_KR:\n+\t\t\treturn 10312;\n+\t\tcase R_125G_REFCLK15625_SGMII:\n+\t\t\treturn 1250;\n+\t\tcase R_5G_REFCLK15625_QSGMII:\n+\t\t\treturn 5000;\n+\t\tcase R_625G_REFCLK15625_RXAUI:\n+\t\t\treturn 6250;\n+\t\tcase R_25G_REFCLK125:\n+\t\t\treturn 2500;\n+\t\tcase R_5G_REFCLK125:\n+\t\t\treturn 5000;\n+\t\tcase R_8G_REFCLK125:\n+\t\t\treturn 8000;\n+\t\tdefault:\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn70xx(int qlm)\n+{\n+\tswitch (qlm) {\n+\tcase 0: /* DLM0/DLM1 - SGMII/QSGMII/RXAUI */\n+\t{\n+\t\tunion cvmx_gmxx_inf_mode inf_mode0, inf_mode1;\n+\n+\t\tinf_mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\t\tinf_mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));\n+\n+\t\t/* SGMII0 SGMII1 */\n+\t\tswitch (inf_mode0.s.mode) {\n+\t\tcase CVMX_GMX_INF_MODE_SGMII:\n+\t\t\tswitch (inf_mode1.s.mode) {\n+\t\t\tcase CVMX_GMX_INF_MODE_SGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII_SGMII;\n+\t\t\tcase CVMX_GMX_INF_MODE_QSGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII_QSGMII;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII_DISABLED;\n+\t\t\t}\n+\t\tcase CVMX_GMX_INF_MODE_QSGMII:\n+\t\t\tswitch (inf_mode1.s.mode) {\n+\t\t\tcase CVMX_GMX_INF_MODE_SGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_QSGMII_SGMII;\n+\t\t\tcase CVMX_GMX_INF_MODE_QSGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_QSGMII_QSGMII;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_QSGMII_DISABLED;\n+\t\t\t}\n+\t\tcase CVMX_GMX_INF_MODE_RXAUI:\n+\t\t\treturn CVMX_QLM_MODE_RXAUI_1X2;\n+\t\tdefault:\n+\t\t\tswitch (inf_mode1.s.mode) {\n+\t\t\tcase CVMX_GMX_INF_MODE_SGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED_SGMII;\n+\t\t\tcase CVMX_GMX_INF_MODE_QSGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED_QSGMII;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tcase 1: /* Sata / pem0 */\n+\t{\n+\t\tunion cvmx_gserx_sata_cfg sata_cfg;\n+\t\tunion cvmx_pemx_cfg pem0_cfg;\n+\n+\t\tsata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));\n+\t\tpem0_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\n+\t\tswitch (pem0_cfg.cn70xx.md) {\n+\t\tcase CVMX_PEM_MD_GEN2_2LANE:\n+\t\tcase CVMX_PEM_MD_GEN1_2LANE:\n+\t\t\treturn CVMX_QLM_MODE_PCIE_1X2;\n+\t\tcase CVMX_PEM_MD_GEN2_1LANE:\n+\t\tcase CVMX_PEM_MD_GEN1_1LANE:\n+\t\t\tif (sata_cfg.s.sata_en)\n+\t\t\t\t/* Both PEM0 and PEM1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\n+\t\t\t/* Only PEM0 */\n+\t\t\treturn CVMX_QLM_MODE_PCIE_1X1;\n+\t\tcase CVMX_PEM_MD_GEN2_4LANE:\n+\t\tcase CVMX_PEM_MD_GEN1_4LANE:\n+\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t\tdefault:\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t}\n+\t}\n+\tcase 2: {\n+\t\tunion cvmx_gserx_sata_cfg sata_cfg;\n+\t\tunion cvmx_pemx_cfg pem0_cfg, pem1_cfg, pem2_cfg;\n+\n+\t\tsata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));\n+\t\tpem0_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\tpem1_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\tpem2_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));\n+\n+\t\tif (sata_cfg.s.sata_en)\n+\t\t\treturn CVMX_QLM_MODE_SATA_2X1;\n+\t\tif (pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_4LANE ||\n+\t\t    pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_4LANE)\n+\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t\tif (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_2LANE ||\n+\t\t    pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_2LANE) {\n+\t\t\treturn CVMX_QLM_MODE_PCIE_1X2;\n+\t\t}\n+\t\tif (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||\n+\t\t    pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {\n+\t\t\tif (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||\n+\t\t\t    pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\t\t\t} else {\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_1X1;\n+\t\t\t}\n+\t\t}\n+\t\tif (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||\n+\t\t    pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE)\n+\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t}\n+\tdefault:\n+\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t}\n+\n+\treturn CVMX_QLM_MODE_DISABLED;\n+}\n+\n+/*\n+ * Get the DLM mode for the interface based on the interface type.\n+ *\n+ * @param interface_type   0 - SGMII/QSGMII/RXAUI interface\n+ *                         1 - PCIe\n+ *                         2 - SATA\n+ * @param interface        interface to use\n+ * @return  the qlm mode the interface is\n+ */\n+enum cvmx_qlm_mode cvmx_qlm_get_dlm_mode(int interface_type, int interface)\n+{\n+\tswitch (interface_type) {\n+\tcase 0: /* SGMII/QSGMII/RXAUI */\n+\t{\n+\t\tenum cvmx_qlm_mode qlm_mode = __cvmx_qlm_get_mode_cn70xx(0);\n+\n+\t\tswitch (interface) {\n+\t\tcase 0:\n+\t\t\tswitch (qlm_mode) {\n+\t\t\tcase CVMX_QLM_MODE_SGMII_SGMII:\n+\t\t\tcase CVMX_QLM_MODE_SGMII_DISABLED:\n+\t\t\tcase CVMX_QLM_MODE_SGMII_QSGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\tcase CVMX_QLM_MODE_QSGMII_QSGMII:\n+\t\t\tcase CVMX_QLM_MODE_QSGMII_DISABLED:\n+\t\t\tcase CVMX_QLM_MODE_QSGMII_SGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_QSGMII;\n+\t\t\tcase CVMX_QLM_MODE_RXAUI_1X2:\n+\t\t\t\treturn CVMX_QLM_MODE_RXAUI;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\tcase 1:\n+\t\t\tswitch (qlm_mode) {\n+\t\t\tcase CVMX_QLM_MODE_SGMII_SGMII:\n+\t\t\tcase CVMX_QLM_MODE_DISABLED_SGMII:\n+\t\t\tcase CVMX_QLM_MODE_QSGMII_SGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\tcase CVMX_QLM_MODE_QSGMII_QSGMII:\n+\t\t\tcase CVMX_QLM_MODE_DISABLED_QSGMII:\n+\t\t\tcase CVMX_QLM_MODE_SGMII_QSGMII:\n+\t\t\t\treturn CVMX_QLM_MODE_QSGMII;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\tdefault:\n+\t\t\treturn qlm_mode;\n+\t\t}\n+\t}\n+\tcase 1: /* PCIe */\n+\t{\n+\t\tenum cvmx_qlm_mode qlm_mode1 = __cvmx_qlm_get_mode_cn70xx(1);\n+\t\tenum cvmx_qlm_mode qlm_mode2 = __cvmx_qlm_get_mode_cn70xx(2);\n+\n+\t\tswitch (interface) {\n+\t\tcase 0: /* PCIe0 can be DLM1 with 1, 2 or 4 lanes */\n+\t\t\treturn qlm_mode1;\n+\t\tcase 1:\n+\t\t\t/*\n+\t\t\t * PCIe1 can be in DLM1 1 lane(1), DLM2 1 lane(0)\n+\t\t\t * or 2 lanes(0-1)\n+\t\t\t */\n+\t\t\tif (qlm_mode1 == CVMX_QLM_MODE_PCIE_2X1)\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\t\t\telse if (qlm_mode2 == CVMX_QLM_MODE_PCIE_1X2 ||\n+\t\t\t\t qlm_mode2 == CVMX_QLM_MODE_PCIE_2X1)\n+\t\t\t\treturn qlm_mode2;\n+\t\t\telse\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\tcase 2: /* PCIe2 can be DLM2 1 lanes(1) */\n+\t\t\tif (qlm_mode2 == CVMX_QLM_MODE_PCIE_2X1)\n+\t\t\t\treturn qlm_mode2;\n+\t\t\telse\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\tdefault:\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t}\n+\t}\n+\tcase 2: /* SATA */\n+\t{\n+\t\tenum cvmx_qlm_mode qlm_mode = __cvmx_qlm_get_mode_cn70xx(2);\n+\n+\t\tif (qlm_mode == CVMX_QLM_MODE_SATA_2X1)\n+\t\t\treturn CVMX_QLM_MODE_SATA_2X1;\n+\t\telse\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t}\n+\tdefault:\n+\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t}\n+}\n+\n+static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn6xxx(int qlm)\n+{\n+\tcvmx_mio_qlmx_cfg_t qlmx_cfg;\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN68XX)) {\n+\t\tqlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t\t/* QLM is disabled when QLM SPD is 15. */\n+\t\tif (qlmx_cfg.s.qlm_spd == 15)\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\n+\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\tcase 0: /* PCIE */\n+\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t\tcase 1: /* ILK */\n+\t\t\treturn CVMX_QLM_MODE_ILK;\n+\t\tcase 2: /* SGMII */\n+\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\tcase 3: /* XAUI */\n+\t\t\treturn CVMX_QLM_MODE_XAUI;\n+\t\tcase 7: /* RXAUI */\n+\t\t\treturn CVMX_QLM_MODE_RXAUI;\n+\t\tdefault:\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t}\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {\n+\t\tqlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t\t/* QLM is disabled when QLM SPD is 15. */\n+\t\tif (qlmx_cfg.s.qlm_spd == 15)\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\n+\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\tcase 0x9: /* SGMII */\n+\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\tcase 0xb: /* XAUI */\n+\t\t\treturn CVMX_QLM_MODE_XAUI;\n+\t\tcase 0x0: /* PCIE gen2 */\n+\t\tcase 0x8: /* PCIE gen2 (alias) */\n+\t\tcase 0x2: /* PCIE gen1 */\n+\t\tcase 0xa: /* PCIE gen1 (alias) */\n+\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t\tcase 0x1: /* SRIO 1x4 short */\n+\t\tcase 0x3: /* SRIO 1x4 long */\n+\t\t\treturn CVMX_QLM_MODE_SRIO_1X4;\n+\t\tcase 0x4: /* SRIO 2x2 short */\n+\t\tcase 0x6: /* SRIO 2x2 long */\n+\t\t\treturn CVMX_QLM_MODE_SRIO_2X2;\n+\t\tcase 0x5: /* SRIO 4x1 short */\n+\t\tcase 0x7: /* SRIO 4x1 long */\n+\t\t\tif (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))\n+\t\t\t\treturn CVMX_QLM_MODE_SRIO_4X1;\n+\t\t\tfallthrough;\n+\t\tdefault:\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t}\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {\n+\t\tcvmx_sriox_status_reg_t status_reg;\n+\t\t/* For now skip qlm2 */\n+\t\tif (qlm == 2) {\n+\t\t\tcvmx_gmxx_inf_mode_t inf_mode;\n+\n+\t\t\tinf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\t\t\tif (inf_mode.s.speed == 15)\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\telse if (inf_mode.s.mode == 0)\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\telse\n+\t\t\t\treturn CVMX_QLM_MODE_XAUI;\n+\t\t}\n+\t\tstatus_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(qlm));\n+\t\tif (status_reg.s.srio)\n+\t\t\treturn CVMX_QLM_MODE_SRIO_1X4;\n+\t\telse\n+\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {\n+\t\tqlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t\t/* QLM is disabled when QLM SPD is 15. */\n+\t\tif (qlmx_cfg.s.qlm_spd == 15)\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0:\n+\t\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\t\tcase 0: /* PCIe 1x4 gen2 / gen1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE;\n+\t\t\tcase 2: /* SGMII */\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\tcase 3: /* XAUI */\n+\t\t\t\treturn CVMX_QLM_MODE_XAUI;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\t\tcase 0: /* PCIe 1x2 gen2 / gen1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_1X2;\n+\t\t\tcase 1: /* PCIe 2x1 gen2 / gen1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\t\tcase 2: /* SGMII */\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\tcase 3: /* XAUI */\n+\t\t\t\treturn CVMX_QLM_MODE_XAUI;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {\n+\t\tqlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t\t/* QLM is disabled when QLM SPD is 15. */\n+\t\tif (qlmx_cfg.s.qlm_spd == 15)\n+\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0:\n+\t\t\tif (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */\n+\t\t\t\treturn CVMX_QLM_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tswitch (qlmx_cfg.s.qlm_cfg) {\n+\t\t\tcase 0: /* PCIe 1x2 gen2 / gen1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_1X2;\n+\t\t\tcase 1: /* PCIe 2x1 gen2 / gen1 */\n+\t\t\t\treturn CVMX_QLM_MODE_PCIE_2X1;\n+\t\t\tdefault:\n+\t\t\t\treturn CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn CVMX_QLM_MODE_DISABLED;\n+}\n+\n+/**\n+ * @INTERNAL\n+ * Decrement the MPLL Multiplier for the DLM as per Errata G-20669\n+ *\n+ * @param qlm            DLM to configure\n+ * @param baud_mhz       Speed of the DLM configured at\n+ * @param old_multiplier MPLL_MULTIPLIER value to decrement\n+ */\n+void __cvmx_qlm_set_mult(int qlm, int baud_mhz, int old_multiplier)\n+{\n+\tcvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;\n+\tcvmx_gserx_dlmx_ref_clkdiv2_t clkdiv;\n+\tu64 meas_refclock, mult;\n+\n+\tif (!OCTEON_IS_MODEL(OCTEON_CN70XX))\n+\t\treturn;\n+\n+\tif (qlm == -1)\n+\t\treturn;\n+\n+\tmeas_refclock = cvmx_qlm_measure_clock(qlm);\n+\tif (meas_refclock == 0) {\n+\t\tprintf(\"DLM%d: Reference clock not running\\n\", qlm);\n+\t\treturn;\n+\t}\n+\n+\t/*\n+\t * The baud rate multiplier needs to be adjusted on the CN70XX if\n+\t * the reference clock is > 100MHz.\n+\t */\n+\tif (qlm == 0) {\n+\t\tclkdiv.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));\n+\t\tif (clkdiv.s.ref_clkdiv2)\n+\t\t\tbaud_mhz *= 2;\n+\t}\n+\tmult = (uint64_t)baud_mhz * 1000000 + (meas_refclock / 2);\n+\tmult /= meas_refclock;\n+\n+\t/*\n+\t * 6. Decrease MPLL_MULTIPLIER by one continually until it reaches\n+\t * the desired long-term setting, ensuring that each MPLL_MULTIPLIER\n+\t * value is constant for at least 1 msec before changing to the next\n+\t * value. The desired long-term setting is as indicated in HRM tables\n+\t * 21-1, 21-2, and 21-3. This is not required with the HRM\n+\t * sequence.\n+\t */\n+\tdo {\n+\t\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\t\tmpll_multiplier.s.mpll_multiplier = --old_multiplier;\n+\t\tcsr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);\n+\t\t/* Wait for 1 ms */\n+\t\tudelay(1000);\n+\t} while (old_multiplier > (int)mult);\n+}\n+\n+enum cvmx_qlm_mode cvmx_qlm_get_mode_cn78xx(int node, int qlm)\n+{\n+\tcvmx_gserx_cfg_t gserx_cfg;\n+\tint qlm_mode[2][9] = { { -1, -1, -1, -1, -1, -1, -1, -1 },\n+\t\t\t       { -1, -1, -1, -1, -1, -1, -1, -1 } };\n+\n+\tif (qlm >= 8)\n+\t\treturn CVMX_QLM_MODE_OCI;\n+\n+\tif (qlm_mode[node][qlm] != -1)\n+\t\treturn qlm_mode[node][qlm];\n+\n+\tgserx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\tif (gserx_cfg.s.pcie) {\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either PEM0 x4 or PEM0 x8 */\n+\t\tcase 1: /* Either PEM0 x8 or PEM1 x4 */\n+\t\t{\n+\t\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM0 x8 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM0 x4 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 2: /* Either PEM2 x4 or PEM2 x8 */\n+\t\t{\n+\t\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM2 x8 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM2 x4 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 3: /* Either PEM2 x8 or PEM3 x4 or PEM3 x8 */\n+\t\t{\n+\t\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM2 x8 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t}\n+\n+\t\t\t/* Can be first 4 lanes of PEM3 */\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM3 x8 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM2 x4 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 4: /* Either PEM3 x8 or PEM3 x4 */\n+\t\t{\n+\t\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM3 x8 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM3 x4 */\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t} else if (gserx_cfg.s.ila) {\n+\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_ILK;\n+\t} else if (gserx_cfg.s.bgx) {\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tcvmx_bgxx_spux_br_pmd_control_t pmd_control;\n+\t\tint bgx = (qlm < 2) ? qlm : qlm - 2;\n+\n+\t\tcmr_config.u64 = csr_rd_node(node, CVMX_BGXX_CMRX_CONFIG(0, bgx));\n+\t\tpmd_control.u64 = csr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(0, bgx));\n+\n+\t\tswitch (cmr_config.s.lmac_type) {\n+\t\tcase 0:\n+\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_XAUI;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_RXAUI;\n+\t\t\tbreak;\n+\t\tcase 3:\n+\t\t\t/*\n+\t\t\t * Use training to determine if we're in 10GBASE-KR\n+\t\t\t * or XFI\n+\t\t\t */\n+\t\t\tif (pmd_control.s.train_en)\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_10G_KR;\n+\t\t\telse\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_XFI;\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\t/*\n+\t\t\t * Use training to determine if we're in 40GBASE-KR\n+\t\t\t * or XLAUI\n+\t\t\t */\n+\t\t\tif (pmd_control.s.train_en)\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_40G_KR4;\n+\t\t\telse\n+\t\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_XLAUI;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\tqlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;\n+\t}\n+\n+\treturn qlm_mode[node][qlm];\n+}\n+\n+enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn73xx(int qlm)\n+{\n+\tcvmx_gserx_cfg_t gserx_cfg;\n+\tint qlm_mode[7] = { -1, -1, -1, -1, -1, -1, -1 };\n+\n+\tif (qlm_mode[qlm] != -1)\n+\t\treturn qlm_mode[qlm];\n+\n+\tif (qlm > 6) {\n+\t\tdebug(\"Invalid QLM(%d) passed\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\tgserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\tif (gserx_cfg.s.pcie) {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either PEM0 x4 or PEM0 x8 */\n+\t\tcase 1: /* Either PEM0 x8 or PEM1 x4 */\n+\t\t{\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM0 x8 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM0/PEM1 x4 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 2: /* Either PEM2 x4 or PEM2 x8 */\n+\t\t{\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM2 x8 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM2 x4 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 5:\n+\t\tcase 6:\t\t\t\t\t\t/* PEM3 x2 */\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X2; /* PEM3 x2 */\n+\t\t\tbreak;\n+\t\tcase 3: /* Either PEM2 x8 or PEM3 x4 */\n+\t\t{\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));\n+\t\t\tif (pemx_cfg.cn78xx.lanes8) {\n+\t\t\t\t/* PEM2 x8 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;\n+\t\t\t} else {\n+\t\t\t\t/* PEM3 x4 */\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t} else if (gserx_cfg.s.bgx) {\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tcvmx_bgxx_cmr_rx_lmacs_t bgx_cmr_rx_lmacs;\n+\t\tcvmx_bgxx_spux_br_pmd_control_t pmd_control;\n+\t\tint bgx = 0;\n+\t\tint start = 0, end = 4, index;\n+\t\tint lane_mask = 0, train_mask = 0;\n+\t\tint mux = 0; // 0:BGX2 (DLM5/DLM6), 1:BGX2(DLM5), 2:BGX2(DLM6)\n+\n+\t\tif (qlm < 4) {\n+\t\t\tbgx = qlm - 2;\n+\t\t} else if (qlm == 5 || qlm == 6) {\n+\t\t\tbgx = 2;\n+\t\t\tmux = cvmx_qlm_mux_interface(bgx);\n+\t\t\tif (mux == 0) {\n+\t\t\t\tstart = 0;\n+\t\t\t\tend = 4;\n+\t\t\t} else if (mux == 1) {\n+\t\t\t\tstart = 0;\n+\t\t\t\tend = 2;\n+\t\t\t} else if (mux == 2) {\n+\t\t\t\tstart = 2;\n+\t\t\t\tend = 4;\n+\t\t\t} else {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\t\treturn qlm_mode[qlm];\n+\t\t\t}\n+\t\t}\n+\n+\t\tfor (index = start; index < end; index++) {\n+\t\t\tcmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));\n+\t\t\tpmd_control.u64 = csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));\n+\t\t\tlane_mask |= (cmr_config.s.lmac_type << (index * 4));\n+\t\t\ttrain_mask |= (pmd_control.s.train_en << (index * 4));\n+\t\t}\n+\n+\t\t/* Need to include DLM5 lmacs when only DLM6 DLM is used */\n+\t\tif (mux == 2)\n+\t\t\tbgx_cmr_rx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(2));\n+\t\tswitch (lane_mask) {\n+\t\tcase 0:\n+\t\t\tif (mux == 1) {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;\n+\t\t\t} else if (mux == 2) {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;\n+\t\t\t\tbgx_cmr_rx_lmacs.s.lmacs = 4;\n+\t\t\t}\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase 0x1:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XAUI;\n+\t\t\tbreak;\n+\t\tcase 0x2:\n+\t\t\tif (mux == 1) {\n+\t\t\t\t// NONE+RXAUI\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;\n+\t\t\t} else if (mux == 0) {\n+\t\t\t\t// RXAUI+SGMII\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\t} else {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 0x202:\n+\t\t\tif (mux == 2) {\n+\t\t\t\t// RXAUI+RXAUI\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;\n+\t\t\t\tbgx_cmr_rx_lmacs.s.lmacs = 4;\n+\t\t\t} else if (mux == 1) {\n+\t\t\t\t// RXAUI+RXAUI\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;\n+\t\t\t} else if (mux == 0) {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;\n+\t\t\t} else {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 0x22:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;\n+\t\t\tbreak;\n+\t\tcase 0x3333:\n+\t\t\t/*\n+\t\t\t * Use training to determine if we're in 10GBASE-KR\n+\t\t\t * or XFI\n+\t\t\t */\n+\t\t\tif (train_mask)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_10G_KR;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XFI;\n+\t\t\tbreak;\n+\t\tcase 0x4:\n+\t\t\t/*\n+\t\t\t * Use training to determine if we're in 40GBASE-KR\n+\t\t\t * or XLAUI\n+\t\t\t */\n+\t\t\tif (train_mask)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_40G_KR4;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XLAUI;\n+\t\t\tbreak;\n+\t\tcase 0x0005:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII;\n+\t\t\tbreak;\n+\t\tcase 0x3335:\n+\t\t\tif (train_mask)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI;\n+\t\t\tbreak;\n+\t\tcase 0x45:\n+\t\t\tif (train_mask)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_40G_KR4;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XLAUI;\n+\t\t\tbreak;\n+\t\tcase 0x225:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_RXAUI;\n+\t\t\tbreak;\n+\t\tcase 0x15:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XAUI;\n+\t\t\tbreak;\n+\n+\t\tcase 0x200:\n+\t\t\tif (mux == 2) {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;\n+\t\t\t\tbgx_cmr_rx_lmacs.s.lmacs = 4;\n+\t\t\t} else\n+\t\tcase 0x205:\n+\t\tcase 0x233:\n+\t\tcase 0x3302:\n+\t\tcase 0x3305:\n+\t\t\tif (mux == 0)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\tcase 0x3300:\n+\t\t\tif (mux == 0) {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\t} else if (mux == 2) {\n+\t\t\t\tif (train_mask)\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;\n+\t\t\t\telse\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;\n+\t\t\t\tbgx_cmr_rx_lmacs.s.lmacs = 4;\n+\t\t\t} else {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 0x33:\n+\t\t\tif (mux == 1 || mux == 2) {\n+\t\t\t\tif (train_mask)\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;\n+\t\t\t\telse\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;\n+\t\t\t\tif (mux == 2)\n+\t\t\t\t\tbgx_cmr_rx_lmacs.s.lmacs = 4;\n+\t\t\t} else {\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 0x0035:\n+\t\t\tif (mux == 0)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\telse if (train_mask)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR_1X1;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI_1X1;\n+\t\t\tbreak;\n+\t\tcase 0x235:\n+\t\t\tif (mux == 0)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (mux == 2) {\n+\t\t\tcsr_wr(CVMX_BGXX_CMR_RX_LMACS(2), bgx_cmr_rx_lmacs.u64);\n+\t\t\tcsr_wr(CVMX_BGXX_CMR_TX_LMACS(2), bgx_cmr_rx_lmacs.u64);\n+\t\t}\n+\t} else if (gserx_cfg.s.sata) {\n+\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SATA_2X1;\n+\t} else {\n+\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t}\n+\n+\treturn qlm_mode[qlm];\n+}\n+\n+enum cvmx_qlm_mode __cvmx_qlm_get_mode_cnf75xx(int qlm)\n+{\n+\tcvmx_gserx_cfg_t gserx_cfg;\n+\tint qlm_mode[9] = { -1, -1, -1, -1, -1, -1, -1 };\n+\n+\tif (qlm_mode[qlm] != -1)\n+\t\treturn qlm_mode[qlm];\n+\n+\tif (qlm > 9) {\n+\t\tdebug(\"Invalid QLM(%d) passed\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\tif ((qlm == 2 || qlm == 3) && (OCTEON_IS_MODEL(OCTEON_CNF75XX))) {\n+\t\tcvmx_sriox_status_reg_t status_reg;\n+\t\tint port = (qlm == 2) ? 0 : 1;\n+\n+\t\tstatus_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));\n+\t\t/* FIXME add different width */\n+\t\tif (status_reg.s.srio)\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SRIO_1X4;\n+\t\telse\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\treturn qlm_mode[qlm];\n+\t}\n+\n+\tgserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\tif (gserx_cfg.s.pcie) {\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either PEM0 x2 or PEM0 x4 */\n+\t\tcase 1: /* Either PEM1 x2 or PEM0 x4 */\n+\t\t{\n+\t\t\t/* FIXME later */\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_PCIE;\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t} else if (gserx_cfg.s.bgx) {\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tcvmx_bgxx_spux_br_pmd_control_t pmd_control;\n+\t\tint bgx = 0;\n+\t\tint start = 0, end = 4, index;\n+\t\tint lane_mask = 0, train_mask = 0;\n+\t\tint mux = 0; // 0:BGX0 (DLM4/DLM5), 1:BGX0(DLM4), 2:BGX0(DLM5)\n+\t\tcvmx_gserx_cfg_t gser1, gser2;\n+\n+\t\tgser1.u64 = csr_rd(CVMX_GSERX_CFG(4));\n+\t\tgser2.u64 = csr_rd(CVMX_GSERX_CFG(5));\n+\t\tif (gser1.s.bgx && gser2.s.bgx) {\n+\t\t\tstart = 0;\n+\t\t\tend = 4;\n+\t\t} else if (gser1.s.bgx) {\n+\t\t\tstart = 0;\n+\t\t\tend = 2;\n+\t\t\tmux = 1;\n+\t\t} else if (gser2.s.bgx) {\n+\t\t\tstart = 2;\n+\t\t\tend = 4;\n+\t\t\tmux = 2;\n+\t\t} else {\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\treturn qlm_mode[qlm];\n+\t\t}\n+\n+\t\tfor (index = start; index < end; index++) {\n+\t\t\tcmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));\n+\t\t\tpmd_control.u64 = csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));\n+\t\t\tlane_mask |= (cmr_config.s.lmac_type << (index * 4));\n+\t\t\ttrain_mask |= (pmd_control.s.train_en << (index * 4));\n+\t\t}\n+\n+\t\tswitch (lane_mask) {\n+\t\tcase 0:\n+\t\t\tif (mux == 1 || mux == 2)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase 0x3300:\n+\t\t\tif (mux == 0)\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_MIXED;\n+\t\t\telse if (mux == 2)\n+\t\t\t\tif (train_mask)\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;\n+\t\t\t\telse\n+\t\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;\n+\t\t\telse\n+\t\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\tqlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;\n+\t}\n+\n+\treturn qlm_mode[qlm];\n+}\n+\n+/*\n+ * Read QLM and return mode.\n+ */\n+enum cvmx_qlm_mode cvmx_qlm_get_mode(int qlm)\n+{\n+\tif (OCTEON_IS_OCTEON2())\n+\t\treturn __cvmx_qlm_get_mode_cn6xxx(qlm);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN70XX))\n+\t\treturn __cvmx_qlm_get_mode_cn70xx(qlm);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN78XX))\n+\t\treturn cvmx_qlm_get_mode_cn78xx(cvmx_get_node_num(), qlm);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\treturn __cvmx_qlm_get_mode_cn73xx(qlm);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX))\n+\t\treturn __cvmx_qlm_get_mode_cnf75xx(qlm);\n+\n+\treturn CVMX_QLM_MODE_DISABLED;\n+}\n+\n+int cvmx_qlm_measure_clock_cn7xxx(int node, int qlm)\n+{\n+\tcvmx_gserx_cfg_t cfg;\n+\tcvmx_gserx_refclk_sel_t refclk_sel;\n+\tcvmx_gserx_lane_mode_t lane_mode;\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN73XX)) {\n+\t\tif (node != 0 || qlm >= 7)\n+\t\t\treturn -1;\n+\t} else if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {\n+\t\tif (qlm >= 8 || node > 1)\n+\t\t\treturn -1; /* FIXME for OCI */\n+\t} else {\n+\t\tdebug(\"%s: Unsupported OCTEON model\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\tcfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\n+\tif (cfg.s.pcie) {\n+\t\trefclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\tif (refclk_sel.s.pcie_refclk125)\n+\t\t\treturn REF_125MHZ; /* Ref 125 Mhz */\n+\t\telse\n+\t\t\treturn REF_100MHZ; /* Ref 100Mhz */\n+\t}\n+\n+\tlane_mode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));\n+\tswitch (lane_mode.s.lmode) {\n+\tcase R_25G_REFCLK100:\n+\t\treturn REF_100MHZ;\n+\tcase R_5G_REFCLK100:\n+\t\treturn REF_100MHZ;\n+\tcase R_8G_REFCLK100:\n+\t\treturn REF_100MHZ;\n+\tcase R_125G_REFCLK15625_KX:\n+\t\treturn REF_156MHZ;\n+\tcase R_3125G_REFCLK15625_XAUI:\n+\t\treturn REF_156MHZ;\n+\tcase R_103125G_REFCLK15625_KR:\n+\t\treturn REF_156MHZ;\n+\tcase R_125G_REFCLK15625_SGMII:\n+\t\treturn REF_156MHZ;\n+\tcase R_5G_REFCLK15625_QSGMII:\n+\t\treturn REF_156MHZ;\n+\tcase R_625G_REFCLK15625_RXAUI:\n+\t\treturn REF_156MHZ;\n+\tcase R_25G_REFCLK125:\n+\t\treturn REF_125MHZ;\n+\tcase R_5G_REFCLK125:\n+\t\treturn REF_125MHZ;\n+\tcase R_8G_REFCLK125:\n+\t\treturn REF_125MHZ;\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+}\n+\n+/**\n+ * Measure the reference clock of a QLM on a multi-node setup\n+ *\n+ * @param node   node to measure\n+ * @param qlm    QLM to measure\n+ *\n+ * @return Clock rate in Hz\n+ */\n+int cvmx_qlm_measure_clock_node(int node, int qlm)\n+{\n+\tif (octeon_has_feature(OCTEON_FEATURE_MULTINODE))\n+\t\treturn cvmx_qlm_measure_clock_cn7xxx(node, qlm);\n+\telse\n+\t\treturn cvmx_qlm_measure_clock(qlm);\n+}\n+\n+/**\n+ * Measure the reference clock of a QLM\n+ *\n+ * @param qlm    QLM to measure\n+ *\n+ * @return Clock rate in Hz\n+ */\n+int cvmx_qlm_measure_clock(int qlm)\n+{\n+\tcvmx_mio_ptp_clock_cfg_t ptp_clock;\n+\tu64 count;\n+\tu64 start_cycle, stop_cycle;\n+\tint evcnt_offset = 0x10;\n+\tint incr_count = 1;\n+\tint ref_clock[16] = { 0 };\n+\n+\tif (ref_clock[qlm])\n+\t\treturn ref_clock[qlm];\n+\n+\tif (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))\n+\t\treturn cvmx_qlm_measure_clock_cn7xxx(cvmx_get_node_num(), qlm);\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN70XX) && qlm == 0) {\n+\t\tcvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;\n+\n+\t\tref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));\n+\t\tif (ref_clkdiv2.s.ref_clkdiv2)\n+\t\t\tincr_count = 2;\n+\t}\n+\n+\t/* Fix reference clock for OCI QLMs */\n+\n+\t/* Disable the PTP event counter while we configure it */\n+\tptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */\n+\tptp_clock.s.evcnt_en = 0;\n+\tcsr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);\n+\n+\t/* Count on rising edge, Choose which QLM to count */\n+\tptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */\n+\tptp_clock.s.evcnt_edge = 0;\n+\tptp_clock.s.evcnt_in = evcnt_offset + qlm;\n+\tcsr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);\n+\n+\t/* Clear MIO_PTP_EVT_CNT */\n+\tcsr_rd(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */\n+\tcount = csr_rd(CVMX_MIO_PTP_EVT_CNT);\n+\tcsr_wr(CVMX_MIO_PTP_EVT_CNT, -count);\n+\n+\t/* Set MIO_PTP_EVT_CNT to 1 billion */\n+\tcsr_wr(CVMX_MIO_PTP_EVT_CNT, 1000000000);\n+\n+\t/* Enable the PTP event counter */\n+\tptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */\n+\tptp_clock.s.evcnt_en = 1;\n+\tcsr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);\n+\n+\tstart_cycle = get_ticks();\n+\t/* Wait for 50ms */\n+\tmdelay(50);\n+\n+\t/* Read the counter */\n+\tcsr_rd(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */\n+\tcount = csr_rd(CVMX_MIO_PTP_EVT_CNT);\n+\tstop_cycle = get_ticks();\n+\n+\t/* Disable the PTP event counter */\n+\tptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */\n+\tptp_clock.s.evcnt_en = 0;\n+\tcsr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);\n+\n+\t/* Clock counted down, so reverse it */\n+\tcount = 1000000000 - count;\n+\tcount *= incr_count;\n+\n+\t/* Return the rate */\n+\tref_clock[qlm] = count * gd->cpu_clk / (stop_cycle - start_cycle);\n+\n+\treturn ref_clock[qlm];\n+}\n+\n+/*\n+ * Perform RX equalization on a QLM\n+ *\n+ * @param node\tNode the QLM is on\n+ * @param qlm\tQLM to perform RX equalization on\n+ * @param lane\tLane to use, or -1 for all lanes\n+ *\n+ * @return Zero on success, negative if any lane failed RX equalization\n+ */\n+int __cvmx_qlm_rx_equalization(int node, int qlm, int lane)\n+{\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_br_rxx_ctl_t rxx_ctl;\n+\tcvmx_gserx_br_rxx_eer_t rxx_eer;\n+\tcvmx_gserx_rx_eie_detsts_t eie_detsts;\n+\tint fail, gbaud, l, lane_mask;\n+\tenum cvmx_qlm_mode mode;\n+\tint max_lanes = cvmx_qlm_get_lanes(qlm);\n+\tcvmx_gserx_lane_mode_t lmode;\n+\tcvmx_gserx_lane_px_mode_1_t pmode_1;\n+\tint pending = 0;\n+\tu64 timeout;\n+\n+\t/* Don't touch QLMs if it is reset or powered down */\n+\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\tif (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)\n+\t\treturn -1;\n+\n+\t/*\n+\t * Check whether GSER PRBS pattern matcher is enabled on any of the\n+\t * applicable lanes. Can't complete RX Equalization while pattern\n+\t * matcher is enabled because it causes errors\n+\t */\n+\tfor (l = 0; l < max_lanes; l++) {\n+\t\tcvmx_gserx_lanex_lbert_cfg_t lbert_cfg;\n+\n+\t\tif (lane != -1 && lane != l)\n+\t\t\tcontinue;\n+\n+\t\tlbert_cfg.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_LBERT_CFG(l, qlm));\n+\t\tif (lbert_cfg.s.lbert_pm_en == 1)\n+\t\t\treturn -1;\n+\t}\n+\n+\t/* Get Lane Mode */\n+\tlmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));\n+\n+\t/*\n+\t * Check to see if in VMA manual mode is set. If in VMA manual mode\n+\t * don't complete rx equalization\n+\t */\n+\tpmode_1.u64 = csr_rd_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm));\n+\tif (pmode_1.s.vma_mm == 1) {\n+#ifdef DEBUG_QLM\n+\t\tdebug(\"N%d:QLM%d: VMA Manual (manual DFE) selected. Not completing Rx equalization\\n\",\n+\t\t      node, qlm);\n+#endif\n+\t\treturn 0;\n+\t}\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX)) {\n+\t\tgbaud = cvmx_qlm_get_gbaud_mhz_node(node, qlm);\n+\t\tmode = cvmx_qlm_get_mode_cn78xx(node, qlm);\n+\t} else {\n+\t\tgbaud = cvmx_qlm_get_gbaud_mhz(qlm);\n+\t\tmode = cvmx_qlm_get_mode(qlm);\n+\t}\n+\n+\t/* Apply RX Equalization for speed >= 8G */\n+\tif (qlm < 8) {\n+\t\tif (gbaud < 6250)\n+\t\t\treturn 0;\n+\t}\n+\n+\t/* Don't run on PCIe Links */\n+\tif (mode == CVMX_QLM_MODE_PCIE || mode == CVMX_QLM_MODE_PCIE_1X8 ||\n+\t    mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1)\n+\t\treturn -1;\n+\n+\tfail = 0;\n+\n+\t/*\n+\t * Before completing Rx equalization wait for\n+\t * GSERx_RX_EIE_DETSTS[CDRLOCK] to be set.\n+\t * This ensures the rx data is valid\n+\t */\n+\tif (lane == -1) {\n+\t\t/*\n+\t\t * check all 4 Lanes (cdrlock = 1111/b) for CDR Lock with\n+\t\t * lane == -1\n+\t\t */\n+\t\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),\n+\t\t\t\t\t       cvmx_gserx_rx_eie_detsts_t, cdrlock, ==,\n+\t\t\t\t\t       (1 << max_lanes) - 1, 500)) {\n+#ifdef DEBUG_QLM\n+\t\t\teie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));\n+\t\t\tdebug(\"ERROR: %d:QLM%d: CDR Lock not detected for all 4 lanes. CDR_LOCK(0x%x)\\n\",\n+\t\t\t      node, qlm, eie_detsts.s.cdrlock);\n+#endif\n+\t\t\treturn -1;\n+\t\t}\n+\t} else {\n+\t\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),\n+\t\t\t\t\t       cvmx_gserx_rx_eie_detsts_t, cdrlock, &, (1 << lane),\n+\t\t\t\t\t       500)) {\n+#ifdef DEBUG_QLM\n+\t\t\teie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));\n+\t\t\tdebug(\"ERROR: %d:QLM%d: CDR Lock not detected for Lane%d CDR_LOCK(0x%x)\\n\",\n+\t\t\t      node, qlm, lane, eie_detsts.s.cdrlock);\n+#endif\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Errata (GSER-20075) GSER(0..13)_BR_RX3_EER[RXT_ERR] is\n+\t * GSER(0..13)_BR_RX2_EER[RXT_ERR]. Since lanes 2-3 trigger at the\n+\t * same time, we need to setup lane 3 before we loop through the lanes\n+\t */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && (lane == -1 || lane == 3)) {\n+\t\t/* Enable software control */\n+\t\trxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(3, qlm));\n+\t\trxx_ctl.s.rxt_swm = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(3, qlm), rxx_ctl.u64);\n+\n+\t\t/* Clear the completion flag */\n+\t\trxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(3, qlm));\n+\t\trxx_eer.s.rxt_esv = 0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_EER(3, qlm), rxx_eer.u64);\n+\t\t/* Initiate a new request on lane 2 */\n+\t\tif (lane == 3) {\n+\t\t\trxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(2, qlm));\n+\t\t\trxx_eer.s.rxt_eer = 1;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_EER(2, qlm), rxx_eer.u64);\n+\t\t}\n+\t}\n+\n+\tfor (l = 0; l < max_lanes; l++) {\n+\t\tif (lane != -1 && lane != l)\n+\t\t\tcontinue;\n+\n+\t\t/*\n+\t\t * Skip lane 3 on 78p1.x due to Errata (GSER-20075).\n+\t\t * Handled above\n+\t\t */\n+\t\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && l == 3) {\n+\t\t\t/*\n+\t\t\t * Need to add lane 3 to pending list for 78xx\n+\t\t\t * pass 1.x\n+\t\t\t */\n+\t\t\tpending |= 1 << 3;\n+\t\t\tcontinue;\n+\t\t}\n+\t\t/* Enable software control */\n+\t\trxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm));\n+\t\trxx_ctl.s.rxt_swm = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm), rxx_ctl.u64);\n+\n+\t\t/* Clear the completion flag and initiate a new request */\n+\t\trxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));\n+\t\trxx_eer.s.rxt_esv = 0;\n+\t\trxx_eer.s.rxt_eer = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm), rxx_eer.u64);\n+\t\tpending |= 1 << l;\n+\t}\n+\n+\t/*\n+\t * Wait for 250ms, approx 10x times measured value, as XFI/XLAUI\n+\t * can take 21-23ms, other interfaces can take 2-3ms.\n+\t */\n+\ttimeout = get_timer(0);\n+\n+\tlane_mask = 0;\n+\twhile (pending) {\n+\t\t/* Wait for RX equalization to complete */\n+\t\tfor (l = 0; l < max_lanes; l++) {\n+\t\t\tlane_mask = 1 << l;\n+\t\t\t/* Only check lanes that are pending */\n+\t\t\tif (!(pending & lane_mask))\n+\t\t\t\tcontinue;\n+\n+\t\t\t/*\n+\t\t\t * Read the registers for checking Electrical Idle/CDR\n+\t\t\t * lock and the status of the RX equalization\n+\t\t\t */\n+\t\t\teie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));\n+\t\t\trxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));\n+\n+\t\t\t/*\n+\t\t\t * Mark failure if lane entered Electrical Idle or lost\n+\t\t\t * CDR Lock. The bit for the lane will have cleared in\n+\t\t\t * either EIESTS or CDRLOCK\n+\t\t\t */\n+\t\t\tif (!(eie_detsts.s.eiests & eie_detsts.s.cdrlock & lane_mask)) {\n+\t\t\t\tfail |= lane_mask;\n+\t\t\t\tpending &= ~lane_mask;\n+\t\t\t} else if (rxx_eer.s.rxt_esv) {\n+\t\t\t\tpending &= ~lane_mask;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Breakout of the loop on timeout */\n+\t\tif (get_timer(timeout) > 250)\n+\t\t\tbreak;\n+\t}\n+\n+\tlane_mask = 0;\n+\t/* Cleanup and report status */\n+\tfor (l = 0; l < max_lanes; l++) {\n+\t\tif (lane != -1 && lane != l)\n+\t\t\tcontinue;\n+\n+\t\tlane_mask = 1 << l;\n+\t\trxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));\n+\t\t/* Switch back to hardware control */\n+\t\trxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm));\n+\t\trxx_ctl.s.rxt_swm = 0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm), rxx_ctl.u64);\n+\n+\t\t/* Report status */\n+\t\tif (fail & lane_mask) {\n+#ifdef DEBUG_QLM\n+\t\t\tdebug(\"%d:QLM%d: Lane%d RX equalization lost CDR Lock or entered Electrical Idle\\n\",\n+\t\t\t      node, qlm, l);\n+#endif\n+\t\t} else if ((pending & lane_mask) || !rxx_eer.s.rxt_esv) {\n+#ifdef DEBUG_QLM\n+\t\t\tdebug(\"%d:QLM%d: Lane %d RX equalization timeout\\n\", node, qlm, l);\n+#endif\n+\t\t\tfail |= 1 << l;\n+\t\t} else {\n+#ifdef DEBUG_QLM\n+\t\t\tchar *dir_label[4] = { \"Hold\", \"Inc\", \"Dec\", \"Hold\" };\n+#ifdef DEBUG_QLM_RX\n+\t\t\tcvmx_gserx_lanex_rx_aeq_out_0_t rx_aeq_out_0;\n+\t\t\tcvmx_gserx_lanex_rx_aeq_out_1_t rx_aeq_out_1;\n+\t\t\tcvmx_gserx_lanex_rx_aeq_out_2_t rx_aeq_out_2;\n+\t\t\tcvmx_gserx_lanex_rx_vma_status_0_t rx_vma_status_0;\n+#endif\n+\t\t\tdebug(\"%d:QLM%d: Lane%d: RX equalization completed.\\n\", node, qlm, l);\n+\t\t\tdebug(\"    Tx Direction Hints TXPRE: %s, TXMAIN: %s, TXPOST: %s, Figure of Merit: %d\\n\",\n+\t\t\t      dir_label[(rxx_eer.s.rxt_esm) & 0x3],\n+\t\t\t      dir_label[((rxx_eer.s.rxt_esm) >> 2) & 0x3],\n+\t\t\t      dir_label[((rxx_eer.s.rxt_esm) >> 4) & 0x3], rxx_eer.s.rxt_esm >> 6);\n+\n+#ifdef DEBUG_QLM_RX\n+\t\t\trx_aeq_out_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_0(l, qlm));\n+\t\t\trx_aeq_out_1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_1(l, qlm));\n+\t\t\trx_aeq_out_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_2(l, qlm));\n+\t\t\trx_vma_status_0.u64 =\n+\t\t\t\tcsr_rd_node(node, CVMX_GSERX_LANEX_RX_VMA_STATUS_0(l, qlm));\n+\t\t\tdebug(\"    DFE Tap1:%lu, Tap2:%ld, Tap3:%ld, Tap4:%ld, Tap5:%ld\\n\",\n+\t\t\t      (unsigned int long)cvmx_bit_extract(rx_aeq_out_1.u64, 0, 5),\n+\t\t\t      (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_1.u64, 5, 9),\n+\t\t\t      (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_1.u64, 10, 14),\n+\t\t\t      (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_0.u64, 0, 4),\n+\t\t\t      (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_0.u64, 5, 9));\n+\t\t\tdebug(\"    Pre-CTLE Gain:%lu, Post-CTLE Gain:%lu, CTLE Peak:%lu, CTLE Pole:%lu\\n\",\n+\t\t\t      (unsigned int long)cvmx_bit_extract(rx_aeq_out_2.u64, 4, 4),\n+\t\t\t      (unsigned int long)cvmx_bit_extract(rx_aeq_out_2.u64, 0, 4),\n+\t\t\t      (unsigned int long)cvmx_bit_extract(rx_vma_status_0.u64, 2, 4),\n+\t\t\t      (unsigned int long)cvmx_bit_extract(rx_vma_status_0.u64, 0, 2));\n+#endif\n+#endif\n+\t\t}\n+\t}\n+\n+\treturn (fail) ? -1 : 0;\n+}\n+\n+/**\n+ * Errata GSER-27882 -GSER 10GBASE-KR Transmit Equalizer\n+ * Training may not update PHY Tx Taps. This function is not static\n+ * so we can share it with BGX KR\n+ *\n+ * @param node\tNode to apply errata workaround\n+ * @param qlm\tQLM to apply errata workaround\n+ * @param lane\tLane to apply the errata\n+ */\n+int cvmx_qlm_gser_errata_27882(int node, int qlm, int lane)\n+{\n+\tcvmx_gserx_lanex_pcs_ctlifc_0_t clifc0;\n+\tcvmx_gserx_lanex_pcs_ctlifc_2_t clifc2;\n+\n+\tif (!(OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) || OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_1) ||\n+\t      OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_2) || OCTEON_IS_MODEL(OCTEON_CNF75XX_PASS1_0) ||\n+\t      OCTEON_IS_MODEL(OCTEON_CN78XX)))\n+\t\treturn 0;\n+\n+\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),\n+\t\t\t\t       cvmx_gserx_rx_eie_detsts_t, cdrlock, &,\n+\t\t\t\t       (1 << lane), 200))\n+\t\treturn -1;\n+\n+\tclifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm));\n+\tclifc0.s.cfg_tx_coeff_req_ovrrd_val = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm), clifc0.u64);\n+\tclifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tclifc2.s.cfg_tx_coeff_req_ovrrd_en = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);\n+\tclifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tclifc2.s.ctlifc_ovrrd_req = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);\n+\tclifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tclifc2.s.cfg_tx_coeff_req_ovrrd_en = 0;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);\n+\tclifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tclifc2.s.ctlifc_ovrrd_req = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);\n+\treturn 0;\n+}\n+\n+/**\n+ * Updates the RX EQ Default Settings Update (CTLE Bias) to support longer\n+ * SERDES channels\n+ *\n+ * @INTERNAL\n+ *\n+ * @param node\tNode number to configure\n+ * @param qlm\tQLM number to configure\n+ */\n+void cvmx_qlm_gser_errata_25992(int node, int qlm)\n+{\n+\tint lane;\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\n+\tif (!(OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) || OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_1) ||\n+\t      OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_2) || OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X)))\n+\t\treturn;\n+\n+\tfor (lane = 0; lane < num_lanes; lane++) {\n+\t\tcvmx_gserx_lanex_rx_ctle_ctrl_t rx_ctle_ctrl;\n+\t\tcvmx_gserx_lanex_rx_cfg_4_t rx_cfg_4;\n+\n+\t\trx_ctle_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(lane, qlm));\n+\t\trx_ctle_ctrl.s.pcs_sds_rx_ctle_bias_ctrl = 3;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(lane, qlm), rx_ctle_ctrl.u64);\n+\n+\t\trx_cfg_4.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_4(lane, qlm));\n+\t\trx_cfg_4.s.cfg_rx_errdet_ctrl = 0xcd6f;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_4(lane, qlm), rx_cfg_4.u64);\n+\t}\n+}\n+\n+void cvmx_qlm_display_registers(int qlm)\n+{\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\tint lane;\n+\tconst __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field();\n+\n+\tdebug(\"%29s\", \"Field[<stop bit>:<start bit>]\");\n+\tfor (lane = 0; lane < num_lanes; lane++)\n+\t\tdebug(\"\\t      Lane %d\", lane);\n+\tdebug(\"\\n\");\n+\n+\twhile (ptr && ptr->name) {\n+\t\tdebug(\"%20s[%3d:%3d]\", ptr->name, ptr->stop_bit, ptr->start_bit);\n+\t\tfor (lane = 0; lane < num_lanes; lane++) {\n+\t\t\tu64 val;\n+\t\t\tint tx_byp = 0;\n+\n+\t\t\t/*\n+\t\t\t * Make sure serdes_tx_byp is set for displaying\n+\t\t\t * TX amplitude and TX demphasis field values.\n+\t\t\t */\n+\t\t\tif (strncmp(ptr->name, \"biasdrv_\", 8) == 0 ||\n+\t\t\t    strncmp(ptr->name, \"tcoeff_\", 7) == 0) {\n+\t\t\t\ttx_byp = cvmx_qlm_jtag_get(qlm, lane, \"serdes_tx_byp\");\n+\t\t\t\tif (tx_byp == 0) {\n+\t\t\t\t\tdebug(\"\\t \\t\");\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tval = cvmx_qlm_jtag_get(qlm, lane, ptr->name);\n+\t\t\tdebug(\"\\t%4llu (0x%04llx)\", (unsigned long long)val,\n+\t\t\t      (unsigned long long)val);\n+\t\t}\n+\t\tdebug(\"\\n\");\n+\t\tptr++;\n+\t}\n+}\n+\n+/* ToDo: CVMX_DUMP_GSER removed for now (unused!) */\n",
    "prefixes": [
        "v1",
        "42/50"
    ]
}