xref: /arm-trusted-firmware/drivers/arm/tzc/tzc380.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <stddef.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <drivers/arm/tzc380.h>
12*91f16700Schasinglulu #include <lib/mmio.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu struct tzc380_instance {
15*91f16700Schasinglulu 	uintptr_t base;
16*91f16700Schasinglulu 	uint8_t addr_width;
17*91f16700Schasinglulu 	uint8_t num_regions;
18*91f16700Schasinglulu };
19*91f16700Schasinglulu 
20*91f16700Schasinglulu struct tzc380_instance tzc380;
21*91f16700Schasinglulu 
22*91f16700Schasinglulu static unsigned int tzc380_read_build_config(uintptr_t base)
23*91f16700Schasinglulu {
24*91f16700Schasinglulu 	return mmio_read_32(base + TZC380_CONFIGURATION_OFF);
25*91f16700Schasinglulu }
26*91f16700Schasinglulu 
27*91f16700Schasinglulu static void tzc380_write_action(uintptr_t base, unsigned int action)
28*91f16700Schasinglulu {
29*91f16700Schasinglulu 	mmio_write_32(base + ACTION_OFF, action);
30*91f16700Schasinglulu }
31*91f16700Schasinglulu 
32*91f16700Schasinglulu static void tzc380_write_region_base_low(uintptr_t base, unsigned int region,
33*91f16700Schasinglulu 				      unsigned int val)
34*91f16700Schasinglulu {
35*91f16700Schasinglulu 	mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val);
36*91f16700Schasinglulu }
37*91f16700Schasinglulu 
38*91f16700Schasinglulu static void tzc380_write_region_base_high(uintptr_t base, unsigned int region,
39*91f16700Schasinglulu 				       unsigned int val)
40*91f16700Schasinglulu {
41*91f16700Schasinglulu 	mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val);
42*91f16700Schasinglulu }
43*91f16700Schasinglulu 
44*91f16700Schasinglulu static void tzc380_write_region_attributes(uintptr_t base, unsigned int region,
45*91f16700Schasinglulu 					unsigned int val)
46*91f16700Schasinglulu {
47*91f16700Schasinglulu 	mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val);
48*91f16700Schasinglulu }
49*91f16700Schasinglulu 
50*91f16700Schasinglulu void tzc380_init(uintptr_t base)
51*91f16700Schasinglulu {
52*91f16700Schasinglulu 	unsigned int tzc_build;
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	assert(base != 0U);
55*91f16700Schasinglulu 	tzc380.base = base;
56*91f16700Schasinglulu 
57*91f16700Schasinglulu 	/* Save values we will use later. */
58*91f16700Schasinglulu 	tzc_build = tzc380_read_build_config(tzc380.base);
59*91f16700Schasinglulu 	tzc380.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
60*91f16700Schasinglulu 			      BUILD_CONFIG_AW_MASK) + 1;
61*91f16700Schasinglulu 	tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
62*91f16700Schasinglulu 			       BUILD_CONFIG_NR_MASK) + 1;
63*91f16700Schasinglulu }
64*91f16700Schasinglulu 
65*91f16700Schasinglulu static uint32_t addr_low(uintptr_t addr)
66*91f16700Schasinglulu {
67*91f16700Schasinglulu 	return (uint32_t)addr;
68*91f16700Schasinglulu }
69*91f16700Schasinglulu 
70*91f16700Schasinglulu static uint32_t addr_high(uintptr_t addr __unused)
71*91f16700Schasinglulu {
72*91f16700Schasinglulu #if (UINTPTR_MAX == UINT64_MAX)
73*91f16700Schasinglulu 	return addr >> 32;
74*91f16700Schasinglulu #else
75*91f16700Schasinglulu 	return 0;
76*91f16700Schasinglulu #endif
77*91f16700Schasinglulu }
78*91f16700Schasinglulu 
79*91f16700Schasinglulu /*
80*91f16700Schasinglulu  * `tzc380_configure_region` is used to program regions into the TrustZone
81*91f16700Schasinglulu  * controller.
82*91f16700Schasinglulu  */
83*91f16700Schasinglulu void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr)
84*91f16700Schasinglulu {
85*91f16700Schasinglulu 	assert(tzc380.base != 0U);
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	assert(region < tzc380.num_regions);
88*91f16700Schasinglulu 
89*91f16700Schasinglulu 	tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base));
90*91f16700Schasinglulu 	tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base));
91*91f16700Schasinglulu 	tzc380_write_region_attributes(tzc380.base, region, attr);
92*91f16700Schasinglulu }
93*91f16700Schasinglulu 
94*91f16700Schasinglulu void tzc380_set_action(unsigned int action)
95*91f16700Schasinglulu {
96*91f16700Schasinglulu 	assert(tzc380.base != 0U);
97*91f16700Schasinglulu 
98*91f16700Schasinglulu 	/*
99*91f16700Schasinglulu 	 * - Currently no handler is provided to trap an error via interrupt
100*91f16700Schasinglulu 	 *   or exception.
101*91f16700Schasinglulu 	 * - The interrupt action has not been tested.
102*91f16700Schasinglulu 	 */
103*91f16700Schasinglulu 	tzc380_write_action(tzc380.base, action);
104*91f16700Schasinglulu }
105