diff --git a/Documentation/ABI/testing/sysfs-driver-scsi-ufs b/Documentation/ABI/testing/sysfs-driver-scsi-ufs
new file mode 100644
index 000000000000..db500197f6a9
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-scsi-ufs
@@ -0,0 +1,8 @@
+What:		/sys/bus/pci/devices/<bus>:<vid>:<pid>.<n>/auto_hibern8
+Date:		July 2017
+Contact:	linux-scsi@vger.kernel.org
+Description:
+		This attribiute provides information on current setting of
+		Auto-Hibern8 UFS Host feature (read <unit: microseconds>)
+		and ability to set the feature on - by writing desired
+		timeout value <unit: microseconds>, or off (by writing '0').
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5e0fee6ab0db..8c6ae132bda4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -931,6 +931,31 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
 }
 
 /**
+ * ufshcd_read_auto_hibern8_state - Reads hosts auto-hibern8 feature state
+ * @hba: per adapter instance
+ */
+u32 ufshcd_read_auto_hibern8_state(struct ufs_hba *hba)
+{
+	return ufshcd_readl(hba, REG_AUTO_HIBERN8_IDLE_TIMER);
+}
+
+/**
+ * ufshcd_setup_auto_hibern8 - Sets up hosts auto-hibern8 feature
+ * @hba: per adapter instance
+ * @scale: timer scale (1/10/100us/1/10/100ms)
+ * @timer_val: value to be multipled with scale (idle timeout)
+ */
+void ufshcd_setup_auto_hibern8(struct ufs_hba *hba, u8 scale, u16 timer_val)
+{
+	u32 val = (scale << UFSHCI_AHIBERN8_SCALE_OFFSET)
+			& UFSHCI_AHIBERN8_SCALE_MASK;
+
+	val |= timer_val & UFSHCI_AHIBERN8_TIMER_MASK;
+
+	ufshcd_writel(hba, val, REG_AUTO_HIBERN8_IDLE_TIMER);
+}
+
+/**
  * ufshcd_is_devfreq_scaling_required - check if scaling is required or not
  * @hba: per adapter instance
  * @scale_up: True if scaling up and false if scaling down
@@ -6583,12 +6608,65 @@ static ssize_t spm_lvl_store(struct device *dev,
 	return ufshcd_pm_lvl_store(dev, attr, buf, count, false);
 }
 
+#define UFS_AHIBERN8_SCALE_STEP_MAGNITUDE	10
+
+static ssize_t auto_hibern8_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	u32 val;
+	unsigned long timer;
+	u8 scale;
+
+	if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT))
+		return -EOPNOTSUPP;
+
+	val = ufshcd_read_auto_hibern8_state(hba);
+	timer = val & UFSHCI_AHIBERN8_TIMER_MASK;
+	scale =	(val & UFSHCI_AHIBERN8_SCALE_MASK)
+			>> UFSHCI_AHIBERN8_SCALE_OFFSET;
+
+	for (; scale > 0; --scale)
+		timer *= UFS_AHIBERN8_SCALE_STEP_MAGNITUDE;
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", timer);
+}
+
+static ssize_t auto_hibern8_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct ufs_hba *hba = dev_get_drvdata(dev);
+	unsigned long timer;
+	u8 scale = UFSHCI_AHIBERN8_SCALE_1US;
+
+	if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT))
+		return -EOPNOTSUPP;
+
+	if (kstrtoul(buf, 0, &timer))
+		return -EINVAL;
+
+	while (timer > UFSHCI_AHIBERN8_TIMER_MASK &&
+	       scale < UFSHCI_AHIBERN8_SCALE_MAX) {
+		timer /= UFS_AHIBERN8_SCALE_STEP_MAGNITUDE;
+		++scale;
+	}
+
+	if (scale >= UFSHCI_AHIBERN8_SCALE_MAX)
+		return -EINVAL;
+
+	ufshcd_setup_auto_hibern8(hba, scale, (u16) timer);
+
+	return count;
+}
+
 static DEVICE_ATTR_RW(rpm_lvl);
 static DEVICE_ATTR_RW(spm_lvl);
+static DEVICE_ATTR_RW(auto_hibern8);
 
 static struct device_attribute *ufshcd_dev_attrs[] = {
 	&dev_attr_rpm_lvl,
 	&dev_attr_spm_lvl,
+	&dev_attr_auto_hibern8,
 	NULL,
 };
 
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index f60145d4a66e..3bf8826318b0 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -48,7 +48,7 @@ enum {
 	REG_UFS_VERSION				= 0x08,
 	REG_CONTROLLER_DEV_ID			= 0x10,
 	REG_CONTROLLER_PROD_ID			= 0x14,
-	REG_AUTO_HIBERNATE_IDLE_TIMER		= 0x18,
+	REG_AUTO_HIBERN8_IDLE_TIMER		= 0x18,
 	REG_INTERRUPT_STATUS			= 0x20,
 	REG_INTERRUPT_ENABLE			= 0x24,
 	REG_CONTROLLER_STATUS			= 0x30,
@@ -86,6 +86,7 @@ enum {
 enum {
 	MASK_TRANSFER_REQUESTS_SLOTS		= 0x0000001F,
 	MASK_TASK_MANAGEMENT_REQUEST_SLOTS	= 0x00070000,
+	MASK_AUTO_HIBERN8_SUPPORT		= 0x00800000,
 	MASK_64_ADDRESSING_SUPPORT		= 0x01000000,
 	MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT	= 0x02000000,
 	MASK_UIC_DME_TEST_MODE_SUPPORT		= 0x04000000,
@@ -136,9 +137,9 @@ enum {
 #define CONTROLLER_FATAL_ERROR			UFS_BIT(16)
 #define SYSTEM_BUS_FATAL_ERROR			UFS_BIT(17)
 
-#define UFSHCD_UIC_PWR_MASK	(UIC_HIBERNATE_ENTER |\
-				UIC_HIBERNATE_EXIT |\
-				UIC_POWER_MODE)
+#define UFSHCD_UHS_MASK		(UIC_HIBERNATE_EXIT | UIC_HIBERNATE_ENTER)
+
+#define UFSHCD_UIC_PWR_MASK	(UFSHCD_UHS_MASK | UIC_POWER_MODE)
 
 #define UFSHCD_UIC_MASK		(UIC_COMMAND_COMPL | UFSHCD_UIC_PWR_MASK)
 
@@ -428,4 +429,18 @@ struct utp_task_req_desc {
 	__le32 task_rsp_upiu[TASK_RSP_UPIU_SIZE_DWORDS];
 };
 
+enum {
+	UFSHCI_AHIBERN8_SCALE_1US	= 0,
+	UFSHCI_AHIBERN8_SCALE_10US	= 1,
+	UFSHCI_AHIBERN8_SCALE_100US	= 2,
+	UFSHCI_AHIBERN8_SCALE_1MS	= 3,
+	UFSHCI_AHIBERN8_SCALE_10MS	= 4,
+	UFSHCI_AHIBERN8_SCALE_100MS	= 5,
+	UFSHCI_AHIBERN8_SCALE_MAX,
+};
+
+#define UFSHCI_AHIBERN8_TIMER_MASK		0x03ff
+#define UFSHCI_AHIBERN8_SCALE_MASK		0x1C00
+#define UFSHCI_AHIBERN8_SCALE_OFFSET		10
+
 #endif /* End of Header */
