get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1415047,
    "url": "http://patchwork.ozlabs.org/api/patches/1415047/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20201211160612.1498780-45-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-45-sr@denx.de>",
    "list_archive_url": null,
    "date": "2020-12-11T16:06:06",
    "name": "[v1,44/50] mips: octeon: Add octeon_qlm.c",
    "commit_ref": "fc6c9c50d12cd463488c99b866f5443af5004c1d",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "6a0657b4f43551b3906ef39d08fabe37a8ccf784",
    "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-45-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/1415047/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1415047/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=wFrwMO7i;\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 4CsxQb1DPxz9sSs\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 12 Dec 2020 03:42:15 +1100 (AEDT)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id DF2FD8278D;\n\tFri, 11 Dec 2020 17:38:51 +0100 (CET)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 48CEC827EA; Fri, 11 Dec 2020 17:09:41 +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 1AEE9825DC\n for <u-boot@lists.denx.de>; Fri, 11 Dec 2020 17:06:43 +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 C06A0A0E06;\n Fri, 11 Dec 2020 17:06:42 +0100 (CET)",
            "from smtp1.mailbox.org ([80.241.60.240])\n by gerste.heinlein-support.de (gerste.heinlein-support.de [91.198.250.173])\n (amavisd-new, port 10030)\n with ESMTP id wZlbpuEYOQen; 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=1607704732;\n\tbh=bF3OXEhE8A4TXmJDnU3p54Hr95tR7xhiX+jf3YK+ck8=;\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=wFrwMO7i4k5KKSWqcsRLY7UoM1u5xl7NCELF/dW5Ypk7JdwC/B23TO2zblgI88Ya8\n\t ay2RLZHAbq2ncPXSLjJVxzZTDZAvFSiMZ3YSNMKHyKofqtiQ6VZIS8x9/uSTARi4cF\n\t QWtZprdSqNgXFLaWCkjtvxa6y9EENtV2Vc+7YsZZawZiEg5gDJxnPO20eMFtqqUD8p\n\t kLo9njNZHozymLu2RFCksC+azandpq4y7OcWq0D/tbdZpcEFTvfz5r0F8y+WMG9W0P\n\t 1FHGRTLike4X1499Oh1JhDrN8cIDVWl7tG+YETex/O9nk2o+5E7x9xK9rsvb4eiDd2\n\t IRfa1kW35XXhA==",
        "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 44/50] mips: octeon: Add octeon_qlm.c",
        "Date": "Fri, 11 Dec 2020 17:06:06 +0100",
        "Message-Id": "<20201211160612.1498780-45-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": "0.73 / 15.00 / 15.00",
        "X-Rspamd-Queue-Id": "AF8101855",
        "X-Rspamd-UID": "a50772",
        "X-Mailman-Approved-At": "Fri, 11 Dec 2020 17:38:11 +0100",
        "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 octeon_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/octeon_qlm.c | 5853 ++++++++++++++++++++++++++++\n 1 file changed, 5853 insertions(+)\n create mode 100644 arch/mips/mach-octeon/octeon_qlm.c",
    "diff": "diff --git a/arch/mips/mach-octeon/octeon_qlm.c b/arch/mips/mach-octeon/octeon_qlm.c\nnew file mode 100644\nindex 0000000000..763692781d\n--- /dev/null\n+++ b/arch/mips/mach-octeon/octeon_qlm.c\n@@ -0,0 +1,5853 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2020 Marvell International Ltd.\n+ */\n+\n+#include <dm.h>\n+#include <time.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/cvmx-qlm.h>\n+#include <mach/octeon_qlm.h>\n+#include <mach/cvmx-pcie.h>\n+\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+DECLARE_GLOBAL_DATA_PTR;\n+\n+/** 2.5GHz with 100MHz reference clock */\n+#define R_2_5G_REFCLK100 0x0\n+/** 5.0GHz with 100MHz reference clock */\n+#define R_5G_REFCLK100 0x1\n+/** 8.0GHz with 100MHz reference clock */\n+#define R_8G_REFCLK100 0x2\n+/** 1.25GHz with 156.25MHz reference clock */\n+#define R_125G_REFCLK15625_KX 0x3\n+/** 3.125Ghz with 156.25MHz reference clock (XAUI) */\n+#define R_3125G_REFCLK15625_XAUI 0x4\n+/** 10.3125GHz with 156.25MHz reference clock (XFI/XLAUI) */\n+#define R_103125G_REFCLK15625_KR 0x5\n+/** 1.25GHz with 156.25MHz reference clock (SGMII) */\n+#define R_125G_REFCLK15625_SGMII 0x6\n+/** 5GHz with 156.25MHz reference clock (QSGMII) */\n+#define R_5G_REFCLK15625_QSGMII 0x7\n+/** 6.25GHz with 156.25MHz reference clock (RXAUI/25G) */\n+#define R_625G_REFCLK15625_RXAUI 0x8\n+/** 2.5GHz with 125MHz reference clock */\n+#define R_2_5G_REFCLK125 0x9\n+/** 5GHz with 125MHz reference clock */\n+#define R_5G_REFCLK125 0xa\n+/** 8GHz with 125MHz reference clock */\n+#define R_8G_REFCLK125 0xb\n+/** Must be last, number of modes */\n+#define R_NUM_LANE_MODES 0xc\n+\n+int cvmx_qlm_is_ref_clock(int qlm, int reference_mhz)\n+{\n+\tint ref_clock = cvmx_qlm_measure_clock(qlm);\n+\tint mhz = ref_clock / 1000000;\n+\tint range = reference_mhz / 10;\n+\n+\treturn ((mhz >= reference_mhz - range) && (mhz <= reference_mhz + range));\n+}\n+\n+static int __get_qlm_spd(int qlm, int speed)\n+{\n+\tint qlm_spd = 0xf;\n+\n+\tif (cvmx_qlm_is_ref_clock(qlm, 100)) {\n+\t\tif (speed == 1250)\n+\t\t\tqlm_spd = 0x3;\n+\t\telse if (speed == 2500)\n+\t\t\tqlm_spd = 0x2;\n+\t\telse if (speed == 5000)\n+\t\t\tqlm_spd = 0x0;\n+\t\telse\n+\t\t\tqlm_spd = 0xf;\n+\t} else if (cvmx_qlm_is_ref_clock(qlm, 125)) {\n+\t\tif (speed == 1250)\n+\t\t\tqlm_spd = 0xa;\n+\t\telse if (speed == 2500)\n+\t\t\tqlm_spd = 0x9;\n+\t\telse if (speed == 3125)\n+\t\t\tqlm_spd = 0x8;\n+\t\telse if (speed == 5000)\n+\t\t\tqlm_spd = 0x6;\n+\t\telse if (speed == 6250)\n+\t\t\tqlm_spd = 0x5;\n+\t\telse\n+\t\t\tqlm_spd = 0xf;\n+\t} else if (cvmx_qlm_is_ref_clock(qlm, 156)) {\n+\t\tif (speed == 1250)\n+\t\t\tqlm_spd = 0x4;\n+\t\telse if (speed == 2500)\n+\t\t\tqlm_spd = 0x7;\n+\t\telse if (speed == 3125)\n+\t\t\tqlm_spd = 0xe;\n+\t\telse if (speed == 3750)\n+\t\t\tqlm_spd = 0xd;\n+\t\telse if (speed == 5000)\n+\t\t\tqlm_spd = 0xb;\n+\t\telse if (speed == 6250)\n+\t\t\tqlm_spd = 0xc;\n+\t\telse\n+\t\t\tqlm_spd = 0xf;\n+\t} else if (cvmx_qlm_is_ref_clock(qlm, 161)) {\n+\t\tif (speed == 6316)\n+\t\t\tqlm_spd = 0xc;\n+\t}\n+\treturn qlm_spd;\n+}\n+\n+static void __set_qlm_pcie_mode_61xx(int pcie_port, int root_complex)\n+{\n+\tint rc = root_complex ? 1 : 0;\n+\tint ep = root_complex ? 0 : 1;\n+\tcvmx_ciu_soft_prst1_t soft_prst1;\n+\tcvmx_ciu_soft_prst_t soft_prst;\n+\tcvmx_mio_rst_ctlx_t rst_ctl;\n+\n+\tif (pcie_port) {\n+\t\tsoft_prst1.u64 = csr_rd(CVMX_CIU_SOFT_PRST1);\n+\t\tsoft_prst1.s.soft_prst = 1;\n+\t\tcsr_wr(CVMX_CIU_SOFT_PRST1, soft_prst1.u64);\n+\t} else {\n+\t\tsoft_prst.u64 = csr_rd(CVMX_CIU_SOFT_PRST);\n+\t\tsoft_prst.s.soft_prst = 1;\n+\t\tcsr_wr(CVMX_CIU_SOFT_PRST, soft_prst.u64);\n+\t}\n+\n+\trst_ctl.u64 = csr_rd(CVMX_MIO_RST_CTLX(pcie_port));\n+\n+\trst_ctl.s.prst_link = rc;\n+\trst_ctl.s.rst_link = ep;\n+\trst_ctl.s.prtmode = rc;\n+\trst_ctl.s.rst_drv = rc;\n+\trst_ctl.s.rst_rcv = 0;\n+\trst_ctl.s.rst_chip = ep;\n+\tcsr_wr(CVMX_MIO_RST_CTLX(pcie_port), rst_ctl.u64);\n+\n+\tif (root_complex == 0) {\n+\t\tif (pcie_port) {\n+\t\t\tsoft_prst1.u64 = csr_rd(CVMX_CIU_SOFT_PRST1);\n+\t\t\tsoft_prst1.s.soft_prst = 0;\n+\t\t\tcsr_wr(CVMX_CIU_SOFT_PRST1, soft_prst1.u64);\n+\t\t} else {\n+\t\t\tsoft_prst.u64 = csr_rd(CVMX_CIU_SOFT_PRST);\n+\t\t\tsoft_prst.s.soft_prst = 0;\n+\t\t\tcsr_wr(CVMX_CIU_SOFT_PRST, soft_prst.u64);\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * Configure qlm speed and mode. MIO_QLMX_CFG[speed,mode] are not set\n+ * for CN61XX.\n+ *\n+ * @param qlm     The QLM to configure\n+ * @param speed   The speed the QLM needs to be configured in Mhz.\n+ * @param mode    The QLM to be configured as SGMII/XAUI/PCIe.\n+ *                  QLM 0: 0 = PCIe0 1X4, 1 = Reserved, 2 = SGMII1, 3 = XAUI1\n+ *                  QLM 1: 0 = PCIe1 1x2, 1 = PCIe(0/1) 2x1, 2 - 3 = Reserved\n+ *                  QLM 2: 0 - 1 = Reserved, 2 = SGMII0, 3 = XAUI0\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP\n+ *\t\t  mode.\n+ * @param pcie2x1 Only used when QLM1 is in PCIE2x1 mode.  The QLM_SPD has a\n+ *\t\t  different value on how PEMx needs to be configured:\n+ *                   0x0 - both PEM0 & PEM1 are in gen1 mode.\n+ *                   0x1 - PEM0 in gen2 and PEM1 in gen1 mode.\n+ *                   0x2 - PEM0 in gen1 and PEM1 in gen2 mode.\n+ *                   0x3 - both PEM0 & PEM1 are in gen2 mode.\n+ *               SPEED value is ignored in this mode. QLM_SPD is set based on\n+ *               pcie2x1 value in this mode.\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+static int octeon_configure_qlm_cn61xx(int qlm, int speed, int mode, int rc, int pcie2x1)\n+{\n+\tcvmx_mio_qlmx_cfg_t qlm_cfg;\n+\n+\t/* The QLM speed varies for SGMII/XAUI and PCIe mode. And depends on\n+\t * reference clock.\n+\t */\n+\tif (!OCTEON_IS_MODEL(OCTEON_CN61XX))\n+\t\treturn -1;\n+\n+\tif (qlm < 3) {\n+\t\tqlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));\n+\t} else {\n+\t\tdebug(\"WARNING: Invalid QLM(%d) passed\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\tswitch (qlm) {\n+\t\t/* SGMII/XAUI mode */\n+\tcase 2: {\n+\t\tif (mode < 2) {\n+\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\tbreak;\n+\t\t}\n+\t\tqlm_cfg.s.qlm_spd = __get_qlm_spd(qlm, speed);\n+\t\tqlm_cfg.s.qlm_cfg = mode;\n+\t\tbreak;\n+\t}\n+\tcase 1: {\n+\t\tif (mode == 1) { /* 2x1 mode */\n+\t\t\tcvmx_mio_qlmx_cfg_t qlm0;\n+\n+\t\t\t/* When QLM0 is configured as PCIe(QLM_CFG=0x0)\n+\t\t\t * and enabled (QLM_SPD != 0xf), QLM1 cannot be\n+\t\t\t * configured as PCIe 2x1 mode (QLM_CFG=0x1)\n+\t\t\t * and enabled (QLM_SPD != 0xf).\n+\t\t\t */\n+\t\t\tqlm0.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));\n+\t\t\tif (qlm0.s.qlm_spd != 0xf && qlm0.s.qlm_cfg == 0) {\n+\t\t\t\tdebug(\"Invalid mode(%d) for QLM(%d) as QLM1 is PCIe mode\\n\",\n+\t\t\t\t      mode, qlm);\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\t/* Set QLM_SPD based on reference clock and mode */\n+\t\t\tif (cvmx_qlm_is_ref_clock(qlm, 100)) {\n+\t\t\t\tif (pcie2x1 == 0x3)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x0;\n+\t\t\t\telse if (pcie2x1 == 0x1)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x2;\n+\t\t\t\telse if (pcie2x1 == 0x2)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x1;\n+\t\t\t\telse if (pcie2x1 == 0x0)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x3;\n+\t\t\t\telse\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\t} else if (cvmx_qlm_is_ref_clock(qlm, 125)) {\n+\t\t\t\tif (pcie2x1 == 0x3)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x4;\n+\t\t\t\telse if (pcie2x1 == 0x1)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x6;\n+\t\t\t\telse if (pcie2x1 == 0x2)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x9;\n+\t\t\t\telse if (pcie2x1 == 0x0)\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0x7;\n+\t\t\t\telse\n+\t\t\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\t}\n+\t\t\tqlm_cfg.s.qlm_cfg = mode;\n+\t\t\tcsr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);\n+\n+\t\t\t/* Set PCIe mode bits */\n+\t\t\t__set_qlm_pcie_mode_61xx(0, rc);\n+\t\t\t__set_qlm_pcie_mode_61xx(1, rc);\n+\t\t\treturn 0;\n+\t\t} else if (mode > 1) {\n+\t\t\tdebug(\"Invalid mode(%d) for QLM(%d).\\n\", mode, qlm);\n+\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* Set speed and mode for PCIe 1x2 mode. */\n+\t\tif (cvmx_qlm_is_ref_clock(qlm, 100)) {\n+\t\t\tif (speed == 5000)\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0x1;\n+\t\t\telse if (speed == 2500)\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0x2;\n+\t\t\telse\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t} else if (cvmx_qlm_is_ref_clock(qlm, 125)) {\n+\t\t\tif (speed == 5000)\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0x4;\n+\t\t\telse if (speed == 2500)\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0x6;\n+\t\t\telse\n+\t\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t} else {\n+\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t}\n+\n+\t\tqlm_cfg.s.qlm_cfg = mode;\n+\t\tcsr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);\n+\n+\t\t/* Set PCIe mode bits */\n+\t\t__set_qlm_pcie_mode_61xx(1, rc);\n+\t\treturn 0;\n+\t}\n+\tcase 0: {\n+\t\t/* QLM_CFG = 0x1 - Reserved */\n+\t\tif (mode == 1) {\n+\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* QLM_CFG = 0x0 - PCIe 1x4(PEM0) */\n+\t\tif (mode == 0 && speed != 5000 && speed != 2500) {\n+\t\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* Set speed and mode */\n+\t\tqlm_cfg.s.qlm_spd = __get_qlm_spd(qlm, speed);\n+\t\tqlm_cfg.s.qlm_cfg = mode;\n+\t\tcsr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);\n+\n+\t\t/* Set PCIe mode bits */\n+\t\tif (mode == 0)\n+\t\t\t__set_qlm_pcie_mode_61xx(0, rc);\n+\n+\t\treturn 0;\n+\t}\n+\tdefault:\n+\t\tdebug(\"WARNING: Invalid QLM(%d) passed\\n\", qlm);\n+\t\tqlm_cfg.s.qlm_spd = 0xf;\n+\t}\n+\tcsr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);\n+\treturn 0;\n+}\n+\n+/* qlm      : DLM to configure\n+ * baud_mhz : speed of the DLM\n+ * ref_clk_sel  :  reference clock speed selection where:\n+ *\t\t\t0:\t100MHz\n+ *\t\t\t1:\t125MHz\n+ *\t\t\t2:\t156.25MHz\n+ *\n+ * ref_clk_input:  reference clock input where:\n+ *\t\t\t0:\tDLMC_REF_CLK0_[P,N]\n+ *\t\t\t1:\tDLMC_REF_CLK1_[P,N]\n+ *\t\t\t2:\tDLM0_REF_CLK_[P,N] (only valid for QLM 0)\n+ * is_sff7000_rxaui : boolean to indicate whether qlm is RXAUI on SFF7000\n+ */\n+static int __dlm_setup_pll_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input,\n+\t\t\t\t  int is_sff7000_rxaui)\n+{\n+\tcvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;\n+\tcvmx_gserx_dlmx_ref_ssp_en_t dlmx_ref_ssp_en;\n+\tcvmx_gserx_dlmx_mpll_en_t dlmx_mpll_en;\n+\tcvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;\n+\tcvmx_gserx_dlmx_tx_amplitude_t tx_amplitude;\n+\tcvmx_gserx_dlmx_tx_preemph_t tx_preemph;\n+\tcvmx_gserx_dlmx_rx_eq_t rx_eq;\n+\tcvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;\n+\tcvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;\n+\tint gmx_ref_clk = 100;\n+\n+\tdebug(\"%s(%d, %d, %d, %d, %d)\\n\", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input,\n+\t      is_sff7000_rxaui);\n+\tif (ref_clk_sel == 1)\n+\t\tgmx_ref_clk = 125;\n+\telse if (ref_clk_sel == 2)\n+\t\tgmx_ref_clk = 156;\n+\n+\tif (qlm != 0 && ref_clk_input == 2) {\n+\t\tprintf(\"%s: Error: can only use reference clock inputs 0 or 1 for DLM %d\\n\",\n+\t\t       __func__, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Hardware defaults are invalid */\n+\ttx_amplitude.u64 = csr_rd(CVMX_GSERX_DLMX_TX_AMPLITUDE(qlm, 0));\n+\tif (is_sff7000_rxaui) {\n+\t\ttx_amplitude.s.tx0_amplitude = 100;\n+\t\ttx_amplitude.s.tx1_amplitude = 100;\n+\t} else {\n+\t\ttx_amplitude.s.tx0_amplitude = 65;\n+\t\ttx_amplitude.s.tx1_amplitude = 65;\n+\t}\n+\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_AMPLITUDE(qlm, 0), tx_amplitude.u64);\n+\n+\ttx_preemph.u64 = csr_rd(CVMX_GSERX_DLMX_TX_PREEMPH(qlm, 0));\n+\n+\tif (is_sff7000_rxaui) {\n+\t\ttx_preemph.s.tx0_preemph = 0;\n+\t\ttx_preemph.s.tx1_preemph = 0;\n+\t} else {\n+\t\ttx_preemph.s.tx0_preemph = 22;\n+\t\ttx_preemph.s.tx1_preemph = 22;\n+\t}\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_PREEMPH(qlm, 0), tx_preemph.u64);\n+\n+\trx_eq.u64 = csr_rd(CVMX_GSERX_DLMX_RX_EQ(qlm, 0));\n+\trx_eq.s.rx0_eq = 0;\n+\trx_eq.s.rx1_eq = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_RX_EQ(qlm, 0), rx_eq.u64);\n+\n+\t/* 1. Write GSER0_DLM0_REF_USE_PAD[REF_USE_PAD] = 1 (to select\n+\t *    reference-clock input)\n+\t *    The documentation for this register in the HRM is useless since\n+\t *    it says it selects between two different clocks that are not\n+\t *    documented anywhere.  What it really does is select between\n+\t *    DLM0_REF_CLK_[P,N] if 1 and DLMC_REF_CLK[0,1]_[P,N] if 0.\n+\t *\n+\t *    This register must be 0 for DLMs 1 and 2 and can only be 1 for\n+\t *    DLM 0.\n+\t */\n+\tcsr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(0, 0), ((ref_clk_input == 2) && (qlm == 0)) ? 1 : 0);\n+\n+\t/* Reference clock was already chosen before we got here */\n+\n+\t/* 2. Write GSER0_DLM0_REFCLK_SEL[REFCLK_SEL] if required for\n+\t *    reference-clock selection.\n+\t *\n+\t *    If GSERX_DLMX_REF_USE_PAD is 1 then this register is ignored.\n+\t */\n+\tcsr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(0, 0), ref_clk_input & 1);\n+\n+\t/* Reference clock was already chosen before we got here */\n+\n+\t/* 3. If required, write GSER0_DLM0_REF_CLKDIV2[REF_CLKDIV2] (must be\n+\t *    set if reference clock > 100 MHz)\n+\t */\n+\t/* Apply workaround for Errata (G-20669) MPLL may not come up. */\n+\tref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));\n+\tif (gmx_ref_clk == 100)\n+\t\tref_clkdiv2.s.ref_clkdiv2 = 0;\n+\telse\n+\t\tref_clkdiv2.s.ref_clkdiv2 = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);\n+\n+\t/* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\n+\t/* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set\n+\t *    GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.\n+\t */\n+\t/* 7. Set GSER0_DLM0_MPLL_EN[MPLL_EN] = 1 */\n+\tdlmx_mpll_en.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_EN(0, 0));\n+\tdlmx_mpll_en.s.mpll_en = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_MPLL_EN(0, 0), dlmx_mpll_en.u64);\n+\n+\t/* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]\n+\t *    to the value in the preceding table, which is different\n+\t *    than the desired setting prescribed by the HRM.\n+\t */\n+\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\tif (gmx_ref_clk == 100)\n+\t\tmpll_multiplier.s.mpll_multiplier = 35;\n+\telse if (gmx_ref_clk == 125)\n+\t\tmpll_multiplier.s.mpll_multiplier = 56;\n+\telse\n+\t\tmpll_multiplier.s.mpll_multiplier = 45;\n+\tdebug(\"%s: Setting mpll multiplier to %u for DLM%d, baud %d, clock rate %uMHz\\n\",\n+\t      __func__, mpll_multiplier.s.mpll_multiplier, qlm, baud_mhz, gmx_ref_clk);\n+\n+\tcsr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);\n+\n+\t/* 5. Clear GSER0_DLM0_TEST_POWERDOWN[TEST_POWERDOWN] */\n+\tdlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));\n+\tdlmx_test_powerdown.s.test_powerdown = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);\n+\n+\t/* 6. Set GSER0_DLM0_REF_SSP_EN[REF_SSP_EN] = 1 */\n+\tdlmx_ref_ssp_en.u64 = csr_rd(CVMX_GSERX_DLMX_REF_SSP_EN(qlm, 0));\n+\tdlmx_ref_ssp_en.s.ref_ssp_en = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_REF_SSP_EN(0, 0), dlmx_ref_ssp_en.u64);\n+\n+\t/* 8. Clear GSER0_DLM0_PHY_RESET[PHY_RESET] = 0 */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\n+\t/* 5. If PCIe or SATA (i.e. if DLM1 or DLM2), set both MPLL_EN\n+\t * and MPLL_EN_OVRD to one in GSER(0)_PHY(1..2)_OVRD_IN_LO.\n+\t */\n+\n+\t/* 6. Decrease MPLL_MULTIPLIER by one continually until it\n+\t * reaches the desired long-term setting, ensuring that each\n+\t * MPLL_MULTIPLIER value is constant for at least 1 msec before\n+\t * changing to the next value.  The desired long-term setting is\n+\t * as indicated in HRM tables 21-1, 21-2, and 21-3.  This is not\n+\t * required with the HRM sequence.\n+\t */\n+\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\t__cvmx_qlm_set_mult(qlm, baud_mhz, mpll_multiplier.s.mpll_multiplier);\n+\n+\t/* 9. Poll until the MPLL locks. Wait for\n+\t *    GSER0_DLM0_MPLL_STATUS[MPLL_STATUS] = 1\n+\t */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_MPLL_STATUS(qlm, 0),\n+\t\t\t\t  cvmx_gserx_dlmx_mpll_status_t, mpll_status, ==, 1, 10000)) {\n+\t\tprintf(\"PLL for DLM%d failed to lock\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int __dlm0_setup_tx_cn70xx(int speed, int ref_clk_sel)\n+{\n+\tint need0, need1;\n+\tcvmx_gmxx_inf_mode_t mode0, mode1;\n+\tcvmx_gserx_dlmx_tx_rate_t rate;\n+\tcvmx_gserx_dlmx_tx_en_t en;\n+\tcvmx_gserx_dlmx_tx_cm_en_t cm_en;\n+\tcvmx_gserx_dlmx_tx_data_en_t data_en;\n+\tcvmx_gserx_dlmx_tx_reset_t tx_reset;\n+\n+\tdebug(\"%s(%d, %d)\\n\", __func__, speed, ref_clk_sel);\n+\tmode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\tmode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));\n+\n+\t/* Which lanes do we need? */\n+\tneed0 = (mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED);\n+\tneed1 = (mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED) ||\n+\t\t(mode0.s.mode == CVMX_GMX_INF_MODE_RXAUI);\n+\n+\t/* 1. Write GSER0_DLM0_TX_RATE[TXn_RATE] (Set according to required\n+\t *    data rate (see Table 21-1).\n+\t */\n+\trate.u64 = csr_rd(CVMX_GSERX_DLMX_TX_RATE(0, 0));\n+\tdebug(\"%s: speed: %d\\n\", __func__, speed);\n+\tswitch (speed) {\n+\tcase 1250:\n+\tcase 2500:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.tx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;\n+\t\t\trate.s.tx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 3125:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.tx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;\n+\t\t\trate.s.tx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 5000: /* QSGMII only */\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */\n+\t\t\trate.s.tx0_rate = 0;\n+\t\t\trate.s.tx1_rate = 0;\n+\t\t\tbreak;\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.tx0_rate = 0;\n+\t\t\trate.s.tx1_rate = 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 6250:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.tx0_rate = 0;\n+\t\t\trate.s.tx1_rate = 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"%s: Invalid rate %d\\n\", __func__, speed);\n+\t\treturn -1;\n+\t}\n+\tdebug(\"%s: tx 0 rate: %d, tx 1 rate: %d\\n\", __func__, rate.s.tx0_rate, rate.s.tx1_rate);\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_RATE(0, 0), rate.u64);\n+\n+\t/* 2. Set GSER0_DLM0_TX_EN[TXn_EN] = 1 */\n+\ten.u64 = csr_rd(CVMX_GSERX_DLMX_TX_EN(0, 0));\n+\ten.s.tx0_en = need0;\n+\ten.s.tx1_en = need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_EN(0, 0), en.u64);\n+\n+\t/* 3 set GSER0_DLM0_TX_CM_EN[TXn_CM_EN] = 1 */\n+\tcm_en.u64 = csr_rd(CVMX_GSERX_DLMX_TX_CM_EN(0, 0));\n+\tcm_en.s.tx0_cm_en = need0;\n+\tcm_en.s.tx1_cm_en = need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_CM_EN(0, 0), cm_en.u64);\n+\n+\t/* 4. Set GSER0_DLM0_TX_DATA_EN[TXn_DATA_EN] = 1 */\n+\tdata_en.u64 = csr_rd(CVMX_GSERX_DLMX_TX_DATA_EN(0, 0));\n+\tdata_en.s.tx0_data_en = need0;\n+\tdata_en.s.tx1_data_en = need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_DATA_EN(0, 0), data_en.u64);\n+\n+\t/* 5. Clear GSER0_DLM0_TX_RESET[TXn_DATA_EN] = 0 */\n+\ttx_reset.u64 = csr_rd(CVMX_GSERX_DLMX_TX_RESET(0, 0));\n+\ttx_reset.s.tx0_reset = !need0;\n+\ttx_reset.s.tx1_reset = !need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_TX_RESET(0, 0), tx_reset.u64);\n+\n+\t/* 6. Poll GSER0_DLM0_TX_STATUS[TXn_STATUS, TXn_CM_STATUS] until both\n+\t *    are set to 1. This prevents GMX from transmitting until the DLM\n+\t *    is ready.\n+\t */\n+\tif (need0) {\n+\t\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),\n+\t\t\t\t\t  cvmx_gserx_dlmx_tx_status_t, tx0_status, ==, 1, 10000)) {\n+\t\t\tprintf(\"DLM0 TX0 status fail\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),\n+\t\t\t\t\t  cvmx_gserx_dlmx_tx_status_t, tx0_cm_status, ==, 1,\n+\t\t\t\t\t  10000)) {\n+\t\t\tprintf(\"DLM0 TX0 CM status fail\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\tif (need1) {\n+\t\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),\n+\t\t\t\t\t  cvmx_gserx_dlmx_tx_status_t, tx1_status, ==, 1, 10000)) {\n+\t\t\tprintf(\"DLM0 TX1 status fail\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),\n+\t\t\t\t\t  cvmx_gserx_dlmx_tx_status_t, tx1_cm_status, ==, 1,\n+\t\t\t\t\t  10000)) {\n+\t\t\tprintf(\"DLM0 TX1 CM status fail\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int __dlm0_setup_rx_cn70xx(int speed, int ref_clk_sel)\n+{\n+\tint need0, need1;\n+\tcvmx_gmxx_inf_mode_t mode0, mode1;\n+\tcvmx_gserx_dlmx_rx_rate_t rate;\n+\tcvmx_gserx_dlmx_rx_pll_en_t pll_en;\n+\tcvmx_gserx_dlmx_rx_data_en_t data_en;\n+\tcvmx_gserx_dlmx_rx_reset_t rx_reset;\n+\n+\tdebug(\"%s(%d, %d)\\n\", __func__, speed, ref_clk_sel);\n+\tmode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\tmode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));\n+\n+\t/* Which lanes do we need? */\n+\tneed0 = (mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED);\n+\tneed1 = (mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED) ||\n+\t\t(mode0.s.mode == CVMX_GMX_INF_MODE_RXAUI);\n+\n+\t/* 1. Write GSER0_DLM0_RX_RATE[RXn_RATE] (must match the\n+\t * GER0_DLM0_TX_RATE[TXn_RATE] setting).\n+\t */\n+\trate.u64 = csr_rd(CVMX_GSERX_DLMX_RX_RATE(0, 0));\n+\tswitch (speed) {\n+\tcase 1250:\n+\tcase 2500:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.rx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;\n+\t\t\trate.s.rx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 3125:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.rx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;\n+\t\t\trate.s.rx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 5000: /* QSGMII only */\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.rx0_rate = 0;\n+\t\t\trate.s.rx1_rate = 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 6250:\n+\t\tswitch (ref_clk_sel) {\n+\t\tcase OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */\n+\t\tcase OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */\n+\t\t\trate.s.rx0_rate = 0;\n+\t\t\trate.s.rx1_rate = 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprintf(\"Invalid reference clock select %d\\n\", ref_clk_sel);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"%s: Invalid rate %d\\n\", __func__, speed);\n+\t\treturn -1;\n+\t}\n+\tdebug(\"%s: rx 0 rate: %d, rx 1 rate: %d\\n\", __func__, rate.s.rx0_rate, rate.s.rx1_rate);\n+\tcsr_wr(CVMX_GSERX_DLMX_RX_RATE(0, 0), rate.u64);\n+\n+\t/* 2. Set GSER0_DLM0_RX_PLL_EN[RXn_PLL_EN] = 1 */\n+\tpll_en.u64 = csr_rd(CVMX_GSERX_DLMX_RX_PLL_EN(0, 0));\n+\tpll_en.s.rx0_pll_en = need0;\n+\tpll_en.s.rx1_pll_en = need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_RX_PLL_EN(0, 0), pll_en.u64);\n+\n+\t/* 3. Set GSER0_DLM0_RX_DATA_EN[RXn_DATA_EN] = 1 */\n+\tdata_en.u64 = csr_rd(CVMX_GSERX_DLMX_RX_DATA_EN(0, 0));\n+\tdata_en.s.rx0_data_en = need0;\n+\tdata_en.s.rx1_data_en = need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_RX_DATA_EN(0, 0), data_en.u64);\n+\n+\t/* 4. Clear GSER0_DLM0_RX_RESET[RXn_DATA_EN] = 0. Now the GMX can be\n+\t * enabled: set GMX(0..1)_INF_MODE[EN] = 1\n+\t */\n+\trx_reset.u64 = csr_rd(CVMX_GSERX_DLMX_RX_RESET(0, 0));\n+\trx_reset.s.rx0_reset = !need0;\n+\trx_reset.s.rx1_reset = !need1;\n+\tcsr_wr(CVMX_GSERX_DLMX_RX_RESET(0, 0), rx_reset.u64);\n+\n+\treturn 0;\n+}\n+\n+static int a_clk;\n+\n+static int __dlm2_sata_uctl_init_cn70xx(void)\n+{\n+\tcvmx_sata_uctl_ctl_t uctl_ctl;\n+\tconst int MAX_A_CLK = 333000000; /* Max of 333Mhz */\n+\tint divisor, a_clkdiv;\n+\n+\t/* Wait for all voltages to reach a stable stable. Ensure the\n+\t * reference clock is up and stable.\n+\t */\n+\n+\t/* 2. Wait for IOI reset to deassert. */\n+\n+\t/* 3. Optionally program the GPIO CSRs for SATA features.\n+\t *    a. For cold-presence detect:\n+\t *\t i. Select a GPIO for the input and program GPIO_SATA_CTL[sel]\n+\t *\t    for port0 and port1.\n+\t *\t ii. Select a GPIO for the output and program\n+\t *\t     GPIO_BIT_CFG*[OUTPUT_SEL] for port0 and port1.\n+\t *    b. For mechanical-presence detect, select a GPIO for the input\n+\t *\t and program GPIO_SATA_CTL[SEL] for port0/port1.\n+\t *    c. For LED activity, select a GPIO for the output and program\n+\t *\t GPIO_BIT_CFG*[OUTPUT_SEL] for port0/port1.\n+\t */\n+\n+\t/* 4. Assert all resets:\n+\t *    a. UAHC reset: SATA_UCTL_CTL[UAHC_RST] = 1\n+\t *    a. UCTL reset: SATA_UCTL_CTL[UCTL_RST] = 1\n+\t */\n+\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.sata_uahc_rst = 1;\n+\tuctl_ctl.s.sata_uctl_rst = 1;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\t/* 5. Configure the ACLK:\n+\t *    a. Reset the clock dividers: SATA_UCTL_CTL[A_CLKDIV_RST] = 1.\n+\t *    b. Select the ACLK frequency (400 MHz maximum)\n+\t *\t i. SATA_UCTL_CTL[A_CLKDIV] = desired value,\n+\t *\t ii. SATA_UCTL_CTL[A_CLKDIV_EN] = 1 to enable the ACLK,\n+\t *    c. Deassert the ACLK clock divider reset:\n+\t *\t SATA_UCTL_CTL[A_CLKDIV_RST] = 0\n+\t */\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.a_clkdiv_rst = 1;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\n+\tdivisor = (gd->bus_clk + MAX_A_CLK - 1) / MAX_A_CLK;\n+\tif (divisor <= 4) {\n+\t\ta_clkdiv = divisor - 1;\n+\t} else if (divisor <= 6) {\n+\t\ta_clkdiv = 4;\n+\t\tdivisor = 6;\n+\t} else if (divisor <= 8) {\n+\t\ta_clkdiv = 5;\n+\t\tdivisor = 8;\n+\t} else if (divisor <= 16) {\n+\t\ta_clkdiv = 6;\n+\t\tdivisor = 16;\n+\t} else if (divisor <= 24) {\n+\t\ta_clkdiv = 7;\n+\t\tdivisor = 24;\n+\t} else {\n+\t\tprintf(\"Unable to determine SATA clock divisor\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* Calculate the final clock rate */\n+\ta_clk = gd->bus_clk / divisor;\n+\n+\tuctl_ctl.s.a_clkdiv_sel = a_clkdiv;\n+\tuctl_ctl.s.a_clk_en = 1;\n+\tuctl_ctl.s.a_clk_byp_sel = 0;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.a_clkdiv_rst = 0;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\tudelay(1);\n+\n+\treturn 0;\n+}\n+\n+static int __sata_dlm_init_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_gserx_sata_cfg_t sata_cfg;\n+\tcvmx_gserx_sata_lane_rst_t sata_lane_rst;\n+\tcvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;\n+\tcvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;\n+\tcvmx_gserx_sata_ref_ssp_en_t ref_ssp_en;\n+\tcvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;\n+\tcvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;\n+\tcvmx_sata_uctl_shim_cfg_t shim_cfg;\n+\tcvmx_gserx_phyx_ovrd_in_lo_t ovrd_in;\n+\tcvmx_sata_uctl_ctl_t uctl_ctl;\n+\tint sata_ref_clk;\n+\n+\tdebug(\"%s(%d, %d, %d, %d)\\n\", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\n+\tswitch (ref_clk_sel) {\n+\tcase 0:\n+\t\tsata_ref_clk = 100;\n+\t\tbreak;\n+\tcase 1:\n+\t\tsata_ref_clk = 125;\n+\t\tbreak;\n+\tcase 2:\n+\t\tsata_ref_clk = 156;\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"%s: Invalid reference clock select %d for qlm %d\\n\", __func__,\n+\t\t       ref_clk_sel, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* 5. Set GSERX0_SATA_CFG[SATA_EN] = 1 to configure DLM2 multiplexing.\n+\t */\n+\tsata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));\n+\tsata_cfg.s.sata_en = 1;\n+\tcsr_wr(CVMX_GSERX_SATA_CFG(0), sata_cfg.u64);\n+\n+\t/* 1. Write GSER(0)_DLM2_REFCLK_SEL[REFCLK_SEL] if required for\n+\t *    reference-clock selection.\n+\t */\n+\tif (ref_clk_input < 2) {\n+\t\tcsr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(qlm, 0), ref_clk_input);\n+\t\tcsr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(qlm, 0), 0);\n+\t} else {\n+\t\tcsr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(qlm, 0), 1);\n+\t}\n+\n+\tref_ssp_en.u64 = csr_rd(CVMX_GSERX_SATA_REF_SSP_EN(0));\n+\tref_ssp_en.s.ref_ssp_en = 1;\n+\tcsr_wr(CVMX_GSERX_SATA_REF_SSP_EN(0), ref_ssp_en.u64);\n+\n+\t/* Apply workaround for Errata (G-20669) MPLL may not come up. */\n+\n+\t/* Set REF_CLKDIV2 based on the Ref Clock */\n+\tref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));\n+\tif (sata_ref_clk == 100)\n+\t\tref_clkdiv2.s.ref_clkdiv2 = 0;\n+\telse\n+\t\tref_clkdiv2.s.ref_clkdiv2 = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);\n+\n+\t/* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\n+\t/* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set\n+\t *    GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.\n+\t */\n+\n+\t/* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]\n+\t *    to the value in the preceding table, which is different\n+\t *    than the desired setting prescribed by the HRM.\n+\t */\n+\n+\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\tif (sata_ref_clk == 100)\n+\t\tmpll_multiplier.s.mpll_multiplier = 35;\n+\telse\n+\t\tmpll_multiplier.s.mpll_multiplier = 56;\n+\tcsr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);\n+\n+\t/* 3. Clear GSER0_DLM2_TEST_POWERDOWN[TEST_POWERDOWN] = 0 */\n+\tdlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));\n+\tdlmx_test_powerdown.s.test_powerdown = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);\n+\n+\t/* 4. Clear either/both lane0 and lane1 resets:\n+\t *    GSER0_SATA_LANE_RST[L0_RST, L1_RST] = 0.\n+\t */\n+\tsata_lane_rst.u64 = csr_rd(CVMX_GSERX_SATA_LANE_RST(0));\n+\tsata_lane_rst.s.l0_rst = 0;\n+\tsata_lane_rst.s.l1_rst = 0;\n+\tcsr_wr(CVMX_GSERX_SATA_LANE_RST(0), sata_lane_rst.u64);\n+\n+\tudelay(1);\n+\n+\t/* 5. Clear GSER0_DLM2_PHY_RESET */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\n+\t/* 6. If PCIe or SATA (i.e. if DLM1 or DLM2), set both MPLL_EN\n+\t * and MPLL_EN_OVRD to one in GSER(0)_PHY(1..2)_OVRD_IN_LO.\n+\t */\n+\tovrd_in.u64 = csr_rd(CVMX_GSERX_PHYX_OVRD_IN_LO(qlm, 0));\n+\tovrd_in.s.mpll_en = 1;\n+\tovrd_in.s.mpll_en_ovrd = 1;\n+\tcsr_wr(CVMX_GSERX_PHYX_OVRD_IN_LO(qlm, 0), ovrd_in.u64);\n+\n+\t/* 7. 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+\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\tif (sata_ref_clk == 100)\n+\t\tmpll_multiplier.s.mpll_multiplier = 0x1e;\n+\telse\n+\t\tmpll_multiplier.s.mpll_multiplier = 0x30;\n+\tcsr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);\n+\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_MPLL_STATUS(qlm, 0),\n+\t\t\t\t  cvmx_gserx_dlmx_mpll_status_t, mpll_status, ==, 1, 10000)) {\n+\t\tprintf(\"ERROR: SATA MPLL failed to set\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_RX_STATUS(qlm, 0), cvmx_gserx_dlmx_rx_status_t,\n+\t\t\t\t  rx0_status, ==, 1, 10000)) {\n+\t\tprintf(\"ERROR: SATA RX0_STATUS failed to set\\n\");\n+\t\treturn -1;\n+\t}\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_RX_STATUS(qlm, 0), cvmx_gserx_dlmx_rx_status_t,\n+\t\t\t\t  rx1_status, ==, 1, 10000)) {\n+\t\tprintf(\"ERROR: SATA RX1_STATUS failed to set\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* 8. Deassert UCTL and UAHC resets:\n+\t *    a. SATA_UCTL_CTL[UCTL_RST] = 0\n+\t *    b. SATA_UCTL_CTL[UAHC_RST] = 0\n+\t *    c. Wait 10 ACLK cycles before accessing any ACLK-only registers.\n+\t */\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.sata_uctl_rst = 0;\n+\tuctl_ctl.s.sata_uahc_rst = 0;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\tudelay(1);\n+\n+\t/* 9. Enable conditional SCLK of UCTL by writing\n+\t *    SATA_UCTL_CTL[CSCLK_EN] = 1\n+\t */\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.csclk_en = 1;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\t/* 10. Initialize UAHC as described in the AHCI Specification (UAHC_*\n+\t *     registers\n+\t */\n+\n+\t/* set-up endian mode */\n+\tshim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);\n+\tshim_cfg.s.dma_endian_mode = 1;\n+\tshim_cfg.s.csr_endian_mode = 3;\n+\tcsr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Initializes DLM 4 for SATA\n+ *\n+ * @param qlm\t\tMust be 4.\n+ * @param baud_mhz\tBaud rate for SATA\n+ * @param ref_clk_sel\tSelects the speed of the reference clock where:\n+ *\t\t\t0 = 100MHz, 1 = 125MHz and 2 = 156.25MHz\n+ * @param ref_clk_input\tReference clock input where 0 = external QLM clock,\n+ *\t\t\t1 = qlmc_ref_clk0 and 2 = qlmc_ref_clk1\n+ */\n+static int __sata_dlm_init_cn73xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_sata_uctl_shim_cfg_t shim_cfg;\n+\tcvmx_gserx_refclk_sel_t refclk_sel;\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_rx_pwr_ctrl_p2_t pwr_ctrl_p2;\n+\tcvmx_gserx_lanex_misc_cfg_0_t misc_cfg_0;\n+\tcvmx_gserx_sata_lane_rst_t lane_rst;\n+\tcvmx_gserx_pll_px_mode_0_t pmode_0;\n+\tcvmx_gserx_pll_px_mode_1_t pmode_1;\n+\tcvmx_gserx_lane_px_mode_0_t lane_pmode_0;\n+\tcvmx_gserx_lane_px_mode_1_t lane_pmode_1;\n+\tcvmx_gserx_cfg_t gserx_cfg;\n+\tcvmx_sata_uctl_ctl_t uctl_ctl;\n+\tint l;\n+\tint i;\n+\n+\t/*\n+\t * 1. Configure the SATA\n+\t */\n+\n+\t/*\n+\t * 2. Configure the QLM Reference clock\n+\t *    Set GSERX_REFCLK_SEL.COM_CLK_SEL to source reference clock\n+\t *    from the external clock mux.\n+\t *      GSERX_REFCLK_SEL.USE_COM1 to select qlmc_refclkn/p_1 or\n+\t *      leave clear to select qlmc_refclkn/p_0\n+\t */\n+\trefclk_sel.u64 = 0;\n+\tif (ref_clk_input == 0) { /* External ref clock */\n+\t\trefclk_sel.s.com_clk_sel = 0;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else if (ref_clk_input == 1) { /* Common reference clock 0 */\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else { /* Common reference clock 1 */\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 1;\n+\t}\n+\n+\tif (ref_clk_sel != 0) {\n+\t\tprintf(\"Wrong reference clock selected for QLM4\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\n+\t/* Reset the QLM after changing the reference clock */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\tudelay(1);\n+\n+\t/*\n+\t * 3. Configure the QLM for SATA mode set GSERX_CFG.SATA\n+\t */\n+\tgserx_cfg.u64 = 0;\n+\tgserx_cfg.s.sata = 1;\n+\tcsr_wr(CVMX_GSERX_CFG(qlm), gserx_cfg.u64);\n+\n+\t/*\n+\t * 12. Clear the appropriate lane resets\n+\t *     clear GSERX_SATA_LANE_RST.LX_RST  where X is the lane number 0-1.\n+\t */\n+\tlane_rst.u64 = csr_rd(CVMX_GSERX_SATA_LANE_RST(qlm));\n+\tlane_rst.s.l0_rst = 0;\n+\tlane_rst.s.l1_rst = 0;\n+\tcsr_wr(CVMX_GSERX_SATA_LANE_RST(qlm), lane_rst.u64);\n+\tcsr_rd(CVMX_GSERX_SATA_LANE_RST(qlm));\n+\n+\tudelay(1);\n+\n+\t/*\n+\t * 4. Take the PHY out of reset\n+\t *    Write GSERX_PHY_CTL.PHY_RESET to a zero\n+\t */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\t/* PCIe mode doesn't become ready until the PEM block attempts to bring\n+\t * the interface up. Skip this check for PCIe\n+\t */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,\n+\t\t\t\t  rst_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Workaround for errata GSER-30310: SATA HDD Not Ready due to\n+\t * PHY SDLL/LDLL lockup at 3GHz\n+\t */\n+\tfor (i = 0; i < 2; i++) {\n+\t\tcvmx_gserx_slicex_pcie1_mode_t pcie1;\n+\t\tcvmx_gserx_slicex_pcie2_mode_t pcie2;\n+\t\tcvmx_gserx_slicex_pcie3_mode_t pcie3;\n+\n+\t\tpcie1.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE1_MODE(i, qlm));\n+\t\tpcie1.s.rx_pi_bwsel = 1;\n+\t\tpcie1.s.rx_ldll_bwsel = 1;\n+\t\tpcie1.s.rx_sdll_bwsel = 1;\n+\t\tcsr_wr(CVMX_GSERX_SLICEX_PCIE1_MODE(i, qlm), pcie1.u64);\n+\n+\t\tpcie2.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE2_MODE(i, qlm));\n+\t\tpcie2.s.rx_pi_bwsel = 1;\n+\t\tpcie2.s.rx_ldll_bwsel = 1;\n+\t\tpcie2.s.rx_sdll_bwsel = 1;\n+\t\tcsr_wr(CVMX_GSERX_SLICEX_PCIE2_MODE(i, qlm), pcie2.u64);\n+\n+\t\tpcie3.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE3_MODE(i, qlm));\n+\t\tpcie3.s.rx_pi_bwsel = 1;\n+\t\tpcie3.s.rx_ldll_bwsel = 1;\n+\t\tpcie3.s.rx_sdll_bwsel = 1;\n+\t\tcsr_wr(CVMX_GSERX_SLICEX_PCIE3_MODE(i, qlm), pcie3.u64);\n+\t}\n+\n+\t/*\n+\t * 7. Change P2 termination\n+\t *    Clear GSERX_RX_PWR_CTRL_P2.P2_RX_SUBBLK_PD[0] (Termination)\n+\t */\n+\tpwr_ctrl_p2.u64 = csr_rd(CVMX_GSERX_RX_PWR_CTRL_P2(qlm));\n+\tpwr_ctrl_p2.s.p2_rx_subblk_pd &= 0x1e;\n+\tcsr_wr(CVMX_GSERX_RX_PWR_CTRL_P2(qlm), pwr_ctrl_p2.u64);\n+\n+\t/*\n+\t * 8. Modify the Electrical IDLE Detect on delay\n+\t *    Change GSERX_LANE(0..3)_MISC_CFG_0.EIE_DET_STL_ON_TIME to a 0x4\n+\t */\n+\tfor (i = 0; i < 2; i++) {\n+\t\tmisc_cfg_0.u64 = csr_rd(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm));\n+\t\tmisc_cfg_0.s.eie_det_stl_on_time = 4;\n+\t\tcsr_wr(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm), misc_cfg_0.u64);\n+\t}\n+\n+\t/*\n+\t * 9. Modify the PLL and Lane Protocol Mode registers to configure\n+\t *    the PHY for SATA.\n+\t *    (Configure all 3 PLLs, doesn't matter what speed it is configured)\n+\t */\n+\n+\t/* Errata (GSER-26724) SATA never indicates GSER QLM_STAT[RST_RDY]\n+\t * We program PLL_PX_MODE_0 last due to this errata\n+\t */\n+\tfor (l = 0; l < 3; l++) {\n+\t\tpmode_1.u64 = csr_rd(CVMX_GSERX_PLL_PX_MODE_1(l, qlm));\n+\t\tlane_pmode_0.u64 = csr_rd(CVMX_GSERX_LANE_PX_MODE_0(l, qlm));\n+\t\tlane_pmode_1.u64 = csr_rd(CVMX_GSERX_LANE_PX_MODE_1(l, qlm));\n+\n+\t\tpmode_1.s.pll_cpadj = 0x2;\n+\t\tpmode_1.s.pll_opr = 0x0;\n+\t\tpmode_1.s.pll_div = 0x1e;\n+\t\tpmode_1.s.pll_pcie3en = 0x0;\n+\t\tpmode_1.s.pll_16p5en = 0x0;\n+\n+\t\tlane_pmode_0.s.ctle = 0x0;\n+\t\tlane_pmode_0.s.pcie = 0x0;\n+\t\tlane_pmode_0.s.tx_ldiv = 0x0;\n+\t\tlane_pmode_0.s.srate = 0;\n+\t\tlane_pmode_0.s.tx_mode = 0x3;\n+\t\tlane_pmode_0.s.rx_mode = 0x3;\n+\n+\t\tlane_pmode_1.s.vma_mm = 1;\n+\t\tlane_pmode_1.s.vma_fine_cfg_sel = 0;\n+\t\tlane_pmode_1.s.cdr_fgain = 0xa;\n+\t\tlane_pmode_1.s.ph_acc_adj = 0x15;\n+\n+\t\tif (l == R_2_5G_REFCLK100)\n+\t\t\tlane_pmode_0.s.rx_ldiv = 0x2;\n+\t\telse if (l == R_5G_REFCLK100)\n+\t\t\tlane_pmode_0.s.rx_ldiv = 0x1;\n+\t\telse\n+\t\t\tlane_pmode_0.s.rx_ldiv = 0x0;\n+\n+\t\tcsr_wr(CVMX_GSERX_PLL_PX_MODE_1(l, qlm), pmode_1.u64);\n+\t\tcsr_wr(CVMX_GSERX_LANE_PX_MODE_0(l, qlm), lane_pmode_0.u64);\n+\t\tcsr_wr(CVMX_GSERX_LANE_PX_MODE_1(l, qlm), lane_pmode_1.u64);\n+\t}\n+\n+\tfor (l = 0; l < 3; l++) {\n+\t\tpmode_0.u64 = csr_rd(CVMX_GSERX_PLL_PX_MODE_0(l, qlm));\n+\t\tpmode_0.s.pll_icp = 0x1;\n+\t\tpmode_0.s.pll_rloop = 0x3;\n+\t\tpmode_0.s.pll_pcs_div = 0x5;\n+\t\tcsr_wr(CVMX_GSERX_PLL_PX_MODE_0(l, qlm), pmode_0.u64);\n+\t}\n+\n+\tfor (i = 0; i < 2; i++) {\n+\t\tcvmx_gserx_slicex_rx_sdll_ctrl_t rx_sdll;\n+\n+\t\trx_sdll.u64 = csr_rd(CVMX_GSERX_SLICEX_RX_SDLL_CTRL(i, qlm));\n+\t\trx_sdll.s.pcs_sds_oob_clk_ctrl = 2;\n+\t\trx_sdll.s.pcs_sds_rx_sdll_tune = 0;\n+\t\trx_sdll.s.pcs_sds_rx_sdll_swsel = 0;\n+\t\tcsr_wr(CVMX_GSERX_SLICEX_RX_SDLL_CTRL(i, qlm), rx_sdll.u64);\n+\t}\n+\n+\tfor (i = 0; i < 2; i++) {\n+\t\tcvmx_gserx_lanex_misc_cfg_0_t misc_cfg;\n+\n+\t\tmisc_cfg.u64 = csr_rd(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm));\n+\t\tmisc_cfg.s.use_pma_polarity = 0;\n+\t\tmisc_cfg.s.cfg_pcs_loopback = 0;\n+\t\tmisc_cfg.s.pcs_tx_mode_ovrrd_en = 0;\n+\t\tmisc_cfg.s.pcs_rx_mode_ovrrd_en = 0;\n+\t\tmisc_cfg.s.cfg_eie_det_cnt = 0;\n+\t\tmisc_cfg.s.eie_det_stl_on_time = 4;\n+\t\tmisc_cfg.s.eie_det_stl_off_time = 0;\n+\t\tmisc_cfg.s.tx_bit_order = 1;\n+\t\tmisc_cfg.s.rx_bit_order = 1;\n+\t\tcsr_wr(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm), misc_cfg.u64);\n+\t}\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\t/* PCIe mode doesn't become ready until the PEM block attempts to bring\n+\t * the interface up. Skip this check for PCIe\n+\t */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,\n+\t\t\t\t  rst_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Poll GSERX_SATA_STATUS for P0_RDY = 1 */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_SATA_STATUS(qlm), cvmx_gserx_sata_status_t,\n+\t\t\t\t  p0_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM4: Timeout waiting for GSERX_SATA_STATUS[p0_rdy]\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* Poll GSERX_SATA_STATUS for P1_RDY = 1 */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_SATA_STATUS(qlm), cvmx_gserx_sata_status_t,\n+\t\t\t\t  p1_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM4: Timeout waiting for GSERX_SATA_STATUS[p1_rdy]\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tudelay(2000);\n+\n+\t/* 6. Deassert UCTL and UAHC resets:\n+\t *    a. SATA_UCTL_CTL[UCTL_RST] = 0\n+\t *    b. SATA_UCTL_CTL[UAHC_RST] = 0\n+\t *    c. Wait 10 ACLK cycles before accessing any ACLK-only registers.\n+\t */\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.sata_uctl_rst = 0;\n+\tuctl_ctl.s.sata_uahc_rst = 0;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\tudelay(1);\n+\n+\t/* 7. Enable conditional SCLK of UCTL by writing\n+\t *    SATA_UCTL_CTL[CSCLK_EN] = 1\n+\t */\n+\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\tuctl_ctl.s.csclk_en = 1;\n+\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\t/* set-up endian mode */\n+\tshim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);\n+\tshim_cfg.s.dma_endian_mode = 1;\n+\tshim_cfg.s.csr_endian_mode = 3;\n+\tcsr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);\n+\n+\treturn 0;\n+}\n+\n+static int __dlm2_sata_uahc_init_cn70xx(int baud_mhz)\n+{\n+\tcvmx_sata_uahc_gbl_cap_t gbl_cap;\n+\tcvmx_sata_uahc_px_sctl_t sctl;\n+\tcvmx_sata_uahc_gbl_pi_t pi;\n+\tcvmx_sata_uahc_px_cmd_t cmd;\n+\tcvmx_sata_uahc_px_sctl_t sctl0, sctl1;\n+\tcvmx_sata_uahc_px_ssts_t ssts;\n+\tcvmx_sata_uahc_px_tfd_t tfd;\n+\tcvmx_sata_uahc_gbl_timer1ms_t gbl_timer1ms;\n+\tu64 done;\n+\tint result = -1;\n+\tint retry_count = 0;\n+\tint spd;\n+\n+\t/* From the synopsis data book, SATA_UAHC_GBL_TIMER1MS is the\n+\t * AMBA clock in MHz * 1000, which is a_clk(Hz) / 1000\n+\t */\n+\tgbl_timer1ms.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_TIMER1MS);\n+\tgbl_timer1ms.s.timv = a_clk / 1000;\n+\tcsr_wr32(CVMX_SATA_UAHC_GBL_TIMER1MS, gbl_timer1ms.u32);\n+\tgbl_timer1ms.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_TIMER1MS);\n+\n+\t/* Set-u global capabilities reg (GBL_CAP) */\n+\tgbl_cap.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_CAP);\n+\tdebug(\"%s: SATA_UAHC_GBL_CAP before: 0x%x\\n\", __func__, gbl_cap.u32);\n+\tgbl_cap.s.sss = 1;\n+\tgbl_cap.s.smps = 1;\n+\tcsr_wr32(CVMX_SATA_UAHC_GBL_CAP, gbl_cap.u32);\n+\tgbl_cap.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_CAP);\n+\tdebug(\"%s: SATA_UAHC_GBL_CAP after: 0x%x\\n\", __func__, gbl_cap.u32);\n+\n+\t/* Set-up global hba control reg (interrupt enables) */\n+\t/* Set-up port SATA control registers (speed limitation) */\n+\tif (baud_mhz == 1500)\n+\t\tspd = 1;\n+\telse if (baud_mhz == 3000)\n+\t\tspd = 2;\n+\telse\n+\t\tspd = 3;\n+\n+\tsctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));\n+\tdebug(\"%s: SATA_UAHC_P0_SCTL before: 0x%x\\n\", __func__, sctl.u32);\n+\tsctl.s.spd = spd;\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl.u32);\n+\tsctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));\n+\tdebug(\"%s: SATA_UAHC_P0_SCTL after: 0x%x\\n\", __func__, sctl.u32);\n+\tsctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));\n+\tdebug(\"%s: SATA_UAHC_P1_SCTL before: 0x%x\\n\", __func__, sctl.u32);\n+\tsctl.s.spd = spd;\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl.u32);\n+\tsctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));\n+\tdebug(\"%s: SATA_UAHC_P1_SCTL after: 0x%x\\n\", __func__, sctl.u32);\n+\n+\t/* Set-up ports implemented reg. */\n+\tpi.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_PI);\n+\tdebug(\"%s: SATA_UAHC_GBL_PI before: 0x%x\\n\", __func__, pi.u32);\n+\tpi.s.pi = 3;\n+\tcsr_wr32(CVMX_SATA_UAHC_GBL_PI, pi.u32);\n+\tpi.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_PI);\n+\tdebug(\"%s: SATA_UAHC_GBL_PI after: 0x%x\\n\", __func__, pi.u32);\n+\n+retry0:\n+\t/* Clear port SERR and IS registers */\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SERR(0), csr_rd32(CVMX_SATA_UAHC_PX_SERR(0)));\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_IS(0), csr_rd32(CVMX_SATA_UAHC_PX_IS(0)));\n+\n+\t/* Set spin-up, power on, FIS RX enable, start, active */\n+\tcmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(0));\n+\tdebug(\"%s: SATA_UAHC_P0_CMD before: 0x%x\\n\", __func__, cmd.u32);\n+\tcmd.s.fre = 1;\n+\tcmd.s.sud = 1;\n+\tcmd.s.pod = 1;\n+\tcmd.s.st = 1;\n+\tcmd.s.icc = 1;\n+\tcmd.s.fbscp = 1; /* Enable FIS-based switching */\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_CMD(0), cmd.u32);\n+\tcmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(0));\n+\tdebug(\"%s: SATA_UAHC_P0_CMD after: 0x%x\\n\", __func__, cmd.u32);\n+\n+\tsctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));\n+\tsctl0.s.det = 1;\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);\n+\n+\t/* check status */\n+\tdone = get_timer(0);\n+\twhile (1) {\n+\t\tssts.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SSTS(0));\n+\n+\t\tif (ssts.s.ipm == 1 && ssts.s.det == 3) {\n+\t\t\tresult = 0;\n+\t\t\tbreak;\n+\t\t} else if (get_timer(done) > 100) {\n+\t\t\tresult = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tudelay(100);\n+\t}\n+\n+\tif (result != -1) {\n+\t\t/* Clear the PxSERR Register, by writing '1s' to each\n+\t\t * implemented bit location\n+\t\t */\n+\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SERR(0), -1);\n+\n+\t\t/*\n+\t\t * Wait for indication that SATA drive is ready. This is\n+\t\t * determined via an examination of PxTFD.STS. If PxTFD.STS.BSY\n+\t\t * PxTFD.STS.DRQ, and PxTFD.STS.ERR are all '0', prior to the\n+\t\t * maximum allowed time as specified in the ATA/ATAPI-7\n+\t\t * specification, the device is ready.\n+\t\t */\n+\t\t/*\n+\t\t * Wait for the device to be ready. BSY(7), DRQ(3), and ERR(0)\n+\t\t * must be clear\n+\t\t */\n+\t\tdone = get_timer(0);\n+\t\twhile (1) {\n+\t\t\ttfd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_TFD(0));\n+\t\t\tif ((tfd.s.sts & 0x89) == 0) {\n+\t\t\t\tresult = 0;\n+\t\t\t\tbreak;\n+\t\t\t} else if (get_timer(done) > 500) {\n+\t\t\t\tif (retry_count < 3) {\n+\t\t\t\t\tsctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));\n+\t\t\t\t\tsctl0.s.det = 1; /* Perform interface reset */\n+\t\t\t\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);\n+\t\t\t\t\tudelay(1000); /* 1ms dicated by AHCI 1.3 spec */\n+\t\t\t\t\tsctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));\n+\t\t\t\t\tsctl0.s.det = 0; /* Perform interface reset */\n+\t\t\t\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);\n+\t\t\t\t\tretry_count++;\n+\t\t\t\t\tgoto retry0;\n+\t\t\t\t}\n+\t\t\t\tresult = -1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tudelay(100);\n+\t\t}\n+\t}\n+\n+\tif (result == -1)\n+\t\tprintf(\"SATA0: not available\\n\");\n+\telse\n+\t\tprintf(\"SATA0: available\\n\");\n+\n+\tsctl1.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));\n+\tsctl1.s.det = 1;\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl1.u32);\n+\n+\tresult = -1;\n+\tretry_count = 0;\n+\n+retry1:\n+\t/* Clear port SERR and IS registers */\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_SERR(1), csr_rd32(CVMX_SATA_UAHC_PX_SERR(1)));\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_IS(1), csr_rd32(CVMX_SATA_UAHC_PX_IS(1)));\n+\n+\t/* Set spin-up, power on, FIS RX enable, start, active */\n+\tcmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(1));\n+\tdebug(\"%s: SATA_UAHC_P1_CMD before: 0x%x\\n\", __func__, cmd.u32);\n+\tcmd.s.fre = 1;\n+\tcmd.s.sud = 1;\n+\tcmd.s.pod = 1;\n+\tcmd.s.st = 1;\n+\tcmd.s.icc = 1;\n+\tcmd.s.fbscp = 1; /* Enable FIS-based switching */\n+\tcsr_wr32(CVMX_SATA_UAHC_PX_CMD(1), cmd.u32);\n+\tcmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(1));\n+\tdebug(\"%s: SATA_UAHC_P1_CMD after: 0x%x\\n\", __func__, cmd.u32);\n+\n+\t/* check status */\n+\tdone = get_timer(0);\n+\twhile (1) {\n+\t\tssts.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SSTS(1));\n+\n+\t\tif (ssts.s.ipm == 1 && ssts.s.det == 3) {\n+\t\t\tresult = 0;\n+\t\t\tbreak;\n+\t\t} else if (get_timer(done) > 1000) {\n+\t\t\tresult = -1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tudelay(100);\n+\t}\n+\n+\tif (result != -1) {\n+\t\t/* Clear the PxSERR Register, by writing '1s' to each\n+\t\t * implemented bit location\n+\t\t */\n+\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SERR(1), csr_rd32(CVMX_SATA_UAHC_PX_SERR(1)));\n+\n+\t\t/*\n+\t\t * Wait for indication that SATA drive is ready. This is\n+\t\t * determined via an examination of PxTFD.STS. If PxTFD.STS.BSY\n+\t\t * PxTFD.STS.DRQ, and PxTFD.STS.ERR are all '0', prior to the\n+\t\t * maximum allowed time as specified in the ATA/ATAPI-7\n+\t\t * specification, the device is ready.\n+\t\t */\n+\t\t/*\n+\t\t * Wait for the device to be ready. BSY(7), DRQ(3), and ERR(0)\n+\t\t * must be clear\n+\t\t */\n+\t\tdone = get_timer(0);\n+\t\twhile (1) {\n+\t\t\ttfd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_TFD(1));\n+\t\t\tif ((tfd.s.sts & 0x89) == 0) {\n+\t\t\t\tresult = 0;\n+\t\t\t\tbreak;\n+\t\t\t} else if (get_timer(done) > 500) {\n+\t\t\t\tif (retry_count < 3) {\n+\t\t\t\t\tsctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));\n+\t\t\t\t\tsctl0.s.det = 1; /* Perform interface reset */\n+\t\t\t\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl0.u32);\n+\t\t\t\t\tudelay(1000); /* 1ms dicated by AHCI 1.3 spec */\n+\t\t\t\t\tsctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));\n+\t\t\t\t\tsctl0.s.det = 0; /* Perform interface reset */\n+\t\t\t\t\tcsr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl0.u32);\n+\t\t\t\t\tretry_count++;\n+\t\t\t\t\tgoto retry1;\n+\t\t\t\t}\n+\t\t\t\tresult = -1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tudelay(100);\n+\t\t}\n+\t}\n+\n+\tif (result == -1)\n+\t\tprintf(\"SATA1: not available\\n\");\n+\telse\n+\t\tprintf(\"SATA1: available\\n\");\n+\n+\treturn 0;\n+}\n+\n+static int __sata_bist_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_sata_uctl_bist_status_t bist_status;\n+\tcvmx_sata_uctl_ctl_t uctl_ctl;\n+\tcvmx_sata_uctl_shim_cfg_t shim_cfg;\n+\tu64 done;\n+\tint result = -1;\n+\n+\tdebug(\"%s(%d, %d, %d, %d)\\n\", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\tbist_status.u64 = csr_rd(CVMX_SATA_UCTL_BIST_STATUS);\n+\n+\t{\n+\t\tif (__dlm2_sata_uctl_init_cn70xx()) {\n+\t\t\tprintf(\"ERROR: Failed to initialize SATA UCTL CSRs\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\t\tresult = __sata_dlm_init_cn73xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\t\telse\n+\t\t\tresult = __sata_dlm_init_cn70xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\t\tif (result) {\n+\t\t\tprintf(\"ERROR: Failed to initialize SATA GSER CSRs\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tuctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);\n+\t\tuctl_ctl.s.start_bist = 1;\n+\t\tcsr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);\n+\n+\t\t/* Set-up for a 1 sec timer. */\n+\t\tdone = get_timer(0);\n+\t\twhile (1) {\n+\t\t\tbist_status.u64 = csr_rd(CVMX_SATA_UCTL_BIST_STATUS);\n+\t\t\tif ((bist_status.s.uctl_xm_r_bist_ndone |\n+\t\t\t     bist_status.s.uctl_xm_w_bist_ndone |\n+\t\t\t     bist_status.s.uahc_p0_rxram_bist_ndone |\n+\t\t\t     bist_status.s.uahc_p1_rxram_bist_ndone |\n+\t\t\t     bist_status.s.uahc_p0_txram_bist_ndone |\n+\t\t\t     bist_status.s.uahc_p1_txram_bist_ndone) == 0) {\n+\t\t\t\tresult = 0;\n+\t\t\t\tbreak;\n+\t\t\t} else if (get_timer(done) > 1000) {\n+\t\t\t\tresult = -1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tudelay(100);\n+\t\t}\n+\t\tif (result == -1) {\n+\t\t\tprintf(\"ERROR: SATA_UCTL_BIST_STATUS = 0x%llx\\n\",\n+\t\t\t       (unsigned long long)bist_status.u64);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tdebug(\"%s: Initializing UAHC\\n\", __func__);\n+\t\tif (__dlm2_sata_uahc_init_cn70xx(baud_mhz)) {\n+\t\t\tprintf(\"ERROR: Failed to initialize SATA UAHC CSRs\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* Change CSR_ENDIAN_MODE to big endian to use Open Source AHCI SATA\n+\t * driver\n+\t */\n+\tshim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);\n+\tshim_cfg.s.csr_endian_mode = 1;\n+\tcsr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);\n+\n+\treturn 0;\n+}\n+\n+static int __setup_sata(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)\n+{\n+\tdebug(\"%s(%d, %d, %d, %d)\\n\", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\treturn __sata_bist_cn70xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+}\n+\n+static int __dlmx_setup_pcie_cn70xx(int qlm, enum cvmx_qlm_mode mode, int gen2, int rc,\n+\t\t\t\t    int ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;\n+\tcvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;\n+\tcvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;\n+\tcvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;\n+\tstatic const u8 ref_clk_mult[2] = { 35, 56 }; /* 100 & 125 MHz ref clock supported. */\n+\n+\tdebug(\"%s(%d, %d, %d, %d, %d, %d)\\n\", __func__, qlm, mode, gen2, rc, ref_clk_sel,\n+\t      ref_clk_input);\n+\tif (rc == 0) {\n+\t\tdebug(\"Skipping initializing PCIe dlm %d in endpoint mode\\n\", qlm);\n+\t\treturn 0;\n+\t}\n+\n+\tif (qlm > 0 && ref_clk_input > 1) {\n+\t\tprintf(\"%s: Error: ref_clk_input can only be 0 or 1 for QLM %d\\n\",\n+\t\t       __func__, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\tif (ref_clk_sel > OCTEON_QLM_REF_CLK_125MHZ) {\n+\t\tprintf(\"%s: Error: ref_clk_sel can only be 100 or 125 MHZ.\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\t/* 1. Write GSER0_DLM(1..2)_REFCLK_SEL[REFCLK_SEL] if required for\n+\t *    reference-clock selection\n+\t */\n+\n+\tcsr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(qlm, 0), ref_clk_input);\n+\n+\t/* 2. If required, write GSER0_DLM(1..2)_REF_CLKDIV2[REF_CLKDIV2] = 1\n+\t *    (must be set if reference clock >= 100 MHz)\n+\t */\n+\n+\t/* 4. Configure the PCIE PIPE:\n+\t *  a. Write GSER0_PCIE_PIPE_PORT_SEL[PIPE_PORT_SEL] to configure the\n+\t *     PCIE PIPE.\n+\t *\t0x0 = disables all pipes\n+\t *\t0x1 = enables pipe0 only (PEM0 4-lane)\n+\t *\t0x2 = enables pipes 0 and 1 (PEM0 and PEM1 2-lanes each)\n+\t *\t0x3 = enables pipes 0, 1, 2, and 3 (PEM0, PEM1, and PEM3 are\n+\t *\t      one-lane each)\n+\t *  b. Configure GSER0_PCIE_PIPE_PORT_SEL[CFG_PEM1_DLM2]. If PEM1 is\n+\t *     to be configured, this bit must reflect which DLM it is logically\n+\t *     tied to. This bit sets multiplexing logic in GSER, and it is used\n+\t *     by the RST logic to determine when the MAC can come out of reset.\n+\t *\t0 = PEM1 is tied to DLM1 (for 3 x 1 PCIe mode).\n+\t *\t1 = PEM1 is tied to DLM2 (for all other PCIe modes).\n+\t */\n+\tif (qlm == 1) {\n+\t\tcvmx_gserx_pcie_pipe_port_sel_t pipe_port;\n+\n+\t\tpipe_port.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_PORT_SEL(0));\n+\t\tpipe_port.s.cfg_pem1_dlm2 = (mode == CVMX_QLM_MODE_PCIE_1X1) ? 1 : 0;\n+\t\tpipe_port.s.pipe_port_sel =\n+\t\t\t\t(mode == CVMX_QLM_MODE_PCIE) ? 1 : /* PEM0 only */\n+\t\t\t\t(mode == CVMX_QLM_MODE_PCIE_1X2) ? 2 : /* PEM0-1 */\n+\t\t\t\t(mode == CVMX_QLM_MODE_PCIE_1X1) ? 3 : /* PEM0-2 */\n+\t\t\t\t(mode == CVMX_QLM_MODE_PCIE_2X1) ? 3 : /* PEM0-1 */\n+\t\t\t\t0; /* PCIe disabled */\n+\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_PORT_SEL(0), pipe_port.u64);\n+\t}\n+\n+\t/* Apply workaround for Errata (G-20669) MPLL may not come up. */\n+\n+\t/* Set REF_CLKDIV2 based on the Ref Clock */\n+\tref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));\n+\tref_clkdiv2.s.ref_clkdiv2 = ref_clk_sel > 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);\n+\n+\t/* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\n+\t/* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set\n+\t *    GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.\n+\t */\n+\n+\t/* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]\n+\t *    to the value in the preceding table, which is different\n+\t *    than the desired setting prescribed by the HRM.\n+\t */\n+\tmpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));\n+\tmpll_multiplier.s.mpll_multiplier = ref_clk_mult[ref_clk_sel];\n+\tdebug(\"%s: Setting MPLL multiplier to %d\\n\", __func__,\n+\t      (int)mpll_multiplier.s.mpll_multiplier);\n+\tcsr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);\n+\t/* 5. Clear GSER0_DLM(1..2)_TEST_POWERDOWN. Configurations that only\n+\t *    use DLM1 need not clear GSER0_DLM2_TEST_POWERDOWN\n+\t */\n+\tdlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));\n+\tdlmx_test_powerdown.s.test_powerdown = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);\n+\n+\t/* 6. Clear GSER0_DLM(1..2)_PHY_RESET. Configurations that use only\n+\t *    need DLM1 need not clear GSER0_DLM2_PHY_RESET\n+\t */\n+\tdlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));\n+\tdlmx_phy_reset.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);\n+\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+\t/* This is set when initializing PCIe after soft reset is asserted. */\n+\n+\t/* 7. Write the GSER0_PCIE_PIPE_RST register to take the appropriate\n+\t *    PIPE out of reset. There is a PIPEn_RST bit for each PIPE. Clear\n+\t *    the appropriate bits based on the configuration (reset is\n+\t *     active high).\n+\t */\n+\tif (qlm == 1) {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\t\tcvmx_pemx_on_t pemx_on;\n+\t\tcvmx_gserx_pcie_pipe_rst_t pipe_rst;\n+\t\tcvmx_rst_ctlx_t rst_ctl;\n+\n+\t\tswitch (mode) {\n+\t\tcase CVMX_QLM_MODE_PCIE:     /* PEM0 on DLM1 & DLM2 */\n+\t\tcase CVMX_QLM_MODE_PCIE_1X2: /* PEM0 on DLM1 */\n+\t\tcase CVMX_QLM_MODE_PCIE_1X1: /* PEM0 on DLM1 using lane 0 */\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\t\tpemx_cfg.cn70xx.hostmd = rc;\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE_1X1) {\n+\t\t\t\tpemx_cfg.cn70xx.md =\n+\t\t\t\t\tgen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;\n+\t\t\t} else if (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_cfg.cn70xx.md =\n+\t\t\t\t\tgen2 ? CVMX_PEM_MD_GEN2_4LANE : CVMX_PEM_MD_GEN1_4LANE;\n+\t\t\t} else {\n+\t\t\t\tpemx_cfg.cn70xx.md =\n+\t\t\t\t\tgen2 ? CVMX_PEM_MD_GEN2_2LANE : CVMX_PEM_MD_GEN1_2LANE;\n+\t\t\t}\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);\n+\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(0));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(0), rst_ctl.u64);\n+\n+\t\t\t/* PEM0 is on DLM1&2 which is pipe0 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe0_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_PCIE_2X1: /* PEM0 and PEM1 on DLM1 */\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\t\tpemx_cfg.cn70xx.hostmd = rc;\n+\t\t\tpemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);\n+\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(0));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(0), rst_ctl.u64);\n+\n+\t\t\t/* PEM0 is on DLM1 which is pipe0 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe0_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\t\tpemx_cfg.cn70xx.hostmd = 1;\n+\t\t\tpemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);\n+\t\t\t/* PEM1 is on DLM2 which is pipe1 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe1_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(1), pemx_on.u64);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\t\tcvmx_pemx_on_t pemx_on;\n+\t\tcvmx_gserx_pcie_pipe_rst_t pipe_rst;\n+\t\tcvmx_rst_ctlx_t rst_ctl;\n+\n+\t\tswitch (mode) {\n+\t\tcase CVMX_QLM_MODE_PCIE_1X2: /* PEM1 on DLM2 */\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\t\tpemx_cfg.cn70xx.hostmd = 1;\n+\t\t\tpemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_2LANE : CVMX_PEM_MD_GEN1_2LANE;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);\n+\n+\t\t\t/* PEM1 is on DLM1 lane 0, which is pipe1 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe1_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(1), pemx_on.u64);\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_PCIE_2X1: /* PEM1 and PEM2 on DLM2 */\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\t\tpemx_cfg.cn70xx.hostmd = 1;\n+\t\t\tpemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);\n+\n+\t\t\t/* PEM1 is on DLM2 lane 0, which is pipe2 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe2_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(1), pemx_on.u64);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));\n+\t\t\tpemx_cfg.cn70xx.hostmd = 1;\n+\t\t\tpemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(2), pemx_cfg.u64);\n+\n+\t\t\trst_ctl.u64 = csr_rd(CVMX_RST_CTLX(2));\n+\t\t\trst_ctl.s.rst_drv = 1;\n+\t\t\tcsr_wr(CVMX_RST_CTLX(2), rst_ctl.u64);\n+\n+\t\t\t/* PEM2 is on DLM2 lane 1, which is pipe3 */\n+\t\t\tpipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));\n+\t\t\tpipe_rst.s.pipe3_rst = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);\n+\n+\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));\n+\t\t\tpemx_on.s.pemon = 1;\n+\t\t\tcsr_wr(CVMX_PEMX_ON(2), pemx_on.u64);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Configure dlm speed and mode for cn70xx.\n+ *\n+ * @param qlm     The DLM to configure\n+ * @param speed   The speed the DLM needs to be configured in Mhz.\n+ * @param mode    The DLM to be configured as SGMII/XAUI/PCIe.\n+ *                  DLM 0: has 2 interfaces which can be configured as\n+ *                         SGMII/QSGMII/RXAUI. Need to configure both at the\n+ *                         same time. These are valid option\n+ *\t\t\t\tCVMX_QLM_MODE_QSGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_SGMII_SGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_SGMII_DISABLED,\n+ *\t\t\t\tCVMX_QLM_MODE_DISABLED_SGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_SGMII_QSGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_QSGMII_QSGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_QSGMII_DISABLED,\n+ *\t\t\t\tCVMX_QLM_MODE_DISABLED_QSGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_QSGMII_SGMII,\n+ *\t\t\t\tCVMX_QLM_MODE_RXAUI_1X2\n+ *\n+ *                  DLM 1: PEM0/1 in PCIE_1x4/PCIE_2x1/PCIE_1X1\n+ *                  DLM 2: PEM0/1/2 in PCIE_1x4/PCIE_1x2/PCIE_2x1/PCIE_1x1\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.\n+ * @param gen2    Only used for PCIe, gen2 = 1, in GEN2 mode else in GEN1 mode.\n+ *\n+ * @param ref_clk_input  The reference-clock input to use to configure QLM\n+ * @param ref_clk_sel    The reference-clock selection to use to configure QLM\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+static int octeon_configure_qlm_cn70xx(int qlm, int speed, int mode, int rc, int gen2,\n+\t\t\t\t       int ref_clk_sel, int ref_clk_input)\n+{\n+\tdebug(\"%s(%d, %d, %d, %d, %d, %d, %d)\\n\", __func__, qlm, speed, mode, rc, gen2, ref_clk_sel,\n+\t      ref_clk_input);\n+\tswitch (qlm) {\n+\tcase 0: {\n+\t\tint is_sff7000_rxaui = 0;\n+\t\tcvmx_gmxx_inf_mode_t 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+\t\tif (inf_mode0.s.en || inf_mode1.s.en) {\n+\t\t\tdebug(\"DLM0 already configured\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tswitch (mode) {\n+\t\tcase CVMX_QLM_MODE_SGMII_SGMII:\n+\t\t\tdebug(\"  Mode SGMII SGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_SGMII_QSGMII:\n+\t\t\tdebug(\"  Mode SGMII QSGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_SGMII_DISABLED:\n+\t\t\tdebug(\"  Mode SGMII Disabled\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_DISABLED_SGMII:\n+\t\t\tdebug(\"Mode Disabled SGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_QSGMII_SGMII:\n+\t\t\tdebug(\"  Mode QSGMII SGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_QSGMII_QSGMII:\n+\t\t\tdebug(\"  Mode QSGMII QSGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_QSGMII_DISABLED:\n+\t\t\tdebug(\"  Mode QSGMII Disabled\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_DISABLED_QSGMII:\n+\t\t\tdebug(\"Mode Disabled QSGMII\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_RXAUI:\n+\t\t\tdebug(\"  Mode RXAUI\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_RXAUI;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tdebug(\"  Mode Disabled Disabled\\n\");\n+\t\t\tinf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tinf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;\n+\t\t\tbreak;\n+\t\t}\n+\t\tcsr_wr(CVMX_GMXX_INF_MODE(0), inf_mode0.u64);\n+\t\tcsr_wr(CVMX_GMXX_INF_MODE(1), inf_mode1.u64);\n+\n+\t\t/* Bringup the PLL */\n+\t\tif (__dlm_setup_pll_cn70xx(qlm, speed, ref_clk_sel, ref_clk_input,\n+\t\t\t\t\t   is_sff7000_rxaui))\n+\t\t\treturn -1;\n+\n+\t\t/* TX Lanes */\n+\t\tif (__dlm0_setup_tx_cn70xx(speed, ref_clk_sel))\n+\t\t\treturn -1;\n+\n+\t\t/* RX Lanes */\n+\t\tif (__dlm0_setup_rx_cn70xx(speed, ref_clk_sel))\n+\t\t\treturn -1;\n+\n+\t\t/* Enable the interface */\n+\t\tinf_mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));\n+\t\tif (inf_mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED)\n+\t\t\tinf_mode0.s.en = 1;\n+\t\tcsr_wr(CVMX_GMXX_INF_MODE(0), inf_mode0.u64);\n+\t\tinf_mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));\n+\t\tif (inf_mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED)\n+\t\t\tinf_mode1.s.en = 1;\n+\t\tcsr_wr(CVMX_GMXX_INF_MODE(1), inf_mode1.u64);\n+\t\tbreak;\n+\t}\n+\tcase 1:\n+\t\tswitch (mode) {\n+\t\tcase CVMX_QLM_MODE_PCIE: /* PEM0 on DLM1 & DLM2 */\n+\t\t\tdebug(\"  Mode PCIe\\n\");\n+\t\t\tif (__dlmx_setup_pcie_cn70xx(1, mode, gen2, rc, ref_clk_sel, ref_clk_input))\n+\t\t\t\treturn -1;\n+\t\t\tif (__dlmx_setup_pcie_cn70xx(2, mode, gen2, rc, ref_clk_sel, ref_clk_input))\n+\t\t\t\treturn -1;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_PCIE_1X2: /* PEM0 on DLM1 */\n+\t\tcase CVMX_QLM_MODE_PCIE_2X1: /* PEM0 & PEM1 on DLM1 */\n+\t\tcase CVMX_QLM_MODE_PCIE_1X1: /* PEM0 on DLM1, only 1 lane */\n+\t\t\tdebug(\"  Mode PCIe 1x2, 2x1 or 1x1\\n\");\n+\t\t\tif (__dlmx_setup_pcie_cn70xx(qlm, mode, gen2, rc, ref_clk_sel,\n+\t\t\t\t\t\t     ref_clk_input))\n+\t\t\t\treturn -1;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_DISABLED:\n+\t\t\tdebug(\"  Mode disabled\\n\");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tdebug(\"DLM1 illegal mode specified\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\tcase 2:\n+\t\tswitch (mode) {\n+\t\tcase CVMX_QLM_MODE_SATA_2X1:\n+\t\t\tdebug(\"%s: qlm 2, mode is SATA 2x1\\n\", __func__);\n+\t\t\t/* DLM2 is SATA, PCIE2 is disabled */\n+\t\t\tif (__setup_sata(qlm, speed, ref_clk_sel, ref_clk_input))\n+\t\t\t\treturn -1;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_PCIE:\n+\t\t\tdebug(\"  Mode PCIe\\n\");\n+\t\t\t/* DLM2 is PCIE0, PCIE1-2 are disabled. */\n+\t\t\t/* Do nothing, its initialized in DLM1 */\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_PCIE_1X2: /* PEM1 on DLM2 */\n+\t\tcase CVMX_QLM_MODE_PCIE_2X1: /* PEM1 & PEM2 on DLM2 */\n+\t\t\tdebug(\"  Mode PCIe 1x2 or 2x1\\n\");\n+\t\t\tif (__dlmx_setup_pcie_cn70xx(qlm, mode, gen2, rc, ref_clk_sel,\n+\t\t\t\t\t\t     ref_clk_input))\n+\t\t\t\treturn -1;\n+\t\t\tbreak;\n+\t\tcase CVMX_QLM_MODE_DISABLED:\n+\t\t\tdebug(\"  Mode Disabled\\n\");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tdebug(\"DLM2 illegal mode specified\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\tdefault:\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Disables DFE for the specified QLM lane(s).\n+ * This function should only be called for low-loss channels.\n+ *\n+ * @param node     Node to configure\n+ * @param qlm      QLM to configure\n+ * @param lane     Lane to configure, or -1 all lanes\n+ * @param baud_mhz The speed the QLM needs to be configured in Mhz.\n+ * @param mode     The QLM to be configured as SGMII/XAUI/PCIe.\n+ */\n+void octeon_qlm_dfe_disable(int node, int qlm, int lane, int baud_mhz, int mode)\n+{\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\tint l;\n+\tcvmx_gserx_lanex_rx_loop_ctrl_t loop_ctrl;\n+\tcvmx_gserx_lanex_rx_valbbd_ctrl_0_t ctrl_0;\n+\tcvmx_gserx_lanex_rx_valbbd_ctrl_1_t ctrl_1;\n+\tcvmx_gserx_lanex_rx_valbbd_ctrl_2_t ctrl_2;\n+\tcvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;\n+\n+\t/* Interfaces below 5Gbaud are already manually tuned. */\n+\tif (baud_mhz < 5000)\n+\t\treturn;\n+\n+\t/* Don't run on PCIe links, SATA or KR.  These interfaces use training */\n+\tswitch (mode) {\n+\tcase CVMX_QLM_MODE_10G_KR_1X2:\n+\tcase CVMX_QLM_MODE_10G_KR:\n+\tcase CVMX_QLM_MODE_40G_KR4:\n+\t\treturn;\n+\tcase CVMX_QLM_MODE_PCIE_1X1:\n+\tcase CVMX_QLM_MODE_PCIE_2X1:\n+\tcase CVMX_QLM_MODE_PCIE_1X2:\n+\tcase CVMX_QLM_MODE_PCIE:\n+\tcase CVMX_QLM_MODE_PCIE_1X8:\n+\t\treturn;\n+\tcase CVMX_QLM_MODE_SATA_2X1:\n+\t\treturn;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\t/* Updating pre_ctle minimum to 0. This works best for short channels */\n+\tlane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));\n+\tlane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = 0;\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);\n+\n+\tfor (l = 0; l < num_lanes; l++) {\n+\t\tif (lane != -1 && lane != l)\n+\t\t\tcontinue;\n+\n+\t\t/* 1. Write GSERX_LANEx_RX_LOOP_CTRL = 0x0270\n+\t\t * (var \"loop_ctrl\" with bits 8 & 1 cleared).\n+\t\t * bit<1> dfe_en_byp = 1'b0\n+\t\t */\n+\t\tloop_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm));\n+\t\tloop_ctrl.s.cfg_rx_lctrl = loop_ctrl.s.cfg_rx_lctrl & 0x3fd;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm), loop_ctrl.u64);\n+\n+\t\t/* 2. Write GSERX_LANEx_RX_VALBBD_CTRL_1 = 0x0000\n+\t\t * (var \"ctrl1\" with all bits cleared)\n+\t\t * bits<14:11> CFG_RX_DFE_C3_MVAL = 4'b0000\n+\t\t * bit<10> CFG_RX_DFE_C3_MSGN = 1'b0\n+\t\t * bits<9:6> CFG_RX_DFE_C2_MVAL = 4'b0000\n+\t\t * bit<5> CFG_RX_DFE_C2_MSGN = 1'b0\n+\t\t * bits<4:0> CFG_RX_DFE_C1_MVAL = 5'b00000\n+\t\t */\n+\t\tctrl_1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_1(l, qlm));\n+\t\tctrl_1.s.dfe_c3_mval = 0;\n+\t\tctrl_1.s.dfe_c3_msgn = 0;\n+\t\tctrl_1.s.dfe_c2_mval = 0;\n+\t\tctrl_1.s.dfe_c2_msgn = 0;\n+\t\tctrl_1.s.dfe_c2_mval = 0;\n+\t\tctrl_1.s.dfe_c1_mval = 0;\n+\t\tctrl_1.s.dfe_c1_msgn = 0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_1(l, qlm), ctrl_1.u64);\n+\n+\t\t/* 3. Write GSERX_LANEx_RX_VALBBD_CTRL_0 = 0x2400\n+\t\t * (var \"ctrl0\" with following bits set/cleared)\n+\t\t * bits<11:10> CFG_RX_DFE_GAIN = 0x1\n+\t\t * bits<9:6> CFG_RX_DFE_C5_MVAL = 4'b0000\n+\t\t * bit<5> CFG_RX_DFE_C5_MSGN = 1'b0\n+\t\t * bits<4:1> CFG_RX_DFE_C4_MVAL = 4'b0000\n+\t\t * bit<0> CFG_RX_DFE_C4_MSGN = 1'b0\n+\t\t */\n+\t\tctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm));\n+\t\tctrl_0.s.dfe_gain = 0x1;\n+\t\tctrl_0.s.dfe_c5_mval = 0;\n+\t\tctrl_0.s.dfe_c5_msgn = 0;\n+\t\tctrl_0.s.dfe_c4_mval = 0;\n+\t\tctrl_0.s.dfe_c4_msgn = 0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm), ctrl_0.u64);\n+\n+\t\t/* 4. Write GSER(0..13)_LANE(0..3)_RX_VALBBD_CTRL_2 = 0x003F\n+\t\t * //enable DFE tap overrides\n+\t\t * bit<5> dfe_ovrd_en = 1\n+\t\t * bit<4> dfe_c5_ovrd_val = 1\n+\t\t * bit<3> dfe_c4_ovrd_val = 1\n+\t\t * bit<2> dfe_c3_ovrd_val = 1\n+\t\t * bit<1> dfe_c2_ovrd_val = 1\n+\t\t * bit<0> dfe_c1_ovrd_val = 1\n+\t\t */\n+\t\tctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_2(l, qlm));\n+\t\tctrl_2.s.dfe_ovrd_en = 0x1;\n+\t\tctrl_2.s.dfe_c5_ovrd_val = 0x1;\n+\t\tctrl_2.s.dfe_c4_ovrd_val = 0x1;\n+\t\tctrl_2.s.dfe_c3_ovrd_val = 0x1;\n+\t\tctrl_2.s.dfe_c2_ovrd_val = 0x1;\n+\t\tctrl_2.s.dfe_c1_ovrd_val = 0x1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_2(l, qlm), ctrl_2.u64);\n+\t}\n+}\n+\n+/**\n+ * Disables DFE, uses fixed CTLE Peak value and AGC settings\n+ * for the specified QLM lane(s).\n+ * This function should only be called for low-loss channels.\n+ * This function prevents Rx equalization from happening on all lanes in a QLM\n+ * This function should be called for all lanes being used in the QLM.\n+ *\n+ * @param  node           Node to configure\n+ * @param  qlm            QLM to configure\n+ * @param  lane           Lane to configure, or -1 all lanes\n+ * @param  baud_mhz       The speed the QLM needs to be configured in Mhz.\n+ * @param  mode           The QLM to be configured as SGMII/XAUI/PCIe.\n+ * @param  ctle_zero      Equalizer Peaking control\n+ * @param  agc_pre_ctle   Pre-CTLE gain\n+ * @param  agc_post_ctle  Post-CTLE gain\n+ * @return Zero on success, negative on failure\n+ */\n+\n+int octeon_qlm_dfe_disable_ctle_agc(int node, int qlm, int lane, int baud_mhz, int mode,\n+\t\t\t\t    int ctle_zero, int agc_pre_ctle, int agc_post_ctle)\n+{\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\tint l;\n+\tcvmx_gserx_lanex_rx_loop_ctrl_t loop_ctrl;\n+\tcvmx_gserx_lanex_rx_valbbd_ctrl_0_t ctrl_0;\n+\tcvmx_gserx_lanex_pwr_ctrl_t lanex_pwr_ctrl;\n+\tcvmx_gserx_lane_mode_t lmode;\n+\tcvmx_gserx_lane_px_mode_1_t px_mode_1;\n+\tcvmx_gserx_lanex_rx_cfg_5_t rx_cfg_5;\n+\tcvmx_gserx_lanex_rx_cfg_2_t rx_cfg_2;\n+\tcvmx_gserx_lanex_rx_ctle_ctrl_t ctle_ctrl;\n+\n+\t/* Check tuning constraints */\n+\tif (ctle_zero < 0 || ctle_zero > 15) {\n+\t\tprintf(\"Error: N%d.QLM%d: Invalid CTLE_ZERO(%d).  Must be between -1 and 15.\\n\",\n+\t\t       node, qlm, ctle_zero);\n+\t\treturn -1;\n+\t}\n+\tif (agc_pre_ctle < 0 || agc_pre_ctle > 15) {\n+\t\tprintf(\"Error: N%d.QLM%d: Invalid AGC_Pre_CTLE(%d)\\n\",\n+\t\t       node, qlm, agc_pre_ctle);\n+\t\treturn -1;\n+\t}\n+\n+\tif (agc_post_ctle < 0 || agc_post_ctle > 15) {\n+\t\tprintf(\"Error: N%d.QLM%d: Invalid AGC_Post_CTLE(%d)\\n\",\n+\t\t       node, qlm, agc_post_ctle);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Interfaces below 5Gbaud are already manually tuned. */\n+\tif (baud_mhz < 5000)\n+\t\treturn 0;\n+\n+\t/* Don't run on PCIe links, SATA or KR.  These interfaces use training */\n+\tswitch (mode) {\n+\tcase CVMX_QLM_MODE_10G_KR_1X2:\n+\tcase CVMX_QLM_MODE_10G_KR:\n+\tcase CVMX_QLM_MODE_40G_KR4:\n+\t\treturn 0;\n+\tcase CVMX_QLM_MODE_PCIE_1X1:\n+\tcase CVMX_QLM_MODE_PCIE_2X1:\n+\tcase CVMX_QLM_MODE_PCIE_1X2:\n+\tcase CVMX_QLM_MODE_PCIE:\n+\tcase CVMX_QLM_MODE_PCIE_1X8:\n+\t\treturn 0;\n+\tcase CVMX_QLM_MODE_SATA_2X1:\n+\t\treturn 0;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tlmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));\n+\n+\t/* 1. Enable VMA manual mode for the QLM's lane mode */\n+\tpx_mode_1.u64 = csr_rd_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm));\n+\tpx_mode_1.s.vma_mm = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm), px_mode_1.u64);\n+\n+\t/* 2. Disable DFE */\n+\tocteon_qlm_dfe_disable(node, qlm, lane, baud_mhz, mode);\n+\n+\tfor (l = 0; l < num_lanes; l++) {\n+\t\tif (lane != -1 && lane != l)\n+\t\t\tcontinue;\n+\n+\t\t/* 3. Write GSERX_LANEx_RX_VALBBD_CTRL_0.CFG_RX_AGC_GAIN = 0x2 */\n+\t\tctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm));\n+\t\tctrl_0.s.agc_gain = 0x2;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm), ctrl_0.u64);\n+\n+\t\t/* 4. Write GSERX_LANEx_RX_LOOP_CTRL\n+\t\t * bit<8> lctrl_men = 1'b1\n+\t\t * bit<0> cdr_en_byp = 1'b1\n+\t\t */\n+\t\tloop_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm));\n+\t\tloop_ctrl.s.cfg_rx_lctrl = loop_ctrl.s.cfg_rx_lctrl | 0x101;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm), loop_ctrl.u64);\n+\n+\t\t/* 5. Write GSERX_LANEx_PWR_CTRL = 0x0040 (var \"lanex_pwr_ctrl\" with\n+\t\t * following bits set)\n+\t\t * bit<6> RX_LCTRL_OVRRD_EN = 1'b1\n+\t\t * all other bits cleared.\n+\t\t */\n+\t\tlanex_pwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(l, qlm));\n+\t\tlanex_pwr_ctrl.s.rx_lctrl_ovrrd_en = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(l, qlm), lanex_pwr_ctrl.u64);\n+\n+\t\t/* --Setting AGC in manual mode and configuring CTLE-- */\n+\t\trx_cfg_5.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_5(l, qlm));\n+\t\trx_cfg_5.s.rx_agc_men_ovrrd_val = 1;\n+\t\trx_cfg_5.s.rx_agc_men_ovrrd_en = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_5(l, qlm), rx_cfg_5.u64);\n+\n+\t\tctle_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(l, qlm));\n+\t\tctle_ctrl.s.pcs_sds_rx_ctle_zero = ctle_zero;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(l, qlm), ctle_ctrl.u64);\n+\n+\t\trx_cfg_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_2(l, qlm));\n+\t\trx_cfg_2.s.rx_sds_rx_agc_mval = (agc_pre_ctle << 4) | agc_post_ctle;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_2(l, qlm), rx_cfg_2.u64);\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Some QLM speeds need to override the default tuning parameters\n+ *\n+ * @param node     Node to configure\n+ * @param qlm      QLM to configure\n+ * @param baud_mhz Desired speed in MHz\n+ * @param lane     Lane the apply the tuning parameters\n+ * @param tx_swing Voltage swing.  The higher the value the lower the voltage,\n+ *\t\t   the default value is 7.\n+ * @param tx_pre   pre-cursor pre-emphasis\n+ * @param tx_post  post-cursor pre-emphasis.\n+ * @param tx_gain   Transmit gain. Range 0-7\n+ * @param tx_vboost Transmit voltage boost. Range 0-1\n+ */\n+void octeon_qlm_tune_per_lane_v3(int node, int qlm, int baud_mhz, int lane, int tx_swing,\n+\t\t\t\t int tx_pre, int tx_post, int tx_gain, int tx_vboost)\n+{\n+\tcvmx_gserx_cfg_t gserx_cfg;\n+\tcvmx_gserx_lanex_tx_cfg_0_t tx_cfg0;\n+\tcvmx_gserx_lanex_tx_pre_emphasis_t pre_emphasis;\n+\tcvmx_gserx_lanex_tx_cfg_1_t tx_cfg1;\n+\tcvmx_gserx_lanex_tx_cfg_3_t tx_cfg3;\n+\tcvmx_bgxx_spux_br_pmd_control_t pmd_control;\n+\tcvmx_gserx_lanex_pcs_ctlifc_0_t pcs_ctlifc_0;\n+\tcvmx_gserx_lanex_pcs_ctlifc_2_t pcs_ctlifc_2;\n+\tint bgx, lmac;\n+\n+\t/* Do not apply QLM tuning to PCIe and KR interfaces. */\n+\tgserx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\tif (gserx_cfg.s.pcie)\n+\t\treturn;\n+\n+\t/* Apply the QLM tuning only to cn73xx and cn78xx models only */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX))\n+\t\tbgx = (qlm < 2) ? qlm : (qlm - 2);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\tbgx = (qlm < 4) ? (qlm - 2) : 2;\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX))\n+\t\tbgx = 0;\n+\telse\n+\t\treturn;\n+\n+\tif ((OCTEON_IS_MODEL(OCTEON_CN73XX) && qlm == 6) ||\n+\t    (OCTEON_IS_MODEL(OCTEON_CNF75XX) && qlm == 5))\n+\t\tlmac = 2;\n+\telse\n+\t\tlmac = lane;\n+\n+\t/* No need to tune 10G-KR and 40G-KR interfaces */\n+\tpmd_control.u64 = csr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(lmac, bgx));\n+\tif (pmd_control.s.train_en)\n+\t\treturn;\n+\n+\tif (tx_pre != -1 && tx_post == -1)\n+\t\ttx_post = 0;\n+\n+\tif (tx_post != -1 && tx_pre == -1)\n+\t\ttx_pre = 0;\n+\n+\t/* Check tuning constraints */\n+\tif (tx_swing < -1 || tx_swing > 25) {\n+\t\tprintf(\"ERROR: N%d:QLM%d: Lane %d: Invalid TX_SWING(%d). TX_SWING must be <= 25.\\n\",\n+\t\t       node, qlm, lane, tx_swing);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_pre < -1 || tx_pre > 10) {\n+\t\tprintf(\"ERROR: N%d:QLM%d: Lane %d: Invalid TX_PRE(%d). TX_PRE must be <= 10.\\n\",\n+\t\t       node, qlm, lane, tx_swing);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_post < -1 || tx_post > 31) {\n+\t\tprintf(\"ERROR: N%d:QLM%d: Lane %d: Invalid TX_POST(%d). TX_POST must be <= 15.\\n\",\n+\t\t       node, qlm, lane, tx_swing);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_pre >= 0 && tx_post >= 0 && tx_swing >= 0 &&\n+\t    tx_pre + tx_post - tx_swing > 2) {\n+\t\tprintf(\"ERROR: N%d.QLM%d: Lane %d: TX_PRE(%d) + TX_POST(%d) - TX_SWING(%d) must be <= 2\\n\",\n+\t\t       node, qlm, lane, tx_pre, tx_post, tx_swing);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_pre >= 0 && tx_post >= 0 && tx_swing >= 0 &&\n+\t    tx_pre + tx_post + tx_swing > 35) {\n+\t\tprintf(\"ERROR: N%d.QLM%d: Lane %d: TX_PRE(%d) + TX_POST(%d) + TX_SWING(%d) must be <= 35\\n\",\n+\t\t       node, qlm, lane, tx_pre, tx_post, tx_swing);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_gain < -1 || tx_gain > 7) {\n+\t\tprintf(\"ERROR: N%d.QLM%d: Lane %d: Invalid TX_GAIN(%d). TX_GAIN must be between 0 and 7\\n\",\n+\t\t       node, qlm, lane, tx_gain);\n+\t\treturn;\n+\t}\n+\n+\tif (tx_vboost < -1 || tx_vboost > 1) {\n+\t\tprintf(\"ERROR: N%d.QLM%d: Lane %d: Invalid TX_VBOOST(%d).  TX_VBOOST must be 0 or 1.\\n\",\n+\t\t       node, qlm, lane, tx_vboost);\n+\t\treturn;\n+\t}\n+\n+\tdebug(\"N%d.QLM%d: Lane %d: TX_SWING=%d, TX_PRE=%d, TX_POST=%d, TX_GAIN=%d, TX_VBOOST=%d\\n\",\n+\t      node, qlm, lane, tx_swing, tx_pre, tx_post, tx_gain, tx_vboost);\n+\n+\t/* Complete the Tx swing and Tx equilization programming */\n+\t/* 1) Enable Tx swing and Tx emphasis overrides */\n+\ttx_cfg1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_1(lane, qlm));\n+\ttx_cfg1.s.tx_swing_ovrrd_en = (tx_swing != -1);\n+\ttx_cfg1.s.tx_premptap_ovrrd_val = (tx_pre != -1) && (tx_post != -1);\n+\ttx_cfg1.s.tx_vboost_en_ovrrd_en = (tx_vboost != -1); /* Vboost override */\n+\t;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_1(lane, qlm), tx_cfg1.u64);\n+\t/* 2) Program the Tx swing and Tx emphasis Pre-cursor and Post-cursor values */\n+\t/* CFG_TX_PREMPTAP[8:4] = Lane X's TX post-cursor value (C+1) */\n+\t/* CFG_TX_PREMPTAP[3:0] = Lane X's TX pre-cursor value (C-1) */\n+\tif (tx_swing != -1) {\n+\t\ttx_cfg0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(lane, qlm));\n+\t\ttx_cfg0.s.cfg_tx_swing = tx_swing;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(lane, qlm), tx_cfg0.u64);\n+\t}\n+\n+\tif ((tx_pre != -1) && (tx_post != -1)) {\n+\t\tpre_emphasis.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_PRE_EMPHASIS(lane, qlm));\n+\t\tpre_emphasis.s.cfg_tx_premptap = (tx_post << 4) | tx_pre;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_PRE_EMPHASIS(lane, qlm), pre_emphasis.u64);\n+\t}\n+\n+\t/* Apply TX gain settings */\n+\tif (tx_gain != -1) {\n+\t\ttx_cfg3.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm));\n+\t\ttx_cfg3.s.pcs_sds_tx_gain = tx_gain;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm), tx_cfg3.u64);\n+\t}\n+\n+\t/* Apply TX vboot settings */\n+\tif (tx_vboost != -1) {\n+\t\ttx_cfg3.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm));\n+\t\ttx_cfg3.s.cfg_tx_vboost_en = tx_vboost;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm), tx_cfg3.u64);\n+\t}\n+\n+\t/* 3) Program override for the Tx coefficient request */\n+\tpcs_ctlifc_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm));\n+\tif (((tx_pre != -1) && (tx_post != -1)) || (tx_swing != -1))\n+\t\tpcs_ctlifc_0.s.cfg_tx_coeff_req_ovrrd_val = 0x1;\n+\tif (tx_vboost != -1)\n+\t\tpcs_ctlifc_0.s.cfg_tx_vboost_en_ovrrd_val = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm), pcs_ctlifc_0.u64);\n+\n+\t/* 4) Enable the Tx coefficient request override enable */\n+\tpcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tif (((tx_pre != -1) && (tx_post != -1)) || (tx_swing != -1))\n+\t\tpcs_ctlifc_2.s.cfg_tx_coeff_req_ovrrd_en = 0x1;\n+\tif (tx_vboost != -1)\n+\t\tpcs_ctlifc_2.s.cfg_tx_vboost_en_ovrrd_en = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);\n+\n+\t/* 5) Issue a Control Interface Configuration Override request to start the Tx equalizer */\n+\tpcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tpcs_ctlifc_2.s.ctlifc_ovrrd_req = 0x1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);\n+\n+\t/* 6) Wait 1 ms for the request to complete */\n+\tudelay(1000);\n+\n+\t/* Steps 7 & 8 required for subsequent Tx swing and Tx equilization adjustment */\n+\t/* 7) Disable the Tx coefficient request override enable */\n+\tpcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tpcs_ctlifc_2.s.cfg_tx_coeff_req_ovrrd_en = 0;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);\n+\t/* 8) Issue a Control Interface Configuration Override request */\n+\tpcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\tpcs_ctlifc_2.s.ctlifc_ovrrd_req = 0x1;\n+\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);\n+}\n+\n+/**\n+ * Some QLM speeds need to override the default tuning parameters\n+ *\n+ * @param node     Node to configure\n+ * @param qlm      QLM to configure\n+ * @param baud_mhz Desired speed in MHz\n+ * @param tx_swing Voltage swing.  The higher the value the lower the voltage,\n+ *\t\t   the default value is 7.\n+ * @param tx_premptap bits [0:3] pre-cursor pre-emphasis, bits[4:8] post-cursor\n+ *\t\t      pre-emphasis.\n+ * @param tx_gain   Transmit gain. Range 0-7\n+ * @param tx_vboost Transmit voltage boost. Range 0-1\n+ *\n+ */\n+void octeon_qlm_tune_v3(int node, int qlm, int baud_mhz, int tx_swing, int tx_premptap, int tx_gain,\n+\t\t\tint tx_vboost)\n+{\n+\tint lane;\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\n+\tfor (lane = 0; lane < num_lanes; lane++) {\n+\t\tint tx_pre = (tx_premptap == -1) ? -1 : tx_premptap & 0xf;\n+\t\tint tx_post = (tx_premptap == -1) ? -1 : (tx_premptap >> 4) & 0x1f;\n+\n+\t\tocteon_qlm_tune_per_lane_v3(node, qlm, baud_mhz, lane, tx_swing, tx_pre, tx_post,\n+\t\t\t\t\t    tx_gain, tx_vboost);\n+\t}\n+}\n+\n+/**\n+ * Some QLMs need to override the default pre-ctle for low loss channels.\n+ *\n+ * @param node     Node to configure\n+ * @param qlm      QLM to configure\n+ * @param pre_ctle pre-ctle settings for low loss channels\n+ */\n+void octeon_qlm_set_channel_v3(int node, int qlm, int pre_ctle)\n+{\n+\tcvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;\n+\n+\tlane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));\n+\tlane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = pre_ctle;\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);\n+}\n+\n+static void __qlm_init_errata_20844(int node, int qlm)\n+{\n+\tint lane;\n+\n+\t/* Only applies to CN78XX pass 1.x */\n+\tif (!OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))\n+\t\treturn;\n+\n+\t/* Errata GSER-20844: Electrical Idle logic can coast\n+\t * 1) After the link first comes up write the following\n+\t * register on each lane to prevent the application logic\n+\t * from stomping on the Coast inputs. This is a one time write,\n+\t * or if you prefer you could put it in the link up loop and\n+\t * write it every time the link comes up.\n+\t * 1a) Then write GSER(0..13)_LANE(0..3)_PCS_CTLIFC_2\n+\t * Set CTLIFC_OVRRD_REQ (later)\n+\t * Set CFG_RX_CDR_COAST_REQ_OVRRD_EN\n+\t * Its not clear if #1 and #1a can be combined, lets try it\n+\t * this way first.\n+\t */\n+\tfor (lane = 0; lane < 4; lane++) {\n+\t\tcvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc_2;\n+\n+\t\tctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\t\tctlifc_2.s.cfg_rx_cdr_coast_req_ovrrd_en = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), ctlifc_2.u64);\n+\n+\t\tmisc_ovrrd.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm));\n+\t\tmisc_ovrrd.s.cfg_rx_eie_det_ovrrd_en = 1;\n+\t\tmisc_ovrrd.s.cfg_rx_eie_det_ovrrd_val = 0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm), misc_ovrrd.u64);\n+\n+\t\tudelay(1);\n+\n+\t\tmisc_ovrrd.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm));\n+\t\tmisc_ovrrd.s.cfg_rx_eie_det_ovrrd_en = 1;\n+\t\tmisc_ovrrd.s.cfg_rx_eie_det_ovrrd_val = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm), misc_ovrrd.u64);\n+\t\tctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));\n+\t\tctlifc_2.s.ctlifc_ovrrd_req = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), ctlifc_2.u64);\n+\t}\n+}\n+\n+/** CN78xx reference clock register settings */\n+struct refclk_settings_cn78xx {\n+\tbool valid; /** Reference clock speed supported */\n+\tunion cvmx_gserx_pll_px_mode_0 mode_0;\n+\tunion cvmx_gserx_pll_px_mode_1 mode_1;\n+\tunion cvmx_gserx_lane_px_mode_0 pmode_0;\n+\tunion cvmx_gserx_lane_px_mode_1 pmode_1;\n+};\n+\n+/** Default reference clock for various modes */\n+static const u8 def_ref_clk_cn78xx[R_NUM_LANE_MODES] = { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 };\n+\n+/**\n+ * This data structure stores the reference clock for each mode for each QLM.\n+ *\n+ * It is indexed first by the node number, then the QLM number and then the\n+ * lane mode.  It is initialized to the default values.\n+ */\n+static u8 ref_clk_cn78xx[CVMX_MAX_NODES][8][R_NUM_LANE_MODES] = {\n+\t{ { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },\n+\t{ { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },\n+\t{ { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },\n+\t{ { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },\n+\t  { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } }\n+};\n+\n+/**\n+ * This data structure contains the register values for the cn78xx PLLs\n+ * It is indexed first by the reference clock and second by the mode.\n+ * Note that not all combinations are supported.\n+ */\n+static const struct refclk_settings_cn78xx refclk_settings_cn78xx[R_NUM_LANE_MODES][4] = {\n+\t{   /* 0\tR_2_5G_REFCLK100 */\n+\t{ /* 100MHz reference clock */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 125MHz reference clock */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x1,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 156.25MHz reference clock */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x10 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } },\n+\t{\n+\t\t/* 1\tR_5G_REFCLK100 */\n+\t\t{ /* 100MHz reference clock */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t\t.pll_cpadj = 0x2,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x19 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x1,\n+\t\t\t\t .tx_ldiv = 0x0,\n+\t\t\t\t .rx_ldiv = 0x0,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x0,\n+\t\t\t\t .cdr_fgain = 0xa,\n+\t\t\t\t .ph_acc_adj = 0x14 } },\n+\t\t{ /* 125MHz reference clock */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t\t.pll_cpadj = 0x1,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x14 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x1,\n+\t\t\t\t .tx_ldiv = 0x0,\n+\t\t\t\t .rx_ldiv = 0x0,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x0,\n+\t\t\t\t .cdr_fgain = 0xa,\n+\t\t\t\t .ph_acc_adj = 0x14 } },\n+\t\t{ /* 156.25MHz reference clock */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t\t.pll_cpadj = 0x2,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x10 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x1,\n+\t\t\t\t .tx_ldiv = 0x0,\n+\t\t\t\t .rx_ldiv = 0x0,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x0,\n+\t\t\t\t .cdr_fgain = 0xa,\n+\t\t\t\t .ph_acc_adj = 0x14 } },\n+\t\t{\n+\t\t\t/* 161.1328125MHz reference clock */\n+\t\t\t.valid = false,\n+\t\t},\n+\t},\n+\t{   /* 2\tR_8G_REFCLK100 */\n+\t{ /* 100MHz reference clock */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x1,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x28 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xb,\n+\t\t\t   .ph_acc_adj = 0x23 } },\n+\t{ /* 125MHz reference clock */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x2, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x1,\n+\t\t\t  .pll_pcie3en = 0x1,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x20 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xb,\n+\t\t\t   .ph_acc_adj = 0x23 } },\n+\t{ /* 156.25MHz reference clock not supported */\n+\t    .valid = false } },\n+\t{\n+\t\t/* 3\tR_125G_REFCLK15625_KX */\n+\t\t{ /* 100MHz reference */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t\t.pll_cpadj = 0x2,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x19 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x0,\n+\t\t\t\t .tx_ldiv = 0x2,\n+\t\t\t\t .rx_ldiv = 0x2,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x1,\n+\t\t\t\t .cdr_fgain = 0xc,\n+\t\t\t\t .ph_acc_adj = 0x1e } },\n+\t\t{ /* 125MHz reference */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t\t.pll_cpadj = 0x2,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x14 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x0,\n+\t\t\t\t .tx_ldiv = 0x2,\n+\t\t\t\t .rx_ldiv = 0x2,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x1,\n+\t\t\t\t .cdr_fgain = 0xc,\n+\t\t\t\t .ph_acc_adj = 0x1e } },\n+\t\t{ /* 156.25MHz reference */\n+\t\t  .valid = true,\n+\t\t  .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t\t  .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t\t.pll_cpadj = 0x3,\n+\t\t\t\t.pll_pcie3en = 0x0,\n+\t\t\t\t.pll_opr = 0x0,\n+\t\t\t\t.pll_div = 0x10 },\n+\t\t  .pmode_0.s = { .ctle = 0x0,\n+\t\t\t\t .pcie = 0x0,\n+\t\t\t\t .tx_ldiv = 0x2,\n+\t\t\t\t .rx_ldiv = 0x2,\n+\t\t\t\t .srate = 0x0,\n+\t\t\t\t .tx_mode = 0x3,\n+\t\t\t\t .rx_mode = 0x3 },\n+\t\t  .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t\t .vma_mm = 0x1,\n+\t\t\t\t .cdr_fgain = 0xc,\n+\t\t\t\t .ph_acc_adj = 0x1e } },\n+\t\t{\n+\t\t\t/* 161.1328125MHz reference clock */\n+\t\t\t.valid = false,\n+\t\t},\n+\t},\n+\t{   /* 4\tR_3125G_REFCLK15625_XAUI */\n+\t{ /* 100MHz reference */\n+\t    .valid = false },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x14 },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{ /* 156.25MHz reference, default */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x14 },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } },\n+\t{   /* 5\tR_103125G_REFCLK15625_KR */\n+\t{ /* 100MHz reference */\n+\t    .valid = false },\n+\t{ /* 125MHz reference */\n+\t    .valid = false },\n+\t{ /* 156.25MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x21 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x1,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0xf } },\n+\t{ /* 161.1328125 reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x20 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x1,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0xf } } },\n+\t{   /* 6\tR_125G_REFCLK15625_SGMII */\n+\t{ /* 100MHz reference clock */\n+\t    .valid = 1,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x2,\n+\t\t\t   .rx_ldiv = 0x2,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{ /* 125MHz reference clock */\n+\t    .valid = 1,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x2,\n+\t\t\t   .rx_ldiv = 0x2,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{ /* 156.25MHz reference clock */\n+\t    .valid = 1,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },\n+\t    .mode_1.s = { .pll_16p5en = 0x1,\n+\t\t\t  .pll_cpadj = 0x3,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x10 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x2,\n+\t\t\t   .rx_ldiv = 0x2,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } } },\n+\t{   /* 7\tR_5G_REFCLK15625_QSGMII */\n+\t{ /* 100MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x2, .pll_pcie3en = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x1, .pll_pcie3en = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{ /* 156.25MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x2, .pll_pcie3en = 0x0,\n+\t\t\t  .pll_div = 0x10 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xc,\n+\t\t\t   .ph_acc_adj = 0x1e } },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } },\n+\t{   /* 8\tR_625G_REFCLK15625_RXAUI */\n+\t{ /* 100MHz reference */\n+\t    .valid = false },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 156.25MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 161.1328125 reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } } },\n+\t{   /* 9\tR_2_5G_REFCLK125 */\n+\t{ /* 100MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x1,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 156,25MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x10 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x1,\n+\t\t\t   .rx_ldiv = 0x1,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x1,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } },\n+\t{   /* 0xa\tR_5G_REFCLK125 */\n+\t{ /* 100MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x19 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x1,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x14 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{ /* 156.25MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x0,\n+\t\t\t  .pll_opr = 0x0,\n+\t\t\t  .pll_div = 0x10 },\n+\t    .pmode_0.s = { .ctle = 0x0,\n+\t\t\t   .pcie = 0x1,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xa,\n+\t\t\t   .ph_acc_adj = 0x14 } },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } },\n+\t{   /* 0xb\tR_8G_REFCLK125 */\n+\t{ /* 100MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x2,\n+\t\t\t  .pll_pcie3en = 0x1,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x28 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xb,\n+\t\t\t   .ph_acc_adj = 0x23 } },\n+\t{ /* 125MHz reference */\n+\t    .valid = true,\n+\t    .mode_0.s = { .pll_icp = 0x2, .pll_rloop = 0x5, .pll_pcs_div = 0xa },\n+\t    .mode_1.s = { .pll_16p5en = 0x0,\n+\t\t\t  .pll_cpadj = 0x1,\n+\t\t\t  .pll_pcie3en = 0x1,\n+\t\t\t  .pll_opr = 0x1,\n+\t\t\t  .pll_div = 0x20 },\n+\t    .pmode_0.s = { .ctle = 0x3,\n+\t\t\t   .pcie = 0x0,\n+\t\t\t   .tx_ldiv = 0x0,\n+\t\t\t   .rx_ldiv = 0x0,\n+\t\t\t   .srate = 0x0,\n+\t\t\t   .tx_mode = 0x3,\n+\t\t\t   .rx_mode = 0x3 },\n+\t    .pmode_1.s = { .vma_fine_cfg_sel = 0x0,\n+\t\t\t   .vma_mm = 0x0,\n+\t\t\t   .cdr_fgain = 0xb,\n+\t\t\t   .ph_acc_adj = 0x23 } },\n+\t{ /* 156.25MHz reference */\n+\t    .valid = false },\n+\t{\n+\t\t  /* 161.1328125MHz reference clock */\n+\t\t  .valid = false,\n+\t  } }\n+};\n+\n+/**\n+ * Set a non-standard reference clock for a node, qlm and lane mode.\n+ *\n+ * @INTERNAL\n+ *\n+ * @param node\t\tnode number the reference clock is used with\n+ * @param qlm\t\tqlm number the reference clock is hooked up to\n+ * @param lane_mode\tcurrent lane mode selected for the QLM\n+ * @param ref_clk_sel\t0 = 100MHz, 1 = 125MHz, 2 = 156.25MHz,\n+ *\t\t\t3 = 161.1328125MHz\n+ *\n+ * @return 0 for success or -1 if the reference clock selector is not supported\n+ *\n+ * NOTE: This must be called before __qlm_setup_pll_cn78xx.\n+ */\n+static int __set_qlm_ref_clk_cn78xx(int node, int qlm, int lane_mode, int ref_clk_sel)\n+{\n+\tif (ref_clk_sel > 3 || ref_clk_sel < 0 ||\n+\t    !refclk_settings_cn78xx[lane_mode][ref_clk_sel].valid) {\n+\t\tdebug(\"%s: Invalid reference clock %d for lane mode %d for node %d, QLM %d\\n\",\n+\t\t      __func__, ref_clk_sel, lane_mode, node, qlm);\n+\t\treturn -1;\n+\t}\n+\tdebug(\"%s(%d, %d, 0x%x, %d)\\n\", __func__, node, qlm, lane_mode, ref_clk_sel);\n+\tref_clk_cn78xx[node][qlm][lane_mode] = ref_clk_sel;\n+\treturn 0;\n+}\n+\n+/**\n+ * KR - Inverted Tx Coefficient Direction Change.  Changing Pre & Post Tap inc/dec direction\n+ *\n+ *\n+ * @INTERNAL\n+ *\n+ * @param node\tNode number to configure\n+ * @param qlm\tQLM number to configure\n+ */\n+static void __qlm_kr_inc_dec_gser26636(int node, int qlm)\n+{\n+\tcvmx_gserx_rx_txdir_ctrl_1_t rx_txdir_ctrl;\n+\n+\t/* Apply workaround for Errata GSER-26636,\n+\t * KR training coefficient update inverted\n+\t */\n+\trx_txdir_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm));\n+\trx_txdir_ctrl.s.rx_precorr_chg_dir = 1;\n+\trx_txdir_ctrl.s.rx_tap1_chg_dir = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm), rx_txdir_ctrl.u64);\n+}\n+\n+/**\n+ * Updating the RX EQ settings to support wider temperature range\n+ * @INTERNAL\n+ *\n+ * @param node\tNode number to configure\n+ * @param qlm\tQLM number to configure\n+ */\n+static void __qlm_rx_eq_temp_gser27140(int node, int qlm)\n+{\n+\tint lane;\n+\tint num_lanes = cvmx_qlm_get_lanes(qlm);\n+\tcvmx_gserx_lanex_rx_valbbd_ctrl_0_t rx_valbbd_ctrl_0;\n+\tcvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;\n+\tcvmx_gserx_lane_vma_fine_ctrl_0_t lane_vma_fine_ctrl_0;\n+\tcvmx_gserx_rx_txdir_ctrl_1_t rx_txdir_ctrl_1;\n+\tcvmx_gserx_eq_wait_time_t eq_wait_time;\n+\tcvmx_gserx_rx_txdir_ctrl_2_t rx_txdir_ctrl_2;\n+\tcvmx_gserx_rx_txdir_ctrl_0_t rx_txdir_ctrl_0;\n+\n+\tfor (lane = 0; lane < num_lanes; lane++) {\n+\t\trx_valbbd_ctrl_0.u64 =\n+\t\t\tcsr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(lane, qlm));\n+\t\trx_valbbd_ctrl_0.s.agc_gain = 3;\n+\t\trx_valbbd_ctrl_0.s.dfe_gain = 2;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(lane, qlm),\n+\t\t\t    rx_valbbd_ctrl_0.u64);\n+\t}\n+\n+\t/* do_pre_ctle_limits_work_around: */\n+\tlane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));\n+\t//lane_vma_fine_ctrl_2.s.rx_prectle_peak_max_fine = 11;\n+\tlane_vma_fine_ctrl_2.s.rx_prectle_gain_max_fine = 11;\n+\t//lane_vma_fine_ctrl_2.s.rx_prectle_peak_min_fine = 6;\n+\tlane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = 6;\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);\n+\n+\t/* do_inc_dec_thres_work_around: */\n+\trx_txdir_ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_0(qlm));\n+\trx_txdir_ctrl_0.s.rx_boost_hi_thrs = 11;\n+\trx_txdir_ctrl_0.s.rx_boost_lo_thrs = 4;\n+\trx_txdir_ctrl_0.s.rx_boost_hi_val = 15;\n+\tcsr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_0(qlm), rx_txdir_ctrl_0.u64);\n+\n+\t/* do_sdll_iq_work_around: */\n+\tlane_vma_fine_ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_0(qlm));\n+\tlane_vma_fine_ctrl_0.s.rx_sdll_iq_max_fine = 14;\n+\tlane_vma_fine_ctrl_0.s.rx_sdll_iq_min_fine = 8;\n+\tlane_vma_fine_ctrl_0.s.rx_sdll_iq_step_fine = 2;\n+\n+\t/* do_vma_window_work_around_2: */\n+\tlane_vma_fine_ctrl_0.s.vma_window_wait_fine = 5;\n+\tlane_vma_fine_ctrl_0.s.lms_wait_time_fine = 5;\n+\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_0(qlm), lane_vma_fine_ctrl_0.u64);\n+\n+\t/* Set dfe_tap_1_lo_thres_val: */\n+\trx_txdir_ctrl_1.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm));\n+\trx_txdir_ctrl_1.s.rx_tap1_lo_thrs = 8;\n+\trx_txdir_ctrl_1.s.rx_tap1_hi_thrs = 0x17;\n+\tcsr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm), rx_txdir_ctrl_1.u64);\n+\n+\t/* do_rxeq_wait_cnt_work_around: */\n+\teq_wait_time.u64 = csr_rd_node(node, CVMX_GSERX_EQ_WAIT_TIME(qlm));\n+\teq_wait_time.s.rxeq_wait_cnt = 6;\n+\tcsr_wr_node(node, CVMX_GSERX_EQ_WAIT_TIME(qlm), eq_wait_time.u64);\n+\n+\t/* do_write_rx_txdir_precorr_thresholds: */\n+\trx_txdir_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_2(qlm));\n+\trx_txdir_ctrl_2.s.rx_precorr_hi_thrs = 0xc0;\n+\trx_txdir_ctrl_2.s.rx_precorr_lo_thrs = 0x40;\n+\tcsr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_2(qlm), rx_txdir_ctrl_2.u64);\n+}\n+\n+/* Errata GSER-26150: 10G PHY PLL Temperature Failure\n+ * This workaround must be completed after the final deassertion of\n+ * GSERx_PHY_CTL[PHY_RESET]\n+ */\n+static int __qlm_errata_gser_26150(int node, int qlm, int is_pcie)\n+{\n+\tint num_lanes = 4;\n+\tint i;\n+\tcvmx_gserx_glbl_pll_cfg_3_t pll_cfg_3;\n+\tcvmx_gserx_glbl_misc_config_1_t misc_config_1;\n+\n+\t/* PCIe only requires the LC-VCO parameters to be updated */\n+\tif (is_pcie) {\n+\t\t/* Update PLL parameters */\n+\t\t/* Step 1: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and\n+\t\t * GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0\n+\t\t */\n+\t\tpll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));\n+\t\tpll_cfg_3.s.pcs_sds_pll_vco_amp = 0;\n+\t\tpll_cfg_3.s.pll_vctrl_sel_lcvco_val = 2;\n+\t\tcsr_wr_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm), pll_cfg_3.u64);\n+\n+\t\t/* Step 2: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */\n+\t\tmisc_config_1.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm));\n+\t\tmisc_config_1.s.pcs_sds_trim_chp_reg = 2;\n+\t\tcsr_wr_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm), misc_config_1.u64);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Applying this errata twice causes problems */\n+\tpll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));\n+\tif (pll_cfg_3.s.pll_vctrl_sel_lcvco_val == 0x2)\n+\t\treturn 0;\n+\n+\t/* (GSER-26150) 10 Gb temperature excursions can cause lock failure */\n+\t/* Change the calibration point of the VCO at start up to shift some\n+\t * available range of the VCO from -deltaT direction to the +deltaT\n+\t * ramp direction allowing a greater range of VCO temperatures before\n+\t * experiencing the failure.\n+\t */\n+\n+\t/* Check for DLMs on CN73XX and CNF75XX */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN73XX) && (qlm == 5 || qlm == 6))\n+\t\tnum_lanes = 2;\n+\n+\t/* Put PHY in P2 Power-down state  Need to Power down all lanes in a\n+\t * QLM/DLM to force PHY to P2 state\n+\t */\n+\tfor (i = 0; i < num_lanes; i++) {\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_0_t ctlifc0;\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_1_t ctlifc1;\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;\n+\n+\t\t/* Step 1: Set Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL]\n+\t\t * = 0x3\n+\t\t * Select P2 power state for Tx lane\n+\t\t */\n+\t\tctlifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm));\n+\t\tctlifc0.s.cfg_tx_pstate_req_ovrrd_val = 0x3;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm), ctlifc0.u64);\n+\t\t/* Step 2: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL]\n+\t\t * = 0x3\n+\t\t * Select P2 power state for Rx lane\n+\t\t */\n+\t\tctlifc1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm));\n+\t\tctlifc1.s.cfg_rx_pstate_req_ovrrd_val = 0x3;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm), ctlifc1.u64);\n+\t\t/* Step 3: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1\n+\t\t * Enable Tx power state override and Set\n+\t\t * GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1\n+\t\t * Enable Rx power state override\n+\t\t */\n+\t\tctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));\n+\t\tctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x1;\n+\t\tctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);\n+\t\t/* Step 4: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1\n+\t\t * Start the CTLIFC override state machine\n+\t\t */\n+\t\tctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));\n+\t\tctlifc2.s.ctlifc_ovrrd_req = 0x1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);\n+\t}\n+\n+\t/* Update PLL parameters */\n+\t/* Step 5: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and\n+\t * GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0\n+\t */\n+\tpll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));\n+\tpll_cfg_3.s.pcs_sds_pll_vco_amp = 0;\n+\tpll_cfg_3.s.pll_vctrl_sel_lcvco_val = 2;\n+\tcsr_wr_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm), pll_cfg_3.u64);\n+\n+\t/* Step 6: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */\n+\tmisc_config_1.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm));\n+\tmisc_config_1.s.pcs_sds_trim_chp_reg = 2;\n+\tcsr_wr_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm), misc_config_1.u64);\n+\n+\t/* Wake up PHY and transition to P0 Power-up state to bring-up the lanes,\n+\t * need to wake up all PHY lanes\n+\t */\n+\tfor (i = 0; i < num_lanes; i++) {\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_0_t ctlifc0;\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_1_t ctlifc1;\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;\n+\t\t/* Step 7: Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL] = 0x0\n+\t\t * Select P0 power state for Tx lane\n+\t\t */\n+\t\tctlifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm));\n+\t\tctlifc0.s.cfg_tx_pstate_req_ovrrd_val = 0x0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm), ctlifc0.u64);\n+\t\t/* Step 8: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL] = 0x0\n+\t\t * Select P0 power state for Rx lane\n+\t\t */\n+\t\tctlifc1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm));\n+\t\tctlifc1.s.cfg_rx_pstate_req_ovrrd_val = 0x0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm), ctlifc1.u64);\n+\t\t/* Step 9: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1\n+\t\t * Enable Tx power state override and Set\n+\t\t * GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1\n+\t\t * Enable Rx power state override\n+\t\t */\n+\t\tctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));\n+\t\tctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x1;\n+\t\tctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);\n+\t\t/* Step 10: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1\n+\t\t * Start the CTLIFC override state machine\n+\t\t */\n+\t\tctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));\n+\t\tctlifc2.s.ctlifc_ovrrd_req = 0x1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);\n+\t}\n+\n+\t/* Step 11: Wait 10 msec */\n+\tmdelay(10);\n+\n+\t/* Release Lane Tx/Rx Power state override enables. */\n+\tfor (i = 0; i < num_lanes; i++) {\n+\t\tcvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;\n+\n+\t\tctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));\n+\t\tctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x0;\n+\t\tctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x0;\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);\n+\t}\n+\n+\t/* Step 12:  Poll GSER()_PLL_STAT.[PLL_LOCK] = 1\n+\t * Poll and check that PLL is locked\n+\t */\n+\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,\n+\t\t\t\t       pll_lock, ==, 1, 10000)) {\n+\t\tprintf(\"%d:QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\\n\", node, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Step 13:  Poll GSER()_QLM_STAT.[RST_RDY] = 1\n+\t * Poll and check that QLM/DLM is Ready\n+\t */\n+\tif (is_pcie == 0 &&\n+\t    CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,\n+\t\t\t\t       rst_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"%d:QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\", node, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Configure all of the PLLs for a particular node and qlm\n+ * @INTERNAL\n+ *\n+ * @param node\tNode number to configure\n+ * @param qlm\tQLM number to configure\n+ */\n+static void __qlm_setup_pll_cn78xx(int node, int qlm)\n+{\n+\tcvmx_gserx_pll_px_mode_0_t mode_0;\n+\tcvmx_gserx_pll_px_mode_1_t mode_1;\n+\tcvmx_gserx_lane_px_mode_0_t pmode_0;\n+\tcvmx_gserx_lane_px_mode_1_t pmode_1;\n+\tint lane_mode;\n+\tint ref_clk;\n+\tconst struct refclk_settings_cn78xx *clk_settings;\n+\n+\tfor (lane_mode = 0; lane_mode < R_NUM_LANE_MODES; lane_mode++) {\n+\t\tmode_0.u64 = csr_rd_node(node, CVMX_GSERX_PLL_PX_MODE_0(lane_mode, qlm));\n+\t\tmode_1.u64 = csr_rd_node(node, CVMX_GSERX_PLL_PX_MODE_1(lane_mode, qlm));\n+\t\tpmode_0.u64 = 0;\n+\t\tpmode_1.u64 = 0;\n+\t\tref_clk = ref_clk_cn78xx[node][qlm][lane_mode];\n+\t\tclk_settings = &refclk_settings_cn78xx[lane_mode][ref_clk];\n+\t\tdebug(\"%s(%d, %d): lane_mode: 0x%x, ref_clk: %d\\n\", __func__, node, qlm, lane_mode,\n+\t\t      ref_clk);\n+\n+\t\tif (!clk_settings->valid) {\n+\t\t\tprintf(\"%s: Error: reference clock %d is not supported for lane mode %d on qlm %d\\n\",\n+\t\t\t       __func__, ref_clk, lane_mode, qlm);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tmode_0.s.pll_icp = clk_settings->mode_0.s.pll_icp;\n+\t\tmode_0.s.pll_rloop = clk_settings->mode_0.s.pll_rloop;\n+\t\tmode_0.s.pll_pcs_div = clk_settings->mode_0.s.pll_pcs_div;\n+\n+\t\tmode_1.s.pll_16p5en = clk_settings->mode_1.s.pll_16p5en;\n+\t\tmode_1.s.pll_cpadj = clk_settings->mode_1.s.pll_cpadj;\n+\t\tmode_1.s.pll_pcie3en = clk_settings->mode_1.s.pll_pcie3en;\n+\t\tmode_1.s.pll_opr = clk_settings->mode_1.s.pll_opr;\n+\t\tmode_1.s.pll_div = clk_settings->mode_1.s.pll_div;\n+\n+\t\tpmode_0.u64 = clk_settings->pmode_0.u64;\n+\n+\t\tpmode_1.u64 = clk_settings->pmode_1.u64;\n+\n+\t\tcsr_wr_node(node, CVMX_GSERX_PLL_PX_MODE_1(lane_mode, qlm), mode_1.u64);\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_0(lane_mode, qlm), pmode_0.u64);\n+\t\tcsr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_1(lane_mode, qlm), pmode_1.u64);\n+\t\tcsr_wr_node(node, CVMX_GSERX_PLL_PX_MODE_0(lane_mode, qlm), mode_0.u64);\n+\t}\n+}\n+\n+/**\n+ * Get the lane mode for the specified node and QLM.\n+ *\n+ * @param ref_clk_sel\tThe reference-clock selection to use to configure QLM\n+ *\t\t\t 0 = REF_100MHZ\n+ *\t\t\t 1 = REF_125MHZ\n+ *\t\t\t 2 = REF_156MHZ\n+ * @param baud_mhz   The speed the QLM needs to be configured in Mhz.\n+ * @param[out] alt_pll_settings\tIf non-NULL this will be set if non-default PLL\n+ *\t\t\t\tsettings are required for the mode.\n+ *\n+ * @return lane mode to use or -1 on error\n+ *\n+ * NOTE: In some modes\n+ */\n+static int __get_lane_mode_for_speed_and_ref_clk(int ref_clk_sel, int baud_mhz,\n+\t\t\t\t\t\t bool *alt_pll_settings)\n+{\n+\tif (alt_pll_settings)\n+\t\t*alt_pll_settings = false;\n+\tswitch (baud_mhz) {\n+\tcase 98304:\n+\tcase 49152:\n+\tcase 24576:\n+\tcase 12288:\n+\t\tif (ref_clk_sel != 3) {\n+\t\t\tprintf(\"Error: Invalid ref clock\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\treturn 0x5;\n+\tcase 6144:\n+\tcase 3072:\n+\t\tif (ref_clk_sel != 3) {\n+\t\t\tprintf(\"Error: Invalid ref clock\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\treturn 0x8;\n+\tcase 1250:\n+\t\tif (alt_pll_settings)\n+\t\t\t*alt_pll_settings = (ref_clk_sel != 2);\n+\t\treturn R_125G_REFCLK15625_SGMII;\n+\tcase 2500:\n+\t\tif (ref_clk_sel == 0)\n+\t\t\treturn R_2_5G_REFCLK100;\n+\n+\t\tif (alt_pll_settings)\n+\t\t\t*alt_pll_settings = (ref_clk_sel != 1);\n+\t\treturn R_2_5G_REFCLK125;\n+\tcase 3125:\n+\t\tif (ref_clk_sel == 2) {\n+\t\t\treturn R_3125G_REFCLK15625_XAUI;\n+\t\t} else if (ref_clk_sel == 1) {\n+\t\t\tif (alt_pll_settings)\n+\t\t\t\t*alt_pll_settings = true;\n+\t\t\treturn R_3125G_REFCLK15625_XAUI;\n+\t\t}\n+\n+\t\tprintf(\"Error: Invalid speed\\n\");\n+\t\treturn -1;\n+\tcase 5000:\n+\t\tif (ref_clk_sel == 0) {\n+\t\t\treturn R_5G_REFCLK100;\n+\t\t} else if (ref_clk_sel == 1) {\n+\t\t\tif (alt_pll_settings)\n+\t\t\t\t*alt_pll_settings = (ref_clk_sel != 1);\n+\t\t\treturn R_5G_REFCLK125;\n+\t\t} else {\n+\t\t\treturn R_5G_REFCLK15625_QSGMII;\n+\t\t}\n+\tcase 6250:\n+\t\tif (ref_clk_sel != 0) {\n+\t\t\tif (alt_pll_settings)\n+\t\t\t\t*alt_pll_settings = (ref_clk_sel != 2);\n+\t\t\treturn R_625G_REFCLK15625_RXAUI;\n+\t\t}\n+\n+\t\tprintf(\"Error: Invalid speed\\n\");\n+\t\treturn -1;\n+\tcase 6316:\n+\t\tif (ref_clk_sel != 3) {\n+\t\t\tprintf(\"Error: Invalid speed\\n\");\n+\t\t} else {\n+\t\t\t*alt_pll_settings = true;\n+\t\t\treturn R_625G_REFCLK15625_RXAUI;\n+\t\t}\n+\tcase 8000:\n+\t\tif (ref_clk_sel == 0)\n+\t\t\treturn R_8G_REFCLK100;\n+\t\telse if (ref_clk_sel == 1)\n+\t\t\treturn R_8G_REFCLK125;\n+\n+\t\tprintf(\"Error: Invalid speed\\n\");\n+\t\treturn -1;\n+\tcase 103125:\n+\t\tif (ref_clk_sel == 3 && alt_pll_settings)\n+\t\t\t*alt_pll_settings = true;\n+\n+\t\tif (ref_clk_sel == 2 || ref_clk_sel == 3)\n+\t\t\treturn R_103125G_REFCLK15625_KR;\n+\n+\tdefault:\n+\t\tprintf(\"Error: Invalid speed\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/*\n+ * Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout\n+ * during speed change. Change SLI_WINDOW_CTL[time] to 525us\n+ */\n+static void __set_sli_window_ctl_errata_31375(int node)\n+{\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX) || OCTEON_IS_MODEL(OCTEON_CN73XX) ||\n+\t    OCTEON_IS_MODEL(OCTEON_CNF75XX)) {\n+\t\tcvmx_sli_window_ctl_t window_ctl;\n+\n+\t\twindow_ctl.u64 = csr_rd_node(node, CVMX_PEXP_SLI_WINDOW_CTL);\n+\t\t/* Configure SLI_WINDOW_CTL only once */\n+\t\tif (window_ctl.s.time != 8191)\n+\t\t\treturn;\n+\n+\t\twindow_ctl.s.time = gd->bus_clk * 525ull / 1000000;\n+\t\tcsr_wr_node(node, CVMX_PEXP_SLI_WINDOW_CTL, window_ctl.u64);\n+\t}\n+}\n+\n+static void __cvmx_qlm_pcie_errata_ep_cn78xx(int node, int pem)\n+{\n+\tcvmx_pciercx_cfg031_t cfg031;\n+\tcvmx_pciercx_cfg032_t cfg032;\n+\tcvmx_pciercx_cfg040_t cfg040;\n+\tcvmx_pemx_cfg_t pemx_cfg;\n+\tcvmx_pemx_on_t pemx_on;\n+\tint low_qlm, high_qlm;\n+\tint qlm, lane;\n+\tu64 start_cycle;\n+\n+\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(pem));\n+\n+\t/* Errata (GSER-21178) PCIe gen3 doesn't work, continued */\n+\n+\t/* Wait for the link to come up as Gen1 */\n+\tprintf(\"PCIe%d: Waiting for EP out of reset\\n\", pem);\n+\twhile (pemx_on.s.pemoor == 0) {\n+\t\tudelay(1000);\n+\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(pem));\n+\t}\n+\n+\t/* Enable gen3 speed selection */\n+\tprintf(\"PCIe%d: Enabling Gen3 for EP\\n\", pem);\n+\t/* Force Gen1 for initial link bringup. We'll fix it later */\n+\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));\n+\tpemx_cfg.s.md = 2;\n+\tcsr_wr_node(node, CVMX_PEMX_CFG(pem), pemx_cfg.u64);\n+\tcfg031.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG031(pem));\n+\tcfg031.s.mls = 2;\n+\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG031(pem), cfg031.u32);\n+\tcfg040.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG040(pem));\n+\tcfg040.s.tls = 3;\n+\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG040(pem), cfg040.u32);\n+\n+\t/* Wait up to 10ms for the link speed change to complete */\n+\tstart_cycle = get_timer(0);\n+\tdo {\n+\t\tif (get_timer(start_cycle) > 10)\n+\t\t\treturn;\n+\n+\t\tmdelay(1);\n+\t\tcfg032.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG032(pem));\n+\t} while (cfg032.s.ls != 3);\n+\n+\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));\n+\tlow_qlm = pem; /* FIXME */\n+\thigh_qlm = (pemx_cfg.cn78xx.lanes8) ? low_qlm + 1 : low_qlm;\n+\n+\t/* Toggle cfg_rx_dll_locken_ovrrd_en and rx_resetn_ovrrd_en across\n+\t * all QM lanes in use\n+\t */\n+\tfor (qlm = low_qlm; qlm <= high_qlm; qlm++) {\n+\t\tfor (lane = 0; lane < 4; lane++) {\n+\t\t\tcvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;\n+\t\t\tcvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;\n+\n+\t\t\tmisc_ovrrd.u64 =\n+\t\t\t\tcsr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem));\n+\t\t\tmisc_ovrrd.s.cfg_rx_dll_locken_ovrrd_en = 1;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem),\n+\t\t\t\t    misc_ovrrd.u64);\n+\t\t\tpwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem));\n+\t\t\tpwr_ctrl.s.rx_resetn_ovrrd_en = 1;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem), pwr_ctrl.u64);\n+\t\t}\n+\t}\n+\tfor (qlm = low_qlm; qlm <= high_qlm; qlm++) {\n+\t\tfor (lane = 0; lane < 4; lane++) {\n+\t\t\tcvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;\n+\t\t\tcvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;\n+\n+\t\t\tmisc_ovrrd.u64 =\n+\t\t\t\tcsr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem));\n+\t\t\tmisc_ovrrd.s.cfg_rx_dll_locken_ovrrd_en = 0;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem),\n+\t\t\t\t    misc_ovrrd.u64);\n+\t\t\tpwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem));\n+\t\t\tpwr_ctrl.s.rx_resetn_ovrrd_en = 0;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem), pwr_ctrl.u64);\n+\t\t}\n+\t}\n+\n+\t//printf(\"PCIe%d: Waiting for EP link up at Gen3\\n\", pem);\n+\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_PEMX_ON(pem), cvmx_pemx_on_t, pemoor, ==, 1,\n+\t\t\t\t       1000000)) {\n+\t\tprintf(\"PCIe%d: Timeout waiting for EP link up at Gen3\\n\", pem);\n+\t\treturn;\n+\t}\n+}\n+\n+static void __cvmx_qlm_pcie_errata_cn78xx(int node, int qlm)\n+{\n+\tint pem, i, q;\n+\tint is_8lanes;\n+\tint is_high_lanes;\n+\tint low_qlm, high_qlm, is_host;\n+\tint need_ep_monitor;\n+\tcvmx_pemx_cfg_t pem_cfg, pem3_cfg;\n+\tcvmx_gserx_slice_cfg_t slice_cfg;\n+\tcvmx_gserx_rx_pwr_ctrl_p1_t pwr_ctrl_p1;\n+\tcvmx_rst_soft_prstx_t soft_prst;\n+\n+\t/* Only applies to CN78XX pass 1.x */\n+\tif (!OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))\n+\t\treturn;\n+\n+\t/* Determine the PEM for this QLM, whether we're in 8 lane mode,\n+\t * and whether these are the top lanes of the 8\n+\t */\n+\tswitch (qlm) {\n+\tcase 0: /* First 4 lanes of PEM0 */\n+\t\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));\n+\t\tpem = 0;\n+\t\tis_8lanes = pem_cfg.cn78xx.lanes8;\n+\t\tis_high_lanes = 0;\n+\t\tbreak;\n+\tcase 1: /* Either last 4 lanes of PEM0, or PEM1 */\n+\t\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));\n+\t\tpem = (pem_cfg.cn78xx.lanes8) ? 0 : 1;\n+\t\tis_8lanes = pem_cfg.cn78xx.lanes8;\n+\t\tis_high_lanes = is_8lanes;\n+\t\tbreak;\n+\tcase 2: /* First 4 lanes of PEM2 */\n+\t\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\tpem = 2;\n+\t\tis_8lanes = pem_cfg.cn78xx.lanes8;\n+\t\tis_high_lanes = 0;\n+\t\tbreak;\n+\tcase 3: /* Either last 4 lanes of PEM2, or PEM3 */\n+\t\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\tpem3_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\tpem = (pem_cfg.cn78xx.lanes8) ? 2 : 3;\n+\t\tis_8lanes = (pem == 2) ? pem_cfg.cn78xx.lanes8 : pem3_cfg.cn78xx.lanes8;\n+\t\tis_high_lanes = (pem == 2) && is_8lanes;\n+\t\tbreak;\n+\tcase 4: /* Last 4 lanes of PEM3 */\n+\t\tpem = 3;\n+\t\tis_8lanes = 1;\n+\t\tis_high_lanes = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn;\n+\t}\n+\n+\t/* These workaround must be applied once per PEM. Since we're called per\n+\t * QLM, wait for the 2nd half of 8 lane setups before doing the workaround\n+\t */\n+\tif (is_8lanes && !is_high_lanes)\n+\t\treturn;\n+\n+\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));\n+\tis_host = pem_cfg.cn78xx.hostmd;\n+\tlow_qlm = (is_8lanes) ? qlm - 1 : qlm;\n+\thigh_qlm = qlm;\n+\tqlm = -1;\n+\n+\tif (!is_host) {\n+\t\t/* Read the current slice config value. If its at the value we will\n+\t\t * program then skip doing the workaround. We're probably doing a\n+\t\t * hot reset and the workaround is already applied\n+\t\t */\n+\t\tslice_cfg.u64 = csr_rd_node(node, CVMX_GSERX_SLICE_CFG(low_qlm));\n+\t\tif (slice_cfg.s.tx_rx_detect_lvl_enc == 7 && OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))\n+\t\t\treturn;\n+\t}\n+\n+\tif (is_host && OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {\n+\t\t/* (GSER-XXXX) GSER PHY needs to be reset at initialization */\n+\t\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\n+\t\tfor (q = low_qlm; q <= high_qlm; q++) {\n+\t\t\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(q));\n+\t\t\tphy_ctl.s.phy_reset = 1;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(q), phy_ctl.u64);\n+\t\t}\n+\t\tudelay(5);\n+\n+\t\tfor (q = low_qlm; q <= high_qlm; q++) {\n+\t\t\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(q));\n+\t\t\tphy_ctl.s.phy_reset = 0;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(q), phy_ctl.u64);\n+\t\t}\n+\t\tudelay(5);\n+\t}\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {\n+\t\t/* (GSER-20936) GSER has wrong PCIe RX detect reset value */\n+\t\tfor (q = low_qlm; q <= high_qlm; q++) {\n+\t\t\tslice_cfg.u64 = csr_rd_node(node, CVMX_GSERX_SLICE_CFG(q));\n+\t\t\tslice_cfg.s.tx_rx_detect_lvl_enc = 7;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_SLICE_CFG(q), slice_cfg.u64);\n+\t\t}\n+\n+\t\t/* Clear the bit in GSERX_RX_PWR_CTRL_P1[p1_rx_subblk_pd]\n+\t\t * that coresponds to \"Lane DLL\"\n+\t\t */\n+\t\tfor (q = low_qlm; q <= high_qlm; q++) {\n+\t\t\tpwr_ctrl_p1.u64 = csr_rd_node(node, CVMX_GSERX_RX_PWR_CTRL_P1(q));\n+\t\t\tpwr_ctrl_p1.s.p1_rx_subblk_pd &= ~4;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_RX_PWR_CTRL_P1(q), pwr_ctrl_p1.u64);\n+\t\t}\n+\n+\t\t/* Errata (GSER-20888) GSER incorrect synchronizers hurts PCIe\n+\t\t * Override TX Power State machine TX reset control signal\n+\t\t */\n+\t\tfor (q = low_qlm; q <= high_qlm; q++) {\n+\t\t\tfor (i = 0; i < 4; i++) {\n+\t\t\t\tcvmx_gserx_lanex_tx_cfg_0_t tx_cfg;\n+\t\t\t\tcvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;\n+\n+\t\t\t\ttx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(i, q));\n+\t\t\t\ttx_cfg.s.tx_resetn_ovrrd_val = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(i, q), tx_cfg.u64);\n+\t\t\t\tpwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(i, q));\n+\t\t\t\tpwr_ctrl.s.tx_p2s_resetn_ovrrd_en = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(i, q), pwr_ctrl.u64);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (!is_host) {\n+\t\tcvmx_pciercx_cfg089_t cfg089;\n+\t\tcvmx_pciercx_cfg090_t cfg090;\n+\t\tcvmx_pciercx_cfg091_t cfg091;\n+\t\tcvmx_pciercx_cfg092_t cfg092;\n+\t\tcvmx_pciercx_cfg548_t cfg548;\n+\t\tcvmx_pciercx_cfg554_t cfg554;\n+\n+\t\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {\n+\t\t\t/* Errata (GSER-21178) PCIe gen3 doesn't work */\n+\t\t\t/* The starting equalization hints are incorrect on CN78XX pass 1.x. Fix\n+\t\t\t * them for the 8 possible lanes. It doesn't hurt to program them even\n+\t\t\t * for lanes not in use\n+\t\t\t */\n+\t\t\tcfg089.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG089(pem));\n+\t\t\tcfg089.s.l1urph = 2;\n+\t\t\tcfg089.s.l1utp = 7;\n+\t\t\tcfg089.s.l0urph = 2;\n+\t\t\tcfg089.s.l0utp = 7;\n+\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG089(pem), cfg089.u32);\n+\t\t\tcfg090.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG090(pem));\n+\t\t\tcfg090.s.l3urph = 2;\n+\t\t\tcfg090.s.l3utp = 7;\n+\t\t\tcfg090.s.l2urph = 2;\n+\t\t\tcfg090.s.l2utp = 7;\n+\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG090(pem), cfg090.u32);\n+\t\t\tcfg091.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG091(pem));\n+\t\t\tcfg091.s.l5urph = 2;\n+\t\t\tcfg091.s.l5utp = 7;\n+\t\t\tcfg091.s.l4urph = 2;\n+\t\t\tcfg091.s.l4utp = 7;\n+\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG091(pem), cfg091.u32);\n+\t\t\tcfg092.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG092(pem));\n+\t\t\tcfg092.s.l7urph = 2;\n+\t\t\tcfg092.s.l7utp = 7;\n+\t\t\tcfg092.s.l6urph = 2;\n+\t\t\tcfg092.s.l6utp = 7;\n+\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG092(pem), cfg092.u32);\n+\t\t\t/* FIXME: Disable phase 2 and phase 3 equalization */\n+\t\t\tcfg548.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG548(pem));\n+\t\t\tcfg548.s.ep2p3d = 1;\n+\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG548(pem), cfg548.u32);\n+\t\t}\n+\t\t/* Errata (GSER-21331) GEN3 Equalization may fail */\n+\t\t/* Disable preset #10 and disable the 2ms timeout */\n+\t\tcfg554.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG554(pem));\n+\t\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))\n+\t\t\tcfg554.s.p23td = 1;\n+\t\tcfg554.s.prv = 0x3ff;\n+\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG554(pem), cfg554.u32);\n+\n+\t\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {\n+\t\t\tneed_ep_monitor = (pem_cfg.s.md == 2);\n+\t\t\tif (need_ep_monitor) {\n+\t\t\t\tcvmx_pciercx_cfg031_t cfg031;\n+\t\t\t\tcvmx_pciercx_cfg040_t cfg040;\n+\n+\t\t\t\t/* Force Gen1 for initial link bringup. We'll\n+\t\t\t\t * fix it later\n+\t\t\t\t */\n+\t\t\t\tpem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));\n+\t\t\t\tpem_cfg.s.md = 0;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(pem), pem_cfg.u64);\n+\t\t\t\tcfg031.u32 = cvmx_pcie_cfgx_read_node(node, pem,\n+\t\t\t\t\t\t\t\t      CVMX_PCIERCX_CFG031(pem));\n+\t\t\t\tcfg031.s.mls = 0;\n+\t\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG031(pem),\n+\t\t\t\t\t\t\t  cfg031.u32);\n+\t\t\t\tcfg040.u32 = cvmx_pcie_cfgx_read_node(node, pem,\n+\t\t\t\t\t\t\t\t      CVMX_PCIERCX_CFG040(pem));\n+\t\t\t\tcfg040.s.tls = 1;\n+\t\t\t\tcvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG040(pem),\n+\t\t\t\t\t\t\t  cfg040.u32);\n+\t\t\t\t__cvmx_qlm_pcie_errata_ep_cn78xx(node, pem);\n+\t\t\t}\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {\n+\t\t/* De-assert the SOFT_RST bit for this QLM (PEM), causing the PCIe\n+\t\t * workarounds code above to take effect.\n+\t\t */\n+\t\tsoft_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(pem));\n+\t\tsoft_prst.s.soft_prst = 0;\n+\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(pem), soft_prst.u64);\n+\t\tudelay(1);\n+\n+\t\t/* Assert the SOFT_RST bit for this QLM (PEM), putting the PCIe back into\n+\t\t * reset state with disturbing the workarounds.\n+\t\t */\n+\t\tsoft_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(pem));\n+\t\tsoft_prst.s.soft_prst = 1;\n+\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(pem), soft_prst.u64);\n+\t}\n+\tudelay(1);\n+}\n+\n+/**\n+ * Setup the PEM to either driver or receive reset from PRST based on RC or EP\n+ *\n+ * @param node   Node to use in a Numa setup\n+ * @param pem    Which PEM to setuo\n+ * @param is_endpoint\n+ *               Non zero if PEM is a EP\n+ */\n+static void __setup_pem_reset(int node, int pem, int is_endpoint)\n+{\n+\tcvmx_rst_ctlx_t rst_ctl;\n+\n+\t/* Make sure is_endpoint is either 0 or 1 */\n+\tis_endpoint = (is_endpoint != 0);\n+\trst_ctl.u64 = csr_rd_node(node, CVMX_RST_CTLX(pem));\n+\trst_ctl.s.prst_link = 0;\t  /* Link down causes soft reset */\n+\trst_ctl.s.rst_link = is_endpoint; /* EP PERST causes a soft reset */\n+\trst_ctl.s.rst_drv = !is_endpoint; /* Drive if RC */\n+\trst_ctl.s.rst_rcv = is_endpoint;  /* Only read PERST in EP mode */\n+\trst_ctl.s.rst_chip = 0;\t\t  /* PERST doesn't pull CHIP_RESET */\n+\tcsr_wr_node(node, CVMX_RST_CTLX(pem), rst_ctl.u64);\n+}\n+\n+/**\n+ * Configure QLM speed and mode for cn78xx.\n+ *\n+ * @param node    Node to configure the QLM\n+ * @param qlm     The QLM to configure\n+ * @param baud_mhz   The speed the QLM needs to be configured in Mhz.\n+ * @param mode    The QLM to be configured as SGMII/XAUI/PCIe.\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.\n+ * @param gen3    Only used for PCIe\n+ *\t\t\tgen3 = 2 GEN3 mode\n+ *\t\t\tgen3 = 1 GEN2 mode\n+ *\t\t\tgen3 = 0 GEN1 mode\n+ *\n+ * @param ref_clk_sel    The reference-clock selection to use to configure QLM\n+ *\t\t\t 0 = REF_100MHZ\n+ *\t\t\t 1 = REF_125MHZ\n+ *\t\t\t 2 = REF_156MHZ\n+ *\t\t\t 3 = REF_161MHZ\n+ * @param ref_clk_input  The reference-clock input to use to configure QLM\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+int octeon_configure_qlm_cn78xx(int node, int qlm, int baud_mhz, int mode, int rc, int gen3,\n+\t\t\t\tint ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_lane_mode_t lmode;\n+\tcvmx_gserx_cfg_t cfg;\n+\tcvmx_gserx_refclk_sel_t refclk_sel;\n+\n+\tint is_pcie = 0;\n+\tint is_ilk = 0;\n+\tint is_bgx = 0;\n+\tint lane_mode = 0;\n+\tint lmac_type = 0;\n+\tbool alt_pll = false;\n+\tint num_ports = 0;\n+\tint lane_to_sds = 0;\n+\n+\tdebug(\"%s(node: %d, qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\\n\",\n+\t      __func__, node, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);\n+\tif (OCTEON_IS_MODEL(OCTEON_CN76XX) && qlm > 4) {\n+\t\tdebug(\"%s: qlm %d not present on CN76XX\\n\", __func__, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout\n+\t * during speed change. Change SLI_WINDOW_CTL[time] to 525us\n+\t */\n+\t__set_sli_window_ctl_errata_31375(node);\n+\n+\tcfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\t/* If PEM is in EP, no need to do anything */\n+\n+\tif (cfg.s.pcie && rc == 0) {\n+\t\tdebug(\"%s: node %d, qlm %d is in PCIe endpoint mode, returning\\n\",\n+\t\t      __func__, node, qlm);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Set the reference clock to use */\n+\trefclk_sel.u64 = 0;\n+\tif (ref_clk_input == 0) { /* External ref clock */\n+\t\trefclk_sel.s.com_clk_sel = 0;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else if (ref_clk_input == 1) {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 1;\n+\t}\n+\n+\tcsr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\n+\t/* Reset the QLM after changing the reference clock */\n+\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 1;\n+\tphy_ctl.s.phy_pd = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\tudelay(1000);\n+\n+\t/* Always restore the reference clocks for a QLM */\n+\tmemcpy(ref_clk_cn78xx[node][qlm], def_ref_clk_cn78xx, sizeof(def_ref_clk_cn78xx));\n+\tswitch (mode) {\n+\tcase CVMX_QLM_MODE_PCIE:\n+\tcase CVMX_QLM_MODE_PCIE_1X8: {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\t\tcvmx_pemx_on_t pemx_on;\n+\n+\t\tis_pcie = 1;\n+\n+\t\tif (ref_clk_sel == 0) {\n+\t\t\trefclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 0;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK100;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK100;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK100;\n+\t\t} else if (ref_clk_sel == 1) {\n+\t\t\trefclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 1;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK125;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK125;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK125;\n+\t\t} else {\n+\t\t\tprintf(\"Invalid reference clock for PCIe on QLM%d\\n\", qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either x4 or x8 based on PEM0 */\n+\t\t{\n+\t\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\n+\t\t\trst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(0));\n+\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);\n+\t\t\t__setup_pem_reset(node, 0, !rc);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));\n+\t\t\tpemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);\n+\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(0), pemx_cfg.u64);\n+\t\t\t/* x8 mode waits for QLM1 setup before turning on the PEM */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 1: /* Either PEM0 x8 or PEM1 x4 */\n+\t\t{\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\t\t\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\n+\t\t\t\trst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(1));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(node, 1, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(1));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(1));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(1), pemx_on.u64);\n+\t\t\t} else {\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(0), pemx_on.u64);\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_rst_soft_prstx_t rst_prst;\n+\n+\t\t\trst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(2));\n+\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(2), rst_prst.u64);\n+\t\t\t__setup_pem_reset(node, 2, !rc);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));\n+\t\t\tpemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);\n+\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(2), pemx_cfg.u64);\n+\t\t\t/* x8 mode waits for QLM3 setup before turning on the PEM */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(2));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(2), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 3: /* Either PEM2 x8 or PEM3 x4 */\n+\t\t{\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/* Last 4 lanes of PEM2 */\n+\t\t\t\t/* PEMX_CFG already setup */\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(2));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(2), pemx_on.u64);\n+\t\t\t}\n+\t\t\t/* Check if PEM3 uses QLM3 and in x4 lane mode */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\n+\t\t\t\trst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(3));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(node, 3, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(3), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 4: /* Either PEM3 x4 or PEM3 x8 */\n+\t\t{\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE_1X8) {\n+\t\t\t\t/* Last 4 lanes of PEM3 */\n+\t\t\t\t/* PEMX_CFG already setup */\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);\n+\t\t\t} else {\n+\t\t\t\t/* 4 lanes of PEM3 */\n+\t\t\t\tcvmx_pemx_qlm_t pemx_qlm;\n+\t\t\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\n+\t\t\t\trst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(3));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr_node(node, CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(node, 3, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_CFG(3), pemx_cfg.u64);\n+\t\t\t\t/* PEM3 is on QLM4 */\n+\t\t\t\tpemx_qlm.u64 = csr_rd_node(node, CVMX_PEMX_QLM(3));\n+\t\t\t\tpemx_qlm.cn78xx.pem3qlm = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_QLM(3), pemx_qlm.u64);\n+\t\t\t\tpemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\tcase CVMX_QLM_MODE_ILK:\n+\t\tis_ilk = 1;\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\t/* FIXME: Set lane_mode for other speeds */\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_SGMII:\n+\t\tis_bgx = 1;\n+\t\tlmac_type = 0;\n+\t\tlane_to_sds = 1;\n+\t\tnum_ports = 4;\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tdebug(\"%s: SGMII lane mode: %d, alternate PLL: %s\\n\", __func__, lane_mode,\n+\t\t      alt_pll ? \"true\" : \"false\");\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_XAUI:\n+\t\tis_bgx = 5;\n+\t\tlmac_type = 1;\n+\t\tlane_to_sds = 0xe4;\n+\t\tnum_ports = 1;\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tdebug(\"%s: XAUI lane mode: %d\\n\", __func__, lane_mode);\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RXAUI:\n+\t\tis_bgx = 3;\n+\t\tlmac_type = 2;\n+\t\tlane_to_sds = 0;\n+\t\tnum_ports = 2;\n+\t\tdebug(\"%s: RXAUI lane mode: %d\\n\", __func__, lane_mode);\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_XFI: /* 10GR_4X1 */\n+\tcase CVMX_QLM_MODE_10G_KR:\n+\t\tis_bgx = 1;\n+\t\tlmac_type = 3;\n+\t\tlane_to_sds = 1;\n+\t\tnum_ports = 4;\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tdebug(\"%s: XFI/10G_KR lane mode: %d\\n\", __func__, lane_mode);\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_XLAUI: /* 40GR4_1X4 */\n+\tcase CVMX_QLM_MODE_40G_KR4:\n+\t\tis_bgx = 5;\n+\t\tlmac_type = 4;\n+\t\tlane_to_sds = 0xe4;\n+\t\tnum_ports = 1;\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\t\tdebug(\"%s: XLAUI/40G_KR4 lane mode: %d\\n\", __func__, lane_mode);\n+\t\tif (lane_mode == -1)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_DISABLED:\n+\t\t/* Power down the QLM */\n+\t\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\t\tphy_ctl.s.phy_pd = 1;\n+\t\tphy_ctl.s.phy_reset = 1;\n+\t\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\t\t/* Disable all modes */\n+\t\tcsr_wr_node(node, CVMX_GSERX_CFG(qlm), 0);\n+\t\t/* Do nothing */\n+\t\treturn 0;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (alt_pll) {\n+\t\tdebug(\"%s: alternate PLL settings used for node %d, qlm %d, lane mode %d, reference clock %d\\n\",\n+\t\t      __func__, node, qlm, lane_mode, ref_clk_sel);\n+\t\tif (__set_qlm_ref_clk_cn78xx(node, qlm, lane_mode, ref_clk_sel)) {\n+\t\t\tprintf(\"%s: Error: reference clock %d is not supported for node %d, qlm %d\\n\",\n+\t\t\t       __func__, ref_clk_sel, node, qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* Power up PHY, but keep it in reset */\n+\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_pd = 0;\n+\tphy_ctl.s.phy_reset = 1;\n+\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/* Errata GSER-20788: GSER(0..13)_CFG[BGX_QUAD]=1 is broken. Force the\n+\t * BGX_QUAD bit to be clear for CN78XX pass 1.x\n+\t */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))\n+\t\tis_bgx &= 3;\n+\n+\t/* Set GSER for the interface mode */\n+\tcfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\tcfg.s.ila = is_ilk;\n+\tcfg.s.bgx = is_bgx & 1;\n+\tcfg.s.bgx_quad = (is_bgx >> 2) & 1;\n+\tcfg.s.bgx_dual = (is_bgx >> 1) & 1;\n+\tcfg.s.pcie = is_pcie;\n+\tcsr_wr_node(node, CVMX_GSERX_CFG(qlm), cfg.u64);\n+\n+\t/* Lane mode */\n+\tlmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));\n+\tlmode.s.lmode = lane_mode;\n+\tcsr_wr_node(node, CVMX_GSERX_LANE_MODE(qlm), lmode.u64);\n+\n+\t/* BGX0-1 can connect to QLM0-1 or QLM 2-3. Program the select bit if we're\n+\t * one of these QLMs and we're using BGX\n+\t */\n+\tif (qlm < 4 && is_bgx) {\n+\t\tint bgx = qlm & 1;\n+\t\tint use_upper = (qlm >> 1) & 1;\n+\t\tcvmx_bgxx_cmr_global_config_t global_cfg;\n+\n+\t\tglobal_cfg.u64 = csr_rd_node(node, CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx));\n+\t\tglobal_cfg.s.pmux_sds_sel = use_upper;\n+\t\tcsr_wr_node(node, CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx), global_cfg.u64);\n+\t}\n+\n+\t/* Bring phy out of reset */\n+\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 0;\n+\tcsr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\tcsr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\n+\t/*\n+\t * Wait 250 ns until the management interface is ready to accept\n+\t * read/write commands.\n+\t */\n+\tudelay(1);\n+\n+\tif (is_bgx) {\n+\t\tint bgx = (qlm < 2) ? qlm : qlm - 2;\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tint index;\n+\n+\t\tfor (index = 0; index < num_ports; index++) {\n+\t\t\tcmr_config.u64 = csr_rd_node(node, CVMX_BGXX_CMRX_CONFIG(index, bgx));\n+\t\t\tcmr_config.s.enable = 0;\n+\t\t\tcmr_config.s.data_pkt_tx_en = 0;\n+\t\t\tcmr_config.s.data_pkt_rx_en = 0;\n+\t\t\tcmr_config.s.lmac_type = lmac_type;\n+\t\t\tcmr_config.s.lane_to_sds = ((lane_to_sds == 1) ?\n+\t\t\t\t\t\t    index : ((lane_to_sds == 0) ?\n+\t\t\t\t\t\t\t     (index ? 0xe : 4) :\n+\t\t\t\t\t\t\t     lane_to_sds));\n+\t\t\tcsr_wr_node(node, CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);\n+\t\t}\n+\t\tcsr_wr_node(node, CVMX_BGXX_CMR_TX_LMACS(bgx), num_ports);\n+\t\tcsr_wr_node(node, CVMX_BGXX_CMR_RX_LMACS(bgx), num_ports);\n+\n+\t\t/* Enable/disable training for 10G_KR/40G_KR4/XFI/XLAUI modes */\n+\t\tfor (index = 0; index < num_ports; index++) {\n+\t\t\tcvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;\n+\n+\t\t\tspu_pmd_control.u64 =\n+\t\t\t\tcsr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));\n+\n+\t\t\tif (mode == CVMX_QLM_MODE_10G_KR || mode == CVMX_QLM_MODE_40G_KR4)\n+\t\t\t\tspu_pmd_control.s.train_en = 1;\n+\t\t\telse if (mode == CVMX_QLM_MODE_XFI || mode == CVMX_QLM_MODE_XLAUI)\n+\t\t\t\tspu_pmd_control.s.train_en = 0;\n+\n+\t\t\tcsr_wr_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),\n+\t\t\t\t    spu_pmd_control.u64);\n+\t\t}\n+\t}\n+\n+\t/* Configure the gser pll */\n+\tif (!is_pcie)\n+\t\t__qlm_setup_pll_cn78xx(node, qlm);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\tif (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_PLL_STAT(qlm),\n+\t\t\t\t       cvmx_gserx_pll_stat_t,\n+\t\t\t\t       pll_lock, ==, 1, 10000)) {\n+\t\tprintf(\"%d:QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\\n\",\n+\t\t       node, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Perform PCIe errata workaround */\n+\tif (is_pcie)\n+\t\t__cvmx_qlm_pcie_errata_cn78xx(node, qlm);\n+\telse\n+\t\t__qlm_init_errata_20844(node, qlm);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\t/* PCIe mode doesn't become ready until the PEM block attempts to bring\n+\t * the interface up. Skip this check for PCIe\n+\t */\n+\tif (!is_pcie && CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_QLM_STAT(qlm),\n+\t\t\t\t\t\t   cvmx_gserx_qlm_stat_t, rst_rdy,\n+\t\t\t\t\t\t   ==, 1, 10000)) {\n+\t\tprintf(\"%d:QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\",\n+\t\t       node, qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Errata GSER-26150: 10G PHY PLL Temperature Failure */\n+\t/* This workaround must be completed after the final deassertion of\n+\t * GSERx_PHY_CTL[PHY_RESET].\n+\t * Apply the workaround to 10.3125Gbps and 8Gbps only.\n+\t */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) &&\n+\t    (baud_mhz == 103125 || (is_pcie && gen3 == 2)))\n+\t\t__qlm_errata_gser_26150(0, qlm, is_pcie);\n+\n+\t/* Errata GSER-26636: 10G-KR/40G-KR - Inverted Tx Coefficient Direction\n+\t * Change. Applied to all 10G standards (required for KR) but also\n+\t * applied to other standards in case software training is used\n+\t */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && baud_mhz == 103125)\n+\t\t__qlm_kr_inc_dec_gser26636(node, qlm);\n+\n+\t/* Errata GSER-25992: RX EQ Default Settings Update (CTLE Bias) */\n+\t/* This workaround will only be applied to Pass 1.x */\n+\t/* It will also only be applied if the SERDES data-rate is 10G */\n+\t/* or if PCIe Gen3 (gen3=2 is PCIe Gen3) */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) &&\n+\t    (baud_mhz == 103125 || (is_pcie && gen3 == 2)))\n+\t\tcvmx_qlm_gser_errata_25992(node, qlm);\n+\n+\t/* Errata GSER-27140: Updating the RX EQ settings due to temperature\n+\t * drift sensitivities\n+\t */\n+\t/* This workaround will also only be applied if the SERDES data-rate is 10G */\n+\tif (baud_mhz == 103125)\n+\t\t__qlm_rx_eq_temp_gser27140(node, qlm);\n+\n+\t/* Reduce the voltage amplitude coming from Marvell PHY and also change\n+\t * DFE threshold settings for RXAUI interface\n+\t */\n+\tif (is_bgx && mode == CVMX_QLM_MODE_RXAUI) {\n+\t\tint l;\n+\n+\t\tfor (l = 0; l < 4; l++) {\n+\t\t\tcvmx_gserx_lanex_rx_cfg_4_t cfg4;\n+\t\t\tcvmx_gserx_lanex_tx_cfg_0_t cfg0;\n+\t\t\t/* Change the Q/QB error sampler 0 threshold from 0xD to 0xF */\n+\t\t\tcfg4.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_4(l, qlm));\n+\t\t\tcfg4.s.cfg_rx_errdet_ctrl = 0xcf6f;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_4(l, qlm), cfg4.u64);\n+\t\t\t/* Reduce the voltage swing to roughly 460mV */\n+\t\t\tcfg0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(l, qlm));\n+\t\t\tcfg0.s.cfg_tx_swing = 0x12;\n+\t\t\tcsr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(l, qlm), cfg0.u64);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int __is_qlm_valid_bgx_cn73xx(int qlm)\n+{\n+\tif (qlm == 2 || qlm == 3 || qlm == 5 || qlm == 6)\n+\t\treturn 0;\n+\treturn 1;\n+}\n+\n+/**\n+ * Configure QLM/DLM speed and mode for cn73xx.\n+ *\n+ * @param qlm     The QLM to configure\n+ * @param baud_mhz   The speed the QLM needs to be configured in Mhz.\n+ * @param mode    The QLM to be configured as SGMII/XAUI/PCIe.\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.\n+ * @param gen3    Only used for PCIe\n+ *\t\t\tgen3 = 2 GEN3 mode\n+ *\t\t\tgen3 = 1 GEN2 mode\n+ *\t\t\tgen3 = 0 GEN1 mode\n+ *\n+ * @param ref_clk_sel   The reference-clock selection to use to configure QLM\n+ *\t\t\t0 = REF_100MHZ\n+ *\t\t\t1 = REF_125MHZ\n+ *\t\t\t2 = REF_156MHZ\n+ *\t\t\t3 = REF_161MHZ\n+ *\n+ * @param ref_clk_input  The reference-clock input to use to configure QLM\n+ *\t\t\t 0 = QLM/DLM reference clock input\n+ *\t\t\t 1 = common reference clock input 0\n+ *\t\t\t 2 = common reference clock input 1\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+static int octeon_configure_qlm_cn73xx(int qlm, int baud_mhz, int mode, int rc, int gen3,\n+\t\t\t\t       int ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_lane_mode_t lmode;\n+\tcvmx_gserx_cfg_t cfg;\n+\tcvmx_gserx_refclk_sel_t refclk_sel;\n+\tint is_pcie = 0;\n+\tint is_bgx = 0;\n+\tint lane_mode = 0;\n+\tshort lmac_type[4] = { 0 };\n+\tshort sds_lane[4] = { 0 };\n+\tbool alt_pll = false;\n+\tint enable_training = 0;\n+\tint additional_lmacs = 0;\n+\n+\tdebug(\"%s(qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\\n\",\n+\t      __func__, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);\n+\n+\t/* Don't configure QLM4 if it is not in SATA mode */\n+\tif (qlm == 4) {\n+\t\tif (mode == CVMX_QLM_MODE_SATA_2X1)\n+\t\t\treturn __setup_sata(qlm, baud_mhz, ref_clk_sel, ref_clk_input);\n+\n+\t\tprintf(\"Invalid mode for QLM4\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tcfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\n+\t/* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout\n+\t * during speed change. Change SLI_WINDOW_CTL[time] to 525us\n+\t */\n+\t__set_sli_window_ctl_errata_31375(0);\n+\t/* If PEM is in EP, no need to do anything */\n+\tif (cfg.s.pcie && rc == 0 &&\n+\t    (mode == CVMX_QLM_MODE_PCIE || mode == CVMX_QLM_MODE_PCIE_1X8 ||\n+\t     mode == CVMX_QLM_MODE_PCIE_1X2)) {\n+\t\tdebug(\"%s: qlm %d is in PCIe endpoint mode, returning\\n\", __func__, qlm);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Set the reference clock to use */\n+\trefclk_sel.u64 = 0;\n+\tif (ref_clk_input == 0) { /* External ref clock */\n+\t\trefclk_sel.s.com_clk_sel = 0;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else if (ref_clk_input == 1) {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 1;\n+\t}\n+\n+\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\n+\t/* Reset the QLM after changing the reference clock */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 1;\n+\tphy_ctl.s.phy_pd = 1;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\tudelay(1000);\n+\n+\t/* Check if QLM is a valid BGX interface */\n+\tif (mode != CVMX_QLM_MODE_PCIE && mode != CVMX_QLM_MODE_PCIE_1X2 &&\n+\t    mode != CVMX_QLM_MODE_PCIE_1X8) {\n+\t\tif (__is_qlm_valid_bgx_cn73xx(qlm))\n+\t\t\treturn -1;\n+\t}\n+\n+\tswitch (mode) {\n+\tcase CVMX_QLM_MODE_PCIE:\n+\tcase CVMX_QLM_MODE_PCIE_1X2:\n+\tcase CVMX_QLM_MODE_PCIE_1X8: {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\t\tcvmx_pemx_on_t pemx_on;\n+\t\tcvmx_pemx_qlm_t pemx_qlm;\n+\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\t\tint port = 0;\n+\n+\t\tis_pcie = 1;\n+\n+\t\tif (qlm < 5 && mode == CVMX_QLM_MODE_PCIE_1X2) {\n+\t\t\tprintf(\"Invalid PCIe mode(%d) for QLM%d\\n\", mode, qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (ref_clk_sel == 0) {\n+\t\t\trefclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK100;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK100;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK100;\n+\t\t} else if (ref_clk_sel == 1) {\n+\t\t\trefclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 1;\n+\t\t\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK125;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK125;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK125;\n+\t\t} else {\n+\t\t\tprintf(\"Invalid reference clock for PCIe on QLM%d\\n\", qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either x4 or x8 based on PEM0 */\n+\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(0));\n+\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);\n+\t\t\t__setup_pem_reset(0, 0, !rc);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\t\tpemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);\n+\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);\n+\t\t\t/* x8 mode waits for QLM1 setup before turning on the PEM */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 1: /* Either PEM0 x8 or PEM1 x4 */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(1));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(0, 1, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(1), pemx_on.u64);\n+\t\t\t} else { /* x8 mode */\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 2: /* Either PEM2 x4 or PEM2 x8 or BGX0 */\n+\t\t{\n+\t\t\tpemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(2));\n+\t\t\tpemx_qlm.cn73xx.pemdlmsel = 0;\n+\t\t\tcsr_wr(CVMX_PEMX_QLM(2), pemx_qlm.u64);\n+\n+\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(2));\n+\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(2), rst_prst.u64);\n+\t\t\t__setup_pem_reset(0, 2, !rc);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));\n+\t\t\tpemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);\n+\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(2), pemx_cfg.u64);\n+\t\t\t/* x8 mode waits for QLM3 setup before turning on the PEM */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(2), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tcase 3: /* Either PEM2 x8 or PEM3 x4 or BGX1 */\n+\t\t\t/* PEM2/PEM3 are configured to use QLM2/3 */\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/* Last 4 lanes of PEM2 */\n+\t\t\t\t/* PEMX_CFG already setup */\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(2), pemx_on.u64);\n+\t\t\t}\n+\t\t\t/* Check if PEM3 uses QLM3 and in x4 lane mode */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE) {\n+\t\t\t\tpemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(3));\n+\t\t\t\tpemx_qlm.cn73xx.pemdlmsel = 0;\n+\t\t\t\tcsr_wr(CVMX_PEMX_QLM(3), pemx_qlm.u64);\n+\n+\t\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(3));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(0, 3, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(3));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr(CVMX_PEMX_CFG(3), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(3));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(3), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 5: /* PEM2/PEM3 x2 or BGX2 */\n+\t\tcase 6:\n+\t\t\tport = (qlm == 5) ? 2 : 3;\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE_1X2) {\n+\t\t\t\t/* PEM2/PEM3 are configured to use DLM5/6 */\n+\t\t\t\tpemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(port));\n+\t\t\t\tpemx_qlm.cn73xx.pemdlmsel = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_QLM(port), pemx_qlm.u64);\n+\t\t\t\t/* 2 lanes of PEM3 */\n+\t\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(port));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(port), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(0, port, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(port));\n+\t\t\t\tpemx_cfg.cn78xx.lanes8 = 0;\n+\t\t\t\tpemx_cfg.cn78xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cn78xx.md = gen3;\n+\t\t\t\tcsr_wr(CVMX_PEMX_CFG(port), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(port));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(port), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\tcase CVMX_QLM_MODE_SGMII:\n+\t\tis_bgx = 1;\n+\t\tlmac_type[0] = 0;\n+\t\tlmac_type[1] = 0;\n+\t\tlmac_type[2] = 0;\n+\t\tlmac_type[3] = 0;\n+\t\tsds_lane[0] = 0;\n+\t\tsds_lane[1] = 1;\n+\t\tsds_lane[2] = 2;\n+\t\tsds_lane[3] = 3;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_SGMII_2X1:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = 0;\n+\t\t\tlmac_type[1] = 0;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[1] = 1;\n+\t\t} else if (qlm == 6) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = -1;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 0;\n+\t\t\tlmac_type[3] = 0;\n+\t\t\tsds_lane[2] = 2;\n+\t\t\tsds_lane[3] = 3;\n+\t\t\tadditional_lmacs = 2;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_XAUI:\n+\t\tis_bgx = 5;\n+\t\tlmac_type[0] = 1;\n+\t\tlmac_type[1] = -1;\n+\t\tlmac_type[2] = -1;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0xe4;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RXAUI:\n+\t\tis_bgx = 3;\n+\t\tlmac_type[0] = 2;\n+\t\tlmac_type[1] = 2;\n+\t\tlmac_type[2] = -1;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0x4;\n+\t\tsds_lane[1] = 0xe;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RXAUI_1X2:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 3;\n+\t\t\tlmac_type[0] = 2;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0x4;\n+\t\t}\n+\t\tif (qlm == 6) {\n+\t\t\tis_bgx = 3;\n+\t\t\tlmac_type[0] = -1;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 2;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[2] = 0xe;\n+\t\t\tadditional_lmacs = 2;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_10G_KR:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_XFI: /* 10GR_4X1 */\n+\t\tis_bgx = 1;\n+\t\tlmac_type[0] = 3;\n+\t\tlmac_type[1] = 3;\n+\t\tlmac_type[2] = 3;\n+\t\tlmac_type[3] = 3;\n+\t\tsds_lane[0] = 0;\n+\t\tsds_lane[1] = 1;\n+\t\tsds_lane[2] = 2;\n+\t\tsds_lane[3] = 3;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_10G_KR_1X2:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_XFI_1X2:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = 3;\n+\t\t\tlmac_type[1] = 3;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[1] = 1;\n+\t\t} else if (qlm == 6) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = -1;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 3;\n+\t\t\tlmac_type[3] = 3;\n+\t\t\tsds_lane[2] = 2;\n+\t\t\tsds_lane[3] = 3;\n+\t\t\tadditional_lmacs = 2;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_40G_KR4:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_XLAUI: /* 40GR4_1X4 */\n+\t\tis_bgx = 5;\n+\t\tlmac_type[0] = 4;\n+\t\tlmac_type[1] = -1;\n+\t\tlmac_type[2] = -1;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0xe4;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_SGMII:\n+\t\tis_bgx = 1;\n+\t\tlmac_type[0] = 5;\n+\t\tlmac_type[1] = 0;\n+\t\tlmac_type[2] = 0;\n+\t\tlmac_type[3] = 0;\n+\t\tsds_lane[0] = 0;\n+\t\tsds_lane[1] = 1;\n+\t\tsds_lane[2] = 2;\n+\t\tsds_lane[3] = 3;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_SGMII_1X1:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = 5;\n+\t\t\tlmac_type[1] = 0;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[1] = 1;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_SGMII_2X1:\n+\t\tif (qlm == 6) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = 5;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 0;\n+\t\t\tlmac_type[3] = 0;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[2] = 0;\n+\t\t\tsds_lane[3] = 1;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_10G_KR:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_RGMII_XFI:\n+\t\tis_bgx = 1;\n+\t\tlmac_type[0] = 5;\n+\t\tlmac_type[1] = 3;\n+\t\tlmac_type[2] = 3;\n+\t\tlmac_type[3] = 3;\n+\t\tsds_lane[0] = 0;\n+\t\tsds_lane[1] = 1;\n+\t\tsds_lane[2] = 2;\n+\t\tsds_lane[3] = 3;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_10G_KR_1X1:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_RGMII_XFI_1X1:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 3;\n+\t\t\tlmac_type[0] = 5;\n+\t\t\tlmac_type[1] = 3;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[1] = 1;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_40G_KR4:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_RGMII_XLAUI:\n+\t\tis_bgx = 5;\n+\t\tlmac_type[0] = 5;\n+\t\tlmac_type[1] = 4;\n+\t\tlmac_type[2] = -1;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0x0;\n+\t\tsds_lane[1] = 0xe4;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_RXAUI:\n+\t\tis_bgx = 3;\n+\t\tlmac_type[0] = 5;\n+\t\tlmac_type[1] = 2;\n+\t\tlmac_type[2] = 2;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0x0;\n+\t\tsds_lane[1] = 0x4;\n+\t\tsds_lane[2] = 0xe;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_RGMII_XAUI:\n+\t\tis_bgx = 5;\n+\t\tlmac_type[0] = 5;\n+\t\tlmac_type[1] = 1;\n+\t\tlmac_type[2] = -1;\n+\t\tlmac_type[3] = -1;\n+\t\tsds_lane[0] = 0;\n+\t\tsds_lane[1] = 0xe4;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (is_pcie == 0)\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);\n+\tdebug(\"%s: %d lane mode: %d, alternate PLL: %s\\n\", __func__, mode, lane_mode,\n+\t      alt_pll ? \"true\" : \"false\");\n+\tif (lane_mode == -1)\n+\t\treturn -1;\n+\n+\tif (alt_pll) {\n+\t\tdebug(\"%s: alternate PLL settings used for qlm %d, lane mode %d, reference clock %d\\n\",\n+\t\t      __func__, qlm, lane_mode, ref_clk_sel);\n+\t\tif (__set_qlm_ref_clk_cn78xx(0, qlm, lane_mode, ref_clk_sel)) {\n+\t\t\tprintf(\"%s: Error: reference clock %d is not supported for qlm %d, lane mode: 0x%x\\n\",\n+\t\t\t       __func__, ref_clk_sel, qlm, lane_mode);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* Power up PHY, but keep it in reset */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_pd = 0;\n+\tphy_ctl.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/* Set GSER for the interface mode */\n+\tcfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\tcfg.s.bgx = is_bgx & 1;\n+\tcfg.s.bgx_quad = (is_bgx >> 2) & 1;\n+\tcfg.s.bgx_dual = (is_bgx >> 1) & 1;\n+\tcfg.s.pcie = is_pcie;\n+\tcsr_wr(CVMX_GSERX_CFG(qlm), cfg.u64);\n+\n+\t/* Lane mode */\n+\tlmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));\n+\tlmode.s.lmode = lane_mode;\n+\tcsr_wr(CVMX_GSERX_LANE_MODE(qlm), lmode.u64);\n+\n+\t/* Program lmac_type to figure out the type of BGX interface configured */\n+\tif (is_bgx) {\n+\t\tint bgx = (qlm < 4) ? qlm - 2 : 2;\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tcvmx_bgxx_cmr_rx_lmacs_t rx_lmacs;\n+\t\tcvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;\n+\t\tint index, total_lmacs = 0;\n+\n+\t\tfor (index = 0; index < 4; index++) {\n+\t\t\tcmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));\n+\t\t\tcmr_config.s.enable = 0;\n+\t\t\tcmr_config.s.data_pkt_rx_en = 0;\n+\t\t\tcmr_config.s.data_pkt_tx_en = 0;\n+\t\t\tif (lmac_type[index] != -1) {\n+\t\t\t\tcmr_config.s.lmac_type = lmac_type[index];\n+\t\t\t\tcmr_config.s.lane_to_sds = sds_lane[index];\n+\t\t\t\ttotal_lmacs++;\n+\t\t\t\t/* RXAUI takes up 2 lmacs */\n+\t\t\t\tif (lmac_type[index] == 2)\n+\t\t\t\t\ttotal_lmacs += 1;\n+\t\t\t}\n+\t\t\tcsr_wr(CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);\n+\n+\t\t\t/* Errata (TBD) RGMII doesn't turn on clock if its by\n+\t\t\t * itself. Force them on\n+\t\t\t */\n+\t\t\tif (lmac_type[index] == 5) {\n+\t\t\t\tcvmx_bgxx_cmr_global_config_t global_config;\n+\n+\t\t\t\tglobal_config.u64 = csr_rd(CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx));\n+\t\t\t\tglobal_config.s.bgx_clk_enable = 1;\n+\t\t\t\tcsr_wr(CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx), global_config.u64);\n+\t\t\t}\n+\n+\t\t\t/* Enable training for 10G_KR/40G_KR4 modes */\n+\t\t\tif (enable_training == 1 &&\n+\t\t\t    (lmac_type[index] == 3 || lmac_type[index] == 4)) {\n+\t\t\t\tspu_pmd_control.u64 =\n+\t\t\t\t\tcsr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));\n+\t\t\t\tspu_pmd_control.s.train_en = 1;\n+\t\t\t\tcsr_wr(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),\n+\t\t\t\t       spu_pmd_control.u64);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Update the total number of lmacs */\n+\t\trx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(bgx));\n+\t\trx_lmacs.s.lmacs = total_lmacs + additional_lmacs;\n+\t\tcsr_wr(CVMX_BGXX_CMR_RX_LMACS(bgx), rx_lmacs.u64);\n+\t\tcsr_wr(CVMX_BGXX_CMR_TX_LMACS(bgx), rx_lmacs.u64);\n+\t}\n+\n+\t/* Bring phy out of reset */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/*\n+\t * Wait 1us until the management interface is ready to accept\n+\t * read/write commands.\n+\t */\n+\tudelay(1);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\t/* PCIe mode doesn't become ready until the PEM block attempts to bring\n+\t * the interface up. Skip this check for PCIe\n+\t */\n+\tif (!is_pcie && CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm),\n+\t\t\t\t\t      cvmx_gserx_qlm_stat_t,\n+\t\t\t\t\t      rst_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Configure the gser pll */\n+\tif (!is_pcie)\n+\t\t__qlm_setup_pll_cn78xx(0, qlm);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,\n+\t\t\t\t  pll_lock, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Errata GSER-26150: 10G PHY PLL Temperature Failure */\n+\t/* This workaround must be completed after the final deassertion of\n+\t * GSERx_PHY_CTL[PHY_RESET].\n+\t * Apply the workaround to 10.3125Gbps and 8Gbps only.\n+\t */\n+\tif (OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) &&\n+\t    (baud_mhz == 103125 || (is_pcie && gen3 == 2)))\n+\t\t__qlm_errata_gser_26150(0, qlm, is_pcie);\n+\n+\t/* Errata GSER-26636: 10G-KR/40G-KR - Inverted Tx Coefficient Direction\n+\t * Change. Applied to all 10G standards (required for KR) but also\n+\t * applied to other standards in case software training is used\n+\t */\n+\tif (baud_mhz == 103125)\n+\t\t__qlm_kr_inc_dec_gser26636(0, qlm);\n+\n+\t/* Errata GSER-25992: RX EQ Default Settings Update (CTLE Bias) */\n+\t/* This workaround will only be applied to Pass 1.x */\n+\t/* It will also only be applied if the SERDES data-rate is 10G */\n+\t/* or if PCIe Gen3 (gen3=2 is PCIe Gen3) */\n+\tif (baud_mhz == 103125 || (is_pcie && gen3 == 2))\n+\t\tcvmx_qlm_gser_errata_25992(0, qlm);\n+\n+\t/* Errata GSER-27140: Updating the RX EQ settings due to temperature\n+\t * drift sensitivities\n+\t */\n+\t/* This workaround will also only be applied if the SERDES data-rate is 10G */\n+\tif (baud_mhz == 103125)\n+\t\t__qlm_rx_eq_temp_gser27140(0, qlm);\n+\n+\t/* Reduce the voltage amplitude coming from Marvell PHY and also change\n+\t * DFE threshold settings for RXAUI interface\n+\t */\n+\tif (is_bgx) {\n+\t\tint l;\n+\n+\t\tfor (l = 0; l < 4; l++) {\n+\t\t\tcvmx_gserx_lanex_rx_cfg_4_t cfg4;\n+\t\t\tcvmx_gserx_lanex_tx_cfg_0_t cfg0;\n+\n+\t\t\tif (lmac_type[l] == 2) {\n+\t\t\t\t/* Change the Q/QB error sampler 0 threshold from 0xD to 0xF */\n+\t\t\t\tcfg4.u64 = csr_rd(CVMX_GSERX_LANEX_RX_CFG_4(l, qlm));\n+\t\t\t\tcfg4.s.cfg_rx_errdet_ctrl = 0xcf6f;\n+\t\t\t\tcsr_wr(CVMX_GSERX_LANEX_RX_CFG_4(l, qlm), cfg4.u64);\n+\t\t\t\t/* Reduce the voltage swing to roughly 460mV */\n+\t\t\t\tcfg0.u64 = csr_rd(CVMX_GSERX_LANEX_TX_CFG_0(l, qlm));\n+\t\t\t\tcfg0.s.cfg_tx_swing = 0x12;\n+\t\t\t\tcsr_wr(CVMX_GSERX_LANEX_TX_CFG_0(l, qlm), cfg0.u64);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int __rmac_pll_config(int baud_mhz, int qlm, int mode)\n+{\n+\tcvmx_gserx_pll_px_mode_0_t pmode0;\n+\tcvmx_gserx_pll_px_mode_1_t pmode1;\n+\tcvmx_gserx_lane_px_mode_0_t lmode0;\n+\tcvmx_gserx_lane_px_mode_1_t lmode1;\n+\tcvmx_gserx_lane_mode_t lmode;\n+\n+\tswitch (baud_mhz) {\n+\tcase 98304:\n+\t\tpmode0.u64 = 0x1a0a;\n+\t\tpmode1.u64 = 0x3228;\n+\t\tlmode0.u64 = 0x600f;\n+\t\tlmode1.u64 = 0xa80f;\n+\t\tbreak;\n+\tcase 49152:\n+\t\tif (mode == CVMX_QLM_MODE_SDL) {\n+\t\t\tpmode0.u64 = 0x3605;\n+\t\t\tpmode1.u64 = 0x0814;\n+\t\t\tlmode0.u64 = 0x000f;\n+\t\t\tlmode1.u64 = 0x6814;\n+\t\t} else {\n+\t\t\tpmode0.u64 = 0x1a0a;\n+\t\t\tpmode1.u64 = 0x3228;\n+\t\t\tlmode0.u64 = 0x650f;\n+\t\t\tlmode1.u64 = 0xe80f;\n+\t\t}\n+\t\tbreak;\n+\tcase 24576:\n+\t\tpmode0.u64 = 0x1a0a;\n+\t\tpmode1.u64 = 0x3228;\n+\t\tlmode0.u64 = 0x6a0f;\n+\t\tlmode1.u64 = 0xe80f;\n+\t\tbreak;\n+\tcase 12288:\n+\t\tpmode0.u64 = 0x1a0a;\n+\t\tpmode1.u64 = 0x3228;\n+\t\tlmode0.u64 = 0x6f0f;\n+\t\tlmode1.u64 = 0xe80f;\n+\t\tbreak;\n+\tcase 6144:\n+\t\tpmode0.u64 = 0x160a;\n+\t\tpmode1.u64 = 0x1019;\n+\t\tlmode0.u64 = 0x000f;\n+\t\tlmode1.u64 = 0x2814;\n+\t\tbreak;\n+\tcase 3072:\n+\t\tpmode0.u64 = 0x160a;\n+\t\tpmode1.u64 = 0x1019;\n+\t\tlmode0.u64 = 0x050f;\n+\t\tlmode1.u64 = 0x6814;\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"Invalid speed for CPRI/SDL configuration\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tlmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));\n+\tcsr_wr(CVMX_GSERX_PLL_PX_MODE_0(lmode.s.lmode, qlm), pmode0.u64);\n+\tcsr_wr(CVMX_GSERX_PLL_PX_MODE_1(lmode.s.lmode, qlm), pmode1.u64);\n+\tcsr_wr(CVMX_GSERX_LANE_PX_MODE_0(lmode.s.lmode, qlm), lmode0.u64);\n+\tcsr_wr(CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm), lmode1.u64);\n+\treturn 0;\n+}\n+\n+/**\n+ * Configure QLM/DLM speed and mode for cnf75xx.\n+ *\n+ * @param qlm     The QLM to configure\n+ * @param baud_mhz   The speed the QLM needs to be configured in Mhz.\n+ * @param mode    The QLM to be configured as SGMII/XAUI/PCIe.\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.\n+ * @param gen3    Only used for PCIe\n+ *\t\t\tgen3 = 2 GEN3 mode\n+ *\t\t\tgen3 = 1 GEN2 mode\n+ *\t\t\tgen3 = 0 GEN1 mode\n+ *\n+ * @param ref_clk_sel    The reference-clock selection to use to configure QLM\n+ *\t\t\t 0 = REF_100MHZ\n+ *\t\t\t 1 = REF_125MHZ\n+ *\t\t\t 2 = REF_156MHZ\n+ *\t\t\t 3 = REF_122MHZ\n+ * @param ref_clk_input  The reference-clock input to use to configure QLM\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+static int octeon_configure_qlm_cnf75xx(int qlm, int baud_mhz, int mode, int rc, int gen3,\n+\t\t\t\t\tint ref_clk_sel, int ref_clk_input)\n+{\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_lane_mode_t lmode;\n+\tcvmx_gserx_cfg_t cfg;\n+\tcvmx_gserx_refclk_sel_t refclk_sel;\n+\tint is_pcie = 0;\n+\tint is_bgx = 0;\n+\tint is_srio = 0;\n+\tint is_rmac = 0;\n+\tint is_rmac_pipe = 0;\n+\tint lane_mode = 0;\n+\tshort lmac_type[4] = { 0 };\n+\tshort sds_lane[4] = { 0 };\n+\tbool alt_pll = false;\n+\tint enable_training = 0;\n+\tint additional_lmacs = 0;\n+\tint port = (qlm == 3) ? 1 : 0;\n+\tcvmx_sriox_status_reg_t status_reg;\n+\n+\tdebug(\"%s(qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\\n\",\n+\t      __func__, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);\n+\tif (qlm > 8) {\n+\t\tprintf(\"Invalid qlm%d passed\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout\n+\t *  during speed change. Change SLI_WINDOW_CTL[time] to 525us\n+\t */\n+\t__set_sli_window_ctl_errata_31375(0);\n+\n+\tcfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\n+\t/* If PEM is in EP, no need to do anything */\n+\tif (cfg.s.pcie && rc == 0) {\n+\t\tdebug(\"%s: qlm %d is in PCIe endpoint mode, returning\\n\", __func__, qlm);\n+\t\treturn 0;\n+\t}\n+\n+\tif (cfg.s.srio && rc == 0) {\n+\t\tdebug(\"%s: qlm %d is in SRIO endpoint mode, returning\\n\", __func__, qlm);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Set the reference clock to use */\n+\trefclk_sel.u64 = 0;\n+\tif (ref_clk_input == 0) { /* External ref clock */\n+\t\trefclk_sel.s.com_clk_sel = 0;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else if (ref_clk_input == 1) {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 0;\n+\t} else {\n+\t\trefclk_sel.s.com_clk_sel = 1;\n+\t\trefclk_sel.s.use_com1 = 1;\n+\t}\n+\n+\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\n+\t/* Reset the QLM after changing the reference clock */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 1;\n+\tphy_ctl.s.phy_pd = 1;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\tudelay(1000);\n+\n+\tswitch (mode) {\n+\tcase CVMX_QLM_MODE_PCIE:\n+\tcase CVMX_QLM_MODE_PCIE_1X2:\n+\tcase CVMX_QLM_MODE_PCIE_2X1: {\n+\t\tcvmx_pemx_cfg_t pemx_cfg;\n+\t\tcvmx_pemx_on_t pemx_on;\n+\t\tcvmx_rst_soft_prstx_t rst_prst;\n+\n+\t\tis_pcie = 1;\n+\n+\t\tif (qlm > 1) {\n+\t\t\tprintf(\"Invalid PCIe mode for QLM%d\\n\", qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (ref_clk_sel == 0) {\n+\t\t\trefclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 0;\n+\t\t\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK100;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK100;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK100;\n+\t\t} else if (ref_clk_sel == 1) {\n+\t\t\trefclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));\n+\t\t\trefclk_sel.s.pcie_refclk125 = 1;\n+\t\t\tcsr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);\n+\t\t\tif (gen3 == 0) /* Gen1 mode */\n+\t\t\t\tlane_mode = R_2_5G_REFCLK125;\n+\t\t\telse if (gen3 == 1) /* Gen2 mode */\n+\t\t\t\tlane_mode = R_5G_REFCLK125;\n+\t\t\telse\n+\t\t\t\tlane_mode = R_8G_REFCLK125;\n+\t\t} else {\n+\t\t\tprintf(\"Invalid reference clock for PCIe on QLM%d\\n\", qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tswitch (qlm) {\n+\t\tcase 0: /* Either x4 or x2 based on PEM0 */\n+\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(0));\n+\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);\n+\t\t\t__setup_pem_reset(0, 0, !rc);\n+\n+\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));\n+\t\t\tpemx_cfg.cnf75xx.hostmd = rc;\n+\t\t\tpemx_cfg.cnf75xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE);\n+\t\t\tpemx_cfg.cnf75xx.md = gen3;\n+\t\t\tcsr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);\n+\t\t\t/* x4 mode waits for QLM1 setup before turning on the PEM */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1) {\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 1: /* Either PEM0 x4 or PEM1 x2 */\n+\t\t\tif (mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1) {\n+\t\t\t\trst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(1));\n+\t\t\t\trst_prst.s.soft_prst = rc;\n+\t\t\t\tcsr_wr(CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);\n+\t\t\t\t__setup_pem_reset(0, 1, !rc);\n+\n+\t\t\t\tpemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));\n+\t\t\t\tpemx_cfg.cnf75xx.hostmd = rc;\n+\t\t\t\tpemx_cfg.cnf75xx.md = gen3;\n+\t\t\t\tcsr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);\n+\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(1), pemx_on.u64);\n+\t\t\t} else {\n+\t\t\t\tpemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));\n+\t\t\t\tpemx_on.s.pemon = 1;\n+\t\t\t\tcsr_wr(CVMX_PEMX_ON(0), pemx_on.u64);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\tcase CVMX_QLM_MODE_SRIO_1X4:\n+\tcase CVMX_QLM_MODE_SRIO_2X2:\n+\tcase CVMX_QLM_MODE_SRIO_4X1: {\n+\t\tint spd = 0xf;\n+\n+\t\tif (cvmx_fuse_read(1601)) {\n+\t\t\tdebug(\"SRIO is not supported on cnf73xx model\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tswitch (baud_mhz) {\n+\t\tcase 1250:\n+\t\t\tswitch (ref_clk_sel) {\n+\t\t\tcase 0: /* 100 MHz ref clock */\n+\t\t\t\tspd = 0x3;\n+\t\t\t\tbreak;\n+\t\t\tcase 1: /* 125 MHz ref clock */\n+\t\t\t\tspd = 0xa;\n+\t\t\t\tbreak;\n+\t\t\tcase 2: /* 156.25 MHz ref clock */\n+\t\t\t\tspd = 0x4;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tspd = 0xf; /* Disabled */\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 2500:\n+\t\t\tswitch (ref_clk_sel) {\n+\t\t\tcase 0: /* 100 MHz ref clock */\n+\t\t\t\tspd = 0x2;\n+\t\t\t\tbreak;\n+\t\t\tcase 1: /* 125 MHz ref clock */\n+\t\t\t\tspd = 0x9;\n+\t\t\t\tbreak;\n+\t\t\tcase 2: /* 156.25 MHz ref clock */\n+\t\t\t\tspd = 0x7;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tspd = 0xf; /* Disabled */\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 3125:\n+\t\t\tswitch (ref_clk_sel) {\n+\t\t\tcase 1: /* 125 MHz ref clock */\n+\t\t\t\tspd = 0x8;\n+\t\t\t\tbreak;\n+\t\t\tcase 2: /* 156.25 MHz ref clock */\n+\t\t\t\tspd = 0xe;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tspd = 0xf; /* Disabled */\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 5000:\n+\t\t\tswitch (ref_clk_sel) {\n+\t\t\tcase 0: /* 100 MHz ref clock */\n+\t\t\t\tspd = 0x0;\n+\t\t\t\tbreak;\n+\t\t\tcase 1: /* 125 MHz ref clock */\n+\t\t\t\tspd = 0x6;\n+\t\t\t\tbreak;\n+\t\t\tcase 2: /* 156.25 MHz ref clock */\n+\t\t\t\tspd = 0xb;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tspd = 0xf; /* Disabled */\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tspd = 0xf;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (spd == 0xf) {\n+\t\t\tprintf(\"ERROR: Invalid SRIO speed (%d) configured for QLM%d\\n\", baud_mhz,\n+\t\t\t       qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tstatus_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));\n+\t\tstatus_reg.s.spd = spd;\n+\t\tcsr_wr(CVMX_SRIOX_STATUS_REG(port), status_reg.u64);\n+\t\tis_srio = 1;\n+\t\tbreak;\n+\t}\n+\n+\tcase CVMX_QLM_MODE_SGMII_2X1:\n+\t\tif (qlm == 4) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = 0;\n+\t\t\tlmac_type[1] = 0;\n+\t\t\tlmac_type[2] = -1;\n+\t\t\tlmac_type[3] = -1;\n+\t\t\tsds_lane[0] = 0;\n+\t\t\tsds_lane[1] = 1;\n+\t\t} else if (qlm == 5) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = -1;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 0;\n+\t\t\tlmac_type[3] = 0;\n+\t\t\tsds_lane[2] = 2;\n+\t\t\tsds_lane[3] = 3;\n+\t\t\tadditional_lmacs = 2;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_10G_KR_1X2:\n+\t\tenable_training = 1;\n+\tcase CVMX_QLM_MODE_XFI_1X2:\n+\t\tif (qlm == 5) {\n+\t\t\tis_bgx = 1;\n+\t\t\tlmac_type[0] = -1;\n+\t\t\tlmac_type[1] = -1;\n+\t\t\tlmac_type[2] = 3;\n+\t\t\tlmac_type[3] = 3;\n+\t\t\tsds_lane[2] = 2;\n+\t\t\tsds_lane[3] = 3;\n+\t\t\tadditional_lmacs = 2;\n+\t\t}\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_CPRI: /* CPRI / JESD204B */\n+\t\tis_rmac = 1;\n+\t\tbreak;\n+\tcase CVMX_QLM_MODE_SDL: /* Serdes Lite (SDL) */\n+\t\tis_rmac = 1;\n+\t\tis_rmac_pipe = 1;\n+\t\tlane_mode = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (is_rmac_pipe == 0 && is_pcie == 0) {\n+\t\tlane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz,\n+\t\t\t\t\t\t\t\t  &alt_pll);\n+\t}\n+\n+\tdebug(\"%s: %d lane mode: %d, alternate PLL: %s\\n\", __func__, mode, lane_mode,\n+\t      alt_pll ? \"true\" : \"false\");\n+\tif (lane_mode == -1)\n+\t\treturn -1;\n+\n+\tif (alt_pll) {\n+\t\tdebug(\"%s: alternate PLL settings used for qlm %d, lane mode %d, reference clock %d\\n\",\n+\t\t      __func__, qlm, lane_mode, ref_clk_sel);\n+\t\tif (__set_qlm_ref_clk_cn78xx(0, qlm, lane_mode, ref_clk_sel)) {\n+\t\t\tprintf(\"%s: Error: reference clock %d is not supported for qlm %d\\n\",\n+\t\t\t       __func__, ref_clk_sel, qlm);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* Power up PHY, but keep it in reset */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_pd = 0;\n+\tphy_ctl.s.phy_reset = 1;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/* Set GSER for the interface mode */\n+\tcfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));\n+\tcfg.s.bgx = is_bgx & 1;\n+\tcfg.s.bgx_quad = (is_bgx >> 2) & 1;\n+\tcfg.s.bgx_dual = (is_bgx >> 1) & 1;\n+\tcfg.s.pcie = is_pcie;\n+\tcfg.s.srio = is_srio;\n+\tcfg.s.rmac = is_rmac;\n+\tcfg.s.rmac_pipe = is_rmac_pipe;\n+\tcsr_wr(CVMX_GSERX_CFG(qlm), cfg.u64);\n+\n+\t/* Lane mode */\n+\tlmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));\n+\tlmode.s.lmode = lane_mode;\n+\tcsr_wr(CVMX_GSERX_LANE_MODE(qlm), lmode.u64);\n+\n+\t/* Because of the Errata where quad mode does not work, program\n+\t * lmac_type to figure out the type of BGX interface configured\n+\t */\n+\tif (is_bgx) {\n+\t\tint bgx = 0;\n+\t\tcvmx_bgxx_cmrx_config_t cmr_config;\n+\t\tcvmx_bgxx_cmr_rx_lmacs_t rx_lmacs;\n+\t\tcvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;\n+\t\tint index, total_lmacs = 0;\n+\n+\t\tfor (index = 0; index < 4; index++) {\n+\t\t\tcmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));\n+\t\t\tcmr_config.s.enable = 0;\n+\t\t\tcmr_config.s.data_pkt_rx_en = 0;\n+\t\t\tcmr_config.s.data_pkt_tx_en = 0;\n+\t\t\tif (lmac_type[index] != -1) {\n+\t\t\t\tcmr_config.s.lmac_type = lmac_type[index];\n+\t\t\t\tcmr_config.s.lane_to_sds = sds_lane[index];\n+\t\t\t\ttotal_lmacs++;\n+\t\t\t}\n+\t\t\tcsr_wr(CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);\n+\n+\t\t\t/* Enable training for 10G_KR/40G_KR4 modes */\n+\t\t\tif (enable_training == 1 &&\n+\t\t\t    (lmac_type[index] == 3 || lmac_type[index] == 4)) {\n+\t\t\t\tspu_pmd_control.u64 =\n+\t\t\t\t\tcsr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));\n+\t\t\t\tspu_pmd_control.s.train_en = 1;\n+\t\t\t\tcsr_wr(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),\n+\t\t\t\t       spu_pmd_control.u64);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Update the total number of lmacs */\n+\t\trx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(bgx));\n+\t\trx_lmacs.s.lmacs = total_lmacs + additional_lmacs;\n+\t\tcsr_wr(CVMX_BGXX_CMR_RX_LMACS(bgx), rx_lmacs.u64);\n+\t\tcsr_wr(CVMX_BGXX_CMR_TX_LMACS(bgx), rx_lmacs.u64);\n+\t}\n+\n+\t/* Bring phy out of reset */\n+\tphy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));\n+\tphy_ctl.s.phy_reset = 0;\n+\tcsr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);\n+\n+\t/*\n+\t * Wait 1us until the management interface is ready to accept\n+\t * read/write commands.\n+\t */\n+\tudelay(1);\n+\n+\tif (is_srio) {\n+\t\tstatus_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));\n+\t\tstatus_reg.s.srio = 1;\n+\t\tcsr_wr(CVMX_SRIOX_STATUS_REG(port), status_reg.u64);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\t/* PCIe mode doesn't become ready until the PEM block attempts to bring\n+\t * the interface up. Skip this check for PCIe\n+\t */\n+\tif (!is_pcie && CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,\n+\t\t\t\t\t      rst_rdy, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Configure the gser pll */\n+\tif (is_rmac)\n+\t\t__rmac_pll_config(baud_mhz, qlm, mode);\n+\telse if (!(is_pcie || is_srio))\n+\t\t__qlm_setup_pll_cn78xx(0, qlm);\n+\n+\t/* Wait for reset to complete and the PLL to lock */\n+\tif (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,\n+\t\t\t\t  pll_lock, ==, 1, 10000)) {\n+\t\tprintf(\"QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\\n\", qlm);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Errata GSER-27140: Updating the RX EQ settings due to temperature\n+\t * drift sensitivities\n+\t */\n+\t/* This workaround will also only be applied if the SERDES data-rate is 10G */\n+\tif (baud_mhz == 103125)\n+\t\t__qlm_rx_eq_temp_gser27140(0, qlm);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Configure qlm/dlm speed and mode.\n+ * @param qlm     The QLM or DLM to configure\n+ * @param speed   The speed the QLM needs to be configured in Mhz.\n+ * @param mode    The QLM to be configured as SGMII/XAUI/PCIe.\n+ * @param rc      Only used for PCIe, rc = 1 for root complex mode, 0 for EP\n+ *\t\t  mode.\n+ * @param pcie_mode Only used when qlm/dlm are in pcie mode.\n+ * @param ref_clk_sel Reference clock to use for 70XX where:\n+ *\t\t\t0: 100MHz\n+ *\t\t\t1: 125MHz\n+ *\t\t\t2: 156.25MHz\n+ *\t\t\t3: 122MHz (Used by RMAC)\n+ * @param ref_clk_input\tThis selects which reference clock input to use.  For\n+ *\t\t\tcn70xx:\n+ *\t\t\t\t0: DLMC_REF_CLK0\n+ *\t\t\t\t1: DLMC_REF_CLK1\n+ *\t\t\t\t2: DLM0_REF_CLK\n+ *\t\t\tcn61xx: (not used)\n+ *\t\t\tcn78xx/cn76xx/cn73xx:\n+ *\t\t\t\t0: Internal clock (QLM[0-7]_REF_CLK)\n+ *\t\t\t\t1: QLMC_REF_CLK0\n+ *\t\t\t\t2: QLMC_REF_CLK1\n+ *\n+ * @return       Return 0 on success or -1.\n+ */\n+int octeon_configure_qlm(int qlm, int speed, int mode, int rc, int pcie_mode, int ref_clk_sel,\n+\t\t\t int ref_clk_input)\n+{\n+\tint node = 0; // ToDo: corrently only node 0 is supported\n+\n+\tdebug(\"%s(%d, %d, %d, %d, %d, %d, %d)\\n\", __func__, qlm, speed, mode, rc, pcie_mode,\n+\t      ref_clk_sel, ref_clk_input);\n+\tif (OCTEON_IS_MODEL(OCTEON_CN61XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))\n+\t\treturn octeon_configure_qlm_cn61xx(qlm, speed, mode, rc, pcie_mode);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN70XX))\n+\t\treturn octeon_configure_qlm_cn70xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,\n+\t\t\t\t\t\t   ref_clk_input);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN78XX))\n+\t\treturn octeon_configure_qlm_cn78xx(node, qlm, speed, mode, rc, pcie_mode,\n+\t\t\t\t\t\t   ref_clk_sel, ref_clk_input);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CN73XX))\n+\t\treturn octeon_configure_qlm_cn73xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,\n+\t\t\t\t\t\t   ref_clk_input);\n+\telse if (OCTEON_IS_MODEL(OCTEON_CNF75XX))\n+\t\treturn octeon_configure_qlm_cnf75xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,\n+\t\t\t\t\t\t    ref_clk_input);\n+\telse\n+\t\treturn -1;\n+}\n+\n+void octeon_init_qlm(int node)\n+{\n+\tint qlm;\n+\tcvmx_gserx_phy_ctl_t phy_ctl;\n+\tcvmx_gserx_cfg_t cfg;\n+\tint baud_mhz;\n+\tint pem;\n+\n+\tif (!OCTEON_IS_MODEL(OCTEON_CN78XX))\n+\t\treturn;\n+\n+\tfor (qlm = 0; qlm < 8; qlm++) {\n+\t\tphy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));\n+\t\tif (phy_ctl.s.phy_reset == 0) {\n+\t\t\tcfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));\n+\t\t\tif (cfg.s.pcie)\n+\t\t\t\t__cvmx_qlm_pcie_errata_cn78xx(node, qlm);\n+\t\t\telse\n+\t\t\t\t__qlm_init_errata_20844(node, qlm);\n+\n+\t\t\tbaud_mhz = cvmx_qlm_get_gbaud_mhz_node(node, qlm);\n+\t\t\tif (baud_mhz == 6250 || baud_mhz == 6316)\n+\t\t\t\tocteon_qlm_tune_v3(node, qlm, baud_mhz, 0xa, 0xa0, -1, -1);\n+\t\t\telse if (baud_mhz == 103125)\n+\t\t\t\tocteon_qlm_tune_v3(node, qlm, baud_mhz, 0xd, 0xd0, -1, -1);\n+\t\t}\n+\t}\n+\n+\t/* Setup how each PEM drives the PERST lines */\n+\tfor (pem = 0; pem < 4; pem++) {\n+\t\tcvmx_rst_ctlx_t rst_ctl;\n+\n+\t\trst_ctl.u64 = csr_rd_node(node, CVMX_RST_CTLX(pem));\n+\t\t__setup_pem_reset(node, pem, !rst_ctl.s.host_mode);\n+\t}\n+}\n",
    "prefixes": [
        "v1",
        "44/50"
    ]
}