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