diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index ef9cb3c..3089abf 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -103,4 +103,13 @@ config CORESIGHT_CPU_DEBUG
 	  properly, please refer Documentation/trace/coresight-cpu-debug.txt
 	  for detailed description and the example for usage.
 
+config CORESIGHT_PANIC_KDUMP
+	bool "CoreSight Panic Kdump driver"
+	depends on ARM || ARM64
+	help
+	  This driver provides panic kdump functionality for CoreSight devices.
+	  When kernel panic happen Coresight device supplied callback function
+	  is to dump trace data to memory. From then on, kdump can be used to
+	  extract the trace data from kernel dump file.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 61db9dd..946fe19 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
 obj-$(CONFIG_CORESIGHT_DYNAMIC_REPLICATOR) += coresight-dynamic-replicator.o
 obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
 obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
+obj-$(CONFIG_CORESIGHT_PANIC_KDUMP) += coresight-panic-kdump.o
diff --git a/drivers/hwtracing/coresight/coresight-panic-kdump.c b/drivers/hwtracing/coresight/coresight-panic-kdump.c
new file mode 100644
index 0000000..f4589e9
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-panic-kdump.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017~2018 Linaro Limited.
+#include <linux/coresight.h>
+#include <linux/coresight-pmu.h>
+#include <linux/cpumask.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "coresight-priv.h"
+
+/**
+ * struct coresight_kdump_node - Node information for dump
+ * @source_csdev:	Handler for source coresight device
+ * @sink_csdev:		Handler for sink coresight device
+ */
+struct coresight_kdump_node {
+	struct coresight_device *source_csdev;
+	struct coresight_device *sink_csdev;
+};
+
+static DEFINE_SPINLOCK(coresight_kdump_lock);
+static struct coresight_kdump_node *coresight_kdump_nodes;
+static struct notifier_block coresight_kdump_nb;
+
+/**
+ * coresight_kdump_source - Set source dump info for specific CPU
+ * @cpu:	CPU ID
+ * @csdev:	Source device structure handler
+ * @data:	Pointer for source device metadata buffer
+ * @data_sz:	Size of source device metadata buffer
+ *
+ * This function is a helper function which is used to set/clear source device
+ * handler and metadata when the tracer is enabled; and it can be used to clear
+ * source device related info when the tracer is disabled.
+ *
+ * Returns:	0 on success, negative errno otherwise.
+ */
+int coresight_kdump_source(int cpu, struct coresight_device *csdev,
+			   char *data, unsigned int data_sz)
+{
+	struct coresight_kdump_node *node;
+	unsigned long flags;
+
+	if (!coresight_kdump_nodes)
+		return -EPROBE_DEFER;
+
+	spin_lock_irqsave(&coresight_kdump_lock, flags);
+
+	node = &coresight_kdump_nodes[cpu];
+	node->source_csdev = csdev;
+
+	csdev->kdump_buf = data;
+	csdev->kdump_buf_sz = data_sz;
+
+	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
+	return 0;
+}
+
+/**
+ * coresight_kdump_sink - Set sink device handler for specific CPU
+ * @cpu:	CPU ID
+ * @csdev:	Sink device structure handler
+ *
+ * This function is a helper function which is used to set sink device handler
+ * when the Coresight path has been enabled for specific CPU; and it can be used
+ * to clear sink device handler when the path is disabled.
+ *
+ * Returns:	0 on success, negative errno otherwise.
+ */
+int coresight_kdump_sink(int cpu, struct coresight_device *csdev)
+{
+	struct coresight_kdump_node *node;
+	unsigned long flags;
+
+	if (!coresight_kdump_nodes)
+		return -EPROBE_DEFER;
+
+	spin_lock_irqsave(&coresight_kdump_lock, flags);
+
+	node = &coresight_kdump_nodes[cpu];
+	node->sink_csdev = csdev;
+
+	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
+	return 0;
+}
+
+/**
+ * coresight_kdump_sink_cb - Invoke sink callback for specific CPU
+ * @cpu:	CPU ID
+ *
+ * This function is to invoke sink device corresponding callback.  It needs
+ * to check two cases: one case is the CPU has not been enabled for Coresight
+ * path so there totally has no trace data for the CPU, another case is the
+ * CPU shares the same sink device with other CPUs but the tracing data has
+ * been dumped by previous CPUs; it skips dump for these two cases.
+ */
+static void coresight_kdump_sink_cb(int cpu)
+{
+	struct coresight_kdump_node *node;
+	struct coresight_device *csdev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&coresight_kdump_lock, flags);
+
+	node = &coresight_kdump_nodes[cpu];
+	csdev = node->sink_csdev;
+
+	/* Path has not been enabled */
+	if (!csdev)
+		goto skip_dump;
+
+	/* Have been dumped by previous CPU */
+	if (csdev->kdump_buf)
+		goto skip_dump;
+
+	/* Invoke panic callback */
+	csdev = coresight_kdump_nodes[cpu].sink_csdev;
+	if (csdev && sink_ops(csdev)->panic_cb)
+		sink_ops(csdev)->panic_cb(csdev);
+
+skip_dump:
+	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
+}
+
+/**
+ * coresight_kdump_notify - Invoke panic dump callbacks
+ * @nb:		Pointer to notifier block
+ * @event:	Notification reason
+ * @_unused:	Pointer to notification data object, unused
+ *
+ * This function is called when panic happens to invoke dump callbacks, it takes
+ * panic CPU tracing data with high priority to firstly invoke panic CPU sink
+ * callback function, then the notifier iterates callback functions one by one
+ * for other CPUs.  If one sink device is shared among CPUs, the sink panic
+ * callback is invoked for the first traversed CPU node and other sequential
+ * CPUs are skipped.
+ *
+ * Returns:	0 on success.
+ */
+static int coresight_kdump_notify(struct notifier_block *nb,
+				  unsigned long event, void *_unused)
+{
+	int cpu, first;
+
+	/* Give panic CPU trace data with high priority */
+	first = atomic_read(&panic_cpu);
+	coresight_kdump_sink_cb(first);
+
+	/* Dump rest CPUs trace data */
+	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
+		if (cpu == first)
+			continue;
+
+		coresight_kdump_sink_cb(cpu);
+	}
+
+	return 0;
+}
+
+/**
+ * coresight_kdump_init - Coresight kdump module initialization
+ *
+ * This function allcoates dump array and register panic norifier.
+ *
+ * Returns:	0 on success, negative errno otherwise.
+ */
+static int __init coresight_kdump_init(void)
+{
+	int ret;
+
+	coresight_kdump_nodes = kmalloc_array(num_possible_cpus(),
+					      sizeof(*coresight_kdump_nodes),
+					      GFP_KERNEL);
+	if (!coresight_kdump_nodes) {
+		pr_err("%s: kmalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(coresight_kdump_nodes, 0,
+	       num_possible_cpus() * sizeof(*coresight_kdump_nodes));
+
+	coresight_kdump_nb.notifier_call = coresight_kdump_notify;
+	ret = atomic_notifier_chain_register(&panic_notifier_list,
+					     &coresight_kdump_nb);
+	if (ret) {
+		pr_err("%s: unable to register notifier: %d\n",
+		       __func__, ret);
+		kfree(coresight_kdump_nodes);
+		return ret;
+	}
+
+	return 0;
+}
+postcore_initcall(coresight_kdump_init);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index f1d0e21d..76d27d6 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -151,4 +151,16 @@ 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_KDUMP
+extern int coresight_kdump_source(int cpu, struct coresight_device *csdev,
+				  char *data, unsigned int data_sz);
+extern int coresight_kdump_sink(int cpu, struct coresight_device *csdev);
+#else
+static inline int coresight_kdump_source(int cpu,
+		struct coresight_device *csdev,
+		char *data, unsigned int data_sz) { return 0; }
+static inline void coresight_kdump_sink(int cpu,
+		struct coresight_device *csdev) { return 0; }
+#endif
+
 #endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index d950dad..89aad8d 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -171,6 +171,8 @@ struct coresight_device {
 	bool orphan;
 	bool enable;	/* true only if configured as part of a path */
 	bool activated;	/* true only if a sink is part of a path */
+	char *kdump_buf;
+	unsigned int kdump_buf_sz;
 };
 
 #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
@@ -189,6 +191,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:		hook function for panic notifier.
  */
 struct coresight_ops_sink {
 	int (*enable)(struct coresight_device *csdev, u32 mode);
@@ -205,6 +208,7 @@ struct coresight_ops_sink {
 	void (*update_buffer)(struct coresight_device *csdev,
 			      struct perf_output_handle *handle,
 			      void *sink_config);
+	void (*panic_cb)(void *data);
 };
 
 /**
