public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: "Thomas Richard (TI.com)" <thomas.richard@bootlin.com>,
	Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>,
	linux-phy@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.19-6.12] phy: ti: phy-j721e-wiz: restore mux selection during resume
Date: Wed, 18 Feb 2026 21:04:04 -0500	[thread overview]
Message-ID: <20260219020422.1539798-28-sashal@kernel.org> (raw)
In-Reply-To: <20260219020422.1539798-1-sashal@kernel.org>

From: "Thomas Richard (TI.com)" <thomas.richard@bootlin.com>

[ Upstream commit 53f6240e88c9e8715e09fc19942f13450db4cb33 ]

While suspend and resume mux selection was getting lost. So save and
restore these values in suspend and resume operations.

Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
Link: https://patch.msgid.link/20251216-phy-ti-phy-j721e-wiz-resume-restore-mux-sel-v1-1-771d564db966@bootlin.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Good. The current tree has the resume function but no suspend function
(the suspend slot is NULL), which matches the pre-patch state in the
diff.

## Analysis Summary

### What the commit does:

1. **Adds a new field** `mux_sel_status[WIZ_MUX_NUM_CLOCKS]` (3 ints) to
   the `struct wiz` to store mux selection state.

2. **Adds a `wiz_suspend_noirq()` callback** that reads the 3 mux
   selection values from hardware registers before suspend, saving them
   in the new array.

3. **Modifies `wiz_resume_noirq()`** to write the saved mux selection
   values back to hardware registers at the beginning of resume, before
   the rest of the initialization.

4. **Updates the PM ops macro** from
   `DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq)` to
   `DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, wiz_suspend_noirq,
   wiz_resume_noirq)`.

### Bug being fixed:

The mux clock selection values (which control how the SERDES reference
clocks are routed) are lost during suspend because the hardware state is
not preserved. On resume, `wiz_resume_noirq()` called `wiz_clock_init()`
and `wiz_init()`, but these re-initialize the clocks to default values
rather than restoring the user/driver-configured mux selections. This
means after resume, the SERDES PHY may not work correctly because the
clock routing is wrong.

### Classification: **Suspend/resume bug fix**

This is a real hardware bug that affects users who suspend and resume
systems using the TI J721E SERDES PHY (common in TI K3 SoC
automotive/industrial platforms). Without this fix, the PHY may not
function correctly after resume, potentially breaking network, PCIe,
USB, or other SERDES-based interfaces.

### Stable kernel rule compliance:

1. **Obviously correct and tested**: Simple save/restore pattern using
   existing regmap_field_read/write APIs. The author works at Bootlin
   for TI platforms.
2. **Fixes a real bug**: Mux selection lost after resume = broken PHY
   after suspend/resume.
3. **Important issue**: Broken hardware functionality after
   suspend/resume.
4. **Small and contained**: ~20 lines of new code, single file, simple
   logic.
5. **No new features**: Restoring state that was lost is a bug fix, not
   a feature.

### Risk assessment:

- **Very low risk**: The save/restore pattern is straightforward and
  well-understood.
- **WIZ_MUX_NUM_CLOCKS is 3**: Only 3 register reads and 3 register
  writes are added.
- **Uses existing regmap_field APIs**: No new infrastructure needed.
- **Only affects TI J721E platforms**: Cannot cause regressions on other
  platforms.
- **Only affects suspend/resume path**: Cannot affect boot or normal
  operation.

### Dependencies:

The resume support was added in commit `b5539abdd013f` (v6.11). The
`wiz_clock_init()` function split was in commit `3c4e13cf9ead7` (also
v6.11). So this fix is applicable to stable trees v6.11+, and possibly
v6.12.y and v6.13.y LTS trees if they exist.

## Verification

- **git log** confirmed the driver was first added in commit
  `091876cc355d6` (phy: ti: j721e-wiz: Add support for WIZ module
  present in TI J721E SoC)
- **git tag --contains** confirmed resume support (`b5539abdd013f`) was
  introduced in v6.11
- **git tag --contains** confirmed `wiz_clock_init()` split
  (`3c4e13cf9ead7`) was also introduced in v6.11
- **Grep for `WIZ_MUX_NUM_CLOCKS`** confirmed it is defined as 3, making
  the save/restore loop iterate only 3 times
- **Grep for `mux_sel_status`** confirmed the field does not yet exist
  in the working tree (commit not yet applied)
- **Grep for `wiz_resume_noirq`** confirmed the current code has resume
  handler but NULL suspend handler, matching the pre-patch state
- **Read of the mux_sel_field usage** (lines 1031, 1056, 1172) confirmed
  these fields control clock mux selection in the WIZ initialization
  path
- **Unverified**: Whether any downstream users (e.g., Android, embedded
  distros) have reported this specific suspend/resume issue. The commit
  message states the problem directly but doesn't include "Reported-by:"
  tags.

## Conclusion

This is a small, well-contained suspend/resume bug fix for the TI J721E
WIZ PHY driver. It fixes a real hardware issue where clock mux
selections are lost during suspend, rendering the SERDES PHY non-
functional after resume. The fix uses a standard save/restore pattern
with minimal code additions (~20 lines in a single file). The risk of
regression is very low since it only affects the suspend/resume path on
TI K3 platforms. It meets all stable kernel criteria.

**YES**

 drivers/phy/ti/phy-j721e-wiz.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index a8b440c6c46bb..ba31b0a1f7f79 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -393,6 +393,7 @@ struct wiz {
 	struct clk		*output_clks[WIZ_MAX_OUTPUT_CLOCKS];
 	struct clk_onecell_data	clk_data;
 	const struct wiz_data	*data;
+	int			mux_sel_status[WIZ_MUX_NUM_CLOCKS];
 };
 
 static int wiz_reset(struct wiz *wiz)
@@ -1654,11 +1655,25 @@ static void wiz_remove(struct platform_device *pdev)
 	pm_runtime_disable(dev);
 }
 
+static int wiz_suspend_noirq(struct device *dev)
+{
+	struct wiz *wiz = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++)
+		regmap_field_read(wiz->mux_sel_field[i], &wiz->mux_sel_status[i]);
+
+	return 0;
+}
+
 static int wiz_resume_noirq(struct device *dev)
 {
 	struct device_node *node = dev->of_node;
 	struct wiz *wiz = dev_get_drvdata(dev);
-	int ret;
+	int ret, i;
+
+	for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++)
+		regmap_field_write(wiz->mux_sel_field[i], wiz->mux_sel_status[i]);
 
 	/* Enable supplemental Control override if available */
 	if (wiz->sup_legacy_clk_override)
@@ -1680,7 +1695,7 @@ static int wiz_resume_noirq(struct device *dev)
 	return ret;
 }
 
-static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
+static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, wiz_suspend_noirq, wiz_resume_noirq);
 
 static struct platform_driver wiz_driver = {
 	.probe		= wiz_probe,
-- 
2.51.0


  parent reply	other threads:[~2026-02-19  2:04 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-19  2:03 [PATCH AUTOSEL 6.19] rust_binder: Fix build failure if !CONFIG_COMPAT Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] usb: chipidea: udc: fix DMA and SG cleanup in _ep_nuke() Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.15] staging: rtl8723bs: fix memory leak on failure path Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19] tty: vt/keyboard: Split apart vt_do_diacrit() Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.10] fix it87_wdt early reboot by reporting running timer Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.15] misc: eeprom: Fix EWEN/EWDS/ERAL commands for 93xx56 and 93xx66 Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.15] mmc: rtsx_pci: add quirk to disable MMC_CAP_AGGRESSIVE_PM for RTS525A Sasha Levin
2026-02-19 10:29   ` Ulf Hansson
2026-02-26 13:23     ` Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.1] fpga: of-fpga-region: Fail if any bridge is missing Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] soundwire: intel_auxdevice: add cs42l45 codec to wake_capable_list Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.10] iio: magnetometer: Remove IRQF_ONESHOT Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.1] watchdog: imx7ulp_wdt: handle the nowayout option Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.10] serial: 8250_dw: handle clock enable errors in runtime_resume Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] most: core: fix resource leak in most_register_interface error paths Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19] block: fix partial IOVA mapping cleanup in blk_rq_dma_map_iova Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.1] misc: bcm_vk: Fix possible null-pointer dereferences in bcm_vk_read() Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.1] dmaengine: sun6i: Choose appropriate burst length under maxburst Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.1] mmc: rtsx: reset power state on suspend Sasha Levin
2026-02-19 10:27   ` Ulf Hansson
2026-02-26 13:24     ` Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19] serial: rsci: Add set_rtrg() callback Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-5.10] Revert "mfd: da9052-spi: Change read-mask to write-mask" Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.18] pinctrl: mediatek: make devm allocations safer and clearer in mtk_eint_do_init() Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] serial: 8250: 8250_omap.c: Add support for handling UART error conditions Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] usb: gadget: f_fs: Fix ioctl error handling Sasha Levin
2026-02-19  2:03 ` [PATCH AUTOSEL 6.19-6.12] phy: cadence-torrent: restore parent clock for refclk during resume Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.10] binder: don't use %pK through printk Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.18] iio: bmi270_i2c: Add MODULE_DEVICE_TABLE for BMI260/270 Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.15] iio: Use IRQF_NO_THREAD Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.12] mfd: intel-lpss: Add Intel Nova Lake-S PCI IDs Sasha Levin
2026-02-19  2:04 ` Sasha Levin [this message]
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.10] MIPS: Loongson: Make cpumask_of_node() robust against NUMA_NO_NODE Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.12] usb: gadget: f_fs: fix DMA-BUF OUT queues Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.10] phy: fsl-imx8mq-usb: disable bind/unbind platform driver feature Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.18] watchdog: rzv2h_wdt: Discard pm_runtime_put() return value Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.1] soundwire: dmi-quirks: add mapping for Avell B.ON (OEM rebranded of NUC15) Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.18] pinctrl: renesas: rzt2h: Allow .get_direction() for IRQ function GPIOs Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.12] dmaengine: stm32-dma3: use module_platform_driver Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.15] staging: rtl8723bs: fix missing status update on sdio_alloc_irq() failure Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.15] phy: mvebu-cp110-utmi: fix dr_mode property read from dts Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.1] usb: typec: ucsi: psy: Fix voltage and current max for non-Fixed PDOs Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-5.10] serial: 8250: 8250_omap.c: Clear DMA RX running status only after DMA termination is done Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.1] dmaengine: stm32-mdma: initialize m2m_hw_period and ccr to fix warnings Sasha Levin
2026-02-19  2:04 ` [PATCH AUTOSEL 6.19-6.18] misc: ti_fpc202: fix a potential memory leak in probe function Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260219020422.1539798-28-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=thomas.richard@bootlin.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox