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