mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support
@ 2026-09-01  3:03 Bard Liao
  2026-09-01  3:03 ` [PATCH v2 1/3] soundwire: bus: add CLOCK_STOP_MODE1 support back Bard Liao
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Bard Liao @ 2026-09-01  3:03 UTC (permalink / raw)
  To: linux-sound, vkoul
  Cc: vinod.koul, linux-kernel, pierre-louis.bossart, peter.ujfalusi,
	bard.liao

Add CLOCK_STOP_MODE1 back to allow the peripheral to utilize it when
the clock is stopped.
This mode is designed for power-sensitive devices as it enables a deeper
power-saving state, although it does not retain the peripheral's state
during the clock stop.

v2:
 - check slave->probed before looking at the driver to avoid NULL pointer
   dereference.
 - add wake_enable parameter to stop_bus ops to stop the clock but keep the
   bus unwakeable during system suspend.

Bard Liao (3):
  soundwire: bus: add CLOCK_STOP_MODE1 support back
  soundwire: Intel: add wake_enable parameter to stop_bus ops
  soundwire: Intel: stop sdw clock in system suspend

 drivers/soundwire/bus.c              | 54 +++++++++++++++++-----------
 drivers/soundwire/intel.h            |  6 ++--
 drivers/soundwire/intel_auxdevice.c  |  7 ++--
 drivers/soundwire/intel_bus_common.c |  8 ++---
 include/linux/soundwire/sdw.h        |  4 +++
 include/linux/soundwire/sdw_intel.h  |  2 +-
 6 files changed, 50 insertions(+), 31 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] soundwire: bus: add CLOCK_STOP_MODE1 support back
  2026-09-01  3:03 [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Bard Liao
@ 2026-09-01  3:03 ` Bard Liao
  2026-09-01  3:03 ` [PATCH v2 2/3] soundwire: Intel: add wake_enable parameter to stop_bus ops Bard Liao
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Bard Liao @ 2026-09-01  3:03 UTC (permalink / raw)
  To: linux-sound, vkoul
  Cc: vinod.koul, linux-kernel, pierre-louis.bossart, peter.ujfalusi,
	bard.liao

CLOCK_STOP_MODE1 is used when the Peripheral might have entered a deeper
power-saving mode that does not retain state while the Clock is stopped.
It is useful when the device is more power consumption sensitive. Add it
back to allow the Peripheral use CLOCK_STOP_MODE1.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 drivers/soundwire/bus.c       | 54 ++++++++++++++++++++++-------------
 include/linux/soundwire/sdw.h |  4 +++
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 0c1cdd603926..4df7899988ad 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -959,8 +959,31 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
 	mutex_unlock(&bus->bus_lock);
 }
 
+static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave)
+{
+	enum sdw_clk_stop_mode mode;
+
+	mode = slave->prop.clk_stop_mode1 ? SDW_CLK_STOP_MODE1 : SDW_CLK_STOP_MODE0;
+
+	mutex_lock(&slave->sdw_dev_lock);
+
+	/*
+	 * Query for clock stop mode if Slave implements
+	 * ops->get_clk_stop_mode, else read from property.
+	 */
+	if (slave->probed) {
+		struct sdw_driver *drv = drv_to_sdw_driver(slave->dev.driver);
+
+		if (drv->ops && drv->ops->get_clk_stop_mode)
+			mode = drv->ops->get_clk_stop_mode(slave);
+	}
+
+	mutex_unlock(&slave->sdw_dev_lock);
+
+	return mode;
+}
+
 static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
-				       enum sdw_clk_stop_mode mode,
 				       enum sdw_clk_stop_type type)
 {
 	int ret = 0;
@@ -972,7 +995,7 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
 		struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
 
 		if (drv->ops && drv->ops->clk_stop)
-			ret = drv->ops->clk_stop(slave, mode, type);
+			ret = drv->ops->clk_stop(slave, slave->clk_stop_mode, type);
 	}
 
 	mutex_unlock(&slave->sdw_dev_lock);
@@ -981,7 +1004,6 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
 }
 
 static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,
-				      enum sdw_clk_stop_mode mode,
 				      bool prepare)
 {
 	bool wake_en;
@@ -993,7 +1015,7 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,
 	if (prepare) {
 		val = SDW_SCP_SYSTEMCTRL_CLK_STP_PREP;
 
-		if (mode == SDW_CLK_STOP_MODE1)
+		if (slave->clk_stop_mode == SDW_CLK_STOP_MODE1)
 			val |= SDW_SCP_SYSTEMCTRL_CLK_STP_MODE1;
 
 		if (wake_en)
@@ -1081,9 +1103,9 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
 		/* Identify if Slave(s) are available on Bus */
 		is_slave = true;
 
-		ret = sdw_slave_clk_stop_callback(slave,
-						  SDW_CLK_STOP_MODE0,
-						  SDW_CLK_PRE_PREPARE);
+		slave->clk_stop_mode = sdw_get_clk_stop_mode(slave);
+
+		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_PRE_PREPARE);
 		if (ret < 0 && ret != -ENODATA) {
 			dev_err(&slave->dev, "clock stop pre-prepare cb failed:%d\n", ret);
 			return ret;
@@ -1093,9 +1115,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
 		if (!slave->prop.simple_clk_stop_capable) {
 			simple_clk_stop = false;
 
-			ret = sdw_slave_clk_stop_prepare(slave,
-							 SDW_CLK_STOP_MODE0,
-							 true);
+			ret = sdw_slave_clk_stop_prepare(slave, true);
 			if (ret < 0 && ret != -ENODATA) {
 				dev_err(&slave->dev, "clock stop prepare failed:%d\n", ret);
 				return ret;
@@ -1133,9 +1153,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
 		    slave->status != SDW_SLAVE_ALERT)
 			continue;
 
-		ret = sdw_slave_clk_stop_callback(slave,
-						  SDW_CLK_STOP_MODE0,
-						  SDW_CLK_POST_PREPARE);
+		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_POST_PREPARE);
 
 		if (ret < 0 && ret != -ENODATA) {
 			dev_err(&slave->dev, "clock stop post-prepare cb failed:%d\n", ret);
@@ -1207,8 +1225,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
 		/* Identify if Slave(s) are available on Bus */
 		is_slave = true;
 
-		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
-						  SDW_CLK_PRE_DEPREPARE);
+		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_PRE_DEPREPARE);
 		if (ret < 0)
 			dev_warn(&slave->dev, "clock stop pre-deprepare cb failed:%d\n", ret);
 
@@ -1216,9 +1233,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
 		if (!slave->prop.simple_clk_stop_capable) {
 			simple_clk_stop = false;
 
-			ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0,
-							 false);
-
+			ret = sdw_slave_clk_stop_prepare(slave, false);
 			if (ret < 0)
 				dev_warn(&slave->dev, "clock stop deprepare failed:%d\n", ret);
 		}
@@ -1246,8 +1261,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus)
 		    slave->status != SDW_SLAVE_ALERT)
 			continue;
 
-		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0,
-						  SDW_CLK_POST_DEPREPARE);
+		ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_POST_DEPREPARE);
 		if (ret < 0)
 			dev_warn(&slave->dev, "clock stop post-deprepare cb failed:%d\n", ret);
 	}
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 769a8ba5b5c6..2a497ef8d33c 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -618,6 +618,7 @@ struct sdw_bus_params {
  * @update_status: Update Slave status
  * @bus_config: Update the bus config for Slave
  * @port_prep: Prepare the port with parameters
+ * @get_clk_stop_mode: Get the clock stop mode of the Slave
  * @clk_stop: handle imp-def sequences before and after prepare and de-prepare
  */
 struct sdw_slave_ops {
@@ -631,6 +632,7 @@ struct sdw_slave_ops {
 	int (*port_prep)(struct sdw_slave *slave,
 			 struct sdw_prepare_ch *prepare_ch,
 			 enum sdw_port_prep_ops pre_ops);
+	enum sdw_clk_stop_mode (*get_clk_stop_mode)(struct sdw_slave *slave);
 	int (*clk_stop)(struct sdw_slave *slave,
 			enum sdw_clk_stop_mode mode,
 			enum sdw_clk_stop_type type);
@@ -649,6 +651,7 @@ struct sdw_slave_ops {
  * @node: node for bus list
  * @port_ready: Port ready completion flag for each Slave port
  * @m_port_map: static Master port map for each Slave port
+ * @clk_stop_mode: The clock stop mode of the Slave
  * @dev_num: Current Device Number, values can be 0 or dev_num_sticky
  * @dev_num_sticky: one-time static Device Number assigned by Bus
  * @probed: boolean tracking driver state
@@ -683,6 +686,7 @@ struct sdw_slave {
 	struct list_head node;
 	struct completion port_ready[SDW_MAX_PORTS];
 	unsigned int m_port_map[SDW_MAX_PORTS];
+	enum sdw_clk_stop_mode clk_stop_mode;
 	u16 dev_num;
 	u16 dev_num_sticky;
 	bool probed;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] soundwire: Intel: add wake_enable parameter to stop_bus ops
  2026-09-01  3:03 [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Bard Liao
  2026-09-01  3:03 ` [PATCH v2 1/3] soundwire: bus: add CLOCK_STOP_MODE1 support back Bard Liao
@ 2026-09-01  3:03 ` Bard Liao
  2026-09-01  3:03 ` [PATCH v2 3/3] soundwire: Intel: stop sdw clock in system suspend Bard Liao
  2026-09-04  7:25 ` [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Pierre-Louis Bossart
  3 siblings, 0 replies; 5+ messages in thread
From: Bard Liao @ 2026-09-01  3:03 UTC (permalink / raw)
  To: linux-sound, vkoul
  Cc: vinod.koul, linux-kernel, pierre-louis.bossart, peter.ujfalusi,
	bard.liao

Currently, we assume the bus is wakeable when the bus clock stops. But
in some case like system suspend, we want to stop the bus but keep the
bus unwakeable.
No function change in this commit.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 drivers/soundwire/intel.h            | 6 +++---
 drivers/soundwire/intel_auxdevice.c  | 6 +++---
 drivers/soundwire/intel_bus_common.c | 8 ++++----
 include/linux/soundwire/sdw_intel.h  | 2 +-
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h
index 86abc465260f..7a2e7e73ad63 100644
--- a/drivers/soundwire/intel.h
+++ b/drivers/soundwire/intel.h
@@ -188,10 +188,10 @@ static inline int sdw_intel_start_bus_after_clock_stop(struct sdw_intel *sdw)
 	return -ENOTSUPP;
 }
 
-static inline int sdw_intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
+static inline int sdw_intel_stop_bus(struct sdw_intel *sdw, bool clock_stop, bool wake_enable)
 {
 	if (SDW_INTEL_CHECK_OPS(sdw, stop_bus))
-		return SDW_INTEL_OPS(sdw, stop_bus)(sdw, clock_stop);
+		return SDW_INTEL_OPS(sdw, stop_bus)(sdw, clock_stop, wake_enable);
 	return -ENOTSUPP;
 }
 
@@ -261,7 +261,7 @@ int intel_start_bus(struct sdw_intel *sdw);
 int intel_start_bus_after_reset(struct sdw_intel *sdw);
 void intel_check_clock_stop(struct sdw_intel *sdw);
 int intel_start_bus_after_clock_stop(struct sdw_intel *sdw);
-int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop);
+int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop, bool wake_enable);
 
 /* common bank switch routines */
 int intel_pre_bank_switch(struct sdw_intel *sdw);
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index a8407560bf4f..77e09e0e9953 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -670,7 +670,7 @@ static int __maybe_unused intel_suspend(struct device *dev)
 		return 0;
 	}
 
-	ret = sdw_intel_stop_bus(sdw, false);
+	ret = sdw_intel_stop_bus(sdw, false, false);
 	if (ret < 0) {
 		dev_err(dev, "%s: cannot stop bus: %d\n", __func__, ret);
 		return ret;
@@ -696,14 +696,14 @@ static int __maybe_unused intel_suspend_runtime(struct device *dev)
 	clock_stop_quirks = sdw->link_res->clock_stop_quirks;
 
 	if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) {
-		ret = sdw_intel_stop_bus(sdw, false);
+		ret = sdw_intel_stop_bus(sdw, false, false);
 		if (ret < 0) {
 			dev_err(dev, "%s: cannot stop bus during teardown: %d\n",
 				__func__, ret);
 			return ret;
 		}
 	} else if (clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET || !clock_stop_quirks) {
-		ret = sdw_intel_stop_bus(sdw, true);
+		ret = sdw_intel_stop_bus(sdw, true, true);
 		if (ret < 0) {
 			dev_err(dev, "%s: cannot stop bus during clock_stop: %d\n",
 				__func__, ret);
diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c
index ad1f8ebdbfc9..fa35eb2fc763 100644
--- a/drivers/soundwire/intel_bus_common.c
+++ b/drivers/soundwire/intel_bus_common.c
@@ -202,11 +202,11 @@ int intel_start_bus_after_clock_stop(struct sdw_intel *sdw)
 	return 0;
 }
 
-int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
+int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop, bool wake_enable)
 {
 	struct device *dev = sdw->cdns.dev;
 	struct sdw_cdns *cdns = &sdw->cdns;
-	bool wake_enable = false;
+	bool en = false;
 	int ret;
 
 	cancel_delayed_work_sync(&cdns->attach_dwork);
@@ -216,7 +216,7 @@ int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
 		if (ret < 0)
 			dev_err(dev, "%s: cannot stop clock: %d\n", __func__, ret);
 		else
-			wake_enable = true;
+			en = wake_enable;
 	}
 
 	ret = sdw_cdns_enable_interrupt(cdns, false);
@@ -231,7 +231,7 @@ int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
 		return ret;
 	}
 
-	sdw_intel_shim_wake(sdw, wake_enable);
+	sdw_intel_shim_wake(sdw, en);
 
 	return 0;
 }
diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 9c9435009537..9710f2dc04e2 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -424,7 +424,7 @@ struct sdw_intel_hw_ops {
 	int (*start_bus)(struct sdw_intel *sdw);
 	int (*start_bus_after_reset)(struct sdw_intel *sdw);
 	int (*start_bus_after_clock_stop)(struct sdw_intel *sdw);
-	int (*stop_bus)(struct sdw_intel *sdw, bool clock_stop);
+	int (*stop_bus)(struct sdw_intel *sdw, bool clock_stop, bool wake_enable);
 
 	int (*link_power_up)(struct sdw_intel *sdw);
 	int (*link_power_down)(struct sdw_intel *sdw);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] soundwire: Intel: stop sdw clock in system suspend
  2026-09-01  3:03 [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Bard Liao
  2026-09-01  3:03 ` [PATCH v2 1/3] soundwire: bus: add CLOCK_STOP_MODE1 support back Bard Liao
  2026-09-01  3:03 ` [PATCH v2 2/3] soundwire: Intel: add wake_enable parameter to stop_bus ops Bard Liao
@ 2026-09-01  3:03 ` Bard Liao
  2026-09-04  7:25 ` [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Pierre-Louis Bossart
  3 siblings, 0 replies; 5+ messages in thread
From: Bard Liao @ 2026-09-01  3:03 UTC (permalink / raw)
  To: linux-sound, vkoul
  Cc: vinod.koul, linux-kernel, pierre-louis.bossart, peter.ujfalusi,
	bard.liao

Perform clock stop with proper mode so that the Peripherals can enter
the deserved power state. And keep the bus unwakeable because there is
no need to wake up the bus in system suspend.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 drivers/soundwire/intel_auxdevice.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index 77e09e0e9953..dfff44a30c7c 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -670,7 +670,8 @@ static int __maybe_unused intel_suspend(struct device *dev)
 		return 0;
 	}
 
-	ret = sdw_intel_stop_bus(sdw, false, false);
+	/* Perform clock stop with proper mode and keep the bus unwakeable in system suspend. */
+	ret = sdw_intel_stop_bus(sdw, true, false);
 	if (ret < 0) {
 		dev_err(dev, "%s: cannot stop bus: %d\n", __func__, ret);
 		return ret;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support
  2026-09-01  3:03 [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Bard Liao
                   ` (2 preceding siblings ...)
  2026-09-01  3:03 ` [PATCH v2 3/3] soundwire: Intel: stop sdw clock in system suspend Bard Liao
@ 2026-09-04  7:25 ` Pierre-Louis Bossart
  3 siblings, 0 replies; 5+ messages in thread
From: Pierre-Louis Bossart @ 2026-09-04  7:25 UTC (permalink / raw)
  To: Bard Liao, linux-sound, vkoul
  Cc: vinod.koul, linux-kernel, peter.ujfalusi, bard.liao

On 9/1/26 05:03, Bard Liao wrote:
> Add CLOCK_STOP_MODE1 back to allow the peripheral to utilize it when
> the clock is stopped.
> This mode is designed for power-sensitive devices as it enables a deeper
> power-saving state, although it does not retain the peripheral's state
> during the clock stop.
> 
> v2:
>  - check slave->probed before looking at the driver to avoid NULL pointer
>    dereference.
>  - add wake_enable parameter to stop_bus ops to stop the clock but keep the
>    bus unwakeable during system suspend.
> 
> Bard Liao (3):
>   soundwire: bus: add CLOCK_STOP_MODE1 support back
>   soundwire: Intel: add wake_enable parameter to stop_bus ops
>   soundwire: Intel: stop sdw clock in system suspend
> 
>  drivers/soundwire/bus.c              | 54 +++++++++++++++++-----------
>  drivers/soundwire/intel.h            |  6 ++--
>  drivers/soundwire/intel_auxdevice.c  |  7 ++--
>  drivers/soundwire/intel_bus_common.c |  8 ++---
>  include/linux/soundwire/sdw.h        |  4 +++
>  include/linux/soundwire/sdw_intel.h  |  2 +-
>  6 files changed, 50 insertions(+), 31 deletions(-)
> 

Thanks Bard, LGTM - this addresses my previous feedback.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-04  8:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-01  3:03 [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Bard Liao
2026-09-01  3:03 ` [PATCH v2 1/3] soundwire: bus: add CLOCK_STOP_MODE1 support back Bard Liao
2026-09-01  3:03 ` [PATCH v2 2/3] soundwire: Intel: add wake_enable parameter to stop_bus ops Bard Liao
2026-09-01  3:03 ` [PATCH v2 3/3] soundwire: Intel: stop sdw clock in system suspend Bard Liao
2026-09-04  7:25 ` [PATCH v2 0/3] soundwire: bus: re-enable CLOCK_STOP_MODE1 support Pierre-Louis Bossart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®