xref: /optee_os/core/drivers/tzc380.c (revision 4c56bf5f97b6344e840519f6a76770552d4c924b)
1*4c56bf5fSPeng Fan /*
2*4c56bf5fSPeng Fan  * Copyright 2017 NXP
3*4c56bf5fSPeng Fan  * All rights reserved.
4*4c56bf5fSPeng Fan  *
5*4c56bf5fSPeng Fan  * Peng Fan <peng.fan@nxp.com>
6*4c56bf5fSPeng Fan  *
7*4c56bf5fSPeng Fan  * Redistribution and use in source and binary forms, with or without
8*4c56bf5fSPeng Fan  * modification, are permitted provided that the following conditions are met:
9*4c56bf5fSPeng Fan  *
10*4c56bf5fSPeng Fan  * 1. Redistributions of source code must retain the above copyright notice,
11*4c56bf5fSPeng Fan  * this list of conditions and the following disclaimer.
12*4c56bf5fSPeng Fan  *
13*4c56bf5fSPeng Fan  * 2. Redistributions in binary form must reproduce the above copyright notice,
14*4c56bf5fSPeng Fan  * this list of conditions and the following disclaimer in the documentation
15*4c56bf5fSPeng Fan  * and/or other materials provided with the distribution.
16*4c56bf5fSPeng Fan  *
17*4c56bf5fSPeng Fan  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*4c56bf5fSPeng Fan  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*4c56bf5fSPeng Fan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*4c56bf5fSPeng Fan  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21*4c56bf5fSPeng Fan  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*4c56bf5fSPeng Fan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*4c56bf5fSPeng Fan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*4c56bf5fSPeng Fan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*4c56bf5fSPeng Fan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*4c56bf5fSPeng Fan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*4c56bf5fSPeng Fan  * POSSIBILITY OF SUCH DAMAGE.
28*4c56bf5fSPeng Fan  */
29*4c56bf5fSPeng Fan 
30*4c56bf5fSPeng Fan #include <assert.h>
31*4c56bf5fSPeng Fan #include <drivers/tzc380.h>
32*4c56bf5fSPeng Fan #include <io.h>
33*4c56bf5fSPeng Fan #include <kernel/panic.h>
34*4c56bf5fSPeng Fan #include <stddef.h>
35*4c56bf5fSPeng Fan #include <trace.h>
36*4c56bf5fSPeng Fan #include <util.h>
37*4c56bf5fSPeng Fan 
38*4c56bf5fSPeng Fan /*
39*4c56bf5fSPeng Fan  * Implementation defined values used to validate inputs later.
40*4c56bf5fSPeng Fan  * Filters : max of 4 ; 0 to 3
41*4c56bf5fSPeng Fan  * Regions : max of 9 ; 0 to 8
42*4c56bf5fSPeng Fan  * Address width : Values between 32 to 64
43*4c56bf5fSPeng Fan  */
44*4c56bf5fSPeng Fan struct tzc_instance {
45*4c56bf5fSPeng Fan 	vaddr_t base;
46*4c56bf5fSPeng Fan 	uint8_t addr_width;
47*4c56bf5fSPeng Fan 	uint8_t num_regions;
48*4c56bf5fSPeng Fan };
49*4c56bf5fSPeng Fan 
50*4c56bf5fSPeng Fan static struct tzc_instance tzc;
51*4c56bf5fSPeng Fan 
52*4c56bf5fSPeng Fan static uint32_t tzc_read_build_config(vaddr_t base)
53*4c56bf5fSPeng Fan {
54*4c56bf5fSPeng Fan 	return read32(base + BUILD_CONFIG_OFF);
55*4c56bf5fSPeng Fan }
56*4c56bf5fSPeng Fan 
57*4c56bf5fSPeng Fan static void tzc_write_action(vaddr_t base, enum tzc_action action)
58*4c56bf5fSPeng Fan {
59*4c56bf5fSPeng Fan 	write32(action, base + ACTION_OFF);
60*4c56bf5fSPeng Fan }
61*4c56bf5fSPeng Fan 
62*4c56bf5fSPeng Fan static void tzc_write_region_base_low(vaddr_t base, uint32_t region,
63*4c56bf5fSPeng Fan 				      uint32_t val)
64*4c56bf5fSPeng Fan {
65*4c56bf5fSPeng Fan 	write32(val, base + REGION_SETUP_LOW_OFF(region));
66*4c56bf5fSPeng Fan }
67*4c56bf5fSPeng Fan 
68*4c56bf5fSPeng Fan static void tzc_write_region_base_high(vaddr_t base, uint32_t region,
69*4c56bf5fSPeng Fan 				       uint32_t val)
70*4c56bf5fSPeng Fan {
71*4c56bf5fSPeng Fan 	write32(val, base + REGION_SETUP_HIGH_OFF(region));
72*4c56bf5fSPeng Fan }
73*4c56bf5fSPeng Fan 
74*4c56bf5fSPeng Fan static void tzc_write_region_attributes(vaddr_t base, uint32_t region,
75*4c56bf5fSPeng Fan 					uint32_t val)
76*4c56bf5fSPeng Fan {
77*4c56bf5fSPeng Fan 	write32(val, base + REGION_ATTRIBUTES_OFF(region));
78*4c56bf5fSPeng Fan }
79*4c56bf5fSPeng Fan 
80*4c56bf5fSPeng Fan void tzc_init(vaddr_t base)
81*4c56bf5fSPeng Fan {
82*4c56bf5fSPeng Fan 	uint32_t tzc_build;
83*4c56bf5fSPeng Fan 
84*4c56bf5fSPeng Fan 	assert(base);
85*4c56bf5fSPeng Fan 	tzc.base = base;
86*4c56bf5fSPeng Fan 
87*4c56bf5fSPeng Fan 	/* Save values we will use later. */
88*4c56bf5fSPeng Fan 	tzc_build = tzc_read_build_config(tzc.base);
89*4c56bf5fSPeng Fan 	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
90*4c56bf5fSPeng Fan 			   BUILD_CONFIG_AW_MASK) + 1;
91*4c56bf5fSPeng Fan 	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
92*4c56bf5fSPeng Fan 			   BUILD_CONFIG_NR_MASK) + 1;
93*4c56bf5fSPeng Fan }
94*4c56bf5fSPeng Fan 
95*4c56bf5fSPeng Fan static uint32_t addr_low(vaddr_t addr)
96*4c56bf5fSPeng Fan {
97*4c56bf5fSPeng Fan 	return (uint32_t)addr;
98*4c56bf5fSPeng Fan }
99*4c56bf5fSPeng Fan 
100*4c56bf5fSPeng Fan static uint32_t addr_high(vaddr_t addr __maybe_unused)
101*4c56bf5fSPeng Fan {
102*4c56bf5fSPeng Fan #if (UINTPTR_MAX == UINT64_MAX)
103*4c56bf5fSPeng Fan 	return addr >> 32;
104*4c56bf5fSPeng Fan #else
105*4c56bf5fSPeng Fan 	return 0;
106*4c56bf5fSPeng Fan #endif
107*4c56bf5fSPeng Fan }
108*4c56bf5fSPeng Fan 
109*4c56bf5fSPeng Fan 
110*4c56bf5fSPeng Fan /*
111*4c56bf5fSPeng Fan  * `tzc_configure_region` is used to program regions into the TrustZone
112*4c56bf5fSPeng Fan  * controller.
113*4c56bf5fSPeng Fan  */
114*4c56bf5fSPeng Fan void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr)
115*4c56bf5fSPeng Fan {
116*4c56bf5fSPeng Fan 	assert(tzc.base);
117*4c56bf5fSPeng Fan 
118*4c56bf5fSPeng Fan 	assert(region < tzc.num_regions);
119*4c56bf5fSPeng Fan 
120*4c56bf5fSPeng Fan 	tzc_write_region_base_low(tzc.base, region, addr_low(region_base));
121*4c56bf5fSPeng Fan 	tzc_write_region_base_high(tzc.base, region, addr_high(region_base));
122*4c56bf5fSPeng Fan 	tzc_write_region_attributes(tzc.base, region, attr);
123*4c56bf5fSPeng Fan }
124*4c56bf5fSPeng Fan 
125*4c56bf5fSPeng Fan void tzc_set_action(enum tzc_action action)
126*4c56bf5fSPeng Fan {
127*4c56bf5fSPeng Fan 	assert(tzc.base);
128*4c56bf5fSPeng Fan 
129*4c56bf5fSPeng Fan 	/*
130*4c56bf5fSPeng Fan 	 * - Currently no handler is provided to trap an error via interrupt
131*4c56bf5fSPeng Fan 	 *   or exception.
132*4c56bf5fSPeng Fan 	 * - The interrupt action has not been tested.
133*4c56bf5fSPeng Fan 	 */
134*4c56bf5fSPeng Fan 	tzc_write_action(tzc.base, action);
135*4c56bf5fSPeng Fan }
136*4c56bf5fSPeng Fan 
137*4c56bf5fSPeng Fan #if TRACE_LEVEL >= TRACE_DEBUG
138*4c56bf5fSPeng Fan 
139*4c56bf5fSPeng Fan static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region)
140*4c56bf5fSPeng Fan {
141*4c56bf5fSPeng Fan 	return read32(base + REGION_ATTRIBUTES_OFF(region));
142*4c56bf5fSPeng Fan }
143*4c56bf5fSPeng Fan 
144*4c56bf5fSPeng Fan static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region)
145*4c56bf5fSPeng Fan {
146*4c56bf5fSPeng Fan 	return read32(base + REGION_SETUP_LOW_OFF(region));
147*4c56bf5fSPeng Fan }
148*4c56bf5fSPeng Fan 
149*4c56bf5fSPeng Fan static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region)
150*4c56bf5fSPeng Fan {
151*4c56bf5fSPeng Fan 	return read32(base + REGION_SETUP_HIGH_OFF(region));
152*4c56bf5fSPeng Fan }
153*4c56bf5fSPeng Fan 
154*4c56bf5fSPeng Fan #define	REGION_MAX	16
155*4c56bf5fSPeng Fan void tzc_dump_state(void)
156*4c56bf5fSPeng Fan {
157*4c56bf5fSPeng Fan 	uint32_t n;
158*4c56bf5fSPeng Fan 	uint32_t temp_32reg, temp_32reg_h;
159*4c56bf5fSPeng Fan 
160*4c56bf5fSPeng Fan 	DMSG("enter");
161*4c56bf5fSPeng Fan 	DMSG("security_inversion_en %x\n",
162*4c56bf5fSPeng Fan 	     read32(tzc.base + SECURITY_INV_EN_OFF));
163*4c56bf5fSPeng Fan 	for (n = 0; n <= REGION_MAX; n++) {
164*4c56bf5fSPeng Fan 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
165*4c56bf5fSPeng Fan 		if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK))
166*4c56bf5fSPeng Fan 			continue;
167*4c56bf5fSPeng Fan 
168*4c56bf5fSPeng Fan 		DMSG("\n");
169*4c56bf5fSPeng Fan 		DMSG("region %d", n);
170*4c56bf5fSPeng Fan 		temp_32reg = tzc_read_region_base_low(tzc.base, n);
171*4c56bf5fSPeng Fan 		temp_32reg_h = tzc_read_region_base_high(tzc.base, n);
172*4c56bf5fSPeng Fan 		DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg);
173*4c56bf5fSPeng Fan 		temp_32reg = tzc_read_region_attributes(tzc.base, n);
174*4c56bf5fSPeng Fan 		DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT);
175*4c56bf5fSPeng Fan 		DMSG("region size: %x\n", (temp_32reg & TZC_REGION_SIZE_MASK) >>
176*4c56bf5fSPeng Fan 				TZC_REGION_SIZE_SHIFT);
177*4c56bf5fSPeng Fan 	}
178*4c56bf5fSPeng Fan 	DMSG("exit");
179*4c56bf5fSPeng Fan }
180*4c56bf5fSPeng Fan 
181*4c56bf5fSPeng Fan #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */
182