diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index be734d65ea72..2abf338e8f1b 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -18,10 +18,10 @@
 #include <linux/serio.h>
 #include <linux/libps2.h>
 #include <linux/dmi.h>
+#include <linux/input/trackpoint.h>
 
 #include "psmouse.h"
 #include "alps.h"
-#include "trackpoint.h"
 
 /*
  * Definitions for ALPS version 3 and 4 command mode protocol
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index a2c9f7144864..6bc515254403 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -21,6 +21,7 @@
 #include <linux/libps2.h>
 #include <linux/mutex.h>
 #include <linux/types.h>
+#include <linux/input/trackpoint.h>
 
 #include "psmouse.h"
 #include "synaptics.h"
@@ -28,7 +29,6 @@
 #include "alps.h"
 #include "hgpk.h"
 #include "lifebook.h"
-#include "trackpoint.h"
 #include "touchkit_ps2.h"
 #include "elantech.h"
 #include "sentelic.h"
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 5f6643b69a2c..53d06d72968a 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -13,8 +13,10 @@
 #include <linux/libps2.h>
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
+#include <linux/input/trackpoint.h>
 #include "psmouse.h"
-#include "trackpoint.h"
+
+static struct trackpoint_data *trackpoint_dev;
 
 static const char * const trackpoint_variants[] = {
 	[TP_VARIANT_IBM]		= "IBM",
@@ -63,6 +65,21 @@ static int trackpoint_write(struct ps2dev *ps2dev, u8 loc, u8 val)
 	return ps2_command(ps2dev, param, MAKE_PS2_CMD(3, 0, TP_COMMAND));
 }
 
+/* Read function for TrackPoint extended registers */
+static int trackpoint_extended_read(struct ps2dev *ps2dev, u8 loc, u8 *val)
+{
+	u8 ext_param[2] = {TP_READ_MEM, loc};
+	int error;
+
+	error = ps2_command(ps2dev,
+			    ext_param, MAKE_PS2_CMD(2, 1, TP_COMMAND));
+
+	if (!error)
+		*val = ext_param[0];
+
+	return error;
+}
+
 static int trackpoint_toggle_bit(struct ps2dev *ps2dev, u8 loc, u8 mask)
 {
 	u8 param[3] = { TP_TOGGLE, loc, mask };
@@ -393,6 +410,96 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
 	return 0;
 }
 
+/* List of known incapable device PNP IDs */
+static const char * const dt_incompatible_devices[] = {
+	"LEN0304",
+	"LEN0306",
+	"LEN0317",
+	"LEN031A",
+	"LEN031B",
+	"LEN031C",
+	"LEN031D",
+};
+
+/*
+ * checks if it’s a doubletap capable device
+ * The PNP ID format eg: is "PNP: LEN030d PNP0f13".
+ */
+bool is_trackpoint_dt_capable(const char *pnp_id)
+{
+	char id[16];
+
+	/* Make sure string starts with "PNP: " */
+	if (strncmp(pnp_id, "PNP: LEN03", 10) != 0)
+		return false;
+
+	/* Extract the first word after "PNP: " */
+	if (sscanf(pnp_id + 5, "%15s", id) != 1)
+		return false;
+
+	/* Check if it's blacklisted */
+	for (size_t i = 0; i < ARRAY_SIZE(dt_incompatible_devices); ++i) {
+		if (strcmp(pnp_id, dt_incompatible_devices[i]) == 0)
+			return false;
+	}
+
+	return true;
+}
+
+/* Trackpoint doubletap status function */
+int trackpoint_doubletap_status(bool *status)
+{
+	struct trackpoint_data *tp = trackpoint_dev;
+	struct ps2dev *ps2dev = &tp->psmouse->ps2dev;
+	u8 reg_val;
+	int rc;
+
+	/* Reading the Doubletap register using extended read */
+	rc = trackpoint_extended_read(ps2dev, TP_DOUBLETAP, &reg_val);
+	if (!rc)
+		*status = reg_val & BIT(TP_DOUBLETAP_STATUS_BIT) ?
+				true : false;
+
+	return rc;
+}
+EXPORT_SYMBOL(trackpoint_doubletap_status);
+
+/* Trackpoint doubletap enable/disable function */
+int trackpoint_set_doubletap(bool enable)
+{
+	struct trackpoint_data *tp = trackpoint_dev;
+	struct ps2dev *ps2dev = &tp->psmouse->ps2dev;
+	static u8 doubletap_status;
+	u8 new_val;
+
+	if (!tp)
+		return -ENODEV;
+
+	new_val = enable ? TP_DOUBLETAP_ENABLE : TP_DOUBLETAP_DISABLE;
+
+	/* Comparing the new value paased with the existing value */
+	if (doubletap_status == new_val) {
+		pr_info("TrackPoint: Doubletap is already %s\n",
+			enable ? "enabled" : "disabled");
+		return 0;
+	}
+
+	doubletap_status = new_val;
+
+	return trackpoint_write(ps2dev, TP_DOUBLETAP, new_val);
+}
+EXPORT_SYMBOL(trackpoint_set_doubletap);
+
+/*
+ * Doubletap capability check
+ * We use PNP ID to check the capability of the device.
+ */
+bool trackpoint_doubletap_support(void)
+{
+	return trackpoint_dev->doubletap_capable;
+}
+EXPORT_SYMBOL(trackpoint_doubletap_support);
+
 int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -425,6 +532,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 	psmouse->reconnect = trackpoint_reconnect;
 	psmouse->disconnect = trackpoint_disconnect;
 
+	trackpoint_dev = psmouse->private;
+	trackpoint_dev->psmouse = psmouse;  /* Set parent reference */
+
 	if (variant_id != TP_VARIANT_IBM) {
 		/* Newer variants do not support extended button query. */
 		button_info = 0x33;
@@ -470,6 +580,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 		     psmouse->vendor, firmware_id,
 		     (button_info & 0xf0) >> 4, button_info & 0x0f);
 
+	/* Checking the doubletap Capability */
+	tp->doubletap_capable = is_trackpoint_dt_capable(ps2dev->serio->firmware_id);
+
 	return 0;
 }
 
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index e7350c9fa3aa..241c1dd5e1f4 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -71,6 +71,7 @@
 #include <linux/uaccess.h>
 #include <linux/units.h>
 #include <linux/workqueue.h>
+#include <linux/input/trackpoint.h>
 
 #include <acpi/battery.h>
 #include <acpi/video.h>
@@ -373,7 +374,8 @@ static struct {
 	u32 hotkey_poll_active:1;
 	u32 has_adaptive_kbd:1;
 	u32 kbd_lang:1;
-	u32 trackpoint_doubletap:1;
+	u32 trackpoint_doubletap_state:1;
+	u32 trackpoint_doubletap_capable:1;
 	struct quirk_entry *quirks;
 } tp_features;
 
@@ -3325,6 +3327,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 	bool radiosw_state  = false;
 	bool tabletsw_state = false;
 	int hkeyv, res, status, camera_shutter_state;
+	bool dt_state;
+	int rc;
 
 	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
 			"initializing hotkey subdriver\n");
@@ -3556,8 +3560,19 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
 	hotkey_poll_setup_safe(true);
 
-	/* Enable doubletap by default */
-	tp_features.trackpoint_doubletap = 1;
+	/* Checking doubletap status by default */
+	tp_features.trackpoint_doubletap_capable = trackpoint_doubletap_support();
+
+	if (tp_features.trackpoint_doubletap_capable) {
+		rc = trackpoint_doubletap_status(&dt_state);
+		if (rc) {
+			/* Disable if access to register fails */
+			tp_features.trackpoint_doubletap_state = false;
+			pr_info("ThinkPad ACPI: Doubletap failed to check status\n");
+		} else {
+			tp_features.trackpoint_doubletap_state = dt_state;
+		}
+	}
 
 	return 0;
 }
@@ -3862,9 +3877,7 @@ static bool hotkey_notify_8xxx(const u32 hkey, bool *send_acpi_ev)
 {
 	switch (hkey) {
 	case TP_HKEY_EV_TRACK_DOUBLETAP:
-		if (tp_features.trackpoint_doubletap)
-			tpacpi_input_send_key(hkey, send_acpi_ev);
-
+		*send_acpi_ev = true;
 		return true;
 	default:
 		return false;
@@ -10738,6 +10751,101 @@ static struct ibm_struct  dytc_profile_driver_data = {
 	.exit = dytc_profile_exit,
 };
 
+/************************************************************************
+ * Trackpoint Doubletap Interface
+ *
+ * Control/Monitoring of Trackpoint Doubletap from
+ * /sys/devices/platform/thinkpad_acpi/tp_doubletap
+ */
+
+static ssize_t tp_doubletap_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	bool status;
+
+	if (!trackpoint_doubletap_status(&status))
+		return sysfs_emit(buf, "access error\n");
+
+	return sysfs_emit(buf, "%s\n", status ? "enabled" : "disabled");
+}
+
+static ssize_t tp_doubletap_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	if (sysfs_streq(buf, "enable")) {
+		/* enabling the doubletap here */
+		if (!trackpoint_set_doubletap(true))
+			tp_features.trackpoint_doubletap_state = true;
+	} else if (sysfs_streq(buf, "disable")) {
+		/* disabling the doubletap here */
+		if (!trackpoint_set_doubletap(false))
+			tp_features.trackpoint_doubletap_state = false;
+	} else {
+		pr_err("ThinkPad ACPI: thinkpad_acpi: Invalid value '%s' for tp_doubletap\n", buf);
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static umode_t tp_doubletap_is_visible(struct kobject *kobj, struct attribute *attr, int index);
+
+static DEVICE_ATTR_RW(tp_doubletap);
+
+static struct attribute *tp_doubletap_attrs[] = {
+	&dev_attr_tp_doubletap.attr,
+	NULL
+};
+
+static const struct attribute_group tp_doubletap_attr_group = {
+	.attrs = tp_doubletap_attrs,
+	.is_visible = tp_doubletap_is_visible,
+};
+
+static umode_t tp_doubletap_is_visible(struct kobject *kobj, struct attribute *attr, int index)
+{
+	/* Only show the attribute if the TrackPoint doubletap is supported */
+	tp_features.trackpoint_doubletap_capable = trackpoint_doubletap_support();
+	if (!tp_features.trackpoint_doubletap_capable)
+		return 0;
+
+	pr_info("ThinkPad ACPI: TrackPoint doubletap sysfs is visible\n");
+
+	return attr->mode;
+}
+
+static struct delayed_work tp_doubletap_work;
+
+static void tp_doubletap_work_func(struct work_struct *work)
+{
+	if (!trackpoint_doubletap_support()) {
+		pr_info("TrackPoint doubletap not supported yet, rechecking later\n");
+		schedule_delayed_work(&tp_doubletap_work, msecs_to_jiffies(2000));
+		return;
+	}
+
+	if (sysfs_create_group(&tpacpi_pdev->dev.kobj, &tp_doubletap_attr_group) == 0)
+		pr_info("TrackPoint doubletap sysfs group created\n");
+	else
+		pr_err("Failed to create TrackPoint doubletap sysfs group\n");
+}
+
+static int __init tp_doubletap_init(struct ibm_init_struct *iibm)
+{
+	INIT_DELAYED_WORK(&tp_doubletap_work, tp_doubletap_work_func);
+	schedule_delayed_work(&tp_doubletap_work, msecs_to_jiffies(1000));
+
+	return 0;
+}
+
+static void tp_doubletap_exit(void)
+{
+	device_remove_file(&tpacpi_pdev->dev, &dev_attr_tp_doubletap);
+}
+
+static struct ibm_struct tp_doubletap_driver_data = {
+	.name = "tp_doubletap",
+	.exit =  tp_doubletap_exit,
+};
+
 /*************************************************************************
  * Keyboard language interface
  */
@@ -11192,7 +11300,7 @@ static struct platform_driver tpacpi_hwmon_pdriver = {
  */
 static bool tpacpi_driver_event(const unsigned int hkey_event)
 {
-	int camera_shutter_state;
+	int camera_shutter_state, rc;
 
 	switch (hkey_event) {
 	case TP_HKEY_EV_BRGHT_UP:
@@ -11284,8 +11392,30 @@ static bool tpacpi_driver_event(const unsigned int hkey_event)
 		mutex_unlock(&tpacpi_inputdev_send_mutex);
 		return true;
 	case TP_HKEY_EV_DOUBLETAP_TOGGLE:
-		tp_features.trackpoint_doubletap = !tp_features.trackpoint_doubletap;
-		return true;
+		if (tp_features.trackpoint_doubletap_capable) {
+			/* Togging the register value */
+			rc = trackpoint_set_doubletap(!tp_features.trackpoint_doubletap_state);
+
+			if (rc) {
+				pr_err("ThinkPad ACPI: Trackpoint doubletap toggle failed\n");
+			} else {
+				/* Toggling the Doubletap Enable/Disable */
+				tp_features.trackpoint_doubletap_state =
+					!tp_features.trackpoint_doubletap_state;
+				pr_info("ThinkPad ACPI: Trackpoint doubletap is %s\n",
+					tp_features.trackpoint_doubletap_state ?
+					"enabled" : "disabled");
+
+				return true;
+			}
+		}
+
+		/*
+		 * Suppress the event if Doubletap is not supported
+		 * or if the trackpoint_set_doubletap() is failing
+		 */
+		return false;
+
 	case TP_HKEY_EV_PROFILE_TOGGLE:
 	case TP_HKEY_EV_PROFILE_TOGGLE2:
 		platform_profile_cycle();
@@ -11751,6 +11881,11 @@ static struct ibm_init_struct ibms_init[] __initdata = {
 		.init = auxmac_init,
 		.data = &auxmac_data,
 	},
+	{
+		.init = tp_doubletap_init,
+		.data = &tp_doubletap_driver_data
+	},
+
 };
 
 static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
diff --git a/drivers/input/mouse/trackpoint.h b/include/linux/input/trackpoint.h
similarity index 90%
rename from drivers/input/mouse/trackpoint.h
rename to include/linux/input/trackpoint.h
index eb5412904fe0..a8165becabe6 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/include/linux/input/trackpoint.h
@@ -69,6 +69,8 @@
 					/* (how hard it is to drag */
 					/* with Z-axis pressed) */
 
+#define TP_DOUBLETAP		0x58	/* TrackPoint doubletap register */
+
 #define TP_MINDRAG		0x59	/* Minimum amount of force needed */
 					/* to trigger dragging */
 
@@ -139,6 +141,12 @@
 #define TP_DEF_TWOHAND		0x00
 #define TP_DEF_SOURCE_TAG	0x00
 
+/* Doubletap register values */
+#define TP_DOUBLETAP_ENABLE	0xFF	/* Enable value */
+#define TP_DOUBLETAP_DISABLE	0xFE	/* Disable value */
+
+#define TP_DOUBLETAP_STATUS_BIT 0	/* 0th bit defines enable/disable */
+
 #define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
 
 struct trackpoint_data {
@@ -150,13 +158,21 @@ struct trackpoint_data {
 	u8 thresh, upthresh;
 	u8 ztime, jenks;
 	u8 drift_time;
+	bool doubletap_capable;
 
 	/* toggles */
 	bool press_to_select;
 	bool skipback;
 	bool ext_dev;
+
+	struct psmouse *psmouse;  /* Parent device */
 };
 
 int trackpoint_detect(struct psmouse *psmouse, bool set_properties);
 
+int trackpoint_doubletap_status(bool *status);
+int trackpoint_set_doubletap(bool enable);
+bool trackpoint_doubletap_support(void);
+bool is_trackpoint_dt_capable(const char *device_id);
+
 #endif /* _TRACKPOINT_H */
