get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1415015,
    "url": "http://patchwork.ozlabs.org/api/patches/1415015/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20201211160612.1498780-44-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-44-sr@denx.de>",
    "list_archive_url": null,
    "date": "2020-12-11T16:06:05",
    "name": "[v1,43/50] mips: octeon: Add octeon_fdt.c",
    "commit_ref": "107d3f57716e4039ffec7dd7daccc5a3ed3f935a",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "15f28b9e1f5dce340d11d6117c1a4ab1259a9004",
    "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-44-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/1415015/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1415015/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=2a01:238:438b:c500:173d:9f52:ddab:ee01; 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=sf7kvkKz;\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\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\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 4CswpQ0hgjz9sSs\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 12 Dec 2020 03:14:21 +1100 (AEDT)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 3249A827DD;\n\tFri, 11 Dec 2020 17:09:18 +0100 (CET)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 14D2C826D6; Fri, 11 Dec 2020 17:08:32 +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 92CE782720\n for <u-boot@lists.denx.de>; Fri, 11 Dec 2020 17:06:30 +0100 (CET)",
            "from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240])\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 3FBA0A0E12;\n Fri, 11 Dec 2020 17:06:30 +0100 (CET)",
            "from smtp1.mailbox.org ([80.241.60.240])\n by spamfilter04.heinlein-hosting.de (spamfilter04.heinlein-hosting.de\n [80.241.56.122]) (amavisd-new, port 10030)\n with ESMTP id E4nqHmi6NM-Q; 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=1607702958;\n\tbh=fiRMyjK0mMd1RM4UvX+yXK5PaLeopiBG1F82VHChJfg=;\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=sf7kvkKzyEQbHd/LxFjtBFjkIJj/ZMq1D/1xRescozYLlazrNkQwyc/U4stlgPU9o\n\t 4sSaFDZI47QVUP5c1Xq5CjMtM2ZmIsuaC191BSVuyRfH0JB4wKJ/OtplBvwzVdLtaz\n\t dkKNpMhEEcINknU4jI2tLBeGsCqJGDVTxo0nQJta83mSmalWgbtJC5hdS3WfzgVrnj\n\t KkDjFuMVsveUXMOtyTiF3EA0IDqsvt6mxORli3fI1QcjPvxYkB24+R6LxrEO7cyK4j\n\t RqIEFbwAuXoRmasOil/QovajW05bH0MGGN/pigmzb8myw5f6IvIh7XgpxKfNIxkutx\n\t s8OCrCrbfDPJQ==",
        "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 43/50] mips: octeon: Add octeon_fdt.c",
        "Date": "Fri, 11 Dec 2020 17:06:05 +0100",
        "Message-Id": "<20201211160612.1498780-44-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.52 / 15.00 / 15.00",
        "X-Rspamd-Queue-Id": "3E546187E",
        "X-Rspamd-UID": "fe8750",
        "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_fdt.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_fdt.c | 1040 ++++++++++++++++++++++++++++\n 1 file changed, 1040 insertions(+)\n create mode 100644 arch/mips/mach-octeon/octeon_fdt.c",
    "diff": "diff --git a/arch/mips/mach-octeon/octeon_fdt.c b/arch/mips/mach-octeon/octeon_fdt.c\nnew file mode 100644\nindex 0000000000..199f692516\n--- /dev/null\n+++ b/arch/mips/mach-octeon/octeon_fdt.c\n@@ -0,0 +1,1040 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2020 Marvell International Ltd.\n+ */\n+\n+#include <env.h>\n+#include <log.h>\n+#include <i2c.h>\n+#include <net.h>\n+#include <dm/device.h>\n+#include <linux/delay.h>\n+\n+#include <mach/cvmx-regs.h>\n+#include <mach/cvmx-csr.h>\n+#include <mach/cvmx-bootmem.h>\n+#include <mach/octeon-model.h>\n+#include <mach/octeon_eth.h>\n+#include <mach/octeon_fdt.h>\n+#include <mach/cvmx-helper-fdt.h>\n+#include <mach/cvmx-helper-gpio.h>\n+#include <mach/cvmx-fuse.h>\n+#include <mach/octeon-feature.h>\n+#include <mach/cvmx-qlm.h>\n+#include <mach/octeon_qlm.h>\n+#include <asm/gpio.h>\n+\n+#ifdef CONFIG_PCA953X\n+#include <pca953x.h>\n+#endif\n+#ifdef CONFIG_PCF857X\n+#include <pcf857x.h>\n+#endif\n+#ifdef CONFIG_PCA9698\n+#include <pca9698.h>\n+#endif\n+#ifdef CONFIG_PCA9554\n+#include <pca9554.h>\n+#endif\n+#ifdef CONFIG_PCA9555\n+#include <pca9555.h>\n+#endif\n+\n+DECLARE_GLOBAL_DATA_PTR;\n+\n+#ifdef CONFIG_PCA9554\n+static const char * const pca9554_gpio_list[] = {\n+\t\"pca9554\",\n+\t\"nxp,pca9554\",\n+\t\"ti,pca9554\",\n+\tNULL,\n+};\n+#endif\n+\n+#ifdef CONFIG_PCA9555\n+static const char * const pca9555_gpio_list[] = {\n+\t\"pca9535\",    \"nxp,pca9535\", \"pca9539\", \"nxp,pca9539\", \"pca9555\",\n+\t\"nxp,pca9555\", \"ti,pca9555\", \"max7312\", \"maxim,max7312\", \"max7313\",\n+\t\"maxim,max7313\", \"tca6416\", \"tca9539\",    NULL,\n+};\n+#endif\n+\n+#ifdef CONFIG_PCA9698\n+/** List of compatible strings supported by pca9698 driver */\n+static const char * const pca9698_gpio_list[] = {\n+\t\"nxp,pca9505\", \"pca9505\", \"nxp,pca9698\", \"pca9698\", NULL,\n+};\n+#endif\n+\n+#ifdef CONFIG_PCA953X\n+/** List of compatible strings supported by pca953x driver */\n+static const char * const pca953x_gpio_list[] = {\n+\t\"nxp,pca9534\", \"nxp,pca9535\", \"nxp,pca9536\", \"nxp,pca9537\", \"nxp,pca9538\", \"nxp,pca9539\",\n+\t\"nxp,pca953x\", \"nxp,pca9554\", \"nxp,pca9555\", \"nxp,pca9556\", \"nxp,pca9557\", \"nxp,pca6107\",\n+\t\"pca9534\",     \"pca9535\",     \"pca9536\",     \"pca9537\",\t    \"pca9538\",\t   \"pca9539\",\n+\t\"pca953x\",     \"pca9554\",     \"pca9555\",     \"pca9556\",\t    \"pca9557\",\t   \"max7310\",\n+\t\"max7312\",     \"max7313\",     \"max7315\",     \"pca6107\",\t    \"tca6408\",\t   \"tca6416\",\n+\t\"tca9555\",     NULL\n+};\n+#endif\n+\n+#ifdef CONFIG_PHY_VITESSE\n+static const char * const vitesse_vsc8488_gpio_list[] = {\n+\t\"vitesse,vsc8486\",   \"microsemi,vsc8486\", \"vitesse,vsc8488\",\n+\t\"microsemi,vsc8488\", \"vitesse,vsc8489\",\t  \"microsemi,vsc8489\",\n+\t\"vitesse,vsc8490\",   \"microsemi,vsc8490\", NULL\n+};\n+#endif\n+\n+/** List of compatible strings supported by Octeon driver */\n+static const char * const octeon_gpio_list[] = {\n+\t\"cavium,octeon-7890-gpio\",\n+\t\"cavium,octeon-3860-gpio\",\n+\tNULL\n+};\n+\n+/**\n+ * Trims nodes from the flat device tree.\n+ *\n+ * @param fdt - pointer to working FDT, usually in gd->fdt_blob\n+ * @param fdt_key - key to preserve.  All non-matching keys are removed\n+ * @param trim_name - name of property to look for.  If NULL use\n+ *\t\t      'cavium,qlm-trim'\n+ *\n+ * The key should look something like device #, type where device # is a\n+ * number from 0-9 and type is a string describing the type.  For QLM\n+ * operations this would typically contain the QLM number followed by\n+ * the type in the device tree, like \"0,xaui\", \"0,sgmii\", etc.  This function\n+ * will trim all items in the device tree which match the device number but\n+ * have a type which does not match.  For example, if a QLM has a xaui module\n+ * installed on QLM 0 and \"0,xaui\" is passed as a key, then all FDT nodes that\n+ * have \"0,xaui\" will be preserved but all others, i.e. \"0,sgmii\" will be\n+ * removed.\n+ *\n+ * Note that the trim_name must also match.  If trim_name is NULL then it\n+ * looks for the property \"cavium,qlm-trim\".\n+ *\n+ * Also, when the trim_name is \"cavium,qlm-trim\" or NULL that the interfaces\n+ * will also be renamed based on their register values.\n+ *\n+ * For example, if a PIP interface is named \"interface@W\" and has the property\n+ * reg = <0> then the interface will be renamed after this function to\n+ * interface@0.\n+ *\n+ * @return 0 for success.\n+ */\n+int __octeon_fdt_patch(void *fdt, const char *fdt_key, const char *trim_name)\n+{\n+\tbool rename = !trim_name || !strcmp(trim_name, \"cavium,qlm-trim\");\n+\n+\treturn octeon_fdt_patch_rename(fdt, fdt_key, trim_name, rename, NULL, NULL);\n+}\n+\n+int octeon_fdt_patch(void *fdt, const char *fdt_key, const char *trim_name)\n+\t__attribute__((weak, alias(\"__octeon_fdt_patch\")));\n+\n+/**\n+ * Trims nodes from the flat device tree.\n+ *\n+ * @param fdt - pointer to working FDT, usually in gd->fdt_blob\n+ * @param fdt_key - key to preserve.  All non-matching keys are removed\n+ * @param trim_name - name of property to look for.  If NULL use\n+ *\t\t      'cavium,qlm-trim'\n+ * @param rename - set to TRUE to rename interfaces.\n+ * @param callback - function to call on matched nodes.\n+ * @param cbarg - passed to callback.\n+ *\n+ * The key should look something like device #, type where device # is a\n+ * number from 0-9 and type is a string describing the type.  For QLM\n+ * operations this would typically contain the QLM number followed by\n+ * the type in the device tree, like \"0,xaui\", \"0,sgmii\", etc.  This function\n+ * will trim all items in the device tree which match the device number but\n+ * have a type which does not match.  For example, if a QLM has a xaui module\n+ * installed on QLM 0 and \"0,xaui\" is passed as a key, then all FDT nodes that\n+ * have \"0,xaui\" will be preserved but all others, i.e. \"0,sgmii\" will be\n+ * removed.\n+ *\n+ * Note that the trim_name must also match.  If trim_name is NULL then it\n+ * looks for the property \"cavium,qlm-trim\".\n+ *\n+ * Also, when the trim_name is \"cavium,qlm-trim\" or NULL that the interfaces\n+ * will also be renamed based on their register values.\n+ *\n+ * For example, if a PIP interface is named \"interface@W\" and has the property\n+ * reg = <0> then the interface will be renamed after this function to\n+ * interface@0.\n+ *\n+ * @return 0 for success.\n+ */\n+int octeon_fdt_patch_rename(void *fdt, const char *fdt_key,\n+\t\t\t    const char *trim_name, bool rename,\n+\t\t\t    void (*callback)(void *fdt, int offset, void *arg),\n+\t\t\t    void *cbarg)\n+\t__attribute__((weak, alias(\"__octeon_fdt_patch_rename\")));\n+\n+int __octeon_fdt_patch_rename(void *fdt, const char *fdt_key,\n+\t\t\t      const char *trim_name, bool rename,\n+\t\t\t      void (*callback)(void *fdt, int offset, void *arg),\n+\t\t\t      void *cbarg)\n+{\n+\tint fdt_key_len;\n+\tint offset, next_offset;\n+\tint aliases;\n+\tconst void *aprop;\n+\tchar qlm[32];\n+\tchar *mode;\n+\tint qlm_key_len;\n+\tint rc;\n+\tint cpu_node;\n+\n+\tif (!trim_name)\n+\t\ttrim_name = \"cavium,qlm-trim\";\n+\n+\tstrncpy(qlm, fdt_key, sizeof(qlm));\n+\tmode = qlm;\n+\tstrsep(&mode, \",\");\n+\tqlm_key_len = strlen(qlm);\n+\n+\tdebug(\"In %s: Patching FDT header at 0x%p with key \\\"%s\\\"\\n\", __func__, fdt, fdt_key);\n+\tif (!fdt || fdt_check_header(fdt) != 0) {\n+\t\tprintf(\"%s: Invalid device tree\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\tfdt_key_len = strlen(fdt_key) + 1;\n+\n+\t/* Prune out the unwanted parts based on the QLM mode.  */\n+\toffset = 0;\n+\tfor (offset = fdt_next_node(fdt, offset, NULL); offset >= 0; offset = next_offset) {\n+\t\tint len;\n+\t\tconst char *val;\n+\t\tconst char *val_comma;\n+\n+\t\tnext_offset = fdt_next_node(fdt, offset, NULL);\n+\n+\t\tval = fdt_getprop(fdt, offset, trim_name, &len);\n+\t\tif (!val)\n+\t\t\tcontinue;\n+\n+\t\tdebug(\"fdt found trim name %s, comparing key \\\"%s\\\"(%d) with \\\"%s\\\"(%d)\\n\",\n+\t\t      trim_name, fdt_key, fdt_key_len, val, len);\n+\t\tval_comma = strchr(val, ',');\n+\t\tif (!val_comma || (val_comma - val) != qlm_key_len)\n+\t\t\tcontinue;\n+\t\tif (strncmp(val, qlm, qlm_key_len) != 0)\n+\t\t\tcontinue; /* Not this QLM. */\n+\n+\t\tdebug(\"fdt key number \\\"%s\\\" matches\\n\", val);\n+\t\tif (!fdt_stringlist_contains(val, len, fdt_key)) {\n+\t\t\tdebug(\"Key \\\"%s\\\" does not match \\\"%s\\\"\\n\", val, fdt_key);\n+\t\t\t/* This QLM, but wrong mode.  Delete it. */\n+\t\t\t/* See if there's an alias that needs deleting */\n+\t\t\tval = fdt_getprop(fdt, offset, \"cavium,qlm-trim-alias\", NULL);\n+\t\t\tif (val) {\n+\t\t\t\tdebug(\"Trimming alias \\\"%s\\\"\\n\", val);\n+\t\t\t\taliases = fdt_path_offset(fdt, \"/aliases\");\n+\t\t\t\tif (aliases) {\n+\t\t\t\t\taprop = fdt_getprop(fdt, aliases, val, NULL);\n+\t\t\t\t\tif (aprop) {\n+\t\t\t\t\t\trc = fdt_nop_property(fdt, aliases, val);\n+\t\t\t\t\t\tif (rc) {\n+\t\t\t\t\t\t\tprintf(\"Error: Could not NOP alias %s in fdt\\n\",\n+\t\t\t\t\t\t\t       val);\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tprintf(\"Error: could not find /aliases/%s in device tree\\n\",\n+\t\t\t\t\t\t       val);\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tputs(\"Error: could not find /aliases in device tree\\n\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tdebug(\"fdt trimming matching key %s\\n\", fdt_key);\n+\t\t\tnext_offset = fdt_parent_offset(fdt, offset);\n+\t\t\trc = fdt_nop_node(fdt, offset);\n+\t\t\tif (rc)\n+\t\t\t\tprintf(\"Error %d noping node in device tree\\n\", rc);\n+\t\t}\n+\t}\n+\n+\tdebug(\"%s: Starting pass 2 for key %s\\n\", __func__, fdt_key);\n+\t/* Second pass: Rewrite names and remove key properties.  */\n+\toffset = -1;\n+\tfor (offset = fdt_next_node(fdt, offset, NULL); offset >= 0; offset = next_offset) {\n+\t\tint len;\n+\t\tconst char *val = fdt_getprop(fdt, offset, trim_name, &len);\n+\n+\t\tnext_offset = fdt_next_node(fdt, offset, NULL);\n+\n+\t\tif (!val)\n+\t\t\tcontinue;\n+\t\tdebug(\"Searching stringlist %s for %s\\n\", val, fdt_key);\n+\t\tif (fdt_stringlist_contains(val, len, fdt_key)) {\n+\t\t\tchar new_name[64];\n+\t\t\tconst char *name;\n+\t\t\tconst char *at;\n+\t\t\tint reg;\n+\n+\t\t\tdebug(\"Found key %s at offset 0x%x\\n\", fdt_key, offset);\n+\t\t\tfdt_nop_property(fdt, offset, trim_name);\n+\n+\t\t\tif (rename) {\n+\t\t\t\tname = fdt_get_name(fdt, offset, NULL);\n+\t\t\t\tdebug(\"  name: %s\\n\", name);\n+\t\t\t\tif (!name)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tat = strchr(name, '@');\n+\t\t\t\tif (!at)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\treg = fdtdec_get_int(fdt, offset, \"reg\", -1);\n+\t\t\t\tif (reg == -1)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tdebug(\"  reg: %d\\n\", reg);\n+\t\t\t\tlen = at - name + 1;\n+\t\t\t\tdebug(\"  len: %d\\n\", len);\n+\t\t\t\tif (len + 9 >= sizeof(new_name))\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tmemcpy(new_name, name, len);\n+\t\t\t\tcpu_node = cvmx_fdt_get_cpu_node(fdt, offset);\n+\t\t\t\tif (cpu_node > 0)\n+\t\t\t\t\tsnprintf(new_name + len, sizeof(new_name) - len, \"%x_%x\",\n+\t\t\t\t\t\t cpu_node, reg);\n+\t\t\t\telse\n+\t\t\t\t\tsprintf(new_name + len, \"%x\", reg);\n+\t\t\t\tdebug(\"Renaming cpu node %d %s to %s\\n\", cpu_node, name, new_name);\n+\t\t\t\tfdt_set_name(fdt, offset, new_name);\n+\t\t\t}\n+\t\t\tif (callback)\n+\t\t\t\tcallback(fdt, offset, cbarg);\n+\n+\t\t\t/* Structure may have changed, start at the beginning. */\n+\t\t\tnext_offset = 0;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+#ifdef CONFIG_CMD_NET\n+static void octeon_set_one_fdt_mac(int node, uint64_t *mac)\n+{\n+\tu8 mac_addr[6];\n+\tint r;\n+\n+\tmac_addr[5] = *mac & 0xff;\n+\tmac_addr[4] = (*mac >> 8) & 0xff;\n+\tmac_addr[3] = (*mac >> 16) & 0xff;\n+\tmac_addr[2] = (*mac >> 24) & 0xff;\n+\tmac_addr[1] = (*mac >> 32) & 0xff;\n+\tmac_addr[0] = (*mac >> 40) & 0xff;\n+\n+\tr = fdt_setprop_inplace(working_fdt, node, \"local-mac-address\", mac_addr, 6);\n+\tif (r == 0)\n+\t\t*mac = *mac + 1;\n+}\n+\n+static uint64_t convert_mac(const u8 mac_addr[6])\n+{\n+\tint i;\n+\tu64 mac = 0;\n+\n+\tfor (i = 0; i < 6; i++)\n+\t\tmac = (mac << 8) | mac_addr[i];\n+\treturn mac;\n+}\n+\n+/**\n+ * Fix up the MAC address in the flat device tree based on the MAC address\n+ * stored in ethaddr or in the board descriptor.\n+ *\n+ * NOTE: This function is weak and an alias for __octeon_fixup_fdt_mac_addr.\n+ */\n+void octeon_fixup_fdt_mac_addr(void) __attribute__((weak, alias(\"__octeon_fixup_fdt_mac_addr\")));\n+\n+void __octeon_fixup_fdt_mac_addr(void)\n+{\n+\tint node, pip, interface, ethernet;\n+\tint i, e;\n+\tu64 mac = 0;\n+\tuchar mac_addr[6];\n+\tchar name[20];\n+\tbool env_mac_addr_valid;\n+\tconst char *p;\n+\n+\tdebug(\"%s: env ethaddr: %s\\n\", __func__, (p = env_get(\"ethaddr\")) ? p : \"not set\");\n+\tif (eth_env_get_enetaddr(\"ethaddr\", mac_addr)) {\n+\t\tmac = convert_mac(mac_addr);\n+\t\tenv_mac_addr_valid = true;\n+\t} else {\n+\t\tmac = convert_mac((uint8_t *)gd->arch.mac_desc.mac_addr_base);\n+\t\tenv_mac_addr_valid = false;\n+\t}\n+\n+\tdebug(\"%s: mac_addr: %pM, board mac: %pM, env valid: %s\\n\", __func__, mac_addr,\n+\t      gd->arch.mac_desc.mac_addr_base, env_mac_addr_valid ? \"true\" : \"false\");\n+\n+\tif (env_mac_addr_valid && memcmp(mac_addr, (void *)gd->arch.mac_desc.mac_addr_base, 6))\n+\t\tprintf(\"Warning: the environment variable ethaddr is set to %pM\\n\"\n+\t\t       \"which does not match the board descriptor MAC address %pM.\\n\"\n+\t\t       \"Please clear the ethaddr environment variable with the command\\n\"\n+\t\t       \"\\\"setenv -f ethaddr; saveenv\\\" or change the board MAC address with the command\\n\"\n+\t\t       \"\\\"tlv_eeprom set mac %pM\\\" to change the board MAC address so that it matches\\n\"\n+\t\t       \"the environment address.\\n\"\n+\t\t       \"Note: the correct MAC address is usually the one stored in the tlv EEPROM.\\n\",\n+\t\t       mac_addr, gd->arch.mac_desc.mac_addr_base, mac_addr);\n+\n+\tfor (i = 0; i < 2; i++) {\n+\t\tsprintf(name, \"mix%x\", i);\n+\t\tp = fdt_get_alias(working_fdt, name);\n+\t\tif (p) {\n+\t\t\tnode = fdt_path_offset(working_fdt, p);\n+\t\t\tif (node > 0)\n+\t\t\t\tocteon_set_one_fdt_mac(node, &mac);\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < 2; i++) {\n+\t\tsprintf(name, \"rgmii%x\", i);\n+\t\tp = fdt_get_alias(working_fdt, name);\n+\t\tif (p) {\n+\t\t\tnode = fdt_path_offset(working_fdt, p);\n+\t\t\tif (node > 0)\n+\t\t\t\tocteon_set_one_fdt_mac(node, &mac);\n+\t\t}\n+\t}\n+\n+\tpip = fdt_node_offset_by_compatible(working_fdt, -1, \"cavium,octeon-3860-pip\");\n+\n+\tif (pip > 0)\n+\t\tfor (i = 0; i < 8; i++) {\n+\t\t\tsprintf(name, \"interface@%d\", i);\n+\t\t\tinterface = fdt_subnode_offset(working_fdt, pip, name);\n+\t\t\tif (interface <= 0)\n+\t\t\t\tcontinue;\n+\t\t\tfor (e = 0; e < 16; e++) {\n+\t\t\t\tsprintf(name, \"ethernet@%d\", e);\n+\t\t\t\tethernet = fdt_subnode_offset(working_fdt, interface, name);\n+\t\t\t\tif (ethernet <= 0)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tocteon_set_one_fdt_mac(ethernet, &mac);\n+\t\t\t}\n+\t\t}\n+\n+\t/* Assign 78XX addresses in the order they appear in the device tree. */\n+\tnode = fdt_node_offset_by_compatible(working_fdt, -1, \"cavium,octeon-7890-bgx-port\");\n+\twhile (node != -FDT_ERR_NOTFOUND) {\n+\t\tocteon_set_one_fdt_mac(node, &mac);\n+\t\tnode = fdt_node_offset_by_compatible(working_fdt, node,\n+\t\t\t\t\t\t     \"cavium,octeon-7890-bgx-port\");\n+\t}\n+}\n+#endif\n+\n+/**\n+ * This function fixes the clock-frequency in the flat device tree for the UART.\n+ *\n+ * NOTE: This function is weak and an alias for __octeon_fixup_fdt_uart.\n+ */\n+void octeon_fixup_fdt_uart(void) __attribute__((weak, alias(\"__octeon_fixup_fdt_uart\")));\n+\n+void __octeon_fixup_fdt_uart(void)\n+{\n+\tu32 clk;\n+\tint node;\n+\n+\tclk = gd->bus_clk;\n+\n+\t/* Device trees already have good values for fast simulator\n+\t * output, real boards need the correct value.\n+\t */\n+\tnode = fdt_node_offset_by_compatible(working_fdt, -1, \"cavium,octeon-3860-uart\");\n+\twhile (node != -FDT_ERR_NOTFOUND) {\n+\t\tfdt_setprop_inplace_cell(working_fdt, node, \"clock-frequency\", clk);\n+\t\tnode = fdt_node_offset_by_compatible(working_fdt, node, \"cavium,octeon-3860-uart\");\n+\t}\n+}\n+\n+/**\n+ * This function fills in the /memory portion of the flat device tree.\n+ *\n+ * NOTE: This function is weak and aliased to __octeon_fixup_fdt_memory.\n+ */\n+void octeon_fixup_fdt_memory(void) __attribute__((weak, alias(\"__octeon_fixup_fdt_memory\")));\n+\n+void __octeon_fixup_fdt_memory(void)\n+{\n+\tu64 sizes[3], addresses[3];\n+\tu64 size_left = gd->ram_size;\n+\tint num_addresses = 0;\n+\tint rc;\n+\tint node;\n+\n+\tsize_left = gd->ram_size;\n+\tsizes[num_addresses] = min_t(u64, size_left, 256 * 1024 * 1024);\n+\tsize_left -= sizes[num_addresses];\n+\taddresses[num_addresses] = 0;\n+\tnum_addresses++;\n+\n+\tif (size_left > 0) {\n+\t\tsizes[num_addresses] = size_left;\n+\t\taddresses[num_addresses] = 0x20000000ULL;\n+\t\tnum_addresses++;\n+\t}\n+\n+\tnode = fdt_path_offset(working_fdt, \"/memory\");\n+\tif (node < 0)\n+\t\tnode = fdt_add_subnode(working_fdt, fdt_path_offset(working_fdt, \"/\"), \"memory\");\n+\tif (node < 0) {\n+\t\tprintf(\"Could not add memory section to fdt: %s\\n\", fdt_strerror(node));\n+\t\treturn;\n+\t}\n+\trc = fdt_fixup_memory_banks(working_fdt, addresses, sizes, num_addresses);\n+\tif (rc != 0)\n+\t\tprintf(\"%s: fdt_fixup_memory_banks returned %d when adding %d addresses\\n\",\n+\t\t       __func__, rc, num_addresses);\n+}\n+\n+void octeon_fixup_fdt(void) __attribute__((weak, alias(\"__octeon_fixup_fdt\")));\n+\n+void __octeon_fixup_fdt(void)\n+{\n+\tif (!working_fdt)\n+\t\treturn;\n+\n+#ifdef CONFIG_CMD_NET\n+\tocteon_fixup_fdt_mac_addr();\n+#endif /* CONFIG_CMD_NET */\n+\n+#if !CONFIG_OCTEON_SIM_SPEED\n+\tocteon_fixup_fdt_uart();\n+#endif\n+\n+\tocteon_fixup_fdt_memory();\n+}\n+\n+int __board_fixup_fdt(void)\n+{\n+\t/*\n+\t * Nothing to do in this dummy implementation\n+\t */\n+\treturn 0;\n+}\n+\n+int board_fixup_fdt(void) __attribute__((weak, alias(\"__board_fixup_fdt\")));\n+\n+/**\n+ * This is a helper function to find the offset of a PHY device given\n+ * an Ethernet device.\n+ *\n+ * @param[in] eth - Ethernet device to search for PHY offset\n+ *\n+ * @returns offset of phy info in device tree or -1 if not found\n+ */\n+//int octeon_fdt_find_phy(const struct eth_device *eth)\n+int octeon_fdt_find_phy(const struct udevice *eth)\n+{\n+\tint aliases;\n+\tconst void *fdt = gd->fdt_blob;\n+\tconst char *pip_path;\n+\tint pip;\n+\tchar buffer[64];\n+#if 0\n+\tstruct octeon_eth_info *oct_eth_info =\n+\t\t\t\t (struct octeon_eth_info *)eth->priv;\n+#else\n+\tstruct octeon_eth_info *oct_eth_info = dev_get_priv(eth);\n+#endif\n+\tint interface, index;\n+\tint phandle;\n+\tint phy;\n+\tu32 *phy_handle;\n+\n+\taliases = fdt_path_offset(fdt, \"/aliases\");\n+\tif (aliases < 0) {\n+\t\tputs(\"/aliases not found in device tree!\\n\");\n+\t\treturn -1;\n+\t}\n+\tpip_path = fdt_getprop(fdt, aliases, \"pip\", NULL);\n+\tif (!pip_path) {\n+\t\tputs(\"pip not found in aliases in device tree\\n\");\n+\t\treturn -1;\n+\t}\n+\tpip = fdt_path_offset(fdt, pip_path);\n+\tif (pip < 0) {\n+\t\tputs(\"pip not found in device tree\\n\");\n+\t\treturn -1;\n+\t}\n+\tsnprintf(buffer, sizeof(buffer), \"interface@%d\", oct_eth_info->interface);\n+\tinterface = fdt_subnode_offset(fdt, pip, buffer);\n+\tif (interface < 0) {\n+\t\tprintf(\"%s: interface@%d not found in device tree for %s\\n\", __func__,\n+\t\t       oct_eth_info->interface, eth->name);\n+\t\treturn -1;\n+\t}\n+\tsnprintf(buffer, sizeof(buffer), \"ethernet@%x\", oct_eth_info->index);\n+\tindex = fdt_subnode_offset(fdt, interface, buffer);\n+\tif (index < 0) {\n+\t\tprintf(\"%s: ethernet@%x not found in device tree for %s\\n\", __func__,\n+\t\t       oct_eth_info->index, eth->name);\n+\t\treturn -1;\n+\t}\n+\tphy_handle = (uint32_t *)fdt_getprop(fdt, index, \"phy-handle\", NULL);\n+\tif (phy_handle < 0) {\n+\t\tprintf(\"%s: phy-handle not found for %s\\n\", __func__, eth->name);\n+\t\treturn -1;\n+\t}\n+\tphandle = fdt32_to_cpu(*phy_handle);\n+\tphy = fdt_node_offset_by_phandle(fdt, phandle);\n+\tif (phy < 0) {\n+\t\tprintf(\"%s: phy not found for %s\\n\", __func__, eth->name);\n+\t\treturn -1;\n+\t}\n+\n+\treturn phy;\n+}\n+\n+/**\n+ * This helper function returns if a node contains the specified vendor name.\n+ *\n+ * @param[in]\tfdt\t\tpointer to device tree blob\n+ * @param\tnodeoffset\toffset of the tree node\n+ * @param[in]\tvendor\t\tname of vendor to check\n+ *\n+ * returns:\n+ *\t0, if the node has a compatible vendor string property\n+ *\t1, if the node does not contain the vendor string property\n+ *\t-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property\n+ *\t-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag\n+ *\t-FDT_ERR_BADMAGIC,\n+ *\t-FDT_ERR_BADVERSION,\n+ *\t-FDT_BADSTATE,\n+ *\t-FDT_ERR_BADSTRUCTURE, standard meanings\n+ */\n+int octeon_fdt_compat_vendor(const void *fdt, int nodeoffset, const char *vendor)\n+{\n+\tconst char *strlist;\n+\tconst char *p;\n+\tint len;\n+\tint listlen;\n+\n+\tstrlist = fdt_getprop(fdt, nodeoffset, \"compatible\", &listlen);\n+\tif (!strlist)\n+\t\treturn listlen;\n+\n+\tlen = strlen(vendor);\n+\n+\tdebug(\"%s(%p, %d, %s (%p)) strlist: %s (%p), len: %d\\n\", __func__, fdt, nodeoffset, vendor,\n+\t      vendor, strlist, strlist, len);\n+\twhile (listlen >= len) {\n+\t\tdebug(\"  Comparing %d bytes of %s and %s\\n\", len, vendor, strlist);\n+\t\tif ((memcmp(vendor, strlist, len) == 0) &&\n+\t\t    ((strlist[len] == ',') || (strlist[len] == '\\0')))\n+\t\t\treturn 0;\n+\t\tp = memchr(strlist, '\\0', listlen);\n+\t\tif (!p)\n+\t\t\treturn 1; /* malformed strlist.. */\n+\t\tlistlen -= (p - strlist) + 1;\n+\t\tstrlist = p + 1;\n+\t}\n+\treturn 1;\n+}\n+\n+/**\n+ * Given a node in the device tree get the OCTEON OCX node number\n+ *\n+ * @param fdt\t\tpointer to flat device tree\n+ * @param nodeoffset\tnode offset to get OCX node for\n+ *\n+ * @return the Octeon OCX node number\n+ */\n+int octeon_fdt_get_soc_node(const void *fdt, int nodeoffset)\n+{\n+\treturn 0;\n+}\n+\n+/**\n+ * Given a FDT node, check if it is compatible with a list of devices\n+ *\n+ * @param[in]\tfdt\t\tFlat device tree pointer\n+ * @param\tnode_offset\tNode offset in device tree\n+ * @param[in]\tstrlist\t\tArray of FDT devices to check, end must be NULL\n+ *\n+ * @return\t0 if at least one device is compatible, 1 if not compatible.\n+ */\n+int octeon_fdt_node_check_compatible(const void *fdt, int node_offset,\n+\t\t\t\t     const char *const *strlist)\n+{\n+\twhile (*strlist && **strlist) {\n+\t\tdebug(\"%s: Checking %s\\n\", __func__, *strlist);\n+\t\tif (!fdt_node_check_compatible(fdt, node_offset, *strlist)) {\n+\t\t\tdebug(\"%s: match found\\n\", __func__);\n+\t\t\treturn 0;\n+\t\t}\n+\t\tstrlist++;\n+\t}\n+\tdebug(\"%s: No match found\\n\", __func__);\n+\treturn 1;\n+}\n+\n+/**\n+ * Given a node offset, find the i2c bus number for that node\n+ *\n+ * @param[in]\tfdt\tPointer to flat device tree\n+ * @param\tnode_offset\tNode offset in device tree\n+ *\n+ * @return\ti2c bus number or -1 if error\n+ */\n+int octeon_fdt_i2c_get_bus(const void *fdt, int node_offset)\n+{\n+\tconst char *compat;\n+\tconst u64 addresses[] = { 0x1180000001000, 0x1180000001200 };\n+\tu64 reg;\n+\tint i;\n+\tint bus = -1;\n+\tbool found = false;\n+\n+\tif (octeon_has_feature(OCTEON_FEATURE_CIU3))\n+\t\tcompat = \"cavium,octeon-7890-twsi\";\n+\telse\n+\t\tcompat = \"cavium,octeon-3860-twsi\";\n+\n+\twhile (node_offset > 0 &&\n+\t       !(found = !fdt_node_check_compatible(fdt, node_offset, compat))) {\n+\t\tnode_offset = fdt_parent_offset(fdt, node_offset);\n+#ifdef CONFIG_OCTEON_I2C_FDT\n+\t\tbus = i2c_get_bus_num_fdt(node_offset);\n+\t\tif (bus >= 0) {\n+\t\t\tdebug(\"%s: Found bus 0x%x\\n\", __func__, bus);\n+\t\t\treturn bus;\n+\t\t}\n+#endif\n+\t}\n+\tif (!found) {\n+\t\tprintf(\"Error: node %d in device tree is not a child of the I2C bus\\n\",\n+\t\t       node_offset);\n+\t\treturn -1;\n+\t}\n+\n+\treg = fdtdec_get_addr(fdt, node_offset, \"reg\");\n+\tif (reg == FDT_ADDR_T_NONE) {\n+\t\tprintf(\"%s: Error: invalid reg address for TWSI bus\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\tfor (i = 0; i < ARRAY_SIZE(addresses); i++)\n+\t\tif (reg == addresses[i]) {\n+\t\t\tbus = i;\n+\t\t\tbreak;\n+\t\t}\n+\n+\tdebug(\"%s: bus 0x%x\\n\", __func__, bus);\n+\treturn bus;\n+}\n+\n+/**\n+ * Given an offset into the fdt, output the i2c bus and address of the device\n+ *\n+ * @param[in]\tfdt\tfdt blob pointer\n+ * @param\tnode\toffset in FDT of device\n+ * @param[out]\tbus\ti2c bus number of device\n+ * @param[out]\taddr\taddress of device on i2c bus\n+ *\n+ * @return\t0 for success, -1 on error\n+ */\n+int octeon_fdt_get_i2c_bus_addr(const void *fdt, int node, int *bus, int *addr)\n+{\n+\t*bus = octeon_fdt_i2c_get_bus(fdt, fdt_parent_offset(fdt, node));\n+\tif (*bus < 0) {\n+\t\tprintf(\"%s: Could not get parent i2c bus\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\t*addr = fdtdec_get_int(fdt, node, \"reg\", -1);\n+\tif (*addr < 0)\n+\t\treturn -1;\n+\treturn 0;\n+}\n+\n+/**\n+ * Reads a GPIO pin given the node of the GPIO device in the device tree and\n+ * the pin number.\n+ *\n+ * @param[in]\tfdt\tfdt blob pointer\n+ * @param\tphandle\tphandle of GPIO node\n+ * @param\tpin\tpin number to read\n+ *\n+ * @return\t0 = pin is low, 1 = pin is high, -1 = error\n+ */\n+int octeon_fdt_read_gpio(const void *fdt, int phandle, int pin)\n+{\n+\tenum cvmx_gpio_type type;\n+\t__maybe_unused int node;\n+\t__maybe_unused int addr;\n+\t__maybe_unused int bus;\n+\t__maybe_unused int old_bus;\n+\tint num_pins;\n+\tint value;\n+\n+\ttype = cvmx_fdt_get_gpio_type(fdt, phandle, &num_pins);\n+\tif ((pin & 0xff) >= num_pins) {\n+\t\tdebug(\"%s: pin number %d out of range\\n\", __func__, pin);\n+\t\treturn -1;\n+\t}\n+\tswitch (type) {\n+#ifdef CONFIG_PCA953X\n+\tcase CVMX_GPIO_PIN_PCA953X:\n+\t\tnode = fdt_node_offset_by_phandle(fdt, phandle);\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tvalue = pca953x_get_val(bus, addr);\n+\t\tif (value < 0) {\n+\t\t\tprintf(\"%s: Error reading PCA953X GPIO at 0x%x:0x%x\\n\", __func__, bus,\n+\t\t\t       addr);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tvalue = (value >> pin) & 1;\n+\t\tbreak;\n+#endif\n+#ifdef CONFIG_PCF857X\n+\tcase CVMX_GPIO_PIN_PCF857X:\n+\t\tnode = fdt_node_offset_by_phandle(fdt, phandle);\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tvalue = pcf857x_get_val(bus, addr);\n+\t\tif (value < 0) {\n+\t\t\tprintf(\"%s: Error reading PCF857X GPIO at 0x%x:0x%x\\n\", __func__, bus,\n+\t\t\t       addr);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tvalue = (value >> pin) & 1;\n+\t\tbreak;\n+#endif\n+#ifdef CONFIG_PCA9698\n+\tcase CVMX_GPIO_PIN_PCA9698:\n+\t\tnode = fdt_node_offset_by_phandle(fdt, phandle);\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\told_bus = i2c_get_bus_num();\n+\t\ti2c_set_bus_num(bus);\n+\t\tvalue = pca9698_get_value(addr, pin);\n+\t\ti2c_set_bus_num(old_bus);\n+\t\tbreak;\n+#endif\n+\tcase CVMX_GPIO_PIN_OCTEON:\n+\t\tvalue = gpio_get_value(pin);\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"%s: Unknown GPIO type %d\\n\", __func__, type);\n+\t\treturn -1;\n+\t}\n+\treturn value;\n+}\n+\n+/**\n+ * Reads a GPIO pin given the node of the GPIO device in the device tree and\n+ * the pin number.\n+ *\n+ * @param[in]\tfdt\tfdt blob pointer\n+ * @param\tphandle\tphandle of GPIO node\n+ * @param\tpin\tpin number to read\n+ * @param\tval\tvalue to write (1 = high, 0 = low)\n+ *\n+ * @return\t0 = success, -1 = error\n+ */\n+int octeon_fdt_set_gpio(const void *fdt, int phandle, int pin, int val)\n+{\n+\tenum cvmx_gpio_type type;\n+\tint node;\n+\tint num_pins;\n+\t__maybe_unused int addr;\n+\t__maybe_unused int bus;\n+\t__maybe_unused int old_bus;\n+\t__maybe_unused int rc;\n+\n+\tnode = fdt_node_offset_by_phandle(fdt, phandle);\n+\tif (node < 0) {\n+\t\tprintf(\"%s: Invalid phandle\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\ttype = cvmx_fdt_get_gpio_type(fdt, phandle, &num_pins);\n+\tif ((pin & 0xff) >= num_pins) {\n+\t\tdebug(\"%s: pin number %d out of range\\n\", __func__, pin);\n+\t\treturn -1;\n+\t}\n+\tswitch (type) {\n+#ifdef CONFIG_PCA953X\n+\tcase CVMX_GPIO_PIN_PCA953X:\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\treturn pca953x_set_val(bus, addr, 1 << pin, val << pin);\n+#endif\n+#ifdef CONFIG_PCF857X\n+\tcase CVMX_GPIO_PIN_PCF857X:\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\treturn pcf957x_set_val(bus, addr, 1 << pin, val << pin);\n+#endif\n+#ifdef CONFIG_PCA9698\n+\tcase CVMX_GPIO_PIN_PCA9698:\n+\t\tif (octeon_fdt_get_i2c_bus_addr(fdt, node, &bus, &addr)) {\n+\t\t\tprintf(\"%s: Could not get gpio bus and/or address\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\told_bus = i2c_get_bus_num();\n+\t\ti2c_set_bus_num(bus);\n+\t\trc = pca9698_set_value(addr, pin, val);\n+\t\ti2c_set_bus_num(old_bus);\n+\t\treturn rc;\n+#endif\n+\tcase CVMX_GPIO_PIN_OCTEON:\n+\t\treturn gpio_set_value(pin, val);\n+\tdefault:\n+\t\tprintf(\"%s: Unknown GPIO type %d\\n\", __func__, type);\n+\t\treturn -1;\n+\t}\n+}\n+\n+/**\n+ * Given the node of a GPIO entry output the GPIO type, i2c bus and i2c\n+ * address.\n+ *\n+ * @param\tfdt_node\tnode of GPIO in device tree, generally\n+ *\t\t\t\tderived from a phandle.\n+ * @param[out]\ttype\t\tType of GPIO detected\n+ * @param[out]\ti2c_bus\t\tFor i2c GPIO expanders, the i2c bus number\n+ * @param[out]\ti2c_addr\tFor i2c GPIO expanders, the i2c address\n+ *\n+ * @return\t0 for success, -1 for errors\n+ *\n+ * NOTE: It is up to the caller to determine the pin number.\n+ */\n+int octeon_fdt_get_gpio_info(int fdt_node, enum octeon_gpio_type *type,\n+\t\t\t     int *i2c_bus, int *i2c_addr)\n+{\n+\tconst void *fdt = gd->fdt_blob;\n+\n+\tint i2c_bus_node __attribute__((unused));\n+\n+\t*type = GPIO_TYPE_UNKNOWN;\n+\n+\tif (!octeon_fdt_node_check_compatible(fdt, fdt_node, octeon_gpio_list)) {\n+\t\tdebug(\"%s: Found Octeon compatible GPIO\\n\", __func__);\n+\t\t*type = GPIO_TYPE_OCTEON;\n+\t\tif (i2c_bus)\n+\t\t\t*i2c_bus = -1;\n+\t\tif (i2c_addr)\n+\t\t\t*i2c_addr = -1;\n+\t\treturn 0;\n+\t}\n+#ifdef CONFIG_PCA9555\n+\tif (!octeon_fdt_node_check_compatible(fdt, fdt_node, pca9555_gpio_list)) {\n+\t\tdebug(\"%s: Found PCA9555 type compatible GPIO\\n\", __func__);\n+\t\t*type = GPIO_TYPE_PCA9555;\n+\t}\n+#endif\n+#ifdef CONFIG_PCA9554\n+\tif (!octeon_fdt_node_check_compatible(fdt, fdt_node, pca9554_gpio_list)) {\n+\t\tdebug(\"%s: Found PCA9555 type compatible GPIO\\n\", __func__);\n+\t\t*type = GPIO_TYPE_PCA9554;\n+\t}\n+#endif\n+#ifdef CONFIG_PCA953X\n+\tif (!octeon_fdt_node_check_compatible(fdt, fdt_node, pca953x_gpio_list)) {\n+\t\tdebug(\"%s: Found PCA953x compatible GPIO\", __func__);\n+\t\t*type = GPIO_TYPE_PCA953X;\n+\t}\n+#endif\n+#ifdef CONFIG_PCA9698\n+\tif (!octeon_fdt_node_check_compatible(fdt, fdt_node, pca9698_gpio_list)) {\n+\t\tdebug(\"%s: Found PCA9698 compatible GPIO\", __func__);\n+\t\t*type = GPIO_TYPE_PCA9698;\n+\t}\n+#endif\n+#if defined(CONFIG_PCA953X) || defined(CONFIG_PCA9698) || \\\n+\tdefined(CONFIG_PCA9555) || defined(CONFIG_PCA9554)\n+\tif (!i2c_addr || !i2c_bus) {\n+\t\tprintf(\"%s: Error: i2c_addr or i2c_bus is NULL\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\t*i2c_addr = fdtdec_get_int(fdt, fdt_node, \"reg\", -1);\n+\ti2c_bus_node = fdt_parent_offset(fdt, fdt_node);\n+\tif (i2c_bus_node < 0) {\n+\t\tprintf(\"%s: Invalid parent\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\t*i2c_bus = i2c_get_bus_num_fdt(i2c_bus_node);\n+#endif\n+\treturn (*type != GPIO_TYPE_UNKNOWN) ? 0 : -1;\n+}\n+\n+#ifdef CONFIG_PHY_VITESSE\n+/**\n+ * Given a node in the flat device tree, return the matching PHY device\n+ *\n+ * @param\tfdt_node\tFDT node in device tree\n+ *\n+ * @return\tpointer to PHY device or NULL if none found.\n+ */\n+static struct phy_device *octeon_fdt_get_phy_device_from_node(int fdt_node)\n+{\n+\tstruct eth_device *dev;\n+\tint i = 0;\n+\tstruct octeon_eth_info *ethinfo = NULL;\n+\n+\tdo {\n+\t\tdev = eth_get_dev_by_index(i++);\n+\t\tif (!dev)\n+\t\t\treturn NULL;\n+\t\tethinfo = dev->priv;\n+\t\tif (ethinfo->phy_offset == fdt_node)\n+\t\t\treturn ethinfo->phydev;\n+\t} while (dev);\n+\treturn NULL;\n+}\n+#endif\n+\n+/**\n+ * Get the PHY data structure for the specified FDT node and output the type\n+ *\n+ * @param\tfdt_node\tFDT node of phy\n+ * @param[out]\ttype\t\tType of GPIO\n+ *\n+ * @return\tpointer to phy device or NULL if no match found.\n+ */\n+struct phy_device *octeon_fdt_get_phy_gpio_info(int fdt_node, enum octeon_gpio_type *type)\n+{\n+#ifdef CONFIG_PHY_VITESSE\n+\tstruct phy_device *phydev;\n+\n+\tif (!octeon_fdt_node_check_compatible(gd->fdt_blob, fdt_node,\n+\t\t\t\t\t      vitesse_vsc8488_gpio_list)) {\n+\t\tphydev = octeon_fdt_get_phy_device_from_node(fdt_node);\n+\t\tif (phydev) {\n+\t\t\tdebug(\"%s: Found Vitesse VSC848X compatible GPIO\\n\", __func__);\n+\t\t\t*type = GPIO_TYPE_VSC8488;\n+\t\t\treturn phydev;\n+\t\t}\n+\n+\t\tdebug(\"%s: Error: phy device not found!\\n\", __func__);\n+\t\treturn NULL;\n+\t}\n+\n+\tdebug(\"%s: No compatible Vitesse PHY type found\\n\", __func__);\n+#endif\n+\treturn NULL;\n+}\n",
    "prefixes": [
        "v1",
        "43/50"
    ]
}