get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2218769,
    "url": "http://patchwork.ozlabs.org/api/patches/2218769/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260401-mtk-mt8189-usb-v1-1-a4bf951aa8ad@baylibre.com/",
    "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": "<20260401-mtk-mt8189-usb-v1-1-a4bf951aa8ad@baylibre.com>",
    "list_archive_url": null,
    "date": "2026-04-01T21:53:45",
    "name": "[1/3] phy: mediatek: new XS-PHY driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "76e9e8c2d1162914f0821770eaf95641a9f35082",
    "submitter": {
        "id": 87228,
        "url": "http://patchwork.ozlabs.org/api/people/87228/?format=api",
        "name": "David Lechner",
        "email": "dlechner@baylibre.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260401-mtk-mt8189-usb-v1-1-a4bf951aa8ad@baylibre.com/mbox/",
    "series": [
        {
            "id": 498396,
            "url": "http://patchwork.ozlabs.org/api/series/498396/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=498396",
            "date": "2026-04-01T21:53:44",
            "name": "arm: mediatek: mt8189: enable USB support",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498396/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218769/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218769/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<u-boot-bounces@lists.denx.de>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=baylibre-com.20230601.gappssmtp.com\n header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256\n header.s=20230601 header.b=c/iW1Toi;\n\tdkim-atps=neutral",
            "legolas.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=patchwork.ozlabs.org)",
            "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=baylibre.com",
            "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de",
            "phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=baylibre-com.20230601.gappssmtp.com\n header.i=@baylibre-com.20230601.gappssmtp.com header.b=\"c/iW1Toi\";\n\tdkim-atps=neutral",
            "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=baylibre.com",
            "phobos.denx.de;\n spf=pass smtp.mailfrom=dlechner@baylibre.com"
        ],
        "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 ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fmJfx3l1zz1yFv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 08:54:33 +1100 (AEDT)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id D2E6784099;\n\tWed,  1 Apr 2026 23:54:21 +0200 (CEST)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 1B8A683CE3; Wed,  1 Apr 2026 23:54:20 +0200 (CEST)",
            "from mail-ot1-x32d.google.com (mail-ot1-x32d.google.com\n [IPv6:2607:f8b0:4864:20::32d])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 51C8083CF5\n for <u-boot@lists.denx.de>; Wed,  1 Apr 2026 23:54:17 +0200 (CEST)",
            "by mail-ot1-x32d.google.com with SMTP id\n 46e09a7af769-7d7f09aa39fso291973a34.0\n for <u-boot@lists.denx.de>; Wed, 01 Apr 2026 14:54:17 -0700 (PDT)",
            "from [127.0.1.1] ([2600:8803:e7e4:500:57c4:ef89:4ac4:d6d9])\n by smtp.gmail.com with ESMTPSA id\n 46e09a7af769-7dba7184e14sm743492a34.11.2026.04.01.14.54.14\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 01 Apr 2026 14:54:15 -0700 (PDT)"
        ],
        "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de",
        "X-Spam-Level": "",
        "X-Spam-Status": "No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1775080456;\n x=1775685256;\n darn=lists.denx.de;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to; bh=jp1oQ54bfsoxe3yefXDFc3Gbq+D+dKMtU54TX0cf41g=;\n b=c/iW1Toib23om/rGwERKjc8IXT4lx2jtsxRwyhgLqy2Iv4Daj49T+gLeVoOfx2s1FK\n 7pTdJr7pnrVLP+8m/MRVhiOZPIdmuP8Xp/DjrkCLyrbzsCM9pmHFhCqFELni0pPIVtkC\n +qfJxsCDAOqwlQPuKgjoEkoThkb6f4PmQRotLybu9A3vbhLa3AP7agjvzxuE9W5aD1/b\n m6qSBlds8y9T1vC83dGbAuy00WisaLUc6S9EyyxZFy4UmW7j8KV38BtaIGcxFqNmPT48\n h/XwPoh8bYOlPgxSE9Ff6V3TVYh1xRfqVfNAzkpVzG40d2upWpY4oBEN8eQ/BsqcKlbj\n A7Cw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775080456; x=1775685256;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=jp1oQ54bfsoxe3yefXDFc3Gbq+D+dKMtU54TX0cf41g=;\n b=pG7AQ/+Vnh+Bpwa03Ce2+lt3LxExXgKSVmR5IHYpc7QIq3zt7Dqf5EI9t67+SscAvd\n ZDrnRPR38/6q6JmJrf1m+d3eYGvqnQNdNlAgFlL+nKmcr3ndEwoizxA8/dnrwg9jQzWL\n d9R9NM/d/OezAUhDle7bJl7OBclazb7r4xaT5Lvekzil9CX92fDBSNSEg7KEmWWHKYHo\n A/szuqe42hlC/H/6VofwKjZkAKj6anOFJW/LVo7ILDXjPBz0QxplVCoJkSbvtc/ts/BB\n L09qbJVL5iRUd3+h8DvPeauJbevHSpPQNHVSTHP9fYf4QPM+XNW26zLRv15W60q0+SoN\n oVqQ==",
        "X-Forwarded-Encrypted": "i=1;\n AJvYcCVWyc5etoTq5VyJMS4ueTHVkaKh7tVYffm6kZmPrpK7MDtmMylEwlnqE+KQNT3c7O6nxUM+Vkc=@lists.denx.de",
        "X-Gm-Message-State": "AOJu0YzGizBpBmHcvlRLEp4Hpone8WX14OcQQd7eqJ/m/GlWUjRfAMae\n iggX5kMkaDUDUpRTpT17hJr1k3MsdHdTk0tQYmHZM1sGkmIlykn6THHf3pc0yOmrNe8=",
        "X-Gm-Gg": "ATEYQzx4dbuIRDyCmJFKBmY3TCxa0i/A95Dr+DYUPCGIINyTKtME6Qa2Gv8ghSZF0Tz\n AsvC6M11DWzspNLUpIfOQMj6lve+whEFwQUyxpc3lSbi4WhFlTRoJR/k79USU2yyaDj09lvKzFW\n 8pjwRD+UW5Od1hehQ3BtHa3HLG/4Tl7FZzU3UWWZy0HvAyd5lkvFKSX4fo+DtHDrbu29pKZySDb\n 9EdTZ7L6iFf611dNe4StXNhXeDsbLmBkO4qXYmTFugq8B3B1VEIlId1CPV75rjClpo5A7DUsQFb\n uflcWQ40dqtwBkWezugYlXi1iOvO/rSls70phKnU7aCRnv4ikREbLI7aVOoW/Zw1v1XSrg/sBCZ\n VxlsuGN+6jIVckEpuN1h1TD83IhkbzFmc2K401+vLibPqnu25TiI3zpMP2vQ1pw/7LdxjC5h54U\n +SNqnwxlheyGEHLmv3hSydeE9PfwPc+Ef1EHl3p/U=",
        "X-Received": "by 2002:a05:6830:348d:b0:7d7:ebf0:34b2 with SMTP id\n 46e09a7af769-7dba7d99e38mr955319a34.14.1775080455903;\n Wed, 01 Apr 2026 14:54:15 -0700 (PDT)",
        "From": "David Lechner <dlechner@baylibre.com>",
        "Date": "Wed, 01 Apr 2026 16:53:45 -0500",
        "Subject": "[PATCH 1/3] phy: mediatek: new XS-PHY driver",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260401-mtk-mt8189-usb-v1-1-a4bf951aa8ad@baylibre.com>",
        "References": "<20260401-mtk-mt8189-usb-v1-0-a4bf951aa8ad@baylibre.com>",
        "In-Reply-To": "<20260401-mtk-mt8189-usb-v1-0-a4bf951aa8ad@baylibre.com>",
        "To": "Tom Rini <trini@konsulko.com>, Ryder Lee <ryder.lee@mediatek.com>,\n Weijie Gao <weijie.gao@mediatek.com>,\n Chunfeng Yun <chunfeng.yun@mediatek.com>,\n Igor Belwon <igor.belwon@mentallysanemainliners.org>,\n GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream@mediatek.com>,\n Macpaul Lin <macpaul.lin@mediatek.com>",
        "Cc": "Julien Stephan <jstephan@baylibre.com>, u-boot@lists.denx.de,\n David Lechner <dlechner@baylibre.com>",
        "X-Mailer": "b4 0.16-dev",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=18987;\n i=dlechner@baylibre.com; h=from:subject:message-id;\n bh=o1axNFlxJXkGdaZyQa8/Sds7ROSSApAGUQp/N7g+h8s=;\n b=owEBhAF7/pANAwAKAcLMIAH/AY/AAcsmYgBpzZPxBLfPQYKmXh+tX/9IkiI2uAnVnx3ic8/G1\n tEj8SyI80uJAUoEAAEKADQWIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCac2T8RYcZGxlY2huZXJA\n YmF5bGlicmUuY29tAAoJEMLMIAH/AY/ADbUH/2d3qWkvN8yjaqQ1IwaRbWDXJZ+DZUlkDyu9oxF\n 6Las5C9QZyqsTFHn/4B4Kfhb/SUD/DVVYc6EMoAEVlF36uhabWKyrwut+cGj5VUneABSrVR7jzh\n u5yv408JZsUiqpZB1lZAJjzK5ZznCpAL2gJyYSglQlmYZwUOBKkno73Z9FLPLj4j3h05DG/NxQu\n yWRMjYPOD4z1F0TpFBeM70USBlEi62SbLW9MsRYq4zuGmKAO5zIj33nvd7T10HMeXD3jAGX/h+y\n 3ms3M2cUkrU7e0u8Mis7EaY16LhRoDu8IK4tRF5T3hKlvrhIXOHcW9vI76dR5CD+R3k9zIF39+q\n El5Y=",
        "X-Developer-Key": "i=dlechner@baylibre.com; a=openpgp;\n fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03",
        "X-BeenThere": "u-boot@lists.denx.de",
        "X-Mailman-Version": "2.1.39",
        "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.103.8 at phobos.denx.de",
        "X-Virus-Status": "Clean"
    },
    "content": "Add a new driver for the Mediatek XS-PHY. This is found on some newer\nMediatek SoCs.\n\nUpstream devicetree bindings already exist. MAINTAINERS is already\ncovered by drivers/phy/phy-mtk-*.\n\nSigned-off-by: David Lechner <dlechner@baylibre.com>\n---\n drivers/phy/Kconfig         |  11 +\n drivers/phy/Makefile        |   1 +\n drivers/phy/phy-mtk-xsphy.c | 600 ++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 612 insertions(+)",
    "diff": "diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig\nindex 09810b62b51..fc4daa00661 100644\n--- a/drivers/phy/Kconfig\n+++ b/drivers/phy/Kconfig\n@@ -292,6 +292,17 @@ config PHY_MTK_UFS\n \t  initialization, power on and power off flow of\n \t  specified M-PHYs.\n \n+config PHY_MTK_XSPHY\n+\tbool \"MediaTek XS-PHY Driver\"\n+\tdepends on PHY\n+\tdepends on ARCH_MEDIATEK\n+\tselect REGMAP\n+\tselect SYSCON\n+\thelp\n+\t  Enable this to support the SuperSpeedPlus XS-PHY transceiver for\n+\t  USB3.1 GEN2 controllers on MediaTek chips. The driver supports\n+\t  multiple USB2.0, USB3.1 GEN2 ports.\n+\n config PHY_NPCM_USB\n \tbool \"Nuvoton NPCM USB PHY support\"\n \tdepends on PHY\ndiff --git a/drivers/phy/Makefile b/drivers/phy/Makefile\nindex 83102349669..684e9a99af8 100644\n--- a/drivers/phy/Makefile\n+++ b/drivers/phy/Makefile\n@@ -38,6 +38,7 @@ obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o\n obj-$(CONFIG_PHY_EXYNOS_USBDRD) += phy-exynos-usbdrd.o\n obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o\n obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o\n+obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o\n obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o\n obj-$(CONFIG_$(PHASE_)PHY_IMX8MQ_USB) += phy-imx8mq-usb.o\n obj-$(CONFIG_PHY_IMX8M_PCIE) += phy-imx8m-pcie.o\ndiff --git a/drivers/phy/phy-mtk-xsphy.c b/drivers/phy/phy-mtk-xsphy.c\nnew file mode 100644\nindex 00000000000..d3418ffb101\n--- /dev/null\n+++ b/drivers/phy/phy-mtk-xsphy.c\n@@ -0,0 +1,600 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * MediaTek USB3.1 gen2 xsphy Driver\n+ *\n+ * Copyright (c) 2026 MediaTek Inc.\n+ * Copyright (c) 2026 BayLibre, SAS\n+ *\n+ * Based on Linux mtk-xsphy driver:\n+ * Copyright (c) 2018 MediaTek Inc.\n+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>\n+ *\n+ * And U-Boot mtk-tphy driver:\n+ * Copyright (c) 2015 - 2019 MediaTek Inc.\n+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>\n+ *\t   Ryder Lee <ryder.lee@mediatek.com>\n+ */\n+\n+#include <clk.h>\n+#include <dm.h>\n+#include <generic-phy.h>\n+#include <malloc.h>\n+#include <mapmem.h>\n+#include <regmap.h>\n+#include <syscon.h>\n+\n+#include <asm/io.h>\n+#include <dm/device_compat.h>\n+#include <dm/devres.h>\n+#include <linux/bitfield.h>\n+#include <linux/bitops.h>\n+#include <linux/delay.h>\n+#include <linux/iopoll.h>\n+\n+#include <dt-bindings/phy/phy.h>\n+\n+/* u2 phy banks */\n+#define SSUSB_SIFSLV_MISC\t\t0x000\n+#define SSUSB_SIFSLV_U2FREQ\t\t0x100\n+#define SSUSB_SIFSLV_U2PHY_COM\t\t0x300\n+\n+/* u3 phy shared banks */\n+#define SSPXTP_SIFSLV_DIG_GLB\t\t0x000\n+#define SSPXTP_SIFSLV_PHYA_GLB\t\t0x100\n+\n+/* u3 phy banks */\n+#define SSPXTP_SIFSLV_DIG_LN_TOP\t0x000\n+#define SSPXTP_SIFSLV_DIG_LN_TX0\t0x100\n+#define SSPXTP_SIFSLV_DIG_LN_RX0\t0x200\n+#define SSPXTP_SIFSLV_DIG_LN_DAIF\t0x300\n+#define SSPXTP_SIFSLV_PHYA_LN\t\t0x400\n+\n+#define XSP_U2FREQ_FMCR0\t((SSUSB_SIFSLV_U2FREQ) + 0x00)\n+#define P2F_RG_FREQDET_EN\t\tBIT(24)\n+#define P2F_RG_CYCLECNT\t\t\tGENMASK(23, 0)\n+\n+#define XSP_U2FREQ_MMONR0\t((SSUSB_SIFSLV_U2FREQ) + 0x0c)\n+\n+#define XSP_U2FREQ_FMMONR1\t((SSUSB_SIFSLV_U2FREQ) + 0x10)\n+#define P2F_RG_FRCK_EN\t\t\tBIT(8)\n+#define P2F_USB_FM_VALID\t\tBIT(0)\n+\n+#define XSP_USBPHYACR0\t\t((SSUSB_SIFSLV_U2PHY_COM) + 0x00)\n+#define P2A0_RG_INTR_EN\t\t\tBIT(5)\n+\n+#define XSP_USBPHYACR1\t\t((SSUSB_SIFSLV_U2PHY_COM) + 0x04)\n+#define P2A1_RG_INTR_CAL\t\tGENMASK(23, 19)\n+#define P2A1_RG_VRT_SEL\t\t\tGENMASK(14, 12)\n+#define P2A1_RG_TERM_SEL\t\tGENMASK(10, 8)\n+\n+#define XSP_USBPHYACR5\t\t((SSUSB_SIFSLV_U2PHY_COM) + 0x014)\n+#define P2A5_RG_HSTX_SRCAL_EN\t\tBIT(15)\n+#define P2A5_RG_HSTX_SRCTRL\t\tGENMASK(14, 12)\n+\n+#define XSP_USBPHYACR6\t\t((SSUSB_SIFSLV_U2PHY_COM) + 0x018)\n+#define P2A6_RG_BC11_SW_EN\t\tBIT(23)\n+#define P2A6_RG_OTG_VBUSCMP_EN\t\tBIT(20)\n+\n+#define XSP_U2PHYDTM1\t\t((SSUSB_SIFSLV_U2PHY_COM) + 0x06C)\n+#define P2D_FORCE_IDDIG\t\t\tBIT(9)\n+#define P2D_RG_VBUSVALID\t\tBIT(5)\n+#define P2D_RG_SESSEND\t\t\tBIT(4)\n+#define P2D_RG_AVALID\t\t\tBIT(2)\n+#define P2D_RG_IDDIG\t\t\tBIT(1)\n+\n+#define SSPXTP_PHYA_GLB_00\t((SSPXTP_SIFSLV_PHYA_GLB) + 0x00)\n+#define RG_XTP_GLB_BIAS_INTR_CTRL\tGENMASK(21, 16)\n+\n+#define SSPXTP_PHYA_LN_04\t((SSPXTP_SIFSLV_PHYA_LN) + 0x04)\n+#define RG_XTP_LN0_TX_IMPSEL\t\tGENMASK(4, 0)\n+\n+#define SSPXTP_PHYA_LN_14\t((SSPXTP_SIFSLV_PHYA_LN) + 0x014)\n+#define RG_XTP_LN0_RX_IMPSEL\t\tGENMASK(4, 0)\n+\n+#define XSP_REF_CLK_MHZ\t\t26\n+#define XSP_SLEW_RATE_COEF\t17\n+#define XSP_SR_COEF_DIVISOR\t1000\n+#define XSP_FM_DET_CYCLE_CNT\t1024\n+\n+/* PHY switch between pcie/usb3/sgmii */\n+#define USB_PHY_SWITCH_CTRL\t0x0\n+#define RG_PHY_SW_TYPE\t\tGENMASK(3, 0)\n+#define RG_PHY_SW_PCIE\t\t0x0\n+#define RG_PHY_SW_USB3\t\t0x1\n+#define RG_PHY_SW_SGMII\t\t0x2\n+\n+struct mtk_xsphy_instance {\n+\tvoid __iomem *port_base;\n+\tstruct device_node *np;\n+\tstruct clk ref_clk;\t/* reference clock of analog phy */\n+\tu32 index;\n+\tu32 type;\n+\tstruct regmap *type_sw;\n+\tu32 type_sw_reg;\n+\tu32 type_sw_index;\n+\t/* only for HQA test */\n+\tu32 efuse_intr;\n+\tu32 efuse_tx_imp;\n+\tu32 efuse_rx_imp;\n+\t/* u2 eye diagram */\n+\tu32 eye_src;\n+\tu32 eye_vrt;\n+\tu32 eye_term;\n+};\n+\n+struct mtk_xsphy {\n+\tstruct udevice *dev;\n+\tvoid __iomem *sif_base;\n+\tstruct mtk_xsphy_instance **phys;\n+\tu32 nphys;\n+\tu32 src_ref_clk_mhz; /* reference clock for slew rate calibrate */\n+\tu32 src_coef; /* coefficient for slew rate calibrate */\n+};\n+\n+static void mtk_xsphy_u2_slew_rate_calibrate(struct mtk_xsphy *xsphy,\n+\t\t\t\t\t     struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\tu32 calib_val;\n+\tu32 fm_out;\n+\tu32 tmp;\n+\n+\t/* use force value */\n+\tif (instance->eye_src)\n+\t\treturn;\n+\n+\t/* enable USB ring oscillator */\n+\tsetbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN);\n+\t/* wait for clock to become stable */\n+\tudelay(1);\n+\n+\t/* enable free run clock */\n+\tsetbits_le32(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN);\n+\n+\t/* set cycle count as 1024 */\n+\tclrsetbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_CYCLECNT,\n+\t\t\tFIELD_PREP(P2F_RG_CYCLECNT, XSP_FM_DET_CYCLE_CNT));\n+\n+\t/* enable frequency meter */\n+\tsetbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN);\n+\n+\t/* ignore return value */\n+\treadl_poll_sleep_timeout(pbase + XSP_U2FREQ_FMMONR1, tmp,\n+\t\t\t\t (tmp & P2F_USB_FM_VALID), 10, 200);\n+\n+\tfm_out = readl(pbase + XSP_U2FREQ_MMONR0);\n+\n+\t/* disable frequency meter */\n+\tclrbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN);\n+\n+\t/* disable free run clock */\n+\tclrbits_le32(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN);\n+\n+\tif (fm_out) {\n+\t\t/* (1024 / FM_OUT) x reference clock frequency x coefficient */\n+\t\ttmp = xsphy->src_ref_clk_mhz * xsphy->src_coef;\n+\t\ttmp = (tmp * XSP_FM_DET_CYCLE_CNT) / fm_out;\n+\t\tcalib_val = DIV_ROUND_CLOSEST(tmp, XSP_SR_COEF_DIVISOR);\n+\t} else {\n+\t\t/* if FM detection fail, set default value */\n+\t\tcalib_val = 3;\n+\t}\n+\tdev_dbg(xsphy->dev, \"phy.%u, fm_out:%u, calib:%u (clk:%u, coef:%u)\\n\",\n+\t\tinstance->index, fm_out, calib_val, xsphy->src_ref_clk_mhz,\n+\t\txsphy->src_coef);\n+\n+\t/* set HS slew rate */\n+\tclrsetbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL,\n+\t\t\tFIELD_PREP(P2A5_RG_HSTX_SRCTRL, calib_val));\n+\n+\t/* disable USB ring oscillator */\n+\tclrbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN);\n+}\n+\n+static void mtk_xsphy_u2_instance_init(struct mtk_xsphy *xsphy,\n+\t\t\t\t       struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\n+\t/* DP/DM BC1.1 path Disable */\n+\tclrbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_BC11_SW_EN);\n+\n+\tsetbits_le32(pbase + XSP_USBPHYACR0, P2A0_RG_INTR_EN);\n+}\n+\n+static void mtk_xsphy_u2_instance_power_on(struct mtk_xsphy *xsphy,\n+\t\t\t\t\t   struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\n+\tsetbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN);\n+\n+\tclrsetbits_le32(pbase + XSP_U2PHYDTM1,\n+\t\t\tP2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND,\n+\t\t\tP2D_RG_VBUSVALID | P2D_RG_AVALID);\n+\n+\tdev_dbg(xsphy->dev, \"%s(%u)\\n\", __func__, instance->index);\n+}\n+\n+static void mtk_xsphy_u2_instance_power_off(struct mtk_xsphy *xsphy,\n+\t\t\t\t\t    struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\n+\tclrbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN);\n+\n+\tclrsetbits_le32(pbase + XSP_U2PHYDTM1,\n+\t\t\tP2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND,\n+\t\t\tP2D_RG_SESSEND);\n+\n+\tdev_dbg(xsphy->dev, \"%s(%u)\\n\", __func__, instance->index);\n+}\n+\n+static void mtk_xsphy_u2_instance_set_mode(struct mtk_xsphy *xsphy,\n+\t\t\t\t\t   struct mtk_xsphy_instance *instance,\n+\t\t\t\t\t   enum phy_mode mode)\n+{\n+\tu32 tmp;\n+\n+\ttmp = readl(instance->port_base + XSP_U2PHYDTM1);\n+\n+\tswitch (mode) {\n+\tcase PHY_MODE_USB_DEVICE:\n+\t\ttmp |= P2D_FORCE_IDDIG | P2D_RG_IDDIG;\n+\t\tbreak;\n+\tcase PHY_MODE_USB_HOST:\n+\t\ttmp |= P2D_FORCE_IDDIG;\n+\t\ttmp &= ~P2D_RG_IDDIG;\n+\t\tbreak;\n+\tcase PHY_MODE_USB_OTG:\n+\t\ttmp &= ~(P2D_FORCE_IDDIG | P2D_RG_IDDIG);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn;\n+\t}\n+\n+\twritel(tmp, instance->port_base + XSP_U2PHYDTM1);\n+}\n+\n+static void mtk_xsphy_parse_property(struct mtk_xsphy *xsphy,\n+\t\t\t\t     struct mtk_xsphy_instance *instance)\n+{\n+\tofnode node = np_to_ofnode(instance->np);\n+\n+\tswitch (instance->type) {\n+\tcase PHY_TYPE_USB2:\n+\t\tofnode_read_u32(node, \"mediatek,efuse-intr\", &instance->efuse_intr);\n+\t\tofnode_read_u32(node, \"mediatek,eye-src\", &instance->eye_src);\n+\t\tofnode_read_u32(node, \"mediatek,eye-vrt\", &instance->eye_vrt);\n+\t\tofnode_read_u32(node, \"mediatek,eye-term\", &instance->eye_term);\n+\n+\t\tdev_dbg(xsphy->dev, \"intr:%u, src:%u, vrt:%u, term:%u\\n\",\n+\t\t\tinstance->efuse_intr, instance->eye_src,\n+\t\t\tinstance->eye_vrt, instance->eye_term);\n+\t\treturn;\n+\tcase PHY_TYPE_USB3:\n+\t\tofnode_read_u32(node, \"mediatek,efuse-intr\", &instance->efuse_intr);\n+\t\tofnode_read_u32(node, \"mediatek,efuse-tx-imp\", &instance->efuse_tx_imp);\n+\t\tofnode_read_u32(node, \"mediatek,efuse-rx-imp\", &instance->efuse_rx_imp);\n+\n+\t\tdev_dbg(xsphy->dev, \"intr:%u, tx-imp:%u, rx-imp:%u\\n\",\n+\t\t\tinstance->efuse_intr, instance->efuse_tx_imp,\n+\t\t\tinstance->efuse_rx_imp);\n+\t\treturn;\n+\tcase PHY_TYPE_PCIE:\n+\tcase PHY_TYPE_SGMII:\n+\t\t/* nothing to do */\n+\t\treturn;\n+\tdefault:\n+\t\tdev_err(xsphy->dev, \"incompatible PHY type\\n\");\n+\t\treturn;\n+\t}\n+}\n+\n+static void mtk_xsphy_u2_props_set(struct mtk_xsphy *xsphy,\n+\t\t\t\t   struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\n+\tif (instance->efuse_intr)\n+\t\tclrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_INTR_CAL,\n+\t\t\t\tFIELD_PREP(P2A1_RG_INTR_CAL, instance->efuse_intr));\n+\n+\tif (instance->eye_src)\n+\t\tclrsetbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL,\n+\t\t\t\tFIELD_PREP(P2A5_RG_HSTX_SRCTRL, instance->eye_src));\n+\n+\tif (instance->eye_vrt)\n+\t\tclrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_VRT_SEL,\n+\t\t\t\tFIELD_PREP(P2A1_RG_VRT_SEL, instance->eye_vrt));\n+\n+\tif (instance->eye_term)\n+\t\tclrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_TERM_SEL,\n+\t\t\t\tFIELD_PREP(P2A1_RG_TERM_SEL, instance->eye_term));\n+}\n+\n+static void mtk_xsphy_u3_props_set(struct mtk_xsphy *xsphy,\n+\t\t\t\t   struct mtk_xsphy_instance *instance)\n+{\n+\tvoid __iomem *pbase = instance->port_base;\n+\n+\tif (instance->efuse_intr)\n+\t\tclrsetbits_le32(xsphy->sif_base + SSPXTP_PHYA_GLB_00,\n+\t\t\t\tRG_XTP_GLB_BIAS_INTR_CTRL,\n+\t\t\t\tFIELD_PREP(RG_XTP_GLB_BIAS_INTR_CTRL, instance->efuse_intr));\n+\n+\tif (instance->efuse_tx_imp)\n+\t\tclrsetbits_le32(pbase + SSPXTP_PHYA_LN_04, RG_XTP_LN0_TX_IMPSEL,\n+\t\t\t\tFIELD_PREP(RG_XTP_LN0_TX_IMPSEL, instance->efuse_tx_imp));\n+\n+\tif (instance->efuse_rx_imp)\n+\t\tclrsetbits_le32(pbase + SSPXTP_PHYA_LN_14, RG_XTP_LN0_RX_IMPSEL,\n+\t\t\t\tFIELD_PREP(RG_XTP_LN0_RX_IMPSEL, instance->efuse_rx_imp));\n+}\n+\n+/* type switch for usb3/pcie/sgmii */\n+static int mtk_xsphy_type_syscon_get(struct udevice *dev,\n+\t\t\t\t     struct mtk_xsphy_instance *instance,\n+\t\t\t\t     ofnode dn)\n+{\n+\tstruct ofnode_phandle_args args;\n+\tint ret;\n+\n+\tif (!ofnode_read_bool(dn, \"mediatek,syscon-type\"))\n+\t\treturn 0;\n+\n+\tret = ofnode_parse_phandle_with_args(dn, \"mediatek,syscon-type\",\n+\t\t\t\t\t     NULL, 2, 0, &args);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tinstance->type_sw_reg = args.args[0];\n+\tinstance->type_sw_index = args.args[1] & 0x3; /* <=3 */\n+\tinstance->type_sw = syscon_node_to_regmap(args.node);\n+\tif (IS_ERR(instance->type_sw))\n+\t\treturn PTR_ERR(instance->type_sw);\n+\n+\tdev_dbg(dev, \"phy-%s.%d: type_sw - reg %#x, index %d\\n\",\n+\t\tdev->name, instance->index, instance->type_sw_reg,\n+\t\tinstance->type_sw_index);\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_type_set(struct mtk_xsphy_instance *instance)\n+{\n+\tint type;\n+\tu32 offset;\n+\n+\tif (!instance->type_sw)\n+\t\treturn 0;\n+\n+\tswitch (instance->type) {\n+\tcase PHY_TYPE_USB3:\n+\t\ttype = RG_PHY_SW_USB3;\n+\t\tbreak;\n+\tcase PHY_TYPE_PCIE:\n+\t\ttype = RG_PHY_SW_PCIE;\n+\t\tbreak;\n+\tcase PHY_TYPE_SGMII:\n+\t\ttype = RG_PHY_SW_SGMII;\n+\t\tbreak;\n+\tcase PHY_TYPE_USB2:\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+\n+\toffset = instance->type_sw_index * BITS_PER_BYTE;\n+\tregmap_update_bits(instance->type_sw, instance->type_sw_reg,\n+\t\t\t   RG_PHY_SW_TYPE << offset, type << offset);\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_init(struct phy *phy)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = xsphy->phys[phy->id];\n+\tint ret;\n+\n+\tret = clk_enable(&instance->ref_clk);\n+\tif (ret) {\n+\t\tdev_err(xsphy->dev, \"failed to enable ref_clk\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tswitch (instance->type) {\n+\tcase PHY_TYPE_USB2:\n+\t\tmtk_xsphy_u2_instance_init(xsphy, instance);\n+\t\tmtk_xsphy_u2_props_set(xsphy, instance);\n+\t\tbreak;\n+\tcase PHY_TYPE_USB3:\n+\t\tmtk_xsphy_u3_props_set(xsphy, instance);\n+\t\tbreak;\n+\tcase PHY_TYPE_PCIE:\n+\tcase PHY_TYPE_SGMII:\n+\t\t/* nothing to do, only used to set type */\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(xsphy->dev, \"incompatible PHY type\\n\");\n+\t\tclk_disable(&instance->ref_clk);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_power_on(struct phy *phy)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = xsphy->phys[phy->id];\n+\n+\tif (instance->type == PHY_TYPE_USB2) {\n+\t\tmtk_xsphy_u2_instance_power_on(xsphy, instance);\n+\t\tmtk_xsphy_u2_slew_rate_calibrate(xsphy, instance);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_power_off(struct phy *phy)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = xsphy->phys[phy->id];\n+\n+\tif (instance->type == PHY_TYPE_USB2)\n+\t\tmtk_xsphy_u2_instance_power_off(xsphy, instance);\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_exit(struct phy *phy)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = xsphy->phys[phy->id];\n+\n+\tclk_disable(&instance->ref_clk);\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_set_mode(struct phy *phy, enum phy_mode mode, int submode)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = xsphy->phys[phy->id];\n+\n+\tif (instance->type == PHY_TYPE_USB2)\n+\t\tmtk_xsphy_u2_instance_set_mode(xsphy, instance, mode);\n+\n+\treturn 0;\n+}\n+\n+static int mtk_xsphy_xlate(struct phy *phy, struct ofnode_phandle_args *args)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(phy->dev);\n+\tstruct mtk_xsphy_instance *instance = NULL;\n+\tconst struct device_node *phy_np = ofnode_to_np(args->node);\n+\tu32 index;\n+\n+\tif (!phy_np) {\n+\t\tdev_err(phy->dev, \"null pointer phy node\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (args->args_count != 2) {\n+\t\tdev_err(phy->dev, \"invalid number of cells in 'phy' property\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (index = 0; index < xsphy->nphys; index++)\n+\t\tif (phy_np == xsphy->phys[index]->np) {\n+\t\t\tinstance = xsphy->phys[index];\n+\t\t\tbreak;\n+\t\t}\n+\n+\tif (!instance) {\n+\t\tdev_err(phy->dev, \"failed to find appropriate phy\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tphy->id = index;\n+\tinstance->type = args->args[1];\n+\tif (!(instance->type == PHY_TYPE_USB2 ||\n+\t      instance->type == PHY_TYPE_USB3 ||\n+\t      instance->type == PHY_TYPE_PCIE ||\n+\t      instance->type == PHY_TYPE_SGMII)) {\n+\t\tdev_err(phy->dev, \"unsupported PHY type\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmtk_xsphy_parse_property(xsphy, instance);\n+\tmtk_xsphy_type_set(instance);\n+\n+\treturn 0;\n+}\n+\n+static const struct phy_ops mtk_xsphy_ops = {\n+\t.init\t\t= mtk_xsphy_init,\n+\t.exit\t\t= mtk_xsphy_exit,\n+\t.power_on\t= mtk_xsphy_power_on,\n+\t.power_off\t= mtk_xsphy_power_off,\n+\t.set_mode\t= mtk_xsphy_set_mode,\n+\t.of_xlate\t= mtk_xsphy_xlate,\n+};\n+\n+static int mtk_xsphy_probe(struct udevice *dev)\n+{\n+\tstruct mtk_xsphy *xsphy = dev_get_priv(dev);\n+\tfdt_addr_t sif_addr;\n+\tofnode subnode;\n+\tint index = 0;\n+\n+\txsphy->nphys = dev_get_child_count(dev);\n+\n+\txsphy->phys = devm_kcalloc(dev, xsphy->nphys, sizeof(*xsphy->phys),\n+\t\t\t\t   GFP_KERNEL);\n+\tif (!xsphy->phys)\n+\t\treturn -ENOMEM;\n+\n+\txsphy->dev = dev;\n+\n+\tsif_addr = ofnode_get_addr(dev_ofnode(dev));\n+\t/* optional, may not exist if no u3 phys */\n+\tif (sif_addr != FDT_ADDR_T_NONE)\n+\t\txsphy->sif_base = map_sysmem(sif_addr, 0);\n+\n+\txsphy->src_ref_clk_mhz = XSP_REF_CLK_MHZ;\n+\txsphy->src_coef = XSP_SLEW_RATE_COEF;\n+\t/* update parameters of slew rate calibrate if exist */\n+\tofnode_read_u32(dev_ofnode(dev), \"mediatek,src-ref-clk-mhz\",\n+\t\t\t&xsphy->src_ref_clk_mhz);\n+\tofnode_read_u32(dev_ofnode(dev), \"mediatek,src-coef\", &xsphy->src_coef);\n+\n+\tdev_for_each_subnode(subnode, dev) {\n+\t\tstruct mtk_xsphy_instance *inst;\n+\t\tfdt_addr_t addr;\n+\t\tint ret;\n+\n+\t\tinst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL);\n+\t\tif (!inst)\n+\t\t\treturn -ENOMEM;\n+\n+\t\txsphy->phys[index] = inst;\n+\n+\t\taddr = ofnode_get_addr(subnode);\n+\t\tif (addr == FDT_ADDR_T_NONE)\n+\t\t\treturn -EADDRNOTAVAIL;\n+\n+\t\tinst->port_base = map_sysmem(addr, 0);\n+\t\tinst->index = index;\n+\t\tinst->np = ofnode_to_np(subnode);\n+\n+\t\tret = clk_get_by_name_nodev(subnode, \"ref\", &inst->ref_clk);\n+\t\tif (ret) {\n+\t\t\tdev_err(dev, \"failed to get ref_clk(id-%d)\\n\", index);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tret = mtk_xsphy_type_syscon_get(dev, inst, subnode);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tindex++;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static const struct udevice_id mtk_xsphy_id_table[] = {\n+\t{ .compatible = \"mediatek,xsphy\" },\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(mtk_xsphy) = {\n+\t.name\t\t= \"mtk-xsphy\",\n+\t.id\t\t= UCLASS_PHY,\n+\t.of_match\t= mtk_xsphy_id_table,\n+\t.ops\t\t= &mtk_xsphy_ops,\n+\t.probe\t\t= mtk_xsphy_probe,\n+\t.priv_auto\t= sizeof(struct mtk_xsphy),\n+};\n",
    "prefixes": [
        "1/3"
    ]
}