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