1 /*
2  * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef __TZC_COMMON_PRIVATE_H__
8 #define __TZC_COMMON_PRIVATE_H__
9 
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <mmio.h>
13 #include <tzc_common.h>
14 
15 #define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name)		\
16 	static inline void _tzc##fn_name##_write_action(		\
17 					uintptr_t base,			\
18 					tzc_action_t action)		\
19 	{								\
20 		mmio_write_32(base + TZC_##macro_name##_ACTION_OFF,	\
21 			action);					\
22 	}
23 
24 #define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name)	\
25 	static inline void _tzc##fn_name##_write_region_base(		\
26 					uintptr_t base,			\
27 					int region_no,			\
28 					unsigned long long region_base)	\
29 	{								\
30 		mmio_write_32(base +					\
31 			TZC_REGION_OFFSET(				\
32 				TZC_##macro_name##_REGION_SIZE,		\
33 				region_no) +				\
34 			TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET,	\
35 			(uint32_t)region_base);				\
36 		mmio_write_32(base +					\
37 			TZC_REGION_OFFSET(				\
38 				TZC_##macro_name##_REGION_SIZE,		\
39 				region_no) +				\
40 			TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET,	\
41 			(uint32_t)(region_base >> 32));			\
42 	}
43 
44 #define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name)		\
45 	static inline void _tzc##fn_name##_write_region_top(		\
46 					uintptr_t base,			\
47 					int region_no,			\
48 					unsigned long long region_top)	\
49 	{								\
50 		mmio_write_32(base +					\
51 			TZC_REGION_OFFSET				\
52 				(TZC_##macro_name##_REGION_SIZE,	\
53 				region_no) +				\
54 			TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET,	\
55 			(uint32_t)region_top);			\
56 		mmio_write_32(base +					\
57 			TZC_REGION_OFFSET(				\
58 				TZC_##macro_name##_REGION_SIZE,		\
59 				region_no) +				\
60 			TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET,	\
61 			(uint32_t)(region_top >> 32));		\
62 	}
63 
64 #define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name)	\
65 	static inline void _tzc##fn_name##_write_region_attributes(	\
66 						uintptr_t base,		\
67 						int region_no,		\
68 						unsigned int attr)	\
69 	{								\
70 		mmio_write_32(base +					\
71 			TZC_REGION_OFFSET(				\
72 				TZC_##macro_name##_REGION_SIZE,		\
73 				region_no) +				\
74 			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
75 			attr);						\
76 	}
77 
78 #define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name)	\
79 	static inline void _tzc##fn_name##_write_region_id_access(	\
80 						uintptr_t base,		\
81 						int region_no,		\
82 						unsigned int val)	\
83 	{								\
84 		mmio_write_32(base +					\
85 			TZC_REGION_OFFSET(				\
86 				TZC_##macro_name##_REGION_SIZE,		\
87 				region_no) +				\
88 			TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET,	\
89 			val);						\
90 	}
91 
92 /*
93  * It is used to program region 0 ATTRIBUTES and ACCESS register.
94  */
95 #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
96 	void _tzc##fn_name##_configure_region0(uintptr_t base,		\
97 			   tzc_region_attributes_t sec_attr,		\
98 			   unsigned int ns_device_access)		\
99 	{								\
100 		assert(base);						\
101 		VERBOSE("TrustZone : Configuring region 0 "		\
102 			"(TZC Interface Base=%p sec_attr=0x%x,"		\
103 			" ns_devs=0x%x)\n", (void *)base,		\
104 			sec_attr, ns_device_access);			\
105 									\
106 		/* Set secure attributes on region 0 */			\
107 		_tzc##fn_name##_write_region_attributes(base, 0,	\
108 			sec_attr << TZC_REGION_ATTR_SEC_SHIFT);		\
109 									\
110 		/***************************************************/	\
111 		/* Specify which non-secure devices have permission*/	\
112 		/* to access region 0.				   */	\
113 		/***************************************************/	\
114 		_tzc##fn_name##_write_region_id_access(base,		\
115 						0,			\
116 						ns_device_access);	\
117 	}
118 
119 /*
120  * It is used to program a region from 1 to 8 in the TrustZone controller.
121  * NOTE:
122  * Region 0 is special; it is preferable to use
123  * ##fn_name##_configure_region0 for this region (see comment for
124  * that function).
125  */
126 #define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name)			\
127 	void _tzc##fn_name##_configure_region(uintptr_t base,		\
128 				unsigned int filters,			\
129 				int region_no,				\
130 				unsigned long long region_base,		\
131 				unsigned long long region_top,		\
132 				tzc_region_attributes_t sec_attr,	\
133 				unsigned int nsaid_permissions)	\
134 	{								\
135 		assert(base);						\
136 		VERBOSE("TrustZone : Configuring region "		\
137 			"(TZC Interface Base: %p, region_no = %d)"	\
138 			"...\n", (void *)base, region_no);		\
139 		VERBOSE("TrustZone : ... base = %llx, top = %llx,"	\
140 			"\n", region_base, region_top);\
141 		VERBOSE("TrustZone : ... sec_attr = 0x%x,"		\
142 			" ns_devs = 0x%x)\n",				\
143 			sec_attr, nsaid_permissions);			\
144 									\
145 		/***************************************************/	\
146 		/* Inputs look ok, start programming registers.    */	\
147 		/* All the address registers are 32 bits wide and  */	\
148 		/* have a LOW and HIGH				   */	\
149 		/* component used to construct an address up to a  */	\
150 		/* 64bit.					   */	\
151 		/***************************************************/	\
152 		_tzc##fn_name##_write_region_base(base,			\
153 					region_no, region_base);	\
154 		_tzc##fn_name##_write_region_top(base,			\
155 					region_no, region_top);		\
156 									\
157 		/* Enable filter to the region and set secure attributes */\
158 		_tzc##fn_name##_write_region_attributes(base,		\
159 				region_no,				\
160 				(sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
161 				(filters << TZC_REGION_ATTR_F_EN_SHIFT));\
162 									\
163 		/***************************************************/	\
164 		/* Specify which non-secure devices have permission*/	\
165 		/* to access this region.			   */	\
166 		/***************************************************/	\
167 		_tzc##fn_name##_write_region_id_access(base,		\
168 						region_no,		\
169 						nsaid_permissions);	\
170 	}
171 
172 #if ENABLE_ASSERTIONS
173 
_tzc_read_peripheral_id(uintptr_t base)174 static inline unsigned int _tzc_read_peripheral_id(uintptr_t base)
175 {
176 	unsigned int id;
177 
178 	id = mmio_read_32(base + PID0_OFF);
179 	/* Masks DESC part in PID1 */
180 	id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
181 
182 	return id;
183 }
184 
185 #ifdef AARCH32
_tzc_get_max_top_addr(int addr_width)186 static inline unsigned long long _tzc_get_max_top_addr(int addr_width)
187 {
188 	/*
189 	 * Assume at least 32 bit wide address and initialize the max.
190 	 * This function doesn't use 64-bit integer arithmetic to avoid
191 	 * having to implement additional compiler library functions.
192 	 */
193 	unsigned long long addr_mask = 0xFFFFFFFF;
194 	uint32_t *addr_ptr = (uint32_t *)&addr_mask;
195 
196 	assert(addr_width >= 32);
197 
198 	/* This logic works only on little - endian platforms */
199 	assert((read_sctlr() & SCTLR_EE_BIT) == 0);
200 
201 	/*
202 	 * If required address width is greater than 32, populate the higher
203 	 * 32 bits of the 64 bit field with the max address.
204 	 */
205 	if (addr_width > 32)
206 		*(addr_ptr + 1) = ((1 << (addr_width - 32)) - 1);
207 
208 	return addr_mask;
209 }
210 #else
211 #define _tzc_get_max_top_addr(addr_width)\
212 	(UINT64_MAX >> (64 - (addr_width)))
213 #endif /* AARCH32 */
214 
215 #endif /* ENABLE_ASSERTIONS */
216 
217 #endif /* __TZC_COMMON_PRIVATE_H__ */
218