xref: /rk3399_ARM-atf/include/lib/pmf/pmf_helpers.h (revision daa9b6ea641c841478b861b0fb459bc066233358)
1afdda571Sdp-arm /*
21af540efSRoberto Vargas  * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
3afdda571Sdp-arm  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
5afdda571Sdp-arm  */
6afdda571Sdp-arm 
7bef9a10fSAntonio Nino Diaz #ifndef PMF_HELPERS_H
8bef9a10fSAntonio Nino Diaz #define PMF_HELPERS_H
9afdda571Sdp-arm 
10afdda571Sdp-arm #include <assert.h>
11afdda571Sdp-arm #include <stddef.h>
122a4b4b71SIsla Mitchell #include <stdint.h>
13afdda571Sdp-arm 
1409d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1509d40e0eSAntonio Nino Diaz #include <common/bl_common.h>
1609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
1709d40e0eSAntonio Nino Diaz 
18afdda571Sdp-arm /*
19afdda571Sdp-arm  * Prototype for PMF service functions.
20afdda571Sdp-arm  */
21afdda571Sdp-arm typedef int (*pmf_svc_init_t)(void);
22afdda571Sdp-arm typedef unsigned long long (*pmf_svc_get_ts_t)(unsigned int tid,
23afdda571Sdp-arm 		 u_register_t mpidr,
24afdda571Sdp-arm 		 unsigned int flags);
25afdda571Sdp-arm 
26afdda571Sdp-arm /*
27afdda571Sdp-arm  * This is the definition of PMF service desc.
28afdda571Sdp-arm  */
29afdda571Sdp-arm typedef struct pmf_svc_desc {
30afdda571Sdp-arm 	/* Structure version information */
31afdda571Sdp-arm 	param_header_t h;
32afdda571Sdp-arm 
33afdda571Sdp-arm 	/* Name of the PMF service */
34afdda571Sdp-arm 	const char *name;
35afdda571Sdp-arm 
36afdda571Sdp-arm 	/* PMF service config: Implementer id, Service id and total id*/
37afdda571Sdp-arm 	unsigned int svc_config;
38afdda571Sdp-arm 
39afdda571Sdp-arm 	/* PMF service initialization handler */
40afdda571Sdp-arm 	pmf_svc_init_t init;
41afdda571Sdp-arm 
42afdda571Sdp-arm 	/* PMF service time-stamp retrieval handler */
43afdda571Sdp-arm 	pmf_svc_get_ts_t get_ts;
44afdda571Sdp-arm } pmf_svc_desc_t;
45afdda571Sdp-arm 
46*daa9b6eaSMadhukar Pappireddy #if ENABLE_PMF
47*daa9b6eaSMadhukar Pappireddy /*
48*daa9b6eaSMadhukar Pappireddy  * Convenience macros for capturing time-stamp.
49*daa9b6eaSMadhukar Pappireddy  */
50*daa9b6eaSMadhukar Pappireddy #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name)			\
51*daa9b6eaSMadhukar Pappireddy 	void pmf_capture_timestamp_with_cache_maint_ ## _name(	\
52*daa9b6eaSMadhukar Pappireddy 				unsigned int tid,		\
53*daa9b6eaSMadhukar Pappireddy 				unsigned long long ts);		\
54*daa9b6eaSMadhukar Pappireddy 	void pmf_capture_timestamp_ ## _name(			\
55*daa9b6eaSMadhukar Pappireddy 				unsigned int tid,		\
56*daa9b6eaSMadhukar Pappireddy 				unsigned long long ts);
57*daa9b6eaSMadhukar Pappireddy 
58*daa9b6eaSMadhukar Pappireddy #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags)			\
59*daa9b6eaSMadhukar Pappireddy 	do {								\
60*daa9b6eaSMadhukar Pappireddy 		unsigned long long ts = read_cntpct_el0();		\
61*daa9b6eaSMadhukar Pappireddy 		if (((_flags) & PMF_CACHE_MAINT) != 0U)			\
62*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\
63*daa9b6eaSMadhukar Pappireddy 		else							\
64*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_ ## _name((_tid), ts);	\
65*daa9b6eaSMadhukar Pappireddy 	} while (0)
66*daa9b6eaSMadhukar Pappireddy 
67*daa9b6eaSMadhukar Pappireddy #define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval)	\
68*daa9b6eaSMadhukar Pappireddy 	do {								\
69*daa9b6eaSMadhukar Pappireddy 		(_tsval) = read_cntpct_el0();				\
70*daa9b6eaSMadhukar Pappireddy 		CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\
71*daa9b6eaSMadhukar Pappireddy 		if (((_flags) & PMF_CACHE_MAINT) != 0U)			\
72*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\
73*daa9b6eaSMadhukar Pappireddy 		else							\
74*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_ ## _name((_tid), (_tsval));\
75*daa9b6eaSMadhukar Pappireddy 	} while (0)
76*daa9b6eaSMadhukar Pappireddy 
77*daa9b6eaSMadhukar Pappireddy #define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval)		\
78*daa9b6eaSMadhukar Pappireddy 	do {								\
79*daa9b6eaSMadhukar Pappireddy 		CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\
80*daa9b6eaSMadhukar Pappireddy 		if (((_flags) & PMF_CACHE_MAINT) != 0U)			\
81*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\
82*daa9b6eaSMadhukar Pappireddy 		else							\
83*daa9b6eaSMadhukar Pappireddy 			pmf_capture_timestamp_ ## _name((_tid), (_wrval));\
84*daa9b6eaSMadhukar Pappireddy 	} while (0)
85*daa9b6eaSMadhukar Pappireddy 
86*daa9b6eaSMadhukar Pappireddy /*
87*daa9b6eaSMadhukar Pappireddy  * Convenience macros for retrieving time-stamp.
88*daa9b6eaSMadhukar Pappireddy  */
89*daa9b6eaSMadhukar Pappireddy #define PMF_DECLARE_GET_TIMESTAMP(_name)			\
90*daa9b6eaSMadhukar Pappireddy 	unsigned long long pmf_get_timestamp_by_index_ ## _name(\
91*daa9b6eaSMadhukar Pappireddy 		unsigned int tid,				\
92*daa9b6eaSMadhukar Pappireddy 		unsigned int cpuid,				\
93*daa9b6eaSMadhukar Pappireddy 		unsigned int flags);				\
94*daa9b6eaSMadhukar Pappireddy 	unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\
95*daa9b6eaSMadhukar Pappireddy 		unsigned int tid,				\
96*daa9b6eaSMadhukar Pappireddy 		u_register_t mpidr,				\
97*daa9b6eaSMadhukar Pappireddy 		unsigned int flags);
98*daa9b6eaSMadhukar Pappireddy 
99*daa9b6eaSMadhukar Pappireddy #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\
100*daa9b6eaSMadhukar Pappireddy 	_tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags)
101*daa9b6eaSMadhukar Pappireddy 
102*daa9b6eaSMadhukar Pappireddy #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\
103*daa9b6eaSMadhukar Pappireddy 	_tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags)
104*daa9b6eaSMadhukar Pappireddy 
105*daa9b6eaSMadhukar Pappireddy /* Convenience macros to register a PMF service.*/
106*daa9b6eaSMadhukar Pappireddy /*
107*daa9b6eaSMadhukar Pappireddy  * This macro is used to register a PMF Service. It allocates PMF memory
108*daa9b6eaSMadhukar Pappireddy  * and defines default service-specific PMF functions.
109*daa9b6eaSMadhukar Pappireddy  */
110*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)	\
111*daa9b6eaSMadhukar Pappireddy 	PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid)		\
112*daa9b6eaSMadhukar Pappireddy 	PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags)		\
113*daa9b6eaSMadhukar Pappireddy 	PMF_DEFINE_GET_TIMESTAMP(_name)
114*daa9b6eaSMadhukar Pappireddy 
115*daa9b6eaSMadhukar Pappireddy /*
116*daa9b6eaSMadhukar Pappireddy  * This macro is used to register a PMF service, including an
117*daa9b6eaSMadhukar Pappireddy  * SMC interface to that service.
118*daa9b6eaSMadhukar Pappireddy  */
119*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\
120*daa9b6eaSMadhukar Pappireddy 	PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)	\
121*daa9b6eaSMadhukar Pappireddy 	PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID,	\
122*daa9b6eaSMadhukar Pappireddy 			_svcid, _totalid, NULL,			\
123*daa9b6eaSMadhukar Pappireddy 			pmf_get_timestamp_by_mpidr_ ## _name)
124*daa9b6eaSMadhukar Pappireddy 
125*daa9b6eaSMadhukar Pappireddy /*
126*daa9b6eaSMadhukar Pappireddy  * This macro is used to register a PMF service that has an SMC interface
127*daa9b6eaSMadhukar Pappireddy  * but provides its own service-specific PMF functions.
128*daa9b6eaSMadhukar Pappireddy  */
129*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid,	\
130*daa9b6eaSMadhukar Pappireddy 		 _init, _getts)						\
131*daa9b6eaSMadhukar Pappireddy 	PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid,	\
132*daa9b6eaSMadhukar Pappireddy 		 _init, _getts)
133*daa9b6eaSMadhukar Pappireddy 
134*daa9b6eaSMadhukar Pappireddy #else
135*daa9b6eaSMadhukar Pappireddy 
136*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags)
137*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)
138*daa9b6eaSMadhukar Pappireddy #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid,	\
139*daa9b6eaSMadhukar Pappireddy 				_init, _getts)
140*daa9b6eaSMadhukar Pappireddy #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name)
141*daa9b6eaSMadhukar Pappireddy #define PMF_DECLARE_GET_TIMESTAMP(_name)
142*daa9b6eaSMadhukar Pappireddy #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags)
143*daa9b6eaSMadhukar Pappireddy #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)
144*daa9b6eaSMadhukar Pappireddy #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)
145*daa9b6eaSMadhukar Pappireddy 
146*daa9b6eaSMadhukar Pappireddy #endif /* ENABLE_PMF */
147*daa9b6eaSMadhukar Pappireddy 
148afdda571Sdp-arm /*
149afdda571Sdp-arm  * Convenience macro to allocate memory for a PMF service.
1501af540efSRoberto Vargas  *
1511af540efSRoberto Vargas  * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
152afdda571Sdp-arm  */
153afdda571Sdp-arm #define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id)		\
1541af540efSRoberto Vargas 	extern unsigned long long pmf_ts_mem_ ## _name[_total_id];	\
1555695cfe7Sdp-arm 	unsigned long long pmf_ts_mem_ ## _name[_total_id]	\
1562d84b46eSdp-arm 	__aligned(CACHE_WRITEBACK_GRANULE)			\
1572d84b46eSdp-arm 	__section("pmf_timestamp_array")			\
1582d84b46eSdp-arm 	__used;
159afdda571Sdp-arm 
160afdda571Sdp-arm /*
161afdda571Sdp-arm  * Convenience macro to validate tid index for the given TS array.
162afdda571Sdp-arm  */
163afdda571Sdp-arm #define PMF_VALIDATE_TID(_name, _tid)	\
164afdda571Sdp-arm 	assert((_tid & PMF_TID_MASK) < (ARRAY_SIZE(pmf_ts_mem_ ## _name)))
165afdda571Sdp-arm 
166afdda571Sdp-arm /*
167afdda571Sdp-arm  * Convenience macros for capturing time-stamp.
1681af540efSRoberto Vargas  *
1691af540efSRoberto Vargas  * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
170afdda571Sdp-arm  */
171afdda571Sdp-arm #define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags)			\
172afdda571Sdp-arm 	void pmf_capture_timestamp_ ## _name(				\
173afdda571Sdp-arm 			unsigned int tid,				\
174afdda571Sdp-arm 			unsigned long long ts)				\
175afdda571Sdp-arm 	{								\
176afdda571Sdp-arm 		CASSERT(_flags, select_proper_config);			\
177afdda571Sdp-arm 		PMF_VALIDATE_TID(_name, tid);				\
178afdda571Sdp-arm 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
179bef9a10fSAntonio Nino Diaz 		if (((_flags) & PMF_STORE_ENABLE) != 0)			\
180afdda571Sdp-arm 			__pmf_store_timestamp(base_addr, tid, ts);	\
181bef9a10fSAntonio Nino Diaz 		if (((_flags) & PMF_DUMP_ENABLE) != 0)			\
182afdda571Sdp-arm 			__pmf_dump_timestamp(tid, ts);			\
183afdda571Sdp-arm 	}								\
184afdda571Sdp-arm 	void pmf_capture_timestamp_with_cache_maint_ ## _name(		\
185afdda571Sdp-arm 			unsigned int tid,				\
186afdda571Sdp-arm 			unsigned long long ts)				\
187afdda571Sdp-arm 	{								\
188afdda571Sdp-arm 		CASSERT(_flags, select_proper_config);			\
189afdda571Sdp-arm 		PMF_VALIDATE_TID(_name, tid);				\
190afdda571Sdp-arm 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
191bef9a10fSAntonio Nino Diaz 		if (((_flags) & PMF_STORE_ENABLE) != 0)			\
192afdda571Sdp-arm 			__pmf_store_timestamp_with_cache_maint(base_addr, tid, ts);\
193bef9a10fSAntonio Nino Diaz 		if (((_flags) & PMF_DUMP_ENABLE) != 0)			\
194afdda571Sdp-arm 			__pmf_dump_timestamp(tid, ts);			\
195afdda571Sdp-arm 	}
196afdda571Sdp-arm 
197afdda571Sdp-arm /*
198afdda571Sdp-arm  * Convenience macros for retrieving time-stamp.
1991af540efSRoberto Vargas  *
2001af540efSRoberto Vargas  * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
201afdda571Sdp-arm  */
202afdda571Sdp-arm #define PMF_DEFINE_GET_TIMESTAMP(_name)					\
203afdda571Sdp-arm 	unsigned long long pmf_get_timestamp_by_index_ ## _name(	\
204afdda571Sdp-arm 		unsigned int tid, unsigned int cpuid, unsigned int flags)\
205afdda571Sdp-arm 	{								\
206afdda571Sdp-arm 		PMF_VALIDATE_TID(_name, tid);				\
207afdda571Sdp-arm 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
208afdda571Sdp-arm 		return __pmf_get_timestamp(base_addr, tid, cpuid, flags);\
209afdda571Sdp-arm 	}								\
210afdda571Sdp-arm 	unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(	\
211afdda571Sdp-arm 		unsigned int tid, u_register_t mpidr, unsigned int flags)\
212afdda571Sdp-arm 	{								\
213afdda571Sdp-arm 		PMF_VALIDATE_TID(_name, tid);				\
214afdda571Sdp-arm 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
215afdda571Sdp-arm 		return __pmf_get_timestamp(base_addr, tid,		\
216afdda571Sdp-arm 			plat_core_pos_by_mpidr(mpidr), flags);		\
217afdda571Sdp-arm 	}
218afdda571Sdp-arm 
219afdda571Sdp-arm /*
220afdda571Sdp-arm  * Convenience macro to register a PMF service.
221afdda571Sdp-arm  * This is needed for services that require SMC handling.
222afdda571Sdp-arm  */
223afdda571Sdp-arm #define PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid,	\
224afdda571Sdp-arm 		_init, _getts_by_mpidr) 				\
225afdda571Sdp-arm 	static const pmf_svc_desc_t __pmf_desc_ ## _name 		\
226afdda571Sdp-arm 	__section("pmf_svc_descs") __used = {		 		\
227afdda571Sdp-arm 		.h.type = PARAM_EP, 					\
228afdda571Sdp-arm 		.h.version = VERSION_1, 				\
229afdda571Sdp-arm 		.h.size = sizeof(pmf_svc_desc_t),			\
230afdda571Sdp-arm 		.h.attr = 0,						\
231afdda571Sdp-arm 		.name = #_name, 					\
232afdda571Sdp-arm 		.svc_config = ((((_implid) << PMF_IMPL_ID_SHIFT) &	\
233afdda571Sdp-arm 						PMF_IMPL_ID_MASK) |	\
234afdda571Sdp-arm 				(((_svcid) << PMF_SVC_ID_SHIFT) &	\
235afdda571Sdp-arm 						PMF_SVC_ID_MASK) |	\
236afdda571Sdp-arm 				(((_totalid) << PMF_TID_SHIFT) &	\
237afdda571Sdp-arm 						PMF_TID_MASK)),		\
238afdda571Sdp-arm 		.init = _init,						\
239afdda571Sdp-arm 		.get_ts = _getts_by_mpidr				\
240afdda571Sdp-arm 	};
241afdda571Sdp-arm 
242afdda571Sdp-arm /* PMF internal functions */
243afdda571Sdp-arm void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts);
244afdda571Sdp-arm void __pmf_store_timestamp(uintptr_t base_addr,
245afdda571Sdp-arm 		unsigned int tid,
246afdda571Sdp-arm 		unsigned long long ts);
247afdda571Sdp-arm void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr,
248afdda571Sdp-arm 		unsigned int tid,
249afdda571Sdp-arm 		unsigned long long ts);
250afdda571Sdp-arm unsigned long long __pmf_get_timestamp(uintptr_t base_addr,
251afdda571Sdp-arm 		unsigned int tid,
252afdda571Sdp-arm 		unsigned int cpuid,
253afdda571Sdp-arm 		unsigned int flags);
254bef9a10fSAntonio Nino Diaz #endif /* PMF_HELPERS_H */
255