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