From nobody Sat Sep 26 05:28:07 2026 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94ED63F58E7 for ; Fri, 4 Sep 2026 08:37:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511076; cv=none; b=pFlWI0Xh+uWDtoEo/momK3J9qwfUX3E7jtEo75bWhLet7vrUcVPM3UfzBsrT19JTOoSvmlDUiFrq6pKkAC7BfjOm8ZOuxsIC4yKC6CheZFG9DK6Ljvei9DYa/gNjCJ82BMdEU8mVpHRjFjXYhrAYr8FvCatfPI9B26iZa3qoes0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511076; c=relaxed/simple; bh=xkpsllmNlr3h3R0y/WdKwA7FKzqgoiG1ehs9mULeTk8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nt8E4CdhmkUtNvGKwEb3ihH4s1Bfq19OvrvgFfzwmhnbIbVBkFq1265lQH5pitsZRxQs+zEFol7cMIvGbFCytUwFJYWrFqhLeTBlX0VBjJdleMza3qxp+f0hiLEBAynapf7GeM3lfsjowCscP8ToITqiBumr1VLDvdfo8hPqFng= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=HdkPUjJj; arc=none smtp.client-ip=209.85.216.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HdkPUjJj" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-398a4dcf289so869834a91.2 for ; Fri, 04 Sep 2026 01:37:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788511074; x=1789115874; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=NC2wfz4K/EJAsThMydrdqvm3KNer12H87aZI1BzTpcw=; b=HdkPUjJjJolbZX5NKSKqTwGVh47Ouv0e0N8dSIqH8wAvYp+qjjmriLKwEQRg63jLZt 2VK41bsSpCKP2so6po5wISE6O7PSyMhLanYhadvtYf4bsEn4pvWn+b1eSLkgcp2rM7Ij jmWihXhNp6+EhChLmwI3HWL2jvE6t6mvea84wklysKxJQuEM01ve83zRbiNu7+YP0+SP JOxtP5ay6i0pycWQAmRo7w1HQ5BYOE6zGFJr1S647yx9xOU2vyzT3tnEnyXge3bkkUWC A78tVcSKQQccLXzIgYKt7EGTSKO5K1bTeVJSzVMUlW8RieQDvgYDtQvRKTqiTYC60CEd 95Bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788511074; x=1789115874; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=NC2wfz4K/EJAsThMydrdqvm3KNer12H87aZI1BzTpcw=; b=SmeDpvYusNEZJ7f71vq3richOzTYeghh6IxcOi+/ZcwtTwUAxayRHZJkh4rV0IUQzx PBzF4Q8DFymYkHFtYU9AFTfzBIVtANlNe0ygMGFPpVlMJmCwUpTEbiQRcfsuLtpsiRfQ PXj9giA8zXwGPM1OGknxcohUR7iTSecTU1CKTvfDNGfEiocAKIGZFTdibg/fNyFc9ao9 PE4z99VshX1Te279wKu8f9fbl095Bvrjp6P4F8eTUEyUC5WYSSuy8WBMx5qhanUuXuDM SI0ETJeGywII91+ndYIhAUXymJtsCv9SMGYdhIcVxFHwMvB+4CEPb748H9QgOE2SF4GA q/UA== X-Forwarded-Encrypted: i=1; AKwUvBxB4aGZMkGH3Ngz3SJLJUHfqCC6OfGzL/BlRBHdpsumNGEbjM+qPTrZaWUlQ5mNgUg2CYHOce7R7HsjYPg=@vger.kernel.org X-Gm-Message-State: AFuF++lCIbOAI8xygA8CzjnlRc3GDxOkGpvYfLkLJXAfV3/ui5J3j5iX quXGZXCeCITQeXBHtxbbwNGYH1Lj5OBIYPt/U3FvBOBZaqTn2cdlkTfP X-Gm-Gg: AYBFou3hcRfZmME1+lD6ZFayX4/c21xK35azQ1ugfb2kAsidW8pryabd5QOYw6sOMq/ RLAUyfw5k+sdi7KWuETSaJvvr8wVz8CK0gzCOV4s07uVF18znct7muNv+IdvLQz+jPYm7Hfa8pN vvMR10nZS51833P97e+vdk1ZnXVyMrrZliEoKkCKyFtl02/R3gjQHBliUbkIxxsq6MvLMQfLah8 aZxxWZckhZ8U1BT++bLPk1vqYrCNbq6amWkxgcTVm1fYiuzrRxdSyK5LAJkaWmOkD8tUl5iKQzD OKciRD/SW+JE52Nr9W2LtTrTYGFR77EFhqfPTE5dEmhhBoXga3VRoCOlotdAycAWBjR4JOuQV53 hqlA7bCTyYPPEUH723rHLzwpgz7bliUqbnMRYS3fwuujT8Osg4UiZ7V5HPg328ECVZsLrAvBbgV arKBWnNnGM2SxTpUIHK9ka1AGetpwxrLpDpG/HvLBlDFTQhY0BUsqBDDV9Rs4= X-Received: by 2002:a17:90b:2ecd:b0:396:40e6:f631 with SMTP id 98e67ed59e1d1-39b2609f306mr7704261a91.3.1788511073930; Fri, 04 Sep 2026 01:37:53 -0700 (PDT) Received: from localhost ([2001:19f0:8000:3e6e:5400:6ff:fe38:3d01]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39b2615039asm3339282a91.15.2026.09.04.01.37.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Sep 2026 01:37:53 -0700 (PDT) From: Inochi Amaoto To: Vinod Koul , Neil Armstrong , Manivannan Sadhasivam Cc: Andy Shevchenko , Inochi Amaoto , linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, Yixun Lan , Longbin Li Subject: [PATCH v2 1/4] phy: core: Add common helper to add phy phandle device link Date: Fri, 4 Sep 2026 16:37:05 +0800 Message-ID: <20260904083709.425893-2-inochiama@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260904083709.425893-1-inochiama@gmail.com> References: <20260904083709.425893-1-inochiama@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" It is very common for adding a device link for phy phandle for device managed phy helper functions. So add a common helper for future reuse. Signed-off-by: Inochi Amaoto Reviewed-by: Andy Shevchenko --- drivers/phy/phy-core.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 21aaf2f76e53..ea79913fbb87 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -606,6 +606,26 @@ int phy_validate(struct phy *phy, enum phy_mode mode, = int submode, } EXPORT_SYMBOL_GPL(phy_validate); =20 +/** + * phy_add_device_link() - Associate the phy with the device + * @dev: the device to link the phy + * @phy: the phy to associate + * + * Associate the phy with the device by using device link. + */ +static void phy_add_device_link(struct device *dev, struct phy *phy) +{ + struct device_link *link; + + if (!phy) + return; + + link =3D device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); + if (!link) + dev_dbg(dev, "failed to create device link to %s\n", + dev_name(phy->dev.parent)); +} + /** * _of_phy_get() - lookup and obtain a reference to a phy by phandle * @np: device_node for which to get the phy @@ -784,7 +804,6 @@ struct phy *phy_get(struct device *dev, const char *str= ing) { int index =3D 0; struct phy *phy; - struct device_link *link; =20 if (dev->of_node) { if (string) @@ -808,10 +827,7 @@ struct phy *phy_get(struct device *dev, const char *st= ring) =20 get_device(&phy->dev); =20 - link =3D device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); - if (!link) - dev_dbg(dev, "failed to create device link to %s\n", - dev_name(phy->dev.parent)); + phy_add_device_link(dev, phy); =20 return phy; } @@ -885,7 +901,6 @@ struct phy *devm_of_phy_get(struct device *dev, struct = device_node *np, const char *con_id) { struct phy **ptr, *phy; - struct device_link *link; =20 ptr =3D devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) @@ -900,10 +915,7 @@ struct phy *devm_of_phy_get(struct device *dev, struct= device_node *np, return phy; } =20 - link =3D device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); - if (!link) - dev_dbg(dev, "failed to create device link to %s\n", - dev_name(phy->dev.parent)); + phy_add_device_link(dev, phy); =20 return phy; } @@ -955,7 +967,6 @@ struct phy *devm_of_phy_get_by_index(struct device *dev= , struct device_node *np, int index) { struct phy **ptr, *phy; - struct device_link *link; =20 ptr =3D devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) @@ -977,10 +988,7 @@ struct phy *devm_of_phy_get_by_index(struct device *de= v, struct device_node *np, *ptr =3D phy; devres_add(dev, ptr); =20 - link =3D device_link_add(dev, &phy->dev, DL_FLAG_STATELESS); - if (!link) - dev_dbg(dev, "failed to create device link to %s\n", - dev_name(phy->dev.parent)); + phy_add_device_link(dev, phy); =20 return phy; } --=20 2.55.0 From nobody Sat Sep 26 05:28:07 2026 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EF563F8709 for ; Fri, 4 Sep 2026 08:37:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511078; cv=none; b=HPL9VqKSCA1n+EjV5UjfiMlViVexwMfmumYu1860rP0OrtkglziZuVS7hZYBr/IyuipvQNQpEnnvihjw9lsiRs//3UwCfsu8eJz23Ol9UueFCq034gDu1pkjHpaqOVlflUCom1smYa96/qqszk4EEGMv7P1bM2nYjR8zd+7OnQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511078; c=relaxed/simple; bh=V4Riq0DdMmZexbumjJENOek9iC1bQ/EYfBK0VK+tk8s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qOoWc1cSKx1DIhLfVqfTP4WsPXDzBsG8JpWMWVsL5TQe0kCiXfNtgahwt5ZVuivOLH4LSTweX+zIZb/GiJ8TNCGrE8iZ5fgTXXvP650TAvXwmMwvpG061QidXAQ9L9m5hgdz0KsRLj6nIL/oeI/rjtk+q+H+7cMrvQ/RCb4lzLo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mspPUS0t; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mspPUS0t" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-ca97d139d5fso816474a12.0 for ; Fri, 04 Sep 2026 01:37:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788511076; x=1789115876; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=m7TrYEnnyTFBxKR6bNzgdL9dbIZbk8gO2x1bfmprK5g=; b=mspPUS0tfEojxMc9gl3PpQ1E+/3xRK9KYgBrTJ984V8kDVsb1rE3HBrhOFgdodKkaM fOIXFS8IvUgybqPPKzveF0j2kugnze+JbM8b8o8p9N2nb+KNldX7OHquQHn3B94Kj90L D5F9FN/fu9owph47oYZtHUXF487yTddnwVMpzAY+w/6BLCurcOqf7GqsY7t5KYMi987j ZGPqkhlWcDJmfnW9QDo3mVbYgUN0FKvyGjxQ5U6GmbG2d14y5d/e6iXE8c8epVyS7jj9 dUwbwpVQkWPhlvePAQf9dExTOWAiR9+32WtkqBoB1WRHXUSud6MvuLxZil8iMEFSRFO1 Rhow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788511076; x=1789115876; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=m7TrYEnnyTFBxKR6bNzgdL9dbIZbk8gO2x1bfmprK5g=; b=QELg3Z5mR9FR6GmnGCxfd2pVZz2v2P8XLGRuQoFpEZKV315jgW4HDr1K/gCaPffilL GPcBcyYEN8gdbj481JEJw8RMY4b8/tWR0QFiFOXoeVR4VQS/dwNhD1FS5V4KPwrOr34K 54fKKEROao48la5MAaMGF8R2/iKyBBMI8hgTYQ6L0knuRkddwPve6lJCRQv6Ri6/dele +mYmyI23lCidLOFa89UXQaMoXAqwJQtAMhxwAlu6F9zBCvGVWfQJm+HPhF3plvfkeJdp gCaKaE8VYdIVEKK8Q6qnAa7oMkaYzWUOG6ySvI8er7HeX5kw3+6Uws6uCPmkxLXxPEQI y5/A== X-Forwarded-Encrypted: i=1; AKwUvBxSQJdJGP8aIgIRSOdaDgc7x4wIuPRN0ssB/Ihi1g3ZoXqjLhkeA4pq5uFhoGwUtTVwOos+6c+V/ee4dP8=@vger.kernel.org X-Gm-Message-State: AFuF++kWKOmbZrC8GAn/MK2BQRucRoe9nin3rsciDHKfvUu6X0mSCA2B m7/nViumUSV4ePSQwVB754U/LuRqcnf0SxJcQlfFMcKwNWazOwWvjCB4 X-Gm-Gg: AYBFou0yiXPujhihBLCT26n3crveMaFIyjBZo/1yf7dXewFAgBkA3+fdAJ3qhWqt0iK rswA6MlM1eiULYGmpur2HwnQhu0EOYpat3H+og7h1MKVBOZvCrqaNOxtPqEo6/hImyqX+0TF03E 4YdVGSlLLF4/12H18GWhDA6ar4qj0JHqF5MTsrkEhFBvaQDr96aP0ZBDKD/dVHaS0SNSobCcm4q i/XIgA2as9O56sRDC1dYGZaixBfqPK/FhvW+0gepHWp6NgCANlxLKe3kXWGu2ZSop96gWUgB8RU 5BYS8cy0e9fMWhMUquqDd3Pp657XrAFENcPZokZeCzC1OA7/8NnSiW+LkexVqMBi+iOr+RitKMN w6hKfmxOYJqErXYHYUyEooofdC6uvq3bFTtZp9bCSaQWdULTZ0d93Oraapfn2Byzckqca7xp9cd gWVN8OIpIIkdfPv6Yz6ocbeud6S9akHxKpSyppbVSvTm0axuTtqTwSH1oCGcA= X-Received: by 2002:a05:6a00:22ca:b0:857:726d:2e9d with SMTP id d2e1a72fcca58-8616b966f55mr6002481b3a.26.1788511076377; Fri, 04 Sep 2026 01:37:56 -0700 (PDT) Received: from localhost ([2001:19f0:8000:3e6e:5400:6ff:fe38:3d01]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-86152e2f1e0sm874077b3a.36.2026.09.04.01.37.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Sep 2026 01:37:56 -0700 (PDT) From: Inochi Amaoto To: Vinod Koul , Neil Armstrong , Manivannan Sadhasivam Cc: Andy Shevchenko , Inochi Amaoto , linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, Yixun Lan , Longbin Li Subject: [PATCH v2 2/4] phy: core: Add common helper for get phy phandle by index Date: Fri, 4 Sep 2026 16:37:06 +0800 Message-ID: <20260904083709.425893-3-inochiama@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260904083709.425893-1-inochiama@gmail.com> References: <20260904083709.425893-1-inochiama@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Several phy helper use index to get phy phandle of a device node, add a common function for the future reuse. Signed-off-by: Inochi Amaoto Reviewed-by: Andy Shevchenko --- drivers/phy/phy-core.c | 51 +++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index ea79913fbb87..a7d7acb5d3c2 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -681,33 +681,49 @@ static struct phy *_of_phy_get(struct device_node *np= , int index) return phy; } =20 +/** + * of_phy_get_by_index() - lookup and obtain a reference to a phy using a + * device_node by index. + * @np: device_node for which to get the phy + * @index: index of the phy from device's point of view + * + * Returns: the phy driver, after getting a refcount to it; or + * -ENODEV if there is no such phy. The caller is responsible for + * calling of_phy_put() to release that count. + */ +static struct phy *of_phy_get_by_index(struct device_node *np, int index) +{ + struct phy *phy; + + phy =3D _of_phy_get(np, index); + if (IS_ERR(phy)) + return phy; + + if (!try_module_get(phy->ops->owner)) + return ERR_PTR(-EPROBE_DEFER); + + get_device(&phy->dev); + + return phy; +} + /** * of_phy_get() - lookup and obtain a reference to a phy using a device_no= de. * @np: device_node for which to get the phy * @con_id: name of the phy from device's point of view * - * Returns the phy driver, after getting a refcount to it; or + * Returns: the phy driver, after getting a refcount to it; or * -ENODEV if there is no such phy. The caller is responsible for * calling of_phy_put() to release that count. */ struct phy *of_phy_get(struct device_node *np, const char *con_id) { - struct phy *phy =3D NULL; int index =3D 0; =20 if (con_id) index =3D of_property_match_string(np, "phy-names", con_id); =20 - phy =3D _of_phy_get(np, index); - if (IS_ERR(phy)) - return phy; - - if (!try_module_get(phy->ops->owner)) - return ERR_PTR(-EPROBE_DEFER); - - get_device(&phy->dev); - - return phy; + return of_phy_get_by_index(np, index); } EXPORT_SYMBOL_GPL(of_phy_get); =20 @@ -957,7 +973,7 @@ EXPORT_SYMBOL_GPL(devm_of_phy_optional_get); * @np: node containing the phy * @index: index of the phy * - * Gets the phy using _of_phy_get(), then gets a refcount to it, + * Gets the phy using of_phy_get_by_index(), then gets a refcount to it, * and associates a device with it using devres. On driver detach, * release function is invoked on the devres data, * then, devres data is freed. @@ -972,19 +988,12 @@ struct phy *devm_of_phy_get_by_index(struct device *d= ev, struct device_node *np, if (!ptr) return ERR_PTR(-ENOMEM); =20 - phy =3D _of_phy_get(np, index); + phy =3D of_phy_get_by_index(np, index); if (IS_ERR(phy)) { devres_free(ptr); return phy; } =20 - if (!try_module_get(phy->ops->owner)) { - devres_free(ptr); - return ERR_PTR(-EPROBE_DEFER); - } - - get_device(&phy->dev); - *ptr =3D phy; devres_add(dev, ptr); =20 --=20 2.55.0 From nobody Sat Sep 26 05:28:07 2026 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 179B03FFF94 for ; Fri, 4 Sep 2026 08:37:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511082; cv=none; b=Ys1D7V66HAVS8C7GJZMV2VSQCau56EbTfIFuNRwgMq3whzqXpvGvVJxVOhjg37M/6ryZS8rSj5l0Ur7GU7gB3H0pFS/e0vwKzqSJUVagaS5KDMjetIvw6vNLF7sp8MXOf8ZB/OACOLxOFM7f9vw0GCfrVVuig/G1C2qX86Uw+PQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511082; c=relaxed/simple; bh=r2YbVQu7loT4b/jjmgOTG0eO0aAdU/gbNLnb5FR77u0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hQBrDex/B77l23P/zlrf0YbWiY8ZUmYRjf42G8woJCb9V7kBOVsHFcZSNwf4ueRD2V2bcvQF3XuoPsMa3G1m7gnVqKX9uuJrXQwfDV+nb113Z1KHzyxCLvy6Np4BJfk0wDqiQEG+O13+edfcHQV7mst4FhIGng0KffjfknyNyss= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=tLaWc7QW; arc=none smtp.client-ip=209.85.210.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tLaWc7QW" Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-855d2bfae95so2296024b3a.1 for ; Fri, 04 Sep 2026 01:37:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788511079; x=1789115879; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=LXsgluCGsQu3NWRJe11WOavM3i5u5c6VI3qIHHMnTG4=; b=tLaWc7QWqJDJvE5xRxtQQ91f4WNfk2WBYjkBfItJaZztAd9M/x+OGVNDSdKCGRx+ML u9z2PHHpzjPyrD3ycLzTrkavSKyI4Gi7iNiN1/sbj5HCgCUOFUf3GIbKwQzCyI91pxYZ CeMCm/vju5pxnpnmObSRUup0u8GmHgZg6GJFqab1iMieSiMGJC+Z9jWPQK1D0joSWzP/ XR6CiiyIMLncJRfA5SiNG0XSNvsD/w7MGYSco7Ag/qBbtrLYyRg2qPUfTQaa1F3WgZDN Q+iQIQHOPn/hylBznx1Dr46qeCZJjxDKd9oUtj7/tMSbdYwFzE79pGHNtnRGOp7rs/qh dhXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788511079; x=1789115879; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=LXsgluCGsQu3NWRJe11WOavM3i5u5c6VI3qIHHMnTG4=; b=SFUiSUAhfAn9IuQSN9f10ZDxtJI+95YPOT4nvserJw3EyqN4M3la70QZILr4WTDKUD qlNw7+XC+1wyQhYBeZUp5aIT9tV6h+m++nofUaXeFnfyFw8TJ7QGTJ9350XVXLl4Jlqc JwJK/0uCS0QLOFFDt3pSYUSP0KSQiEqg9XX9hpVzhNaW/cYF+QBbRZ9aA2t20BRu/hGn BuEa3uRyxnp73DchJCAXotTnWk5VCtVbT+phbCDdmtwyri87p7GvZ5bpcmlVnMvR6j3d VZS0FrId+MXt03/lqzaUjprfSHv4NwzDzXilzrm+gjwXU2lRp4RQ/9RKc/xc/d2qz/1o b1aA== X-Forwarded-Encrypted: i=1; AKwUvByEG/0dXz4XgQerb4+/kJS2ThUJ+AcO46s2K3y4lrPxV9SsPdFdpfznZXEEt1ptVWMvgVIgPOOtpHJAEY0=@vger.kernel.org X-Gm-Message-State: AFuF++kn16RSXTfsQQBtp+/j5LaLiWk0Nsp5NLv1v0DhKuQ1yhoD9qGC aMxs8t0kZWaJh5lD/gS6dSnZo/+dOfjHkPKwp8OimTceijiK35YnuWRG X-Gm-Gg: AYBFou2eYvaodSiyuj6Hx5BTloB3B5Elu+DG8NsXHqK6CdYyYLg1eiicaxIJvTo+8pd 4RIOefRpQULWWXYJF5vrpA/9nSNJ9aLyxAanoSdNzi1cDz3VtKbfLK39QBPF74hipDXKjDQfeo/ k2RlBV4pbU3hiROFNydplFgF7jefzbwG0hwc+r5Am2S8VFoB8+QDkn6z9K6O9Looz4/eUHlzOpt a+ijgQoF5JIgSL3zrHUGwtm4VPC4fTusai22VDO69NGwXqBBLzzc8u6bKUtUgYSpG/nU0gjC4Y6 Yq2RhNFFLN0s4I4ShNEkfLm+78FOTmvqh2oX3lSUlDbP0fnJ1OTENEwqdunSDJUCQLhJ17nTUE7 W3e0R/DTa6jaQHNmoOX555qWL8HwcmURwSU+xeJ/B4Of9p+817gTrqUsv4GVNlV/tZluzLxAHv9 NSrGmaWAUCtuOlvc5emVMxv1G6lSelLCl82yE2jdJeycDAQQx2PufXj/1meIg= X-Received: by 2002:a05:6a21:e8a:b0:3cc:8716:4702 with SMTP id adf61e73a8af0-3da3be4a2f5mr3598057637.8.1788511079082; Fri, 04 Sep 2026 01:37:59 -0700 (PDT) Received: from localhost ([2001:19f0:8000:3e6e:5400:6ff:fe38:3d01]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-cc45515397asm645664a12.1.2026.09.04.01.37.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Sep 2026 01:37:58 -0700 (PDT) From: Inochi Amaoto To: Vinod Koul , Neil Armstrong , Manivannan Sadhasivam Cc: Andy Shevchenko , Inochi Amaoto , linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, Yixun Lan , Longbin Li Subject: [PATCH v2 3/4] phy: core: Add phy bulk data helper functions Date: Fri, 4 Sep 2026 16:37:07 +0800 Message-ID: <20260904083709.425893-4-inochiama@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260904083709.425893-1-inochiama@gmail.com> References: <20260904083709.425893-1-inochiama@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add several helper functions that allow drivers to get several phy consumers in one operation. If any of the phy cannot be acquired then any phys that were got will be put before returning to the caller. This can relieve the driver owners' life who needs to handle many phys, as well as each phy error reporting. Signed-off-by: Inochi Amaoto --- drivers/phy/phy-core.c | 413 ++++++++++++++++++++++++++++++++++++++++ include/linux/phy/phy.h | 143 ++++++++++++++ 2 files changed, 556 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a7d7acb5d3c2..f5596b8dfcfc 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -1003,6 +1003,419 @@ struct phy *devm_of_phy_get_by_index(struct device = *dev, struct device_node *np, } EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); =20 +/** + * of_phy_get_count() - Get the number of phys of a device node + * @np: device_node for which to get the phy + * + * Return: the phy count if successful, %0 if no phy handle is found, + * negative error value if error occurs. + */ +static int of_phy_get_count(const struct device_node *np) +{ + int count; + + count =3D of_count_phandle_with_args(np, "phys", "#phy-cells"); + + if (count =3D=3D -ENOENT) + return 0; + + return count; +} + +/** + * phy_bulk_put() - release a set of PHYs obtained with phy_bulk_get() + * @dev: device that acquired the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHYs set + * + * Releases the PHY references in reverse order and clears the PHY pointer= in + * each entry. The caller owns the phys array and is responsible for freei= ng it + * if necessary. + */ +void phy_bulk_put(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + while (num_phys--) { + if (!IS_ERR_OR_NULL(phys[num_phys].phy)) + phy_put(dev, phys[num_phys].phy); + phys[num_phys].phy =3D NULL; + } +} +EXPORT_SYMBOL_GPL(phy_bulk_put); + +/** + * of_phy_bulk_put() - release a set of PHYs obtained with of_phy_bulk_get= () + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHYs set + * + * Releases the PHY references in reverse order and clears the PHY pointer= in + * each entry. The caller owns the phys array and is responsible for freei= ng it + * if necessary. + */ +void of_phy_bulk_put(unsigned int num_phys, struct phy_bulk_data *phys) +{ + while (num_phys--) { + of_phy_put(phys[num_phys].phy); + phys[num_phys].phy =3D NULL; + } +} +EXPORT_SYMBOL_GPL(of_phy_bulk_put); + +static int __phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys, bool optional) +{ + unsigned int i; + int ret; + + for (i =3D 0; i < num_phys; i++) + phys[i].phy =3D NULL; + + for (i =3D 0; i < num_phys; i++) { + phys[i].phy =3D phy_get(dev, phys[i].id); + + ret =3D PTR_ERR_OR_ZERO(phys[i].phy); + if (ret) { + phys[i].phy =3D NULL; + + if (ret =3D=3D -ENODEV && optional) + continue; + + dev_err_probe(dev, ret, "Failed to get phy: (%s)\n", + phys[i].id); + goto err; + } + } + + return 0; + +err: + phy_bulk_put(dev, i, phys); + + return ret; +} + +/** + * phy_bulk_get() - lookup and obtain references to multiple PHYs + * @dev: device that requests the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets each PHY using phy_get(). This supports both device tree lookups a= nd + * non-device-tree lookups registered with phy_create_lookup(). The caller= must + * call phy_bulk_put() to release the PHY references. + * + * Return: %0 if successful, a negative error code otherwise + */ +int phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return __phy_bulk_get(dev, num_phys, phys, false); +} +EXPORT_SYMBOL_GPL(phy_bulk_get); + +/** + * phy_bulk_get_optional() - obtain references to multiple optional PHYs + * @dev: device that requests the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets each PHY using phy_get(). A PHY that is not present is stored as N= ULL + * instead of causing the operation to fail. The caller must call + * phy_bulk_put() to release the PHY references. + * + * Return: %0 if successful, a negative error code otherwise + */ +int phy_bulk_get_optional(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return __phy_bulk_get(dev, num_phys, phys, true); +} +EXPORT_SYMBOL_GPL(phy_bulk_get_optional); + +/** + * of_phy_bulk_get() - obtain references to multiple PHYs from a device no= de + * @np: device node containing the PHY references + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets each PHY using of_phy_get() and the specified device node. The cal= ler + * must call of_phy_bulk_put() to release the PHY references. + * + * Return: %0 if successful, a negative error code otherwise + */ +int of_phy_bulk_get(struct device_node *np, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + unsigned int i; + int ret; + + for (i =3D 0; i < num_phys; i++) + phys[i].phy =3D NULL; + + for (i =3D 0; i < num_phys; i++) { + phys[i].phy =3D of_phy_get(np, phys[i].id); + ret =3D PTR_ERR_OR_ZERO(phys[i].phy); + if (ret) { + phys[i].phy =3D NULL; + goto err; + } + } + + return 0; + +err: + of_phy_bulk_put(i, phys); + + return ret; +} +EXPORT_SYMBOL_GPL(of_phy_bulk_get); + +static int of_phy_bulk_get_by_index(struct device_node *np, + unsigned int num_phys, + struct phy_bulk_data *phys) +{ + unsigned int i; + int ret; + + for (i =3D 0; i < num_phys; i++) { + phys[i].id =3D NULL; + phys[i].phy =3D NULL; + } + + for (i =3D 0; i < num_phys; i++) { + of_property_read_string_index(np, "phy-names", i, &phys[i].id); + + phys[i].phy =3D of_phy_get_by_index(np, i); + + ret =3D PTR_ERR_OR_ZERO(phys[i].phy); + if (ret) { + phys[i].phy =3D NULL; + goto err; + } + } + + return 0; + +err: + of_phy_bulk_put(i, phys); + + return ret; +} + +/** + * of_phy_bulk_get_all() - obtain all PHYs from a device node + * @np: device node containing the PHY references + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * Gets every PHY referenced by the phys property in index order. PHY name= s are + * read from phy-names when present. The caller must call + * of_phy_bulk_put_all() to release the PHY references and free the array. + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int of_phy_bulk_get_all(struct device_node *np, struct phy_bulk_data **phy= s) +{ + struct phy_bulk_data *phy_bulk; + int num_phys; + int ret; + + num_phys =3D of_phy_get_count(np); + if (num_phys <=3D 0) + return num_phys; + + phy_bulk =3D kmalloc_objs(*phy_bulk, num_phys); + if (!phy_bulk) + return -ENOMEM; + + ret =3D of_phy_bulk_get_by_index(np, num_phys, phy_bulk); + if (ret) { + kfree(phy_bulk); + return ret; + } + + *phys =3D phy_bulk; + + return num_phys; +} +EXPORT_SYMBOL_GPL(of_phy_bulk_get_all); + +/** + * of_phy_bulk_put_all() - release and free PHYs obtained by + * of_phy_bulk_get_all() + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to release and free + */ +void of_phy_bulk_put_all(unsigned int num_phys, struct phy_bulk_data *phys) +{ + if (IS_ERR_OR_NULL(phys)) + return; + + of_phy_bulk_put(num_phys, phys); + kfree(phys); +} +EXPORT_SYMBOL_GPL(of_phy_bulk_put_all); + +/** + * phy_bulk_get_all() - obtain all PHYs requested by a device + * @dev: device that requests the PHYs + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * Gets every PHY referenced by the device's device tree node and creates a + * device link for each PHY. The caller must call phy_bulk_put_all() to re= lease + * the PHY references and free the array. + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys) +{ + struct device_node *np =3D dev_of_node(dev); + int ret; + + *phys =3D NULL; + + if (!np) + return 0; + + ret =3D of_phy_bulk_get_all(np, phys); + if (ret > 0) + for (int i =3D 0; i < ret; i++) + phy_add_device_link(dev, (*phys)[i].phy); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_bulk_get_all); + +/** + * phy_bulk_put_all() - release and free PHYs obtained by phy_bulk_get_all= () + * @dev: device that acquired the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to release and free + */ +void phy_bulk_put_all(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + if (IS_ERR_OR_NULL(phys)) + return; + + phy_bulk_put(dev, num_phys, phys); + kfree(phys); +} +EXPORT_SYMBOL_GPL(phy_bulk_put_all); + +/** + * phy_bulk_init() - initialize multiple PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to initialize + * + * Initializes the PHYs in array order. If an initialization fails, all PH= Ys + * initialized by this call are exited in reverse order. + * + * Return: %0 if successful, a negative error code otherwise + */ +int phy_bulk_init(unsigned int num_phys, struct phy_bulk_data *phys) +{ + unsigned int i; + int ret; + + for (i =3D 0; i < num_phys; i++) { + ret =3D phy_init(phys[i].phy); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + phy_exit(phys[i].phy); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_bulk_init); + +/** + * phy_bulk_exit() - exit multiple PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to exit + * + * Exits the PHYs in reverse array order. All PHYs are processed even if an + * error occurs. + * + * Return: %0 if successful, the first negative error code otherwise + */ +int phy_bulk_exit(unsigned int num_phys, struct phy_bulk_data *phys) +{ + int ret =3D 0; + int err; + + while (num_phys--) { + err =3D phy_exit(phys[num_phys].phy); + if (err && !ret) + ret =3D err; + } + + return ret; +} +EXPORT_SYMBOL_GPL(phy_bulk_exit); + +/** + * phy_bulk_power_on() - power on multiple PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to power on + * + * Powers on the PHYs in array order. If a power-on operation fails, all P= HYs + * powered on by this call are powered off in reverse order. + * + * Return: %0 if successful, a negative error code otherwise + */ +int phy_bulk_power_on(unsigned int num_phys, struct phy_bulk_data *phys) +{ + unsigned int i; + int ret; + + for (i =3D 0; i < num_phys; i++) { + ret =3D phy_power_on(phys[i].phy); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + phy_power_off(phys[i].phy); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_bulk_power_on); + +/** + * phy_bulk_power_off() - power off multiple PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data to power off + * + * Powers off the PHYs in reverse array order. All PHYs are processed even= if + * an error occurs. + * + * Return: %0 if successful, the first negative error code otherwise + */ +int phy_bulk_power_off(unsigned int num_phys, struct phy_bulk_data *phys) +{ + int ret =3D 0; + int err; + + while (num_phys--) { + err =3D phy_power_off(phys[num_phys].phy); + if (err && !ret) + ret =3D err; + } + + return ret; +} +EXPORT_SYMBOL_GPL(phy_bulk_power_off); + /** * phy_create() - create a new phy * @dev: device that is creating the new phy diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index ea47975e288a..13f9f030122f 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -81,6 +81,17 @@ union phy_configure_opts { struct phy_configure_opts_hdmi hdmi; }; =20 +/** + * struct phy_bulk_data - Data used for bulk phy operations. + * + * @id: phy consumer ID + * @phy: struct phy * to store the associated phy + */ +struct phy_bulk_data { + const char *id; + struct phy *phy; +}; + /** * struct phy_ops - set of function pointers for performing phy operations * @init: operation to be performed for initializing phy @@ -309,6 +320,26 @@ void devm_of_phy_provider_unregister(struct device *de= v, struct phy_provider *phy_provider); int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev= _id); void phy_remove_lookup(struct phy *phy, const char *con_id, const char *de= v_id); + +int phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +int phy_bulk_get_optional(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +int of_phy_bulk_get(struct device_node *np, unsigned int num_phys, + struct phy_bulk_data *phys); +int phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys); +int of_phy_bulk_get_all(struct device_node *np, struct phy_bulk_data **phy= s); +void phy_bulk_put(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +void of_phy_bulk_put(unsigned int num_phys, struct phy_bulk_data *phys); +void phy_bulk_put_all(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +void of_phy_bulk_put_all(unsigned int num_phys, struct phy_bulk_data *phys= ); +int phy_bulk_init(unsigned int num_phys, struct phy_bulk_data *phys); +int phy_bulk_exit(unsigned int num_phys, struct phy_bulk_data *phys); +int phy_bulk_power_on(unsigned int num_phys, struct phy_bulk_data *phys); +int phy_bulk_power_off(unsigned int num_phys, struct phy_bulk_data *phys); + #else static inline int phy_pm_runtime_get(struct phy *phy) { @@ -493,6 +524,118 @@ static inline struct phy *devm_of_phy_get_by_index(st= ruct device *dev, return ERR_PTR(-ENOSYS); } =20 +static inline int phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return -EOPNOTSUPP; +} + +static inline int phy_bulk_get_optional(struct device *dev, + unsigned int num_phys, + struct phy_bulk_data *phys) +{ + if (!phys) + return 0; + + for (unsigned int i =3D 0; i < num_phys; i++) + phys[i].phy =3D NULL; + + return 0; +} + +static inline int of_phy_bulk_get(struct device_node *np, unsigned int num= _phys, + struct phy_bulk_data *phys) +{ + return -EOPNOTSUPP; +} + +static inline int phy_bulk_get_all(struct device *dev, + struct phy_bulk_data **phys) +{ + if (phys) + *phys =3D NULL; + + return -EOPNOTSUPP; +} + +static inline int of_phy_bulk_get_all(struct device_node *np, + struct phy_bulk_data **phys) +{ + if (phys) + *phys =3D NULL; + + return -EOPNOTSUPP; +} + +static inline void phy_bulk_put(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + if (!phys) + return; + + while (num_phys--) + phys[num_phys].phy =3D NULL; +} + +static inline void of_phy_bulk_put(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + if (!phys) + return; + + while (num_phys--) + phys[num_phys].phy =3D NULL; +} + +static inline void phy_bulk_put_all(struct device *dev, unsigned int num_p= hys, + struct phy_bulk_data *phys) +{ + phy_bulk_put(dev, num_phys, phys); +} + +static inline void of_phy_bulk_put_all(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + of_phy_bulk_put(num_phys, phys); +} + +static inline int phy_bulk_check_disabled(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + if (!phys) + return 0; + + for (unsigned int i =3D 0; i < num_phys; i++) + if (phys[i].phy) + return -EOPNOTSUPP; + + return 0; +} + +static inline int phy_bulk_init(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return phy_bulk_check_disabled(num_phys, phys); +} + +static inline int phy_bulk_exit(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return phy_bulk_check_disabled(num_phys, phys); +} + +static inline int phy_bulk_power_on(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return phy_bulk_check_disabled(num_phys, phys); +} + +static inline int phy_bulk_power_off(unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return phy_bulk_check_disabled(num_phys, phys); +} + static inline void of_phy_put(struct phy *phy) { } --=20 2.55.0 From nobody Sat Sep 26 05:28:07 2026 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36B863EDAD5 for ; Fri, 4 Sep 2026 08:38:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511084; cv=none; b=rbVL+6qtXlYoMJYVLtnKzsya5jlW2Tuz7rVnpQYOY5pWmiVnKf93o68yh/tldla22iyTLvOswl9qmGGqcvUUvDoUaKz3XKOGJCpNrzjKULHdTKY2fPpiU9VxEwAHpLAWeWvNhteojmQeC0MoLNriFpc+lMI1L5BqW03jSvIvAPM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788511084; c=relaxed/simple; bh=biJmwja02rvAee5NwhmdA8ImFbtTkB1f9MBOmtuQW/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vEiviyP1FMJmnlxoN0aaGV9X9sPFt61FcTfmjndLXpqHc4CuQ9OHgVHYO/OPW0hIk8VqS6ybHVKdHgl3rrWLF6WQ6MbwZy/VOgRf98W5oq/mq+2vXQpzB1FMo2z2pAeoi0r2xHIJGVS2kAyzSd4crW0hJPZgcoEgFg5siVzSXBU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=fygSyulv; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fygSyulv" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2d5335cf904so7037025ad.2 for ; Fri, 04 Sep 2026 01:38:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788511082; x=1789115882; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=2uIP2PaSZV7t0ZnwDpHDOn//v4Nee7XCb1/Ur7myjFU=; b=fygSyulvNaBHIUtirOOwG8by5AHey9NBSY8JVlb16hNpmXwF/pSOuhQEq/qaxDi1Cu A/KvzNrdl7s0Go/lG64X/jFL+QLuCWvjYpVA/a41ASQJcil7cYawW8+4bS9Iu/4LmOjt Q+0Ph+JlbHqOBcEFm2dTj5Z6P76XHpT9SrFKfhm6Pu6bBIY3RkOXiB9vgujI63cdiWvK 70zNCf4UmQmHXYOqJQ+VYt+l6T67vpNFCZuUuRG5+dT2ZyyHfrJQ3wm0qV1p5U7hqUKz oD0Xw0wHmrkBUWUyFPgv5m7cChuPEZJmzYf9wBFKSbPXBCUbq77W+hA0v4D6n3qg8a5W yYUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788511082; x=1789115882; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=2uIP2PaSZV7t0ZnwDpHDOn//v4Nee7XCb1/Ur7myjFU=; b=bSzWVq1afBHzWkUsE7evZmod2M7JXnaQY3TUN5r9Aocls6pQC/SItY5ErHuzzAcgju fNm893uAufDm0OlHHfIfD9d9f3pJhhK51DCF+O9P7whAOCQ3E0OBnjUVBRw9SgeRhqHq NiqbH1lTUdpSm18/uIGsVTlibdpQTmuj8eBJhfEakT79Ed50n3XUazPm4LokQ3eJhk1Y LdWCAyIviJou2jOg1Kj2wPSh9JPqApz9K9RRfNCN4NC5p1jW+v1jhZdbGX/gHYA5hyNJ HKDhCnpGCoWuA+jaHnUyB4ezjSXmPRHERpXsg1kwPW5vjTZAz4z+giqFeg1i8fo3nNs3 uhDw== X-Forwarded-Encrypted: i=1; AKwUvBxuksRaIGCejr2jwkiZRl5vD9LDh2cG3ynbDTqj1BRDSSFVP1E5CYKj8FX3QUU5BuIg0XapApMbrNMbKwM=@vger.kernel.org X-Gm-Message-State: AFuF++nOEvxjKSoLy0ojnfSzBQdoAvSRLacIu97JQnmcLKQqNN1VIVz4 tpE2COVKWw0yAHeUxalcR8HiY7ja/S68JdZX/myR4xbU6FVaFppfY7TP X-Gm-Gg: AYBFou2WOaYrUds/saqGegawvGdphbZrhddJlf6gAYE3ERvbqj6hLMDIyrQ2EJMxwQZ 7fR3uEkNIMfgG02VEa4iDP11jx25ZxDhwhlP/B7Y9j7HT4z3kU3kmbK7LrRSDlF3aLjw99ivqti 1Y6uv2OqQ5sFdCrXyD8SjRPBV7qv//4RWtobHoGqQNs1xoS7k7ayARK6FWvb92wj4kpnMVsfJTC IxpHUhL7zzmWygN0am0vZUdjvXkhvAl6D9LztDuyIIHIWTn1geAiEVP4mVKk/8a0YjgcNEPhImK 8XQ6fRKeoEQsIE1Ybduwg23PSYOKAINgVZSqRG/8KvrvQPBfFE5P4cVKizJp2XU38GhSieTyp1C XdNp7d89dzMm+ZPq/cuxLeUqxVOmZzCPXdGBvsOTGL6D4PwdierSCLMkB+M0BvLOQ/UxAeQb9PI vksA2LWcuJRGRyjl4/HtzIxV26vi+Rd6Vlj6KqzLmyuvszUjGYkMQZc5/RshM= X-Received: by 2002:a17:903:46c5:b0:2d9:123c:8c49 with SMTP id d9443c01a7336-2db1975804bmr41593555ad.14.1788511082398; Fri, 04 Sep 2026 01:38:02 -0700 (PDT) Received: from localhost ([2001:19f0:8000:3e6e:5400:6ff:fe38:3d01]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2db1495a0b2sm6716595ad.28.2026.09.04.01.38.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Sep 2026 01:38:02 -0700 (PDT) From: Inochi Amaoto To: Vinod Koul , Neil Armstrong , Manivannan Sadhasivam Cc: Andy Shevchenko , Inochi Amaoto , linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org, Yixun Lan , Longbin Li Subject: [PATCH v2 4/4] phy: core: Add managed phy bulk data helper functions Date: Fri, 4 Sep 2026 16:37:08 +0800 Message-ID: <20260904083709.425893-5-inochiama@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260904083709.425893-1-inochiama@gmail.com> References: <20260904083709.425893-1-inochiama@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add device managed variants of the phy bulk helper functions. So the driver can benefit from automatically managed phy handles. Signed-off-by: Inochi Amaoto --- drivers/phy/phy-core.c | 198 ++++++++++++++++++++++++++++++++++++++++ include/linux/phy/phy.h | 43 +++++++++ 2 files changed, 241 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index f5596b8dfcfc..e28206f8dc89 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -1304,6 +1304,204 @@ void phy_bulk_put_all(struct device *dev, unsigned = int num_phys, } EXPORT_SYMBOL_GPL(phy_bulk_put_all); =20 +struct phy_bulk_devres { + struct phy_bulk_data *phys; + unsigned int num_phys; +}; + +static void devm_phy_bulk_release(struct device *dev, void *res) +{ + struct phy_bulk_devres *devres =3D res; + + phy_bulk_put(dev, devres->num_phys, devres->phys); +} + +static int __devm_phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys, bool optional) +{ + struct phy_bulk_devres *devres; + int ret; + + devres =3D devres_alloc(devm_phy_bulk_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret =3D __phy_bulk_get(dev, num_phys, phys, optional); + if (ret) { + devres_free(devres); + return ret; + } + + devres->phys =3D phys; + devres->num_phys =3D num_phys; + devres_add(dev, devres); + + return 0; +} + +/** + * devm_phy_bulk_get() - managed lookup of multiple PHYs + * @dev: device that requests the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets the PHYs using phy_bulk_get() and associates the references with @= dev. + * The references are automatically released on driver detach. + * + * Return: %0 if successful, a negative error code otherwise + */ +int devm_phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return __devm_phy_bulk_get(dev, num_phys, phys, false); +} +EXPORT_SYMBOL_GPL(devm_phy_bulk_get); + +/** + * devm_phy_bulk_get_optional() - managed lookup of multiple optional PHYs + * @dev: device that requests the PHYs + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets the PHYs using phy_bulk_get_optional() and associates the referenc= es + * with @dev. Missing PHYs are stored as NULL. The references are automati= cally + * released on driver detach. + * + * Return: %0 if successful, a negative error code otherwise + */ +int devm_phy_bulk_get_optional(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return __devm_phy_bulk_get(dev, num_phys, phys, true); +} +EXPORT_SYMBOL_GPL(devm_phy_bulk_get_optional); + +/** + * devm_of_phy_bulk_get() - managed lookup of multiple PHYs from a device = node + * @dev: device that requests the PHYs + * @np: device node containing the PHY references + * @num_phys: number of entries in the phys array + * @phys: array of struct phy_bulk_data with PHY names set + * + * Gets the PHYs using of_phy_bulk_get() from the specified device node, + * associates the references with @dev, and creates a device link for each= PHY. + * The references are automatically released on driver detach. + * + * Return: %0 if successful, a negative error code otherwise + */ +int devm_of_phy_bulk_get(struct device *dev, struct device_node *np, + unsigned int num_phys, struct phy_bulk_data *phys) +{ + struct phy_bulk_devres *devres; + int ret; + + devres =3D devres_alloc(devm_phy_bulk_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret =3D of_phy_bulk_get(np, num_phys, phys); + if (ret) { + devres_free(devres); + return ret; + } + + for (unsigned int i =3D 0; i < num_phys; i++) + phy_add_device_link(dev, phys[i].phy); + + devres->phys =3D phys; + devres->num_phys =3D num_phys; + devres_add(dev, devres); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_of_phy_bulk_get); + +static void devm_phy_bulk_release_all(struct device *dev, void *res) +{ + struct phy_bulk_devres *devres =3D res; + + phy_bulk_put_all(dev, devres->num_phys, devres->phys); +} + +/** + * devm_phy_bulk_get_all() - managed lookup of all PHYs requested by a dev= ice + * @dev: device that requests the PHYs + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * Gets all PHYs using phy_bulk_get_all() and associates the allocated arr= ay and + * PHY references with @dev. They are automatically released on driver det= ach. + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int devm_phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys) +{ + struct phy_bulk_devres *devres; + int ret; + + *phys =3D NULL; + + devres =3D devres_alloc(devm_phy_bulk_release_all, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret =3D phy_bulk_get_all(dev, &devres->phys); + if (ret > 0) { + *phys =3D devres->phys; + devres->num_phys =3D ret; + devres_add(dev, devres); + } else { + devres_free(devres); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_phy_bulk_get_all); + +/** + * devm_of_phy_bulk_get_all() - managed lookup of all PHYs from a device n= ode + * @dev: device that requests the PHYs + * @np: device node containing the PHY references + * @phys: pointer to store the allocated array of struct phy_bulk_data + * + * Gets all PHYs from the specified device node, associates the allocated = array + * and PHY references with @dev, and creates a device link for each PHY. T= hey + * are automatically released on driver detach. + * + * Return: the number of PHYs on success, %0 if no PHYs are found, or a + * negative error code otherwise + */ +int devm_of_phy_bulk_get_all(struct device *dev, struct device_node *np, + struct phy_bulk_data **phys) +{ + struct phy_bulk_devres *devres; + int ret; + + *phys =3D NULL; + + devres =3D devres_alloc(devm_phy_bulk_release_all, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret =3D of_phy_bulk_get_all(np, &devres->phys); + if (ret > 0) { + for (int i =3D 0; i < ret; i++) + phy_add_device_link(dev, devres->phys[i].phy); + *phys =3D devres->phys; + devres->num_phys =3D ret; + devres_add(dev, devres); + } else { + devres_free(devres); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_phy_bulk_get_all); + /** * phy_bulk_init() - initialize multiple PHYs * @num_phys: number of entries in the phys array diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 13f9f030122f..2af240f4b257 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -327,8 +327,17 @@ int phy_bulk_get_optional(struct device *dev, unsigned= int num_phys, struct phy_bulk_data *phys); int of_phy_bulk_get(struct device_node *np, unsigned int num_phys, struct phy_bulk_data *phys); +int devm_phy_bulk_get(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +int devm_phy_bulk_get_optional(struct device *dev, unsigned int num_phys, + struct phy_bulk_data *phys); +int devm_of_phy_bulk_get(struct device *dev, struct device_node *np, + unsigned int num_phys, struct phy_bulk_data *phys); int phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys); int of_phy_bulk_get_all(struct device_node *np, struct phy_bulk_data **phy= s); +int devm_phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys); +int devm_of_phy_bulk_get_all(struct device *dev, struct device_node *np, + struct phy_bulk_data **phys); void phy_bulk_put(struct device *dev, unsigned int num_phys, struct phy_bulk_data *phys); void of_phy_bulk_put(unsigned int num_phys, struct phy_bulk_data *phys); @@ -549,6 +558,27 @@ static inline int of_phy_bulk_get(struct device_node *= np, unsigned int num_phys, return -EOPNOTSUPP; } =20 +static inline int devm_phy_bulk_get(struct device *dev, unsigned int num_p= hys, + struct phy_bulk_data *phys) +{ + return -EOPNOTSUPP; +} + +static inline int devm_phy_bulk_get_optional(struct device *dev, + unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return phy_bulk_get_optional(dev, num_phys, phys); +} + +static inline int devm_of_phy_bulk_get(struct device *dev, + struct device_node *np, + unsigned int num_phys, + struct phy_bulk_data *phys) +{ + return -EOPNOTSUPP; +} + static inline int phy_bulk_get_all(struct device *dev, struct phy_bulk_data **phys) { @@ -567,6 +597,19 @@ static inline int of_phy_bulk_get_all(struct device_no= de *np, return -EOPNOTSUPP; } =20 +static inline int devm_phy_bulk_get_all(struct device *dev, + struct phy_bulk_data **phys) +{ + return phy_bulk_get_all(dev, phys); +} + +static inline int devm_of_phy_bulk_get_all(struct device *dev, + struct device_node *np, + struct phy_bulk_data **phys) +{ + return of_phy_bulk_get_all(np, phys); +} + static inline void phy_bulk_put(struct device *dev, unsigned int num_phys, struct phy_bulk_data *phys) { --=20 2.55.0