Merge "soc: qcom: memory_dump: Support ETB/ETR register dump"
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 6597fd6..c9c22d0 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -28,10 +28,13 @@
 #include <linux/of.h>
 #include <linux/coresight.h>
 #include <linux/amba/bus.h>
+#include <soc/qcom/memory_dump.h>
 
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
 
+#define TMC_REG_DUMP_MAGIC 0x42445953
+
 void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
 	/* Ensure formatter, unformatter and hardware fifo are empty */
@@ -61,11 +64,85 @@
 	tmc_wait_for_tmcready(drvdata);
 }
 
+static void __tmc_reg_dump(struct tmc_drvdata *drvdata)
+{
+	struct dump_vaddr_entry *dump_entry;
+	struct msm_dump_data *dump_data;
+	uint32_t *reg_buf;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		dump_entry = get_msm_dump_ptr(MSM_DUMP_DATA_TMC_ETR_REG);
+		dev_dbg(drvdata->dev, "%s: TMC ETR dump entry ptr is %pK\n",
+			__func__, dump_entry);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETB ||
+			drvdata->config_type == TMC_CONFIG_TYPE_ETF) {
+		dump_entry = get_msm_dump_ptr(MSM_DUMP_DATA_TMC_ETF_REG);
+		dev_dbg(drvdata->dev, "%s: TMC ETF dump entry ptr is %pK\n",
+			__func__, dump_entry);
+	} else
+		return;
+
+	if (dump_entry == NULL)
+		return;
+
+	reg_buf = (uint32_t *)(dump_entry->dump_vaddr);
+	dump_data = dump_entry->dump_data_vaddr;
+
+	if (reg_buf == NULL || dump_data == NULL)
+		return;
+
+	dev_dbg(drvdata->dev, "%s: TMC dump reg ptr is %pK, dump_data is %pK\n",
+		__func__, reg_buf, dump_data);
+
+	reg_buf[1] = readl_relaxed(drvdata->base + TMC_RSZ);
+	reg_buf[3] = readl_relaxed(drvdata->base + TMC_STS);
+	reg_buf[5] = readl_relaxed(drvdata->base + TMC_RRP);
+	reg_buf[6] = readl_relaxed(drvdata->base + TMC_RWP);
+	reg_buf[7] = readl_relaxed(drvdata->base + TMC_TRG);
+	reg_buf[8] = readl_relaxed(drvdata->base + TMC_CTL);
+	reg_buf[10] = readl_relaxed(drvdata->base + TMC_MODE);
+	reg_buf[11] = readl_relaxed(drvdata->base + TMC_LBUFLEVEL);
+	reg_buf[12] = readl_relaxed(drvdata->base + TMC_CBUFLEVEL);
+	reg_buf[13] = readl_relaxed(drvdata->base + TMC_BUFWM);
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		reg_buf[14] = readl_relaxed(drvdata->base + TMC_RRPHI);
+		reg_buf[15] = readl_relaxed(drvdata->base + TMC_RWPHI);
+		reg_buf[68] = readl_relaxed(drvdata->base + TMC_AXICTL);
+		reg_buf[70] = readl_relaxed(drvdata->base + TMC_DBALO);
+		reg_buf[71] = readl_relaxed(drvdata->base + TMC_DBAHI);
+	}
+	reg_buf[192] = readl_relaxed(drvdata->base + TMC_FFSR);
+	reg_buf[193] = readl_relaxed(drvdata->base + TMC_FFCR);
+	reg_buf[194] = readl_relaxed(drvdata->base + TMC_PSCR);
+	reg_buf[1000] = readl_relaxed(drvdata->base + CORESIGHT_CLAIMSET);
+	reg_buf[1001] = readl_relaxed(drvdata->base + CORESIGHT_CLAIMCLR);
+	reg_buf[1005] = readl_relaxed(drvdata->base + CORESIGHT_LSR);
+	reg_buf[1006] = readl_relaxed(drvdata->base + CORESIGHT_AUTHSTATUS);
+	reg_buf[1010] = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	reg_buf[1011] = readl_relaxed(drvdata->base + CORESIGHT_DEVTYPE);
+	reg_buf[1012] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR4);
+	reg_buf[1013] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR5);
+	reg_buf[1014] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR6);
+	reg_buf[1015] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR7);
+	reg_buf[1016] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0);
+	reg_buf[1017] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR1);
+	reg_buf[1018] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR2);
+	reg_buf[1019] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR3);
+	reg_buf[1020] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR0);
+	reg_buf[1021] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR1);
+	reg_buf[1022] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR2);
+	reg_buf[1023] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR3);
+
+	dump_data->magic = TMC_REG_DUMP_MAGIC;
+}
+
 void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
 	drvdata->enable = true;
 	drvdata->sticky_enable = true;
 	writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
+	if (drvdata->force_reg_dump)
+		__tmc_reg_dump(drvdata);
 }
 
 void tmc_disable_hw(struct tmc_drvdata *drvdata)
