xref: /optee_os/core/drivers/tzc400.c (revision 5d1638f3e6d743a3b2caead5ae988dea97495fc9)
1*5d1638f3SJens Wiklander /*
2*5d1638f3SJens Wiklander  * Copyright (c) 2015, Linaro Limited
3*5d1638f3SJens Wiklander  * All rights reserved.
4*5d1638f3SJens Wiklander  *
5*5d1638f3SJens Wiklander  * Redistribution and use in source and binary forms, with or without
6*5d1638f3SJens Wiklander  * modification, are permitted provided that the following conditions are met:
7*5d1638f3SJens Wiklander  *
8*5d1638f3SJens Wiklander  * 1. Redistributions of source code must retain the above copyright notice,
9*5d1638f3SJens Wiklander  * this list of conditions and the following disclaimer.
10*5d1638f3SJens Wiklander  *
11*5d1638f3SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*5d1638f3SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
13*5d1638f3SJens Wiklander  * and/or other materials provided with the distribution.
14*5d1638f3SJens Wiklander  *
15*5d1638f3SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*5d1638f3SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*5d1638f3SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*5d1638f3SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*5d1638f3SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*5d1638f3SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*5d1638f3SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*5d1638f3SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*5d1638f3SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*5d1638f3SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*5d1638f3SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
26*5d1638f3SJens Wiklander  */
27*5d1638f3SJens Wiklander  /*
28*5d1638f3SJens Wiklander  * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
29*5d1638f3SJens Wiklander  *
30*5d1638f3SJens Wiklander  * Redistribution and use in source and binary forms, with or without
31*5d1638f3SJens Wiklander  * modification, are permitted provided that the following conditions are met:
32*5d1638f3SJens Wiklander  *
33*5d1638f3SJens Wiklander  * Redistributions of source code must retain the above copyright notice, this
34*5d1638f3SJens Wiklander  * list of conditions and the following disclaimer.
35*5d1638f3SJens Wiklander  *
36*5d1638f3SJens Wiklander  * Redistributions in binary form must reproduce the above copyright notice,
37*5d1638f3SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
38*5d1638f3SJens Wiklander  * and/or other materials provided with the distribution.
39*5d1638f3SJens Wiklander  *
40*5d1638f3SJens Wiklander  * Neither the name of ARM nor the names of its contributors may be used
41*5d1638f3SJens Wiklander  * to endorse or promote products derived from this software without specific
42*5d1638f3SJens Wiklander  * prior written permission.
43*5d1638f3SJens Wiklander  *
44*5d1638f3SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
45*5d1638f3SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46*5d1638f3SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47*5d1638f3SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
48*5d1638f3SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49*5d1638f3SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50*5d1638f3SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51*5d1638f3SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52*5d1638f3SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53*5d1638f3SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54*5d1638f3SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
55*5d1638f3SJens Wiklander  */
56*5d1638f3SJens Wiklander 
57*5d1638f3SJens Wiklander #include <assert.h>
58*5d1638f3SJens Wiklander #include <drivers/tzc400.h>
59*5d1638f3SJens Wiklander #include <io.h>
60*5d1638f3SJens Wiklander #include <kernel/panic.h>
61*5d1638f3SJens Wiklander #include <stddef.h>
62*5d1638f3SJens Wiklander #include <trace.h>
63*5d1638f3SJens Wiklander #include <util.h>
64*5d1638f3SJens Wiklander 
65*5d1638f3SJens Wiklander /*
66*5d1638f3SJens Wiklander  * Implementation defined values used to validate inputs later.
67*5d1638f3SJens Wiklander  * Filters : max of 4 ; 0 to 3
68*5d1638f3SJens Wiklander  * Regions : max of 9 ; 0 to 8
69*5d1638f3SJens Wiklander  * Address width : Values between 32 to 64
70*5d1638f3SJens Wiklander  */
71*5d1638f3SJens Wiklander struct tzc_instance {
72*5d1638f3SJens Wiklander 	vaddr_t base;
73*5d1638f3SJens Wiklander 	uint8_t addr_width;
74*5d1638f3SJens Wiklander 	uint8_t num_filters;
75*5d1638f3SJens Wiklander 	uint8_t num_regions;
76*5d1638f3SJens Wiklander };
77*5d1638f3SJens Wiklander 
78*5d1638f3SJens Wiklander static struct tzc_instance tzc;
79*5d1638f3SJens Wiklander 
80*5d1638f3SJens Wiklander 
81*5d1638f3SJens Wiklander static uint32_t tzc_read_build_config(vaddr_t base)
82*5d1638f3SJens Wiklander {
83*5d1638f3SJens Wiklander 	return read32(base + BUILD_CONFIG_OFF);
84*5d1638f3SJens Wiklander }
85*5d1638f3SJens Wiklander 
86*5d1638f3SJens Wiklander static uint32_t tzc_read_gate_keeper(vaddr_t base)
87*5d1638f3SJens Wiklander {
88*5d1638f3SJens Wiklander 	return read32(base + GATE_KEEPER_OFF);
89*5d1638f3SJens Wiklander }
90*5d1638f3SJens Wiklander 
91*5d1638f3SJens Wiklander static void tzc_write_gate_keeper(vaddr_t base, uint32_t val)
92*5d1638f3SJens Wiklander {
93*5d1638f3SJens Wiklander 	write32(val, base + GATE_KEEPER_OFF);
94*5d1638f3SJens Wiklander }
95*5d1638f3SJens Wiklander 
96*5d1638f3SJens Wiklander static void tzc_write_action(vaddr_t base, enum tzc_action action)
97*5d1638f3SJens Wiklander {
98*5d1638f3SJens Wiklander 	write32(action, base + ACTION_OFF);
99*5d1638f3SJens Wiklander }
100*5d1638f3SJens Wiklander 
101*5d1638f3SJens Wiklander static void tzc_write_region_base_low(vaddr_t base, uint32_t region,
102*5d1638f3SJens Wiklander 				      uint32_t val)
103*5d1638f3SJens Wiklander {
104*5d1638f3SJens Wiklander 	write32(val, base + REGION_BASE_LOW_OFF +
105*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
106*5d1638f3SJens Wiklander }
107*5d1638f3SJens Wiklander 
108*5d1638f3SJens Wiklander static void tzc_write_region_base_high(vaddr_t base, uint32_t region,
109*5d1638f3SJens Wiklander 				       uint32_t val)
110*5d1638f3SJens Wiklander {
111*5d1638f3SJens Wiklander 	write32(val, base + REGION_BASE_HIGH_OFF +
112*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
113*5d1638f3SJens Wiklander }
114*5d1638f3SJens Wiklander 
115*5d1638f3SJens Wiklander static void tzc_write_region_top_low(vaddr_t base, uint32_t region,
116*5d1638f3SJens Wiklander 				     uint32_t val)
117*5d1638f3SJens Wiklander {
118*5d1638f3SJens Wiklander 	write32(val, base + REGION_TOP_LOW_OFF +
119*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
120*5d1638f3SJens Wiklander }
121*5d1638f3SJens Wiklander 
122*5d1638f3SJens Wiklander static void tzc_write_region_top_high(vaddr_t base, uint32_t region,
123*5d1638f3SJens Wiklander 				      uint32_t val)
124*5d1638f3SJens Wiklander {
125*5d1638f3SJens Wiklander 	write32(val, base + REGION_TOP_HIGH_OFF +
126*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
127*5d1638f3SJens Wiklander }
128*5d1638f3SJens Wiklander 
129*5d1638f3SJens Wiklander static void tzc_write_region_attributes(vaddr_t base, uint32_t region,
130*5d1638f3SJens Wiklander 					uint32_t val)
131*5d1638f3SJens Wiklander {
132*5d1638f3SJens Wiklander 	write32(val, base + REGION_ATTRIBUTES_OFF +
133*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
134*5d1638f3SJens Wiklander }
135*5d1638f3SJens Wiklander 
136*5d1638f3SJens Wiklander static void tzc_write_region_id_access(vaddr_t base, uint32_t region,
137*5d1638f3SJens Wiklander 				       uint32_t val)
138*5d1638f3SJens Wiklander {
139*5d1638f3SJens Wiklander 	write32(val, base + REGION_ID_ACCESS_OFF +
140*5d1638f3SJens Wiklander 		REGION_NUM_OFF(region));
141*5d1638f3SJens Wiklander }
142*5d1638f3SJens Wiklander 
143*5d1638f3SJens Wiklander static uint32_t tzc_read_component_id(vaddr_t base)
144*5d1638f3SJens Wiklander {
145*5d1638f3SJens Wiklander 	uint32_t id;
146*5d1638f3SJens Wiklander 
147*5d1638f3SJens Wiklander 	id = read8(base + CID0_OFF);
148*5d1638f3SJens Wiklander 	id |= SHIFT_U32(read8(base + CID1_OFF), 8);
149*5d1638f3SJens Wiklander 	id |= SHIFT_U32(read8(base + CID2_OFF), 16);
150*5d1638f3SJens Wiklander 	id |= SHIFT_U32(read8(base + CID3_OFF), 24);
151*5d1638f3SJens Wiklander 
152*5d1638f3SJens Wiklander 	return id;
153*5d1638f3SJens Wiklander }
154*5d1638f3SJens Wiklander 
155*5d1638f3SJens Wiklander static uint32_t tzc_get_gate_keeper(vaddr_t base, uint8_t filter)
156*5d1638f3SJens Wiklander {
157*5d1638f3SJens Wiklander 	uint32_t tmp;
158*5d1638f3SJens Wiklander 
159*5d1638f3SJens Wiklander 	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
160*5d1638f3SJens Wiklander 		GATE_KEEPER_OS_MASK;
161*5d1638f3SJens Wiklander 
162*5d1638f3SJens Wiklander 	return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
163*5d1638f3SJens Wiklander }
164*5d1638f3SJens Wiklander 
165*5d1638f3SJens Wiklander /* This function is not MP safe. */
166*5d1638f3SJens Wiklander static void tzc_set_gate_keeper(vaddr_t base, uint8_t filter, uint32_t val)
167*5d1638f3SJens Wiklander {
168*5d1638f3SJens Wiklander 	uint32_t tmp;
169*5d1638f3SJens Wiklander 
170*5d1638f3SJens Wiklander 	/* Upper half is current state. Lower half is requested state. */
171*5d1638f3SJens Wiklander 	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
172*5d1638f3SJens Wiklander 		GATE_KEEPER_OS_MASK;
173*5d1638f3SJens Wiklander 
174*5d1638f3SJens Wiklander 	if (val)
175*5d1638f3SJens Wiklander 		tmp |=  (1 << filter);
176*5d1638f3SJens Wiklander 	else
177*5d1638f3SJens Wiklander 		tmp &= ~(1 << filter);
178*5d1638f3SJens Wiklander 
179*5d1638f3SJens Wiklander 	tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
180*5d1638f3SJens Wiklander 			      GATE_KEEPER_OR_SHIFT);
181*5d1638f3SJens Wiklander 
182*5d1638f3SJens Wiklander 	/* Wait here until we see the change reflected in the TZC status. */
183*5d1638f3SJens Wiklander 	while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
184*5d1638f3SJens Wiklander 		GATE_KEEPER_OS_MASK) != tmp)
185*5d1638f3SJens Wiklander 		;
186*5d1638f3SJens Wiklander }
187*5d1638f3SJens Wiklander 
188*5d1638f3SJens Wiklander 
189*5d1638f3SJens Wiklander void tzc_init(vaddr_t base)
190*5d1638f3SJens Wiklander {
191*5d1638f3SJens Wiklander 	uint32_t tzc_id, tzc_build;
192*5d1638f3SJens Wiklander 
193*5d1638f3SJens Wiklander 	assert(base);
194*5d1638f3SJens Wiklander 	tzc.base = base;
195*5d1638f3SJens Wiklander 
196*5d1638f3SJens Wiklander 	/*
197*5d1638f3SJens Wiklander 	 * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
198*5d1638f3SJens Wiklander 	 * component ID is expected to be "0xB105F00D".
199*5d1638f3SJens Wiklander 	 */
200*5d1638f3SJens Wiklander 	tzc_id = tzc_read_component_id(tzc.base);
201*5d1638f3SJens Wiklander 	if (tzc_id != TZC400_COMPONENT_ID) {
202*5d1638f3SJens Wiklander 		EMSG("TZC : Wrong device ID (0x%x).\n", tzc_id);
203*5d1638f3SJens Wiklander 		panic();
204*5d1638f3SJens Wiklander 	}
205*5d1638f3SJens Wiklander 
206*5d1638f3SJens Wiklander 	/* Save values we will use later. */
207*5d1638f3SJens Wiklander 	tzc_build = tzc_read_build_config(tzc.base);
208*5d1638f3SJens Wiklander 	tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
209*5d1638f3SJens Wiklander 			   BUILD_CONFIG_NF_MASK) + 1;
210*5d1638f3SJens Wiklander 	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
211*5d1638f3SJens Wiklander 			   BUILD_CONFIG_AW_MASK) + 1;
212*5d1638f3SJens Wiklander 	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
213*5d1638f3SJens Wiklander 			   BUILD_CONFIG_NR_MASK) + 1;
214*5d1638f3SJens Wiklander }
215*5d1638f3SJens Wiklander 
216*5d1638f3SJens Wiklander static uint32_t addr_low(vaddr_t addr)
217*5d1638f3SJens Wiklander {
218*5d1638f3SJens Wiklander 	return (uint32_t)addr;
219*5d1638f3SJens Wiklander }
220*5d1638f3SJens Wiklander 
221*5d1638f3SJens Wiklander static uint32_t addr_high(vaddr_t addr __unused)
222*5d1638f3SJens Wiklander {
223*5d1638f3SJens Wiklander #if (UINTPTR_MAX == UINT64_MAX)
224*5d1638f3SJens Wiklander 	return (addr >> 32);
225*5d1638f3SJens Wiklander #else
226*5d1638f3SJens Wiklander 	return 0;
227*5d1638f3SJens Wiklander #endif
228*5d1638f3SJens Wiklander }
229*5d1638f3SJens Wiklander 
230*5d1638f3SJens Wiklander 
231*5d1638f3SJens Wiklander /*
232*5d1638f3SJens Wiklander  * `tzc_configure_region` is used to program regions into the TrustZone
233*5d1638f3SJens Wiklander  * controller. A region can be associated with more than one filter. The
234*5d1638f3SJens Wiklander  * associated filters are passed in as a bitmap (bit0 = filter0).
235*5d1638f3SJens Wiklander  * NOTE:
236*5d1638f3SJens Wiklander  * The region 0 covers the whole address space and is enabled on all filters,
237*5d1638f3SJens Wiklander  * this cannot be changed. It is, however, possible to change some region 0
238*5d1638f3SJens Wiklander  * permissions.
239*5d1638f3SJens Wiklander  */
240*5d1638f3SJens Wiklander void tzc_configure_region(uint32_t filters,
241*5d1638f3SJens Wiklander 			  uint8_t  region,
242*5d1638f3SJens Wiklander 			  vaddr_t  region_base,
243*5d1638f3SJens Wiklander 			  vaddr_t  region_top,
244*5d1638f3SJens Wiklander 			  enum tzc_region_attributes sec_attr,
245*5d1638f3SJens Wiklander 			  uint32_t ns_device_access)
246*5d1638f3SJens Wiklander {
247*5d1638f3SJens Wiklander 	assert(tzc.base);
248*5d1638f3SJens Wiklander 
249*5d1638f3SJens Wiklander 	/* Do range checks on filters and regions. */
250*5d1638f3SJens Wiklander 	assert(((filters >> tzc.num_filters) == 0) &&
251*5d1638f3SJens Wiklander 	       (region < tzc.num_regions));
252*5d1638f3SJens Wiklander 
253*5d1638f3SJens Wiklander 	/*
254*5d1638f3SJens Wiklander 	 * Do address range check based on TZC configuration. A 64bit address is
255*5d1638f3SJens Wiklander 	 * the max and expected case.
256*5d1638f3SJens Wiklander 	 */
257*5d1638f3SJens Wiklander #if (UINTPTR_MAX == UINT64_MAX)
258*5d1638f3SJens Wiklander 	assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
259*5d1638f3SJens Wiklander 		(region_base < region_top)));
260*5d1638f3SJens Wiklander #endif
261*5d1638f3SJens Wiklander 	/* region_base and (region_top + 1) must be 4KB aligned */
262*5d1638f3SJens Wiklander 	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
263*5d1638f3SJens Wiklander 
264*5d1638f3SJens Wiklander 	assert(sec_attr <= TZC_REGION_S_RDWR);
265*5d1638f3SJens Wiklander 
266*5d1638f3SJens Wiklander 	/*
267*5d1638f3SJens Wiklander 	 * Inputs look ok, start programming registers.
268*5d1638f3SJens Wiklander 	 * All the address registers are 32 bits wide and have a LOW and HIGH
269*5d1638f3SJens Wiklander 	 * component used to construct a up to a 64bit address.
270*5d1638f3SJens Wiklander 	 */
271*5d1638f3SJens Wiklander 	tzc_write_region_base_low(tzc.base, region,
272*5d1638f3SJens Wiklander 				  addr_low(region_base));
273*5d1638f3SJens Wiklander 	tzc_write_region_base_high(tzc.base, region,
274*5d1638f3SJens Wiklander 				   addr_high(region_base));
275*5d1638f3SJens Wiklander 
276*5d1638f3SJens Wiklander 	tzc_write_region_top_low(tzc.base, region,
277*5d1638f3SJens Wiklander 				addr_low(region_top));
278*5d1638f3SJens Wiklander 	tzc_write_region_top_high(tzc.base, region,
279*5d1638f3SJens Wiklander 				addr_high(region_top));
280*5d1638f3SJens Wiklander 
281*5d1638f3SJens Wiklander 	/* Assign the region to a filter and set secure attributes */
282*5d1638f3SJens Wiklander 	tzc_write_region_attributes(tzc.base, region,
283*5d1638f3SJens Wiklander 		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
284*5d1638f3SJens Wiklander 
285*5d1638f3SJens Wiklander 	/*
286*5d1638f3SJens Wiklander 	 * Specify which non-secure devices have permission to access this
287*5d1638f3SJens Wiklander 	 * region.
288*5d1638f3SJens Wiklander 	 */
289*5d1638f3SJens Wiklander 	tzc_write_region_id_access(tzc.base, region, ns_device_access);
290*5d1638f3SJens Wiklander }
291*5d1638f3SJens Wiklander 
292*5d1638f3SJens Wiklander 
293*5d1638f3SJens Wiklander void tzc_set_action(enum tzc_action action)
294*5d1638f3SJens Wiklander {
295*5d1638f3SJens Wiklander 	assert(tzc.base);
296*5d1638f3SJens Wiklander 
297*5d1638f3SJens Wiklander 	/*
298*5d1638f3SJens Wiklander 	 * - Currently no handler is provided to trap an error via interrupt
299*5d1638f3SJens Wiklander 	 *   or exception.
300*5d1638f3SJens Wiklander 	 * - The interrupt action has not been tested.
301*5d1638f3SJens Wiklander 	 */
302*5d1638f3SJens Wiklander 	tzc_write_action(tzc.base, action);
303*5d1638f3SJens Wiklander }
304*5d1638f3SJens Wiklander 
305*5d1638f3SJens Wiklander 
306*5d1638f3SJens Wiklander void tzc_enable_filters(void)
307*5d1638f3SJens Wiklander {
308*5d1638f3SJens Wiklander 	uint32_t state;
309*5d1638f3SJens Wiklander 	uint32_t filter;
310*5d1638f3SJens Wiklander 
311*5d1638f3SJens Wiklander 	assert(tzc.base);
312*5d1638f3SJens Wiklander 
313*5d1638f3SJens Wiklander 	for (filter = 0; filter < tzc.num_filters; filter++) {
314*5d1638f3SJens Wiklander 		state = tzc_get_gate_keeper(tzc.base, filter);
315*5d1638f3SJens Wiklander 		if (state) {
316*5d1638f3SJens Wiklander 			/*
317*5d1638f3SJens Wiklander 			 * The TZC filter is already configured. Changing the
318*5d1638f3SJens Wiklander 			 * programmer's view in an active system can cause
319*5d1638f3SJens Wiklander 			 * unpredictable behavior therefore panic for now rather
320*5d1638f3SJens Wiklander 			 * than try to determine whether this is safe in this
321*5d1638f3SJens Wiklander 			 * instance. See:
322*5d1638f3SJens Wiklander 			 * http://infocenter.arm.com/help/index.jsp?\
323*5d1638f3SJens Wiklander 			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html
324*5d1638f3SJens Wiklander 			 */
325*5d1638f3SJens Wiklander 			EMSG("TZC : Filter %d Gatekeeper already enabled.\n",
326*5d1638f3SJens Wiklander 				filter);
327*5d1638f3SJens Wiklander 			panic();
328*5d1638f3SJens Wiklander 		}
329*5d1638f3SJens Wiklander 		tzc_set_gate_keeper(tzc.base, filter, 1);
330*5d1638f3SJens Wiklander 	}
331*5d1638f3SJens Wiklander }
332*5d1638f3SJens Wiklander 
333*5d1638f3SJens Wiklander 
334*5d1638f3SJens Wiklander void tzc_disable_filters(void)
335*5d1638f3SJens Wiklander {
336*5d1638f3SJens Wiklander 	uint32_t filter;
337*5d1638f3SJens Wiklander 
338*5d1638f3SJens Wiklander 	assert(tzc.base);
339*5d1638f3SJens Wiklander 
340*5d1638f3SJens Wiklander 	/*
341*5d1638f3SJens Wiklander 	 * We don't do the same state check as above as the Gatekeepers are
342*5d1638f3SJens Wiklander 	 * disabled after reset.
343*5d1638f3SJens Wiklander 	 */
344*5d1638f3SJens Wiklander 	for (filter = 0; filter < tzc.num_filters; filter++)
345*5d1638f3SJens Wiklander 		tzc_set_gate_keeper(tzc.base, filter, 0);
346*5d1638f3SJens Wiklander }
347*5d1638f3SJens Wiklander 
348*5d1638f3SJens Wiklander #if TRACE_LEVEL >= TRACE_DEBUG
349*5d1638f3SJens Wiklander 
350*5d1638f3SJens Wiklander static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region)
351*5d1638f3SJens Wiklander {
352*5d1638f3SJens Wiklander 	return read32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region));
353*5d1638f3SJens Wiklander }
354*5d1638f3SJens Wiklander 
355*5d1638f3SJens Wiklander static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region)
356*5d1638f3SJens Wiklander {
357*5d1638f3SJens Wiklander 	return read32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region));
358*5d1638f3SJens Wiklander }
359*5d1638f3SJens Wiklander 
360*5d1638f3SJens Wiklander static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region)
361*5d1638f3SJens Wiklander {
362*5d1638f3SJens Wiklander 	return read32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region));
363*5d1638f3SJens Wiklander }
364*5d1638f3SJens Wiklander 
365*5d1638f3SJens Wiklander static uint32_t tzc_read_region_top_low(vaddr_t base, uint32_t region)
366*5d1638f3SJens Wiklander {
367*5d1638f3SJens Wiklander 	return read32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region));
368*5d1638f3SJens Wiklander }
369*5d1638f3SJens Wiklander 
370*5d1638f3SJens Wiklander static uint32_t tzc_read_region_top_high(vaddr_t base, uint32_t region)
371*5d1638f3SJens Wiklander {
372*5d1638f3SJens Wiklander 	return read32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region));
373*5d1638f3SJens Wiklander }
374*5d1638f3SJens Wiklander 
375*5d1638f3SJens Wiklander #define	REGION_MAX		8
376*5d1638f3SJens Wiklander static const __maybe_unused char * const tzc_attr_msg[] = {
377*5d1638f3SJens Wiklander 	"TZC_REGION_S_NONE",
378*5d1638f3SJens Wiklander 	"TZC_REGION_S_RD",
379*5d1638f3SJens Wiklander 	"TZC_REGION_S_WR",
380*5d1638f3SJens Wiklander 	"TZC_REGION_S_RDWR"
381*5d1638f3SJens Wiklander };
382*5d1638f3SJens Wiklander 
383*5d1638f3SJens Wiklander void tzc_dump_state(void)
384*5d1638f3SJens Wiklander {
385*5d1638f3SJens Wiklander 	uint32_t n;
386*5d1638f3SJens Wiklander 	uint32_t temp_32reg, temp_32reg_h;
387*5d1638f3SJens Wiklander 
388*5d1638f3SJens Wiklander 	DMSG("enter");
389*5d1638f3SJens Wiklander 	for (n = 0; n <= REGION_MAX; n++) {
390*5d1638f3SJens Wiklander 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
391*5d1638f3SJens Wiklander 		if (!(temp_32reg & REG_ATTR_F_EN_MASK))
392*5d1638f3SJens Wiklander 			continue;
393*5d1638f3SJens Wiklander 
394*5d1638f3SJens Wiklander 		DMSG("\n");
395*5d1638f3SJens Wiklander 		DMSG("region %d", n);
396*5d1638f3SJens Wiklander 		temp_32reg = tzc_read_region_base_low(tzc.base, n);
397*5d1638f3SJens Wiklander 		temp_32reg_h = tzc_read_region_base_high(tzc.base, n);
398*5d1638f3SJens Wiklander 		DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg);
399*5d1638f3SJens Wiklander 		temp_32reg = tzc_read_region_top_low(tzc.base, n);
400*5d1638f3SJens Wiklander 		temp_32reg_h = tzc_read_region_top_high(tzc.base, n);
401*5d1638f3SJens Wiklander 		DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg);
402*5d1638f3SJens Wiklander 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
403*5d1638f3SJens Wiklander 		DMSG("secure rw: %s",
404*5d1638f3SJens Wiklander 		     tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]);
405*5d1638f3SJens Wiklander 		if (temp_32reg & (1 << 0))
406*5d1638f3SJens Wiklander 			DMSG("filter 0 enable");
407*5d1638f3SJens Wiklander 		if (temp_32reg & (1 << 1))
408*5d1638f3SJens Wiklander 			DMSG("filter 1 enable");
409*5d1638f3SJens Wiklander 		if (temp_32reg & (1 << 2))
410*5d1638f3SJens Wiklander 			DMSG("filter 2 enable");
411*5d1638f3SJens Wiklander 		if (temp_32reg & (1 << 3))
412*5d1638f3SJens Wiklander 			DMSG("filter 3 enable");
413*5d1638f3SJens Wiklander 	}
414*5d1638f3SJens Wiklander 	DMSG("exit");
415*5d1638f3SJens Wiklander }
416*5d1638f3SJens Wiklander 
417*5d1638f3SJens Wiklander #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */
418