return -EAGAIN;
 }
 
+static int cdns_set_wait(struct sdw_cdns *cdns, int offset, u32 mask, u32 value)
+{
+       int timeout = 10;
+       u32 reg_read;
+
+       /* Wait for bit to be set */
+       do {
+               reg_read = readl(cdns->registers + offset);
+               if ((reg_read & mask) == value)
+                       return 0;
+
+               timeout--;
+               usleep_range(50, 100);
+       } while (timeout != 0);
+
+       return -ETIMEDOUT;
+}
+
 /*
  * all changes to the MCP_CONFIG, MCP_CONTROL, MCP_CMDCTRL and MCP_PHYCTRL
  * need to be confirmed with a write to MCP_CONFIG_UPDATE
 }
 EXPORT_SYMBOL(sdw_cdns_is_clock_stop);
 
+/**
+ * sdw_cdns_clock_stop: Cadence clock stop configuration routine
+ *
+ * @cdns: Cadence instance
+ * @block_wake: prevent wakes if required by the platform
+ */
+int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
+{
+       bool slave_present = false;
+       struct sdw_slave *slave;
+       int ret;
+
+       /* Check suspend status */
+       if (sdw_cdns_is_clock_stop(cdns)) {
+               dev_dbg(cdns->dev, "Clock is already stopped\n");
+               return 0;
+       }
+
+       /*
+        * For specific platforms, it is required to be able to put
+        * master into a state in which it ignores wake-up trials
+        * in clock stop state
+        */
+       if (block_wake)
+               cdns_updatel(cdns, CDNS_MCP_CONTROL,
+                            CDNS_MCP_CONTROL_BLOCK_WAKEUP,
+                            CDNS_MCP_CONTROL_BLOCK_WAKEUP);
+
+       list_for_each_entry(slave, &cdns->bus.slaves, node) {
+               if (slave->status == SDW_SLAVE_ATTACHED ||
+                   slave->status == SDW_SLAVE_ALERT) {
+                       slave_present = true;
+                       break;
+               }
+       }
+
+       /*
+        * This CMD_ACCEPT should be used when there are no devices
+        * attached on the link when entering clock stop mode. If this is
+        * not set and there is a broadcast write then the command ignored
+        * will be treated as a failure
+        */
+       if (!slave_present)
+               cdns_updatel(cdns, CDNS_MCP_CONTROL,
+                            CDNS_MCP_CONTROL_CMD_ACCEPT,
+                            CDNS_MCP_CONTROL_CMD_ACCEPT);
+       else
+               cdns_updatel(cdns, CDNS_MCP_CONTROL,
+                            CDNS_MCP_CONTROL_CMD_ACCEPT, 0);
+
+       /* commit changes */
+       ret = cdns_config_update(cdns);
+       if (ret < 0) {
+               dev_err(cdns->dev, "%s: config_update failed\n", __func__);
+               return ret;
+       }
+
+       /* Prepare slaves for clock stop */
+       ret = sdw_bus_prep_clk_stop(&cdns->bus);
+       if (ret < 0) {
+               dev_err(cdns->dev, "prepare clock stop failed %d", ret);
+               return ret;
+       }
+
+       /*
+        * Enter clock stop mode and only report errors if there are
+        * Slave devices present (ALERT or ATTACHED)
+        */
+       ret = sdw_bus_clk_stop(&cdns->bus);
+       if (ret < 0 && slave_present && ret != -ENODATA) {
+               dev_err(cdns->dev, "bus clock stop failed %d", ret);
+               return ret;
+       }
+
+       ret = cdns_set_wait(cdns, CDNS_MCP_STAT,
+                           CDNS_MCP_STAT_CLK_STOP,
+                           CDNS_MCP_STAT_CLK_STOP);
+       if (ret < 0)
+               dev_err(cdns->dev, "Clock stop failed %d\n", ret);
+
+       return ret;
+}
+EXPORT_SYMBOL(sdw_cdns_clock_stop);
+
+/**
+ * sdw_cdns_clock_restart: Cadence PM clock restart configuration routine
+ *
+ * @cdns: Cadence instance
+ * @bus_reset: context may be lost while in low power modes and the bus
+ * may require a Severe Reset and re-enumeration after a wake.
+ */
+int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset)
+{
+       int ret;
+
+       ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
+                            CDNS_MCP_CONTROL_CLK_STOP_CLR);
+       if (ret < 0) {
+               dev_err(cdns->dev, "Couldn't exit from clock stop\n");
+               return ret;
+       }
+
+       ret = cdns_set_wait(cdns, CDNS_MCP_STAT, CDNS_MCP_STAT_CLK_STOP, 0);
+       if (ret < 0) {
+               dev_err(cdns->dev, "clock stop exit failed %d\n", ret);
+               return ret;
+       }
+
+       cdns_updatel(cdns, CDNS_MCP_CONTROL,
+                    CDNS_MCP_CONTROL_BLOCK_WAKEUP, 0);
+
+       /*
+        * clear CMD_ACCEPT so that the command ignored
+        * will be treated as a failure during a broadcast write
+        */
+       cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT, 0);
+
+       if (!bus_reset) {
+
+               /* enable bus operations with clock and data */
+               cdns_updatel(cdns, CDNS_MCP_CONFIG,
+                            CDNS_MCP_CONFIG_OP,
+                            CDNS_MCP_CONFIG_OP_NORMAL);
+
+               ret = cdns_config_update(cdns);
+               if (ret < 0) {
+                       dev_err(cdns->dev, "%s: config_update failed\n", __func__);
+                       return ret;
+               }
+
+               ret = sdw_bus_exit_clk_stop(&cdns->bus);
+               if (ret < 0)
+                       dev_err(cdns->dev, "bus failed to exit clock stop %d\n", ret);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(sdw_cdns_clock_restart);
+
 /**
  * sdw_cdns_probe() - Cadence probe routine
  * @cdns: Cadence instance