@@ -626,6 +703,8 @@
 			return -EPROBE_DEFER;
 		}
 	}
+	if (of_property_read_bool(drvdata->dev->of_node, "qcom,force-reg-dump"))
+		drvdata->force_reg_dump = true;
 
 	desc.pdata = pdata;
 	desc.dev = dev;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 0a271e5..2372be6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -192,6 +192,7 @@
 	struct coresight_csr	*csr;
 	const char		*csr_name;
 	struct byte_cntr	*byte_cntr;
+	bool			force_reg_dump;
 };
 
 /* Generic functions */
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 0bc9439..7cdb459 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -3898,6 +3898,8 @@
 
 static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
 {
+	struct dump_vaddr_entry *dump_entry;
+
 	if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
 		drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
 					    GFP_KERNEL);
@@ -3939,10 +3941,13 @@
 			return -ENOMEM;
 
 		if (of_property_read_bool(drvdata->dev->of_node,
-						    "qcom,dump-enable"))
-			drvdata->cmb->mcmb->mcmb_msr_dump_ptr =
-				(uint32_t *)get_msm_dump_ptr(
-						MSM_DUMP_DATA_TPDM_SWAO_MCMB);
+						    "qcom,dump-enable")) {
+			dump_entry = get_msm_dump_ptr(
+				MSM_DUMP_DATA_TPDM_SWAO_MCMB);
+			if (dump_entry)
+				drvdata->cmb->mcmb->mcmb_msr_dump_ptr =
+					(uint32_t *)(dump_entry->dump_vaddr);
+		}
 	}
 	return 0;
 }
diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c
index b76fe86..5912ff2 100644
--- a/drivers/soc/qcom/memory_dump_v2.c
+++ b/drivers/soc/qcom/memory_dump_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,15 +39,6 @@
 	struct msm_dump_table *table;
 };
 
-struct dump_vaddr_entry {
-	uint32_t id;
-	void *dump_vaddr;
-};
-
-struct msm_mem_dump_vaddr_tbl {
-	uint8_t num_node;
-	struct dump_vaddr_entry *entries;
-};
 
 static struct msm_memory_dump memdump;
 static struct msm_mem_dump_vaddr_tbl vaddr_tbl;
@@ -156,7 +147,7 @@
 }
 EXPORT_SYMBOL(msm_dump_data_register);
 
-void *get_msm_dump_ptr(enum msm_dump_data_ids id)
+struct dump_vaddr_entry *get_msm_dump_ptr(enum msm_dump_data_ids id)
 {
 	int i;
 
@@ -174,7 +165,7 @@
 	if (i == vaddr_tbl.num_node)
 		return NULL;
 
-	return (void *)vaddr_tbl.entries[i].dump_vaddr;
+	return &vaddr_tbl.entries[i];
 }
 EXPORT_SYMBOL(get_msm_dump_ptr);
 
@@ -333,6 +324,7 @@
 		} else if (vaddr_tbl.entries) {
 			vaddr_tbl.entries[i].id = id;
 			vaddr_tbl.entries[i].dump_vaddr = dump_vaddr;
+			vaddr_tbl.entries[i].dump_data_vaddr = dump_data;
 			i++;
 		}
 	}
diff --git a/include/soc/qcom/memory_dump.h b/include/soc/qcom/memory_dump.h
index 5bc50b5..a962a16 100644
--- a/include/soc/qcom/memory_dump.h
+++ b/include/soc/qcom/memory_dump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -87,7 +87,8 @@
 	MSM_DUMP_DATA_POWER_REGS = 0xED,
 	MSM_DUMP_DATA_TMC_ETF = 0xF0,
 	MSM_DUMP_DATA_TPDM_SWAO_MCMB = 0xF2,
-	MSM_DUMP_DATA_TMC_REG = 0x100,
+	MSM_DUMP_DATA_TMC_ETR_REG = 0x100,
+	MSM_DUMP_DATA_TMC_ETF_REG = 0x101,
 	MSM_DUMP_DATA_LOG_BUF = 0x110,
 	MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111,
 	MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130,
@@ -121,11 +122,22 @@
 	uint64_t addr;
 };
 
+struct dump_vaddr_entry {
+	uint32_t id;
+	void *dump_vaddr;
+	struct msm_dump_data *dump_data_vaddr;
+};
+
+struct msm_mem_dump_vaddr_tbl {
+	uint8_t num_node;
+	struct dump_vaddr_entry *entries;
+};
+
 #ifdef CONFIG_QCOM_MEMORY_DUMP_V2
 extern int msm_dump_data_register(enum msm_dump_table_ids id,
 				  struct msm_dump_entry *entry);
 
-extern void *get_msm_dump_ptr(enum msm_dump_data_ids id);
+extern struct dump_vaddr_entry *get_msm_dump_ptr(enum msm_dump_data_ids id);
 #else
 static inline int msm_dump_data_register(enum msm_dump_table_ids id,
 					 struct msm_dump_entry *entry)