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)