1/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef __PMF_H__
8#define __PMF_H__
9
10#include <cassert.h>
11#include <pmf_helpers.h>
12
13/*
14 * Constants used for/by PMF services.
15 */
16#define PMF_ARM_TIF_IMPL_ID	0x41
17#define PMF_TID_SHIFT		0
18#define PMF_TID_MASK		(0xFF << PMF_TID_SHIFT)
19#define PMF_SVC_ID_SHIFT	10
20#define PMF_SVC_ID_MASK		(0x3F << PMF_SVC_ID_SHIFT)
21#define PMF_IMPL_ID_SHIFT	24
22#define PMF_IMPL_ID_MASK	(0xFFU << PMF_IMPL_ID_SHIFT)
23
24/*
25 * Flags passed to PMF_REGISTER_SERVICE
26 */
27#define PMF_STORE_ENABLE	(1 << 0)
28#define PMF_DUMP_ENABLE		(1 << 1)
29
30/*
31 * Flags passed to PMF_GET_TIMESTAMP_XXX
32 * and PMF_CAPTURE_TIMESTAMP
33 */
34#define PMF_CACHE_MAINT		(1 << 0)
35#define PMF_NO_CACHE_MAINT	0
36
37/*
38 * Defines for PMF SMC function ids.
39 */
40#define PMF_SMC_GET_TIMESTAMP_32	0x82000010
41#define PMF_SMC_GET_TIMESTAMP_64	0xC2000010
42#define PMF_NUM_SMC_CALLS		2
43
44/*
45 * The macros below are used to identify
46 * PMF calls from the SMC function ID.
47 */
48#define PMF_FID_MASK	0xffe0u
49#define PMF_FID_VALUE	0u
50#define is_pmf_fid(_fid)	(((_fid) & PMF_FID_MASK) == PMF_FID_VALUE)
51
52/* Following are the supported PMF service IDs */
53#define PMF_PSCI_STAT_SVC_ID	0
54#define PMF_RT_INSTR_SVC_ID	1
55
56#if ENABLE_PMF
57/*
58 * Convenience macros for capturing time-stamp.
59 */
60#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name)			\
61	void pmf_capture_timestamp_with_cache_maint_ ## _name(	\
62				unsigned int tid,		\
63				unsigned long long ts);		\
64	void pmf_capture_timestamp_ ## _name(			\
65				unsigned int tid,		\
66				unsigned long long ts);
67
68#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags)			\
69	do {								\
70		unsigned long long ts = read_cntpct_el0();		\
71		if ((_flags) & PMF_CACHE_MAINT)				\
72			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\
73		else							\
74			pmf_capture_timestamp_ ## _name((_tid), ts);	\
75	} while (0)
76
77#define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval)	\
78	do {								\
79		(_tsval) = read_cntpct_el0();				\
80		CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\
81		if ((_flags) & PMF_CACHE_MAINT)				\
82			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\
83		else							\
84			pmf_capture_timestamp_ ## _name((_tid), (_tsval));\
85	} while (0)
86
87#define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval)		\
88	do {								\
89		CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\
90		if ((_flags) & PMF_CACHE_MAINT)				\
91			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\
92		else							\
93			pmf_capture_timestamp_ ## _name((_tid), (_wrval));\
94	} while (0)
95
96/*
97 * Convenience macros for retrieving time-stamp.
98 */
99#define PMF_DECLARE_GET_TIMESTAMP(_name)			\
100	unsigned long long pmf_get_timestamp_by_index_ ## _name(\
101		unsigned int tid,				\
102		unsigned int cpuid,				\
103		unsigned int flags);				\
104	unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\
105		unsigned int tid,				\
106		u_register_t mpidr,				\
107		unsigned int flags);
108
109#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\
110	_tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags)
111
112#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\
113	_tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags)
114
115/* Convenience macros to register a PMF service.*/
116/*
117 * This macro is used to register a PMF Service. It allocates PMF memory
118 * and defines default service-specific PMF functions.
119 */
120#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)	\
121	PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid)		\
122	PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags)		\
123	PMF_DEFINE_GET_TIMESTAMP(_name)
124
125/*
126 * This macro is used to register a PMF service, including an
127 * SMC interface to that service.
128 */
129#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\
130	PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)	\
131	PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID,	\
132			_svcid, _totalid, NULL,			\
133			pmf_get_timestamp_by_mpidr_ ## _name)
134
135/*
136 * This macro is used to register a PMF service that has an SMC interface
137 * but provides its own service-specific PMF functions.
138 */
139#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid,	\
140		 _init, _getts)						\
141	PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid,	\
142		 _init, _getts)
143
144#else
145
146#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)
147#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)
148#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid,	\
149				_init, _getts)
150#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name)
151#define PMF_DECLARE_GET_TIMESTAMP(_name)
152#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags)
153#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)
154#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)
155
156#endif /* ENABLE_PMF */
157
158/*******************************************************************************
159 * Function & variable prototypes
160 ******************************************************************************/
161/* PMF common functions */
162int pmf_get_timestamp_smc(unsigned int tid,
163		u_register_t mpidr,
164		unsigned int flags,
165		unsigned long long *ts);
166int pmf_setup(void);
167uintptr_t pmf_smc_handler(unsigned int smc_fid,
168		u_register_t x1,
169		u_register_t x2,
170		u_register_t x3,
171		u_register_t x4,
172		void *cookie,
173		void *handle,
174		u_register_t flags);
175
176#endif /* __PMF_H__ */
177