diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index d01b2e5c8c44..7488e71f159f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -4495,7 +4495,7 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
 
 	spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags);
 
-	if (ctlr->bus_lock_flag)
+	if (ctlr->bus_lock_flag || ctlr->offload_hw_trigger_mode_enabled)
 		ret = -EBUSY;
 	else
 		ret = __spi_async(spi, message);
@@ -4638,6 +4638,12 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
 	int ret;
 
 	mutex_lock(&spi->controller->bus_lock_mutex);
+
+	if (spi->controller->offload_hw_trigger_mode_enabled) {
+		mutex_unlock(&spi->controller->bus_lock_mutex);
+		return -EBUSY;
+	}
+
 	ret = __spi_sync(spi, message);
 	mutex_unlock(&spi->controller->bus_lock_mutex);
 
@@ -4680,7 +4686,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked);
  * exclusive access is over. Data transfer must be done by spi_sync_locked
  * and spi_async_locked calls when the SPI bus lock is held.
  *
- * Return: always zero.
+ * Return: 0 on success, -EBUSY if the bus is reserved by offload hardware.
  */
 int spi_bus_lock(struct spi_controller *ctlr)
 {
@@ -4688,6 +4694,11 @@ int spi_bus_lock(struct spi_controller *ctlr)
 
 	mutex_lock(&ctlr->bus_lock_mutex);
 
+	if (ctlr->offload_hw_trigger_mode_enabled) {
+		mutex_unlock(&ctlr->bus_lock_mutex);
+		return -EBUSY;
+	}
+
 	spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags);
 	ctlr->bus_lock_flag = 1;
 	spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
@@ -4874,6 +4885,85 @@ void spi_offload_unprepare(struct spi_device *spi, const char *id,
 }
 EXPORT_SYMBOL_GPL(spi_offload_unprepare);
 
+/**
+ * spi_offload_hw_trigger_mode_enable - enables hardware trigger for offload
+ * @spi:	The spi device to use for the transfers.
+ * @id:		Function ID if SPI device uses more than one offload or NULL.
+ *
+ * There must be a prepared offload instance with the specified ID (i.e.
+ * spi_offload_prepare() was called with the same ID). This will also reserve
+ * the bus for exclusive use by the offload instance until the hardware trigger
+ * is disabled. Any other attempts to send a transfer or lock the bus will fail
+ * with -EBUSY during this time.
+ *
+ * Calls must be balanced with spi_offload_hw_trigger_mode_disable().
+ *
+ * Context: can sleep
+ * Return: 0 on success, else a negative error code.
+ */
+int spi_offload_hw_trigger_mode_enable(struct spi_device *spi, const char *id)
+{
+	struct spi_controller *ctlr = spi->controller;
+	unsigned long flags;
+	int ret;
+
+	if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_mode_enable)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&ctlr->bus_lock_mutex);
+
+	if (ctlr->offload_hw_trigger_mode_enabled) {
+		mutex_unlock(&ctlr->bus_lock_mutex);
+		return -EBUSY;
+	}
+
+	spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags);
+	ctlr->offload_hw_trigger_mode_enabled = true;
+	spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
+
+	/* TODO: how to wait for empty message queue? */
+
+	mutex_lock(&ctlr->io_mutex);
+	ret = ctlr->offload_ops->hw_trigger_mode_enable(spi, id);
+	mutex_unlock(&ctlr->io_mutex);
+
+	if (ret) {
+		ctlr->offload_hw_trigger_mode_enabled = false;
+		mutex_unlock(&ctlr->bus_lock_mutex);
+		return ret;
+	}
+
+	mutex_unlock(&ctlr->bus_lock_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_offload_hw_trigger_mode_enable);
+
+/**
+ * spi_offload_hw_trigger_mode_disable - disables hardware trigger for offload
+ * @spi:	The same SPI device passed to spi_offload_hw_trigger_mode_enable()
+ * @id:		The same ID device passed to spi_offload_hw_trigger_mode_enable()
+ *
+ * Disables the hardware trigger for the offload instance with the specified ID
+ * and releases the bus for use by other clients.
+ *
+ * Context: can sleep
+ */
+void spi_offload_hw_trigger_mode_disable(struct spi_device *spi, const char *id)
+{
+	struct spi_controller *ctlr = spi->controller;
+
+	if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_mode_disable)
+		return;
+
+	mutex_lock(&ctlr->io_mutex);
+	ctlr->offload_ops->hw_trigger_mode_disable(spi, id);
+	mutex_unlock(&ctlr->io_mutex);
+
+	ctlr->offload_hw_trigger_mode_enabled = false;
+}
+EXPORT_SYMBOL_GPL(spi_offload_hw_trigger_mode_disable);
+
 /*-------------------------------------------------------------------------*/
 
 #if IS_ENABLED(CONFIG_OF_DYNAMIC)
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 4998b48ea7fd..685548883004 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -634,6 +634,9 @@ struct spi_controller {
 	/* Flag indicating that the SPI bus is locked for exclusive use */
 	bool			bus_lock_flag;
 
+	/* Flag indicating the bus is reserved for use by hardware trigger */
+	bool			offload_hw_trigger_mode_enabled;
+
 	/*
 	 * Setup mode and clock, etc (SPI driver may call many times).
 	 *
@@ -1604,12 +1607,49 @@ struct spi_controller_offload_ops {
 	 * @unprepare: Required callback to release any resources used by prepare().
 	 */
 	void (*unprepare)(struct spi_device *spi, const char *id);
+	/**
+	 * @hw_trigger_mode_enable: Optional callback to enable the hardware
+	 * trigger for the given offload instance.
+	 */
+	int (*hw_trigger_mode_enable)(struct spi_device *spi, const char *id);
+	/**
+	 * @hw_trigger_mode_disable: Optional callback to disable the hardware
+	 * trigger for the given offload instance.
+	 */
+	void (*hw_trigger_mode_disable)(struct spi_device *spi, const char *id);
+	/**
+	 * @hw_trigger_get_clk: Optional callback for controllers that have a
+	 * hardware offload trigger that is connected to a clock.
+	 */
+	struct clk *(*hw_trigger_get_clk)(struct spi_device *spi, const char *id);
 };
 
 extern int spi_offload_prepare(struct spi_device *spi, const char *id,
 			       struct spi_message *msg);
 extern void spi_offload_unprepare(struct spi_device *spi, const char *id,
 				  struct spi_message *msg);
+extern int spi_offload_hw_trigger_mode_enable(struct spi_device *spi, const char *id);
+extern void spi_offload_hw_trigger_mode_disable(struct spi_device *spi, const char *id);
+
+/**
+ * spi_offload_hw_trigger_get_clk - Get the clock for the offload trigger
+ * @spi: SPI device
+ * @id: Function ID if SPI device uses more than one offload or NULL.
+ *
+ * The caller is responsible for calling clk_put() on the returned clock.
+ *
+ * Return: The clock for the offload trigger, or negative error code
+ */
+static inline
+struct clk *spi_offload_hw_trigger_get_clk(struct spi_device *spi, const char *id)
+{
+	struct spi_controller *ctlr = spi->controller;
+
+	if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_get_clk)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return ctlr->offload_ops->hw_trigger_get_clk(spi, id);
+}
 
 /*---------------------------------------------------------------------------*/
 
