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_HELPERS_H__
8 #define __PMF_HELPERS_H__
9 
10 #include <arch_helpers.h>
11 #include <assert.h>
12 #include <bl_common.h>
13 #include <platform.h>
14 #include <pmf.h>
15 #include <stddef.h>
16 #include <stdint.h>
17 
18 /*
19  * Prototype for PMF service functions.
20  */
21 typedef int (*pmf_svc_init_t)(void);
22 typedef unsigned long long (*pmf_svc_get_ts_t)(unsigned int tid,
23 		 u_register_t mpidr,
24 		 unsigned int flags);
25 
26 /*
27  * This is the definition of PMF service desc.
28  */
29 typedef struct pmf_svc_desc {
30 	/* Structure version information */
31 	param_header_t h;
32 
33 	/* Name of the PMF service */
34 	const char *name;
35 
36 	/* PMF service config: Implementer id, Service id and total id*/
37 	unsigned int svc_config;
38 
39 	/* PMF service initialization handler */
40 	pmf_svc_init_t init;
41 
42 	/* PMF service time-stamp retrieval handler */
43 	pmf_svc_get_ts_t get_ts;
44 } pmf_svc_desc_t;
45 
46 /*
47  * Convenience macro to allocate memory for a PMF service.
48  */
49 #define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id)		\
50 	unsigned long long pmf_ts_mem_ ## _name[_total_id]	\
51 	__aligned(CACHE_WRITEBACK_GRANULE)			\
52 	__section("pmf_timestamp_array")			\
53 	__used;
54 
55 /*
56  * Convenience macro to validate tid index for the given TS array.
57  */
58 #define PMF_VALIDATE_TID(_name, _tid)	\
59 	assert((_tid & PMF_TID_MASK) < (ARRAY_SIZE(pmf_ts_mem_ ## _name)))
60 
61 /*
62  * Convenience macros for capturing time-stamp.
63  */
64 #define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags)			\
65 	void pmf_capture_timestamp_ ## _name(				\
66 			unsigned int tid,				\
67 			unsigned long long ts)				\
68 	{								\
69 		CASSERT(_flags, select_proper_config);			\
70 		PMF_VALIDATE_TID(_name, tid);				\
71 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
72 		if ((_flags) & PMF_STORE_ENABLE)			\
73 			__pmf_store_timestamp(base_addr, tid, ts);	\
74 		if ((_flags) & PMF_DUMP_ENABLE)				\
75 			__pmf_dump_timestamp(tid, ts);			\
76 	}								\
77 	void pmf_capture_timestamp_with_cache_maint_ ## _name(		\
78 			unsigned int tid,				\
79 			unsigned long long ts)				\
80 	{								\
81 		CASSERT(_flags, select_proper_config);			\
82 		PMF_VALIDATE_TID(_name, tid);				\
83 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
84 		if ((_flags) & PMF_STORE_ENABLE)			\
85 			__pmf_store_timestamp_with_cache_maint(base_addr, tid, ts);\
86 		if ((_flags) & PMF_DUMP_ENABLE)				\
87 			__pmf_dump_timestamp(tid, ts);			\
88 	}
89 
90 /*
91  * Convenience macros for retrieving time-stamp.
92  */
93 #define PMF_DEFINE_GET_TIMESTAMP(_name)					\
94 	unsigned long long pmf_get_timestamp_by_index_ ## _name(	\
95 		unsigned int tid, unsigned int cpuid, unsigned int flags)\
96 	{								\
97 		PMF_VALIDATE_TID(_name, tid);				\
98 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
99 		return __pmf_get_timestamp(base_addr, tid, cpuid, flags);\
100 	}								\
101 	unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(	\
102 		unsigned int tid, u_register_t mpidr, unsigned int flags)\
103 	{								\
104 		PMF_VALIDATE_TID(_name, tid);				\
105 		uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name;	\
106 		return __pmf_get_timestamp(base_addr, tid,		\
107 			plat_core_pos_by_mpidr(mpidr), flags);		\
108 	}
109 
110 /*
111  * Convenience macro to register a PMF service.
112  * This is needed for services that require SMC handling.
113  */
114 #define PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid,	\
115 		_init, _getts_by_mpidr) 				\
116 	static const pmf_svc_desc_t __pmf_desc_ ## _name 		\
117 	__section("pmf_svc_descs") __used = {		 		\
118 		.h.type = PARAM_EP, 					\
119 		.h.version = VERSION_1, 				\
120 		.h.size = sizeof(pmf_svc_desc_t),			\
121 		.h.attr = 0,						\
122 		.name = #_name, 					\
123 		.svc_config = ((((_implid) << PMF_IMPL_ID_SHIFT) &	\
124 						PMF_IMPL_ID_MASK) |	\
125 				(((_svcid) << PMF_SVC_ID_SHIFT) &	\
126 						PMF_SVC_ID_MASK) |	\
127 				(((_totalid) << PMF_TID_SHIFT) &	\
128 						PMF_TID_MASK)),		\
129 		.init = _init,						\
130 		.get_ts = _getts_by_mpidr				\
131 	};
132 
133 /* PMF internal functions */
134 void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts);
135 void __pmf_store_timestamp(uintptr_t base_addr,
136 		unsigned int tid,
137 		unsigned long long ts);
138 void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr,
139 		unsigned int tid,
140 		unsigned long long ts);
141 unsigned long long __pmf_get_timestamp(uintptr_t base_addr,
142 		unsigned int tid,
143 		unsigned int cpuid,
144 		unsigned int flags);
145 #endif /* __PMF_HELPERS_H__ */
146