// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2020-2022 Linaro Limited, All rights reserved.
 * Author: Mike Leach <mike.leach@linaro.org>
 */
#include <linux/types.h>
#include <linux/unistd.h>
#include <stdio.h>
#include <unistd.h>

#include "coresight-cfg-examples.h"

#define TRCPRGCTLR			0x004
#define TRCPROCSELR			0x008
#define TRCSTATR			0x00C
#define TRCCONFIGR			0x010
#define TRCAUXCTLR			0x018
#define TRCEVENTCTL0R			0x020
#define TRCEVENTCTL1R			0x024
#define TRCRSR				0x028
#define TRCSTALLCTLR			0x02C
#define TRCTSCTLR			0x030
#define TRCSYNCPR			0x034
#define TRCCCCTLR			0x038
#define TRCBBCTLR			0x03C
#define TRCTRACEIDR			0x040
#define TRCQCTLR			0x044
/* Filtering control registers */
#define TRCVICTLR			0x080
#define TRCVIIECTLR			0x084
#define TRCVISSCTLR			0x088
#define TRCVIPCSSCTLR			0x08C
/* Derived resources registers */
#define TRCSEQEVRn(n)			(0x100 + (n * 4)) /* n = 0-2 */
#define TRCSEQRSTEVR			0x118
#define TRCSEQSTR			0x11C
#define TRCEXTINSELR			0x120
#define TRCEXTINSELRn(n)		(0x120 + (n * 4)) /* n = 0-3 */
#define TRCCNTRLDVRn(n)			(0x140 + (n * 4)) /* n = 0-3 */
#define TRCCNTCTLRn(n)			(0x150 + (n * 4)) /* n = 0-3 */
#define TRCCNTVRn(n)			(0x160 + (n * 4)) /* n = 0-3 */
/* ID registers */
#define TRCIDR8				0x180
#define TRCIDR9				0x184
#define TRCIDR10			0x188
#define TRCIDR11			0x18C
#define TRCIDR12			0x190
#define TRCIDR13			0x194
#define TRCIMSPEC0			0x1C0
#define TRCIMSPECn(n)			(0x1C0 + (n * 4)) /* n = 1-7 */
#define TRCIDR0				0x1E0
#define TRCIDR1				0x1E4
#define TRCIDR2				0x1E8
#define TRCIDR3				0x1EC
#define TRCIDR4				0x1F0
#define TRCIDR5				0x1F4
#define TRCIDR6				0x1F8
#define TRCIDR7				0x1FC
/*
 * Resource selection registers, n = 2-31.
 * First pair (regs 0, 1) is always present and is reserved.
 */
#define TRCRSCTLRn(n)			(0x200 + (n * 4))
/* Single-shot comparator registers, n = 0-7 */
#define TRCSSCCRn(n)			(0x280 + (n * 4))
#define TRCSSCSRn(n)			(0x2A0 + (n * 4))
#define TRCSSPCICRn(n)			(0x2C0 + (n * 4))
/* Management registers (0x300-0x314) */
#define TRCOSLAR			0x300
#define TRCOSLSR			0x304
#define TRCPDCR				0x310
#define TRCPDSR				0x314
/* Trace registers (0x318-0xEFC) */
/* Address Comparator registers n = 0-15 */
#define TRCACVRn(n)			(0x400 + (n * 8))
#define TRCACATRn(n)			(0x480 + (n * 8))
/* ContextID/Virtual ContextID comparators, n = 0-7 */
#define TRCCIDCVRn(n)			(0x600 + (n * 8))
#define TRCVMIDCVRn(n)			(0x640 + (n * 8))
#define TRCCIDCCTLR0			0x680
#define TRCCIDCCTLR1			0x684
#define TRCVMIDCCTLR0			0x688
#define TRCVMIDCCTLR1			0x68C
/* Management register (0xF00) */
/* Integration control registers */
#define TRCITCTRL			0xF00
/* Trace registers (0xFA0-0xFA4) */
/* Claim tag registers */
#define TRCCLAIMSET			0xFA0
#define TRCCLAIMCLR			0xFA4
/* Management registers (0xFA8-0xFFC) */
#define TRCDEVAFF0			0xFA8
#define TRCDEVAFF1			0xFAC
#define TRCLAR				0xFB0
#define TRCLSR				0xFB4
#define TRCAUTHSTATUS			0xFB8
#define TRCDEVARCH			0xFBC
#define TRCDEVID			0xFC8
#define TRCDEVTYPE			0xFCC
#define TRCPIDR4			0xFD0
#define TRCPIDR5			0xFD4
#define TRCPIDR6			0xFD8
#define TRCPIDR7			0xFDC
#define TRCPIDR0			0xFE0
#define TRCPIDR1			0xFE4
#define TRCPIDR2			0xFE8
#define TRCPIDR3			0xFEC
#define TRCCIDR0			0xFF0
#define TRCCIDR1			0xFF4
#define TRCCIDR2			0xFF8
#define TRCCIDR3			0xFFC

#define ETM4_CFG_RES_CTR	0x001
#define ETM4_CFG_RES_CMP	0x002
#define ETM4_CFG_RES_CMP_PAIR0	0x003
#define ETM4_CFG_RES_CMP_PAIR1	0x004
#define ETM4_CFG_RES_SEL	0x005
#define ETM4_CFG_RES_SEL_PAIR0	0x006
#define ETM4_CFG_RES_SEL_PAIR1	0x007
#define ETM4_CFG_RES_SEQ	0x008
#define ETM4_CFG_RES_TS		0x009
#define ETM4_CFG_RES_MASK	0x00F

static struct cscfg_regval_desc strobe_regs[] = {
	/* resource selectors */
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCRSCTLRn(2),
		.hw_info = ETM4_CFG_RES_SEL,
		.val32 = 0x20001,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCRSCTLRn(3),
		.hw_info = ETM4_CFG_RES_SEQ,
		.val32 = 0x20002,
	},
	/* strobe window counter 0 - reload from param 0 */
	{
		.type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
		.offset = TRCCNTVRn(0),
		.hw_info = ETM4_CFG_RES_CTR,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
		.offset = TRCCNTRLDVRn(0),
		.hw_info = ETM4_CFG_RES_CTR,
		.val32 = 0,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCCNTCTLRn(0),
		.hw_info = ETM4_CFG_RES_CTR,
		.val32 = 0x10001,
	},
	/* strobe period counter 1 - reload from param 1 */
	{
		.type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
		.offset = TRCCNTVRn(1),
		.hw_info = ETM4_CFG_RES_CTR,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
		.offset = TRCCNTRLDVRn(1),
		.hw_info = ETM4_CFG_RES_CTR,
		.val32 = 1,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCCNTCTLRn(1),
		.hw_info = ETM4_CFG_RES_CTR,
		.val32 = 0x8102,
	},
	/* sequencer */
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCSEQEVRn(0),
		.hw_info = ETM4_CFG_RES_SEQ,
		.val32 = 0x0081,
	},
	{
		.type = CS_CFG_REG_TYPE_RESOURCE,
		.offset = TRCSEQEVRn(1),
		.hw_info = ETM4_CFG_RES_SEQ,
		.val32 = 0x0000,
	},
	/* view-inst */
	{
		.type = CS_CFG_REG_TYPE_STD | CS_CFG_REG_TYPE_VAL_MASK,
		.offset = TRCVICTLR,
		.val32 = 0x0003,
		.mask32 = 0x0003,
	},
	/* end of regs */
};

struct cscfg_feature_desc strobe_etm4x = {
	.name = "strobing-cfgfs",
	.description = "Generate periodic trace capture windows.\n"
		       "parameter \'window\': a number of CPU cycles (W)\n"
		       "parameter \'period\': trace enabled for W cycles every period x W cycles\n",
	.match_flags = CS_CFG_MATCH_CLASS_SRC_ETM4,
	.nr_params = 0,
	.params_desc = NULL,
	.nr_regs = ARRAY_SIZE(strobe_regs),
	.regs_desc = strobe_regs,
};

static struct cscfg_feature_desc *sample_feats[] = {
	&strobe_etm4x,
        NULL
};

static struct cscfg_config_desc *sample_cfgs[] = {
	NULL
};

struct cscfg_file_eg_info file_info_afdo = {
	.example_name = "example_afdo",
	.filename = "example_afdo.cscfg",
	.config_descs = sample_cfgs,
	.feat_descs = sample_feats,
};
