diff --git a/Documentation/ABI/testing/sysfs-bus-mhi b/Documentation/ABI/testing/sysfs-bus-mhi
new file mode 100644
index 0000000..8b06404
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-mhi
@@ -0,0 +1,10 @@
+What:           /sys/bus/mhi/devices/<controller device>/soc_reset
+Date:		May 2020
+KernelVersion:  5.8
+Contact:        linux-arm-msm@vger.kernel.org
+Description:
+                Initiates a SoC reset on the MHI controller.  A SoC reset is
+		a reset of last resort, and will require a complete re-init.
+		This can be useful as a method of recovery if the device is
+		non-responsive, or as a means of loading new firmware as a
+		system administration task.
diff --git a/MAINTAINERS b/MAINTAINERS
index e64e5db..f38edac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11018,6 +11018,7 @@ M:	Hemant Kumar <hemantk@codeaurora.org>
 L:	linux-arm-msm@vger.kernel.org
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git
+F:	Documentation/ABI/testing/sysfs-bus-mhi
 F:	Documentation/mhi/
 F:	drivers/bus/mhi/
 F:	include/linux/mhi.h
diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/core/boot.c
index ebad5eb..ebb8e00 100644
--- a/drivers/bus/mhi/core/boot.c
+++ b/drivers/bus/mhi/core/boot.c
@@ -112,9 +112,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
 			/* Hardware reset so force device to enter RDDM */
 			dev_dbg(dev,
 				"Did not enter RDDM, do a host req reset\n");
-			mhi_write_reg(mhi_cntrl, mhi_cntrl->regs,
-				      MHI_SOC_RESET_REQ_OFFSET,
-				      MHI_SOC_RESET_REQ);
+			mhi_do_soc_reset(mhi_cntrl);
 			udelay(delayus);
 		}
 
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index eb2ab05..198afe3 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -799,6 +799,39 @@ static int parse_config(struct mhi_controller *mhi_cntrl,
 	return ret;
 }
 
+static ssize_t soc_reset_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct mhi_device *mhi_dev = container_of(dev, struct mhi_device, dev);
+	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+	unsigned long value;
+	int rc;
+
+	rc = kstrtoul(buf, 0, &value);
+
+	if (rc) {
+		count = -EINVAL;
+		goto out;
+	}
+
+	mhi_do_soc_reset(mhi_cntrl);
+
+out:
+	return count;
+}
+
+DEVICE_ATTR_WO(soc_reset);
+
+static struct attribute *reset_attrs[] = {
+	&dev_attr_soc_reset.attr,
+	NULL,
+};
+
+static struct attribute_group cntrl_soc_reset_group = {
+	.attrs = reset_attrs,
+};
+
 int mhi_register_controller(struct mhi_controller *mhi_cntrl,
 			    struct mhi_controller_config *config)
 {
@@ -909,8 +942,15 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
 
 	mhi_cntrl->mhi_dev = mhi_dev;
 
+	ret = device_add_group(&mhi_dev->dev, &cntrl_soc_reset_group);
+	if (ret)
+		goto error_add_reset;
+
 	return 0;
 
+error_add_reset:
+	device_del(&mhi_dev->dev);
+
 error_add_dev:
 	put_device(&mhi_dev->dev);
 
diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
index 0ac0643..ec7c3a0 100644
--- a/drivers/bus/mhi/core/main.c
+++ b/drivers/bus/mhi/core/main.c
@@ -1519,3 +1519,12 @@ int mhi_poll(struct mhi_device *mhi_dev, u32 budget)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mhi_poll);
+
+void mhi_do_soc_reset(struct mhi_controller *mhi_cntrl)
+{
+	if (mhi_cntrl)
+		mhi_write_reg(mhi_cntrl, mhi_cntrl->regs,
+			      MHI_SOC_RESET_REQ_OFFSET,
+			      MHI_SOC_RESET_REQ);
+}
+EXPORT_SYMBOL_GPL(mhi_do_soc_reset);
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 3d7c3c2..dcdacf2 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -701,4 +701,10 @@ int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir,
 int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
 		  struct sk_buff *skb, size_t len, enum mhi_flags mflags);
 
+/**
+ * mhi_do_soc_reset - Perform a SoC reset to the specified controller
+ * @mhi_cntrl: Controller to reset
+ */
+void mhi_do_soc_reset(struct mhi_controller *mhi_cntrl);
+
 #endif /* _MHI_H_ */
