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

Commit 26fb8ab7 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents e3f130c7 157fb304
Loading
Loading
Loading
Loading
+80 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2012,2017-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012,2017-2019,2021, The Linux Foundation. All rights reserved.
 *
 * Description: CoreSight Trace Memory Controller driver
 */
@@ -23,10 +23,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 */
@@ -56,10 +59,84 @@ 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;
	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)
@@ -650,6 +727,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
@@ -268,6 +268,7 @@ struct tmc_drvdata {
	struct idr		idr;
	struct mutex		idr_mutex;
	struct etr_buf		*perf_buf;
	bool			force_reg_dump;
};

struct etr_buf_operations {
+39 −1
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ struct msm_memory_dump {
};

static struct msm_memory_dump memdump;
static struct msm_mem_dump_vaddr_tbl vaddr_tbl;

/**
 * update_reg_dump_table - update the register dump table
@@ -699,6 +700,28 @@ int msm_dump_data_register_nominidump(enum msm_dump_table_ids id,
}
EXPORT_SYMBOL(msm_dump_data_register_nominidump);

struct dump_vaddr_entry *get_msm_dump_ptr(enum msm_dump_data_ids id)
{
	int i;

	if (!vaddr_tbl.entries)
		return NULL;

	if (id > MSM_DUMP_DATA_MAX)
		return NULL;

	for (i = 0; i < vaddr_tbl.num_node; i++) {
		if (vaddr_tbl.entries[i].id == id)
			break;
	}

	if (i == vaddr_tbl.num_node)
		return NULL;

	return &vaddr_tbl.entries[i];
}
EXPORT_SYMBOL(get_msm_dump_ptr);

#define MSM_DUMP_TOTAL_SIZE_OFFSET	0x724
static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr,
					size_t size)
@@ -787,6 +810,14 @@ static int mem_dump_alloc(struct platform_device *pdev)
	uint32_t ns_vmids[] = {VMID_HLOS};
	uint32_t ns_vm_perms[] = {PERM_READ | PERM_WRITE};
	u64 shm_bridge_handle;
	int i = 0;

	vaddr_tbl.num_node = of_get_child_count(node);
	vaddr_tbl.entries = devm_kcalloc(&pdev->dev, vaddr_tbl.num_node,
				 sizeof(struct dump_vaddr_entry),
				 GFP_KERNEL);
	if (!vaddr_tbl.entries)
		dev_err(&pdev->dev, "Unable to allocate mem for ptr addr\n");

	total_size = size = ret = no_of_nodes = 0;
	/* For dump table registration with IMEM */
@@ -862,9 +893,16 @@ static int mem_dump_alloc(struct platform_device *pdev)
		dump_entry.addr = phys_addr;
		ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS,
					&dump_entry);
		if (ret)
		if (ret) {
			dev_err(&pdev->dev, "Data dump setup failed, id = %d\n",
				id);
		} else if (vaddr_tbl.entries) {
			vaddr_tbl.entries[i].id = id;
			vaddr_tbl.entries[i].dump_vaddr =
					 dump_vaddr + MSM_DUMP_DATA_SIZE;
			vaddr_tbl.entries[i].dump_data_vaddr = dump_data;
			i++;
		}

		md_entry.phys_addr = dump_data->addr;
		md_entry.virt_addr = (uintptr_t)dump_vaddr + MSM_DUMP_DATA_SIZE;
+15 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2012, 2014-2017, 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012, 2014-2017, 2019, 2021, The Linux Foundation. All rights reserved.
 */

#ifndef __MSM_MEMORY_DUMP_H
@@ -79,6 +79,8 @@ enum msm_dump_data_ids {
	MSM_DUMP_DATA_TMC_ETF = 0xF0,
	MSM_DUMP_DATA_TMC_ETF_SWAO = 0xF1,
	MSM_DUMP_DATA_TMC_REG = 0x100,
	MSM_DUMP_DATA_TMC_ETR_REG = 0x100,
	MSM_DUMP_DATA_TMC_ETF_REG = 0x101,
	MSM_DUMP_DATA_TMC_ETF_SWAO_REG = 0x102,
	MSM_DUMP_DATA_LOG_BUF = 0x110,
	MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111,
@@ -113,11 +115,23 @@ 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 int msm_dump_data_register_nominidump(enum msm_dump_table_ids id,
				  struct msm_dump_entry *entry);
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)