Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27cb80ae authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: memory_dump: Support ETB/ETR register dump"

parents 9967a150 525f1035
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -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 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
	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 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
			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;
+1 −0
Original line number Diff line number Diff line
@@ -192,6 +192,7 @@ struct tmc_drvdata {
	struct coresight_csr	*csr;
	const char		*csr_name;
	struct byte_cntr	*byte_cntr;
	bool			force_reg_dump;
};

/* Generic functions */
+9 −4
Original line number Diff line number Diff line
@@ -3898,6 +3898,8 @@ static const struct attribute_group *tpdm_attr_grps[] = {

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 @@ static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
			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(
						    "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;
}
+4 −12
Original line number Diff line number Diff line
/* 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_memory_dump {
	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 @@ int msm_dump_data_register(enum msm_dump_table_ids id,
}
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 @@ void *get_msm_dump_ptr(enum msm_dump_data_ids id)
	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 @@ static int mem_dump_probe(struct platform_device *pdev)
		} 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++;
		}
	}
+15 −3
Original line number Diff line number Diff line
/* 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 @@ enum msm_dump_data_ids {
	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 @@ struct msm_dump_entry {
	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)