diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 8d55d6d..8890023 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -103,4 +103,14 @@ config CORESIGHT_CPU_DEBUG
 	  properly, please refer Documentation/trace/coresight-cpu-debug.txt
 	  for detailed description and the example for usage.
 
+config CORESIGHT_PANIC_DUMP
+	bool "CoreSight Panic Dump driver"
+	depends on ARM || ARM64
+	depends on CORESIGHT_LINKS_AND_SINKS
+	help
+	  This driver provides panic dump functionality for coresight
+	  devices; when kernel panic happens, we can use callback functions
+	  to save trace data to memory. Finally can rely on kdump to extract
+	  out these trace data from kernel dump file.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 433d590..0ac3216 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
 obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
 obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
 obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
+obj-$(CONFIG_CORESIGHT_PANIC_DUMP) += coresight-panic-dump.o
diff --git a/drivers/hwtracing/coresight/coresight-panic-dump.c b/drivers/hwtracing/coresight/coresight-panic-dump.c
new file mode 100644
index 0000000..23869ff
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-panic-dump.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright(C) 2017 Linaro Limited. All rights reserved.
+ * Author: Leo Yan <leo.yan@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include <linux/coresight-pmu.h>
+#include <linux/cpumask.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+static DEFINE_MUTEX(coresight_panic_lock);
+static struct list_head coresight_panic_list;
+static struct notifier_block coresight_panic_nb;
+
+struct coresight_panic_node {
+	char *name;
+	struct coresight_device *csdev;
+	struct list_head list;
+};
+
+static int coresight_panic_notify(struct notifier_block *nb,
+				  unsigned long mode, void *_unused)
+{
+	int ret = 0, err;
+	struct coresight_panic_node *node;
+	struct coresight_device *csdev;
+	u32 type;
+
+	mutex_lock(&coresight_panic_lock);
+
+	list_for_each_entry(node, &coresight_panic_list, list) {
+		csdev = node->csdev;
+		type = csdev->type;
+
+		dev_info(&csdev->dev, "invoke panic dump...\n");
+
+		switch (type) {
+		case CORESIGHT_DEV_TYPE_SINK:
+		case CORESIGHT_DEV_TYPE_LINKSINK:
+			err = sink_ops(csdev)->panic_cb(csdev);
+			if (err)
+				ret = err;
+			break;
+		default:
+			dev_err(&csdev->dev,
+				"Unsupported type for panic dump\n");
+			break;
+		}
+	}
+
+	mutex_unlock(&coresight_panic_lock);
+	return ret;
+}
+
+int coresight_add_panic_cb(struct coresight_device *csdev)
+{
+	struct coresight_panic_node *node;
+
+	node = kzalloc(sizeof(struct coresight_panic_node), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	node->name = kstrndup(dev_name(&csdev->dev), 16, GFP_KERNEL);
+	if (!node->name) {
+		kfree(node);
+		return -ENOMEM;
+	}
+	node->csdev = csdev;
+
+	mutex_lock(&coresight_panic_lock);
+	list_add_tail(&node->list, &coresight_panic_list);
+	mutex_unlock(&coresight_panic_lock);
+
+	return 0;
+}
+
+void coresight_del_panic_cb(struct coresight_device *csdev)
+{
+	struct coresight_panic_node *node;
+
+	mutex_lock(&coresight_panic_lock);
+
+	list_for_each_entry(node, &coresight_panic_list, list) {
+		if (node->csdev == csdev) {
+			list_del(&node->list);
+			kfree(node->name);
+			kfree(node);
+			mutex_unlock(&coresight_panic_lock);
+			return;
+		}
+	}
+
+	dev_err(&csdev->dev, "Failed to find panic node.\n");
+	mutex_unlock(&coresight_panic_lock);
+}
+
+static int __init coresight_panic_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&coresight_panic_list);
+
+	coresight_panic_nb.notifier_call = coresight_panic_notify;
+	ret = atomic_notifier_chain_register(&panic_notifier_list,
+					     &coresight_panic_nb);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+subsys_initcall(coresight_panic_init);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 5f662d8..e6ed3e9 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -122,4 +122,14 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
 static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
 #endif
 
+#ifdef CONFIG_CORESIGHT_PANIC_DUMP
+extern int coresight_add_panic_cb(struct coresight_device *csdev);
+extern void coresight_del_panic_cb(struct coresight_device *csdev);
+#else
+static inline int coresight_add_panic_cb(struct coresight_device *csdev)
+{ return 0; }
+static inline void coresight_del_panic_cb(struct coresight_device *csdev)
+{ return; }
+#endif
+
 #endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d950dad..31fcaeb 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -189,6 +189,7 @@ struct coresight_device {
  * @set_buffer:		initialises buffer mechanic before a trace session.
  * @reset_buffer:	finalises buffer mechanic after a trace session.
  * @update_buffer:	update buffer pointers after a trace session.
+ * @panic_cb:		hooks callback function for panic notifier.
  */
 struct coresight_ops_sink {
 	int (*enable)(struct coresight_device *csdev, u32 mode);
@@ -205,6 +206,7 @@ struct coresight_ops_sink {
 	void (*update_buffer)(struct coresight_device *csdev,
 			      struct perf_output_handle *handle,
 			      void *sink_config);
+	int (*panic_cb)(struct coresight_device *csdev);
 };
 
 /**
