{"id":2220019,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2220019/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260405144944.41074-2-lucienzx159@gmail.com/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.2/projects/18/?format=json","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":"<20260405144944.41074-2-lucienzx159@gmail.com>","list_archive_url":null,"date":"2026-04-05T14:49:41","name":"[v3,1/4] phy: add common PHY properties support","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"cca9583ab52c76923e8ffbdc07ee5418007ffea5","submitter":{"id":90627,"url":"http://patchwork.ozlabs.org/api/1.2/people/90627/?format=json","name":"Lucien.Jheng","email":"lucienzx159@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260405144944.41074-2-lucienzx159@gmail.com/mbox/","series":[{"id":498806,"url":"http://patchwork.ozlabs.org/api/1.2/series/498806/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=498806","date":"2026-04-05T14:49:40","name":"phy: add common PHY polarity properties support","version":3,"mbox":"http://patchwork.ozlabs.org/series/498806/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2220019/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2220019/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=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=YTm5o5ae;\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=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b=\"YTm5o5ae\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=lucienzx159@gmail.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)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fpkK16dfYz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 06 Apr 2026 06:17:25 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id D3C2383CD3;\n\tSun,  5 Apr 2026 22:17:13 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id BCA1C8394E; Sun,  5 Apr 2026 16:50:54 +0200 (CEST)","from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com\n [IPv6:2607:f8b0:4864:20::102c])\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 E418D8341A\n for <u-boot@lists.denx.de>; Sun,  5 Apr 2026 16:50:51 +0200 (CEST)","by mail-pj1-x102c.google.com with SMTP id\n 98e67ed59e1d1-3590042fa8eso2224930a91.1\n for <u-boot@lists.denx.de>; Sun, 05 Apr 2026 07:50:51 -0700 (PDT)","from localhost.localdomain (124-218-201-66.cm.dynamic.apol.com.tw.\n [124.218.201.66]) by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-35dbe959358sm15333261a91.13.2026.04.05.07.50.46\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sun, 05 Apr 2026 07:50:49 -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=-0.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_GMAIL_RCVD,\n FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_BLOCKED,\n SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1775400650; x=1776005450; darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=h/PiWOgfNgtRKRK2u7+gqq6/yVtGPAdihviG6t48NS4=;\n b=YTm5o5aeP7FCcDjKfRKMbuD+xeNEg+osgmbVU94zNppyczGq5jg9pJ7L4wNsXIEsl3\n 6bZwnjtwta553rmBnPqfb8FReAuttOJ4+1t+zyUsWFgoRbvo3+gv5YHaQT7sjf3usFO2\n ZsG0HMtgyWBXX5p9rJh724+cr4UqO8oQzG2fW7OYj6dMNSy5JxL9dRTTm2JhIDNrNFUa\n cXmpZRSM2PUVxsyuEfJcdiQw71zoaiKPZdWp0tgwzgzGALGKnC3asAbfraXhR6OOOToa\n MtiXaw6Yet2fjOZobVwJY8N3mCbNtnPvTfZ23ius7HG/WRHLGC+cMv/xZOVq3e0OM9Ko\n iHPw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775400650; x=1776005450;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=h/PiWOgfNgtRKRK2u7+gqq6/yVtGPAdihviG6t48NS4=;\n b=P269N2SXAWo7PYCi5kLCMEro8vp3jzgNtFlHh+RELcJ2zvzZFcHLS+GrrvdKqscfRH\n IetXTDV9yZtAgvZrf8qFwvzgFUPMObFQ+JApXb0ueEX/W73YsCWeL8mz6SD8KJ9iuJd2\n NU8bbtwO5uL48YsKUwWir/MAq2ikjwCu6tO1wbGz0+Sr8Ws8cElAnAVJQVdYhsqHCMCD\n qoSPZXEGnNtWebRs3thGJvuJz4aBKg6pLVygXpru31c4zWaBZbSz1qdV9Rlzfhijve9u\n EGT0ULn6Cum/2ZTydYIsaO/SmapC+hL0cOrw7tIvMuS2k24qULrVOANT8mIWY3yTmker\n EMuQ==","X-Forwarded-Encrypted":"i=1;\n AJvYcCWtbdqazwYr41NhxLjRYAQmRgllAxa59V7G0J4UWEMRdAxVUAz4eh73MvR18k+sNMrAjgoC2jA=@lists.denx.de","X-Gm-Message-State":"AOJu0YywX+/vN8UIgSuLn6CKThhJZ2SCOjj+uKkyopLKQ8LJ3wfcn8pu\n 6AuqjcL9M3zweMckTzYXlBLS4GXFJmrOFBM8NeQoZueOufCv57ht+bSt","X-Gm-Gg":"AeBDiesmKrZdbXYc5urdt29V3XcntGMC6NVk4GtkJm4KXekR3JfYcr1lDS5REoN5df7\n 22bAE9QQ2P/jh8CGzCxSHbTtc8itAJICDNIk5rgCnIS3jgvquGfz0Jv6ItN1R+mSoqgIUZQ6A7k\n ty+qNq6mR8cZSyuhXrxs3ihH+d0z+4PsZ2KGNECkSCcQXrJDlEbYLN5uNOPQi6JsPmWye9qO+71\n wRaZSOF11xezjp1H276PLEH1bh0uX5HsUlNcqIX46AgDDo+YQ2mb9RMCjyXYMI7as52k4rn3icT\n Jsoq9651GB1TZbWO8hzBIocvIllVxb5WCeJFS2XksAzFYGnzmqmC2PyHjX9ehFkN+IlRTHOIo7i\n GV9GlFbCK2oZS+iXhPGUew7XY0NCksRA7SeHk4DPvvgcpg9EYMGRCdyQHJW1g2iS4ypAWD6NB3o\n fhsIsDSk0NBJEKY+F1vHCn2kBFIQ5/mgB8eC/eaedQXBx5ijsPm3yh3nB/Au+YAWGppdMAs8Hez\n jzl0l+s5Ty2xZMnmWM9FQ==","X-Received":"by 2002:a17:90b:3e43:b0:35d:a4c0:a0ac with SMTP id\n 98e67ed59e1d1-35de6813794mr9464886a91.3.1775400650277;\n Sun, 05 Apr 2026 07:50:50 -0700 (PDT)","From":"\"Lucien.Jheng\" <lucienzx159@gmail.com>","To":"trini@konsulko.com, jerome.forissier@arm.com, sumit.garg@kernel.org,\n marek.vasut+renesas@mailbox.org, vladimir.oltean@nxp.com","Cc":"ericwouds@gmail.com, kabel@kernel.org, frank-w@public-files.de,\n daniel@makrotopia.org, ansuelsmth@gmail.com, mkorpershoek@kernel.org,\n skylake.huang@mediatek.com, lucien.jheng@airoha.com, u-boot@lists.denx.de,\n \"Lucien.Jheng\" <lucienzx159@gmail.com>","Subject":"[PATCH v3 1/4] phy: add common PHY properties support","Date":"Sun,  5 Apr 2026 22:49:41 +0800","Message-Id":"<20260405144944.41074-2-lucienzx159@gmail.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20260405144944.41074-1-lucienzx159@gmail.com>","References":"<20260405144944.41074-1-lucienzx159@gmail.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-Mailman-Approved-At":"Sun, 05 Apr 2026 22:17:12 +0200","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 PHY_COMMON_PROPS library that provides helper functions for\nPHY drivers to read standardized polarity properties from the device\ntree node:\n\n  - phy_get_rx_polarity() / phy_get_tx_polarity()\n  - phy_get_manual_rx_polarity() / phy_get_manual_tx_polarity()\n\nThe dt-bindings/phy/phy.h header with PHY_POL_NORMAL, PHY_POL_INVERT,\nand PHY_POL_AUTO constants is provided via dts/upstream/include, which\nis already in the build include path.\n\nPorted from Merge tag 'phy-for-7.0':\n  git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy\n\nLink: https://git.kernel.org/linus/e7556b59ba65179612bce3fa56bb53d1b4fb20db\nSigned-off-by: Lucien.Jheng <lucienzx159@gmail.com>\n---\n drivers/phy/Kconfig                  |   8 +\n drivers/phy/Makefile                 |   1 +\n drivers/phy/phy-common-props.c       | 286 +++++++++++++++++++++++++++\n include/linux/phy/phy-common-props.h |  69 +++++++\n 4 files changed, 364 insertions(+)\n create mode 100644 drivers/phy/phy-common-props.c\n create mode 100644 include/linux/phy/phy-common-props.h","diff":"diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig\nindex 09810b62b51..18419c1d490 100644\n--- a/drivers/phy/Kconfig\n+++ b/drivers/phy/Kconfig\n@@ -339,4 +339,12 @@ source \"drivers/phy/qcom/Kconfig\"\n source \"drivers/phy/renesas/Kconfig\"\n source \"drivers/phy/starfive/Kconfig\"\n \n+config PHY_COMMON_PROPS\n+\tbool \"Common PHY properties support\"\n+\thelp\n+\t  Enable support for common PHY properties defined in the device tree,\n+\t  such as rx-polarity and tx-polarity. This provides helpers for PHY\n+\t  drivers to read polarity and other standard PHY properties from the\n+\t  device tree node.\n+\n endmenu\ndiff --git a/drivers/phy/Makefile b/drivers/phy/Makefile\nindex 83102349669..91610692cc0 100644\n--- a/drivers/phy/Makefile\n+++ b/drivers/phy/Makefile\n@@ -42,6 +42,7 @@ 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\n obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o\n+obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o\n obj-y += cadence/\n obj-y += ti/\n obj-y += qcom/\ndiff --git a/drivers/phy/phy-common-props.c b/drivers/phy/phy-common-props.c\nnew file mode 100644\nindex 00000000000..36fe48fc1b9\n--- /dev/null\n+++ b/drivers/phy/phy-common-props.c\n@@ -0,0 +1,286 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/*\n+ * phy-common-props.c  --  Common PHY properties\n+ *\n+ * Copyright 2025-2026 NXP\n+ */\n+#include <dm/ofnode.h>\n+#include <log.h>\n+#include <malloc.h>\n+#include <linux/phy/phy-common-props.h>\n+#include <linux/bitops.h>\n+#include <linux/err.h>\n+#include <linux/errno.h>\n+\n+/**\n+ * ofnode_count_u32_prop - Count number of u32 elements in a property\n+ * @node: Device tree node\n+ * @propname: Property name\n+ *\n+ * Return: number of u32 elements, or negative error code\n+ */\n+static int ofnode_count_u32_prop(ofnode node, const char *propname)\n+{\n+\tint size;\n+\n+\tsize = ofnode_read_size(node, propname);\n+\tif (size < 0) {\n+\t\tpr_debug(\"%s: property '%s' not found (err=%d)\\n\",\n+\t\t\t __func__, propname, size);\n+\t\treturn size;\n+\t}\n+\n+\tpr_debug(\"%s: property '%s' has %zu bytes (%zu elements)\\n\",\n+\t\t __func__, propname, (size_t)size, (size_t)(size / sizeof(u32)));\n+\n+\treturn size / sizeof(u32);\n+}\n+\n+/**\n+ * ofnode_get_u32_prop_for_name - Find u32 property by name, or default value\n+ * @node: Device tree node; if invalid or @props_title is absent, @default_val is used\n+ * @name: Property name used as lookup key in @names_title (must not be NULL)\n+ * @props_title: Name of u32 array property holding values\n+ * @names_title: Name of string array property holding lookup keys\n+ * @default_val: Default value if @node is invalid, @props_title is absent, or empty\n+ * @val: Pointer to store the returned value\n+ *\n+ * This function retrieves a u32 value from @props_title based on a name lookup\n+ * in @names_title. The value stored in @val is determined as follows:\n+ *\n+ * - If @node is invalid or @props_title is absent: @default_val is used\n+ * - If @props_title exists but is empty: @default_val is used\n+ * - If @props_title has exactly one element and @names_title is empty:\n+ *   that element is used\n+ * - Otherwise: @val is set to the element at the same index where @name is\n+ *   found in @names_title.\n+ * - If @name is not found, the function looks for a \"default\" entry in\n+ *   @names_title and uses the corresponding value from @props_title\n+ *\n+ * When both @props_title and @names_title are present, they must have the\n+ * same number of elements (except when @props_title has exactly one element).\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+static int ofnode_get_u32_prop_for_name(ofnode node, const char *name,\n+\t\t\t\t\tconst char *props_title,\n+\t\t\t\t\tconst char *names_title,\n+\t\t\t\t\tunsigned int default_val,\n+\t\t\t\t\tunsigned int *val)\n+{\n+\tint err, n_props, n_names, idx;\n+\tu32 *props;\n+\n+\tif (!name) {\n+\t\tprintf(\"Error: Lookup key inside \\\"%s\\\" is mandatory\\n\",\n+\t\t       names_title);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tpr_debug(\"%s: looking up '%s' in props='%s' names='%s' default=%u\\n\",\n+\t\t __func__, name, props_title, names_title, default_val);\n+\n+\tn_props = ofnode_count_u32_prop(node, props_title);\n+\tif (n_props < 0) {\n+\t\t/* property is absent */\n+\t\tpr_debug(\"%s: '%s' is absent, using default value %u\\n\",\n+\t\t\t __func__, props_title, default_val);\n+\t\t*val = default_val;\n+\t\treturn 0;\n+\t}\n+\tif (n_props == 0) {\n+\t\t/* property exists but is empty, use default */\n+\t\tpr_debug(\"%s: '%s' is empty, using default value %u\\n\",\n+\t\t\t __func__, props_title, default_val);\n+\t\t*val = default_val;\n+\t\treturn 0;\n+\t}\n+\n+\tn_names = ofnode_read_string_count(node, names_title);\n+\n+\tpr_debug(\"%s: '%s' has %d elements, '%s' has %d entries\\n\",\n+\t\t __func__, props_title, n_props, names_title, n_names);\n+\tif (n_names >= 0 && n_props != n_names) {\n+\t\tprintf(\"Error: mismatch between \\\"%s\\\" and \\\"%s\\\" property count (%d vs %d)\\n\",\n+\t\t       props_title, names_title, n_props, n_names);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tidx = ofnode_stringlist_search(node, names_title, name);\n+\tif (idx >= 0) {\n+\t\tpr_debug(\"%s: found '%s' at index %d in '%s'\\n\",\n+\t\t\t __func__, name, idx, names_title);\n+\t} else {\n+\t\tpr_debug(\"%s: '%s' not found in '%s', trying 'default'\\n\",\n+\t\t\t __func__, name, names_title);\n+\t\tidx = ofnode_stringlist_search(node, names_title, \"default\");\n+\t\tif (idx >= 0)\n+\t\t\tpr_debug(\"%s: 'default' entry found at index %d\\n\",\n+\t\t\t\t __func__, idx);\n+\t\telse\n+\t\t\tpr_debug(\"%s: 'default' entry not found in '%s'\\n\",\n+\t\t\t\t __func__, names_title);\n+\t}\n+\t/*\n+\t * If the mode name is missing, it can only mean the specified property\n+\t * is the default one for all modes, so reject any other property count\n+\t * than 1.\n+\t */\n+\tif (idx < 0 && n_props != 1) {\n+\t\tprintf(\"Error: \\\"%s\\\" property has %d elements, but cannot find \\\"%s\\\" in \\\"%s\\\" and there is no default value\\n\",\n+\t\t       props_title, n_props, name, names_title);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (n_props == 1) {\n+\t\tpr_debug(\"%s: single-element '%s', reading directly\\n\",\n+\t\t\t __func__, props_title);\n+\t\terr = ofnode_read_u32(node, props_title, val);\n+\t\tif (err) {\n+\t\t\tpr_debug(\"%s: failed to read '%s' (err=%d)\\n\",\n+\t\t\t\t __func__, props_title, err);\n+\t\t\treturn err;\n+\t\t}\n+\t\tpr_debug(\"%s: resolved value %u for name '%s' from '%s'\\n\",\n+\t\t\t __func__, *val, name, props_title);\n+\t\treturn 0;\n+\t}\n+\n+\t/* We implicitly know idx >= 0 here */\n+\tprops = calloc(n_props, sizeof(*props));\n+\tif (!props)\n+\t\treturn -ENOMEM;\n+\n+\terr = ofnode_read_u32_array(node, props_title, props, n_props);\n+\tif (err >= 0) {\n+\t\t*val = props[idx];\n+\t\tpr_debug(\"%s: resolved value %u at index %d for name '%s' from '%s'\\n\",\n+\t\t\t __func__, *val, idx, name, props_title);\n+\t} else {\n+\t\tpr_debug(\"%s: failed to read u32 array '%s' (err=%d)\\n\",\n+\t\t\t __func__, props_title, err);\n+\t}\n+\n+\tfree(props);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * phy_get_polarity_for_mode - Get polarity for a specific PHY mode\n+ * @node: Device tree node\n+ * @mode_name: The name of the PHY mode to look up\n+ * @supported: Bit mask of supported polarity values\n+ * @default_val: Default polarity value if property is missing\n+ * @polarity_prop: Name of the polarity property\n+ * @names_prop: Name of the names property\n+ * @val: Pointer to returned polarity\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+static int phy_get_polarity_for_mode(ofnode node, const char *mode_name,\n+\t\t\t\t     unsigned int supported,\n+\t\t\t\t     unsigned int default_val,\n+\t\t\t\t     const char *polarity_prop,\n+\t\t\t\t     const char *names_prop,\n+\t\t\t\t     unsigned int *val)\n+{\n+\tint err;\n+\n+\tpr_debug(\"%s: querying '%s' for mode '%s' (supported=0x%x, default=%u)\\n\",\n+\t\t __func__, polarity_prop, mode_name, supported, default_val);\n+\n+\terr = ofnode_get_u32_prop_for_name(node, mode_name, polarity_prop,\n+\t\t\t\t\t   names_prop, default_val, val);\n+\tif (err) {\n+\t\tpr_debug(\"%s: '%s' lookup failed for mode '%s' (err=%d)\\n\",\n+\t\t\t __func__, polarity_prop, mode_name, err);\n+\t\treturn err;\n+\t}\n+\n+\tpr_debug(\"%s: '%s' for mode '%s' = %u\\n\",\n+\t\t __func__, polarity_prop, mode_name, *val);\n+\n+\tif (!(supported & BIT(*val))) {\n+\t\tprintf(\"Error: %d is not a supported value for '%s' element '%s'\\n\",\n+\t\t       *val, polarity_prop, mode_name);\n+\t\terr = -EOPNOTSUPP;\n+\t}\n+\n+\treturn err;\n+}\n+\n+/**\n+ * phy_get_rx_polarity - Get RX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO\n+ * @default_val: Default polarity value if property is missing\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_rx_polarity(ofnode node, const char *mode_name,\n+\t\t\tunsigned int supported, unsigned int default_val,\n+\t\t\tunsigned int *val)\n+{\n+\treturn phy_get_polarity_for_mode(node, mode_name, supported,\n+\t\t\t\t\t default_val, \"rx-polarity\",\n+\t\t\t\t\t \"rx-polarity-names\", val);\n+}\n+\n+/**\n+ * phy_get_tx_polarity - Get TX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO\n+ * @default_val: Default polarity value if property is missing\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_tx_polarity(ofnode node, const char *mode_name,\n+\t\t\tunsigned int supported, unsigned int default_val,\n+\t\t\tunsigned int *val)\n+{\n+\treturn phy_get_polarity_for_mode(node, mode_name, supported,\n+\t\t\t\t\t default_val, \"tx-polarity\",\n+\t\t\t\t\t \"tx-polarity-names\", val);\n+}\n+\n+/**\n+ * phy_get_manual_rx_polarity - Get manual RX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Helper for PHYs which do not support protocols with automatic RX polarity\n+ * detection and correction.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_manual_rx_polarity(ofnode node, const char *mode_name,\n+\t\t\t       unsigned int *val)\n+{\n+\treturn phy_get_rx_polarity(node, mode_name,\n+\t\t\t\t   BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),\n+\t\t\t\t   PHY_POL_NORMAL, val);\n+}\n+\n+/**\n+ * phy_get_manual_tx_polarity - Get manual TX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Helper for PHYs without any custom default value for the TX polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_manual_tx_polarity(ofnode node, const char *mode_name,\n+\t\t\t       unsigned int *val)\n+{\n+\treturn phy_get_tx_polarity(node, mode_name,\n+\t\t\t\t   BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),\n+\t\t\t\t   PHY_POL_NORMAL, val);\n+}\ndiff --git a/include/linux/phy/phy-common-props.h b/include/linux/phy/phy-common-props.h\nnew file mode 100644\nindex 00000000000..9158851f2e1\n--- /dev/null\n+++ b/include/linux/phy/phy-common-props.h\n@@ -0,0 +1,69 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * phy-common-props.h -- Common properties for generic PHYs\n+ *\n+ * Copyright 2025-2026 NXP\n+ */\n+\n+#ifndef __PHY_COMMON_PROPS_H\n+#define __PHY_COMMON_PROPS_H\n+\n+#include <dt-bindings/phy/phy.h>\n+#include <dm/ofnode.h>\n+\n+/**\n+ * phy_get_rx_polarity - Get RX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO\n+ * @default_val: Default polarity value if property is missing\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_rx_polarity(ofnode node, const char *mode_name,\n+\t\t\tunsigned int supported, unsigned int default_val,\n+\t\t\tunsigned int *val);\n+\n+/**\n+ * phy_get_tx_polarity - Get TX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO\n+ * @default_val: Default polarity value if property is missing\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_tx_polarity(ofnode node, const char *mode_name,\n+\t\t\tunsigned int supported, unsigned int default_val,\n+\t\t\tunsigned int *val);\n+\n+/**\n+ * phy_get_manual_rx_polarity - Get manual RX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Helper for PHYs which do not support protocols with automatic RX polarity\n+ * detection and correction.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_manual_rx_polarity(ofnode node, const char *mode_name,\n+\t\t\t       unsigned int *val);\n+\n+/**\n+ * phy_get_manual_tx_polarity - Get manual TX polarity for PHY differential lane\n+ * @node: Pointer to the PHY's device tree node.\n+ * @mode_name: The name of the PHY mode to look up.\n+ * @val: Pointer to returned polarity.\n+ *\n+ * Helper for PHYs without any custom default value for the TX polarity.\n+ *\n+ * Return: zero on success, negative error on failure.\n+ */\n+int phy_get_manual_tx_polarity(ofnode node, const char *mode_name,\n+\t\t\t       unsigned int *val);\n+\n+#endif /* __PHY_COMMON_PROPS_H */\n","prefixes":["v3","1/4"]}