11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 24c56bf5fSPeng Fan /* 3dd13645cSClement Faure * Copyright 2017-2020 NXP 44c56bf5fSPeng Fan * All rights reserved. 54c56bf5fSPeng Fan * 64c56bf5fSPeng Fan * Peng Fan <peng.fan@nxp.com> 74c56bf5fSPeng Fan * 84c56bf5fSPeng Fan * Redistribution and use in source and binary forms, with or without 94c56bf5fSPeng Fan * modification, are permitted provided that the following conditions are met: 104c56bf5fSPeng Fan * 114c56bf5fSPeng Fan * 1. Redistributions of source code must retain the above copyright notice, 124c56bf5fSPeng Fan * this list of conditions and the following disclaimer. 134c56bf5fSPeng Fan * 144c56bf5fSPeng Fan * 2. Redistributions in binary form must reproduce the above copyright notice, 154c56bf5fSPeng Fan * this list of conditions and the following disclaimer in the documentation 164c56bf5fSPeng Fan * and/or other materials provided with the distribution. 174c56bf5fSPeng Fan * 184c56bf5fSPeng Fan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 194c56bf5fSPeng Fan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 204c56bf5fSPeng Fan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 214c56bf5fSPeng Fan * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 224c56bf5fSPeng Fan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 234c56bf5fSPeng Fan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 244c56bf5fSPeng Fan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 254c56bf5fSPeng Fan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 264c56bf5fSPeng Fan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 274c56bf5fSPeng Fan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 284c56bf5fSPeng Fan * POSSIBILITY OF SUCH DAMAGE. 294c56bf5fSPeng Fan */ 304c56bf5fSPeng Fan 314c56bf5fSPeng Fan #include <assert.h> 324c56bf5fSPeng Fan #include <drivers/tzc380.h> 334c56bf5fSPeng Fan #include <io.h> 344c56bf5fSPeng Fan #include <kernel/panic.h> 35343c1571SPeng Fan #include <mm/core_memprot.h> 36343c1571SPeng Fan #include <mm/core_mmu.h> 374c56bf5fSPeng Fan #include <stddef.h> 384c56bf5fSPeng Fan #include <trace.h> 394c56bf5fSPeng Fan #include <util.h> 404c56bf5fSPeng Fan 414c56bf5fSPeng Fan /* 424c56bf5fSPeng Fan * Implementation defined values used to validate inputs later. 434c56bf5fSPeng Fan * Filters : max of 4 ; 0 to 3 444c56bf5fSPeng Fan * Regions : max of 9 ; 0 to 8 454c56bf5fSPeng Fan * Address width : Values between 32 to 64 464c56bf5fSPeng Fan */ 474c56bf5fSPeng Fan struct tzc_instance { 484c56bf5fSPeng Fan vaddr_t base; 494c56bf5fSPeng Fan uint8_t addr_width; 504c56bf5fSPeng Fan uint8_t num_regions; 514c56bf5fSPeng Fan }; 524c56bf5fSPeng Fan 534c56bf5fSPeng Fan static struct tzc_instance tzc; 544c56bf5fSPeng Fan 554c56bf5fSPeng Fan static uint32_t tzc_read_build_config(vaddr_t base) 564c56bf5fSPeng Fan { 57918bb3a5SEtienne Carriere return io_read32(base + BUILD_CONFIG_OFF); 584c56bf5fSPeng Fan } 594c56bf5fSPeng Fan 604c56bf5fSPeng Fan static void tzc_write_action(vaddr_t base, enum tzc_action action) 614c56bf5fSPeng Fan { 62918bb3a5SEtienne Carriere io_write32(base + ACTION_OFF, action); 634c56bf5fSPeng Fan } 644c56bf5fSPeng Fan 657eedcd15SRouven Czerwinski static uint32_t tzc_read_action(vaddr_t base) 667eedcd15SRouven Czerwinski { 677eedcd15SRouven Czerwinski return io_read32(base + ACTION_OFF); 687eedcd15SRouven Czerwinski } 697eedcd15SRouven Czerwinski 704c56bf5fSPeng Fan static void tzc_write_region_base_low(vaddr_t base, uint32_t region, 714c56bf5fSPeng Fan uint32_t val) 724c56bf5fSPeng Fan { 73918bb3a5SEtienne Carriere io_write32(base + REGION_SETUP_LOW_OFF(region), val); 744c56bf5fSPeng Fan } 754c56bf5fSPeng Fan 764c56bf5fSPeng Fan static void tzc_write_region_base_high(vaddr_t base, uint32_t region, 774c56bf5fSPeng Fan uint32_t val) 784c56bf5fSPeng Fan { 79918bb3a5SEtienne Carriere io_write32(base + REGION_SETUP_HIGH_OFF(region), val); 804c56bf5fSPeng Fan } 814c56bf5fSPeng Fan 82343c1571SPeng Fan static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) 83343c1571SPeng Fan { 84918bb3a5SEtienne Carriere return io_read32(base + REGION_ATTRIBUTES_OFF(region)); 85343c1571SPeng Fan } 86343c1571SPeng Fan 874c56bf5fSPeng Fan static void tzc_write_region_attributes(vaddr_t base, uint32_t region, 884c56bf5fSPeng Fan uint32_t val) 894c56bf5fSPeng Fan { 90918bb3a5SEtienne Carriere io_write32(base + REGION_ATTRIBUTES_OFF(region), val); 914c56bf5fSPeng Fan } 924c56bf5fSPeng Fan 934c56bf5fSPeng Fan void tzc_init(vaddr_t base) 944c56bf5fSPeng Fan { 954c56bf5fSPeng Fan uint32_t tzc_build; 964c56bf5fSPeng Fan 974c56bf5fSPeng Fan assert(base); 984c56bf5fSPeng Fan tzc.base = base; 994c56bf5fSPeng Fan 1004c56bf5fSPeng Fan /* Save values we will use later. */ 1014c56bf5fSPeng Fan tzc_build = tzc_read_build_config(tzc.base); 1024c56bf5fSPeng Fan tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & 1034c56bf5fSPeng Fan BUILD_CONFIG_AW_MASK) + 1; 1044c56bf5fSPeng Fan tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & 1054c56bf5fSPeng Fan BUILD_CONFIG_NR_MASK) + 1; 1064c56bf5fSPeng Fan } 1074c56bf5fSPeng Fan 108343c1571SPeng Fan /* 109343c1571SPeng Fan * There are two modes of operation for the region security 110343c1571SPeng Fan * permissions, with or without security inversion. 111343c1571SPeng Fan * Check TZC380 "2.2.5 Region security permissions" for 112343c1571SPeng Fan * more details. 113343c1571SPeng Fan */ 114343c1571SPeng Fan void tzc_security_inversion_en(vaddr_t base) 115343c1571SPeng Fan { 116918bb3a5SEtienne Carriere io_write32(base + SECURITY_INV_EN_OFF, 1); 117343c1571SPeng Fan } 118343c1571SPeng Fan 119343c1571SPeng Fan /* 120343c1571SPeng Fan * Enable a single region. Sometimes we could not use tzc_configure_region 121343c1571SPeng Fan * to enable the region, when security inversion is on. 122343c1571SPeng Fan * When need security inversion, we need to first configure 123343c1571SPeng Fan * region address and attribute, then configure security inversion, 124343c1571SPeng Fan * then enable the regions. 125343c1571SPeng Fan */ 126343c1571SPeng Fan void tzc_region_enable(uint8_t region) 127343c1571SPeng Fan { 128343c1571SPeng Fan uint32_t val; 129343c1571SPeng Fan 130343c1571SPeng Fan val = tzc_read_region_attributes(tzc.base, region); 131343c1571SPeng Fan val |= TZC_ATTR_REGION_EN_MASK; 132343c1571SPeng Fan tzc_write_region_attributes(tzc.base, region, val); 133343c1571SPeng Fan } 134343c1571SPeng Fan 135343c1571SPeng Fan /* 136343c1571SPeng Fan * Dump info when TZC380 catchs an unallowed access with TZC 137343c1571SPeng Fan * interrupt enabled. 138343c1571SPeng Fan */ 139343c1571SPeng Fan void tzc_fail_dump(void) 140343c1571SPeng Fan { 141343c1571SPeng Fan vaddr_t base __maybe_unused = core_mmu_get_va(tzc.base, 142c2e4eb43SAnton Rybakov MEM_AREA_IO_SEC, 143c2e4eb43SAnton Rybakov TZC400_REG_SIZE); 144343c1571SPeng Fan 145343c1571SPeng Fan EMSG("Fail address Low 0x%" PRIx32, 146918bb3a5SEtienne Carriere io_read32(base + FAIL_ADDRESS_LOW_OFF)); 147343c1571SPeng Fan EMSG("Fail address High 0x%" PRIx32, 148918bb3a5SEtienne Carriere io_read32(base + FAIL_ADDRESS_HIGH_OFF)); 149918bb3a5SEtienne Carriere EMSG("Fail Control 0x%" PRIx32, io_read32(base + FAIL_CONTROL_OFF)); 150918bb3a5SEtienne Carriere EMSG("Fail Id 0x%" PRIx32, io_read32(base + FAIL_ID)); 151343c1571SPeng Fan } 152343c1571SPeng Fan 153343c1571SPeng Fan void tzc_int_clear(void) 154343c1571SPeng Fan { 155c2e4eb43SAnton Rybakov vaddr_t base = core_mmu_get_va(tzc.base, MEM_AREA_IO_SEC, 156c2e4eb43SAnton Rybakov TZC400_REG_SIZE); 157343c1571SPeng Fan 158918bb3a5SEtienne Carriere io_write32(base + INT_CLEAR, 0); 159343c1571SPeng Fan } 160343c1571SPeng Fan 1614c56bf5fSPeng Fan static uint32_t addr_low(vaddr_t addr) 1624c56bf5fSPeng Fan { 1634c56bf5fSPeng Fan return (uint32_t)addr; 1644c56bf5fSPeng Fan } 1654c56bf5fSPeng Fan 1664c56bf5fSPeng Fan static uint32_t addr_high(vaddr_t addr __maybe_unused) 1674c56bf5fSPeng Fan { 1684c56bf5fSPeng Fan #if (UINTPTR_MAX == UINT64_MAX) 1694c56bf5fSPeng Fan return addr >> 32; 1704c56bf5fSPeng Fan #else 1714c56bf5fSPeng Fan return 0; 1724c56bf5fSPeng Fan #endif 1734c56bf5fSPeng Fan } 1744c56bf5fSPeng Fan 1754c56bf5fSPeng Fan 1764c56bf5fSPeng Fan /* 1774c56bf5fSPeng Fan * `tzc_configure_region` is used to program regions into the TrustZone 1784c56bf5fSPeng Fan * controller. 1794c56bf5fSPeng Fan */ 1804c56bf5fSPeng Fan void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr) 1814c56bf5fSPeng Fan { 1824c56bf5fSPeng Fan assert(tzc.base); 1834c56bf5fSPeng Fan 1844c56bf5fSPeng Fan assert(region < tzc.num_regions); 1854c56bf5fSPeng Fan 186fe1404daSPeng Fan /* 187fe1404daSPeng Fan * For region 0, this high/low/size/en field is Read Only (RO). 188fe1404daSPeng Fan * So should not configure those field for region 0. 189fe1404daSPeng Fan */ 190fe1404daSPeng Fan if (region) { 191fe1404daSPeng Fan tzc_write_region_base_low(tzc.base, region, 192fe1404daSPeng Fan addr_low(region_base)); 193fe1404daSPeng Fan tzc_write_region_base_high(tzc.base, region, 194fe1404daSPeng Fan addr_high(region_base)); 1954c56bf5fSPeng Fan tzc_write_region_attributes(tzc.base, region, attr); 196fe1404daSPeng Fan } else { 197fe1404daSPeng Fan tzc_write_region_attributes(tzc.base, region, 198fe1404daSPeng Fan attr & TZC_ATTR_SP_MASK); 199fe1404daSPeng Fan } 2004c56bf5fSPeng Fan } 2014c56bf5fSPeng Fan 2024c56bf5fSPeng Fan void tzc_set_action(enum tzc_action action) 2034c56bf5fSPeng Fan { 2044c56bf5fSPeng Fan assert(tzc.base); 2054c56bf5fSPeng Fan 2064c56bf5fSPeng Fan /* 2074c56bf5fSPeng Fan * - Currently no handler is provided to trap an error via interrupt 2084c56bf5fSPeng Fan * or exception. 2094c56bf5fSPeng Fan * - The interrupt action has not been tested. 2104c56bf5fSPeng Fan */ 2114c56bf5fSPeng Fan tzc_write_action(tzc.base, action); 2124c56bf5fSPeng Fan } 2134c56bf5fSPeng Fan 2147eedcd15SRouven Czerwinski uint32_t tzc_get_action(void) 2157eedcd15SRouven Czerwinski { 2167eedcd15SRouven Czerwinski assert(tzc.base); 2177eedcd15SRouven Czerwinski 2187eedcd15SRouven Czerwinski return tzc_read_action(tzc.base); 2197eedcd15SRouven Czerwinski } 2207eedcd15SRouven Czerwinski 221e8e7f1c5SRouven Czerwinski int tzc_auto_configure(vaddr_t addr, vaddr_t size, uint32_t attr, 222e8e7f1c5SRouven Czerwinski uint8_t region) 223e8e7f1c5SRouven Czerwinski { 224e8e7f1c5SRouven Czerwinski uint64_t sub_region_size = 0; 225e8e7f1c5SRouven Czerwinski uint64_t area = 0; 226e8e7f1c5SRouven Czerwinski uint8_t lregion = region; 227e8e7f1c5SRouven Czerwinski uint64_t region_size = 0; 228e8e7f1c5SRouven Czerwinski vaddr_t sub_address = 0; 229e8e7f1c5SRouven Czerwinski vaddr_t address = addr; 230e8e7f1c5SRouven Czerwinski uint64_t lsize = size; 231e8e7f1c5SRouven Czerwinski uint32_t mask = 0; 232e8e7f1c5SRouven Czerwinski int i = 0; 233dd13645cSClement Faure uint8_t pow = 0; 234dd13645cSClement Faure 235dd13645cSClement Faure assert(tzc.base); 236dd13645cSClement Faure 237dd13645cSClement Faure /* 238dd13645cSClement Faure * TZC380 RM 239dd13645cSClement Faure * For region_attributes_<n> registers, region_size: 240dd13645cSClement Faure * Note: The AXI address width, that is AXI_ADDRESS_MSB+1, controls the 241dd13645cSClement Faure * upper limit value of the field. 242dd13645cSClement Faure */ 243dd13645cSClement Faure pow = tzc.addr_width; 244e8e7f1c5SRouven Czerwinski 245e8e7f1c5SRouven Czerwinski while (lsize != 0 && pow > 15) { 246e8e7f1c5SRouven Czerwinski region_size = 1ULL << pow; 247e8e7f1c5SRouven Czerwinski 248e8e7f1c5SRouven Czerwinski /* Case region fits alignment and covers requested area */ 249e8e7f1c5SRouven Czerwinski if ((address % region_size == 0) && 250e8e7f1c5SRouven Czerwinski ((address + lsize) % region_size == 0)) { 251e8e7f1c5SRouven Czerwinski tzc_configure_region(lregion, address, 252e8e7f1c5SRouven Czerwinski TZC_ATTR_REGION_SIZE(pow - 1) | 253e8e7f1c5SRouven Czerwinski TZC_ATTR_REGION_EN_MASK | 254e8e7f1c5SRouven Czerwinski attr); 255e8e7f1c5SRouven Czerwinski lregion++; 256e8e7f1c5SRouven Czerwinski address += region_size; 257e8e7f1c5SRouven Czerwinski lsize -= region_size; 2585ae1f02aSRouven Czerwinski pow = tzc.addr_width; 259e8e7f1c5SRouven Czerwinski continue; 260e8e7f1c5SRouven Czerwinski } 261e8e7f1c5SRouven Czerwinski 262e8e7f1c5SRouven Czerwinski /* Cover area using several subregions */ 263e8e7f1c5SRouven Czerwinski sub_region_size = region_size / 8; 264e8e7f1c5SRouven Czerwinski if (address % sub_region_size == 0 && 265e8e7f1c5SRouven Czerwinski lsize > 2 * sub_region_size) { 266e8e7f1c5SRouven Czerwinski sub_address = (address / region_size) * region_size; 267e8e7f1c5SRouven Czerwinski mask = 0; 268e8e7f1c5SRouven Czerwinski for (i = 0; i < 8; i++) { 269e8e7f1c5SRouven Czerwinski area = (i + 1) * sub_region_size; 270e8e7f1c5SRouven Czerwinski if (sub_address + area <= address || 271e8e7f1c5SRouven Czerwinski sub_address + area > address + lsize) { 272e8e7f1c5SRouven Czerwinski mask |= TZC_ATTR_SUBREGION_DIS(i); 273e8e7f1c5SRouven Czerwinski } else { 274e8e7f1c5SRouven Czerwinski address += sub_region_size; 275e8e7f1c5SRouven Czerwinski lsize -= sub_region_size; 276e8e7f1c5SRouven Czerwinski } 277e8e7f1c5SRouven Czerwinski } 278e8e7f1c5SRouven Czerwinski tzc_configure_region(lregion, sub_address, 279e8e7f1c5SRouven Czerwinski TZC_ATTR_REGION_SIZE(pow - 1) | 280e8e7f1c5SRouven Czerwinski TZC_ATTR_REGION_EN_MASK | 281e8e7f1c5SRouven Czerwinski mask | attr); 282e8e7f1c5SRouven Czerwinski lregion++; 2835ae1f02aSRouven Czerwinski pow = tzc.addr_width; 284e8e7f1c5SRouven Czerwinski continue; 285e8e7f1c5SRouven Czerwinski } 286e8e7f1c5SRouven Czerwinski pow--; 287e8e7f1c5SRouven Czerwinski } 288e8e7f1c5SRouven Czerwinski assert(lsize == 0); 289e8e7f1c5SRouven Czerwinski assert(address == addr + size); 290e8e7f1c5SRouven Czerwinski return lregion; 291e8e7f1c5SRouven Czerwinski } 292e8e7f1c5SRouven Czerwinski 2935544b89dSRouven Czerwinski /* 2945544b89dSRouven Czerwinski * `region_lockdown` is used to lockdown the TZC380 configuration to prevent 2955544b89dSRouven Czerwinski * unintended overwrites of the configuration. Returns TEE_ERROR_SECURITY in 2965544b89dSRouven Czerwinski * case the lockdown fails. 2975544b89dSRouven Czerwinski */ 2985544b89dSRouven Czerwinski TEE_Result tzc_regions_lockdown(void) 2995544b89dSRouven Czerwinski { 3005544b89dSRouven Czerwinski uint32_t val = 0; 3015544b89dSRouven Czerwinski uint32_t check = 0; 3025544b89dSRouven Czerwinski 303*552e0c1cSClement Faure val = LOCKDOWN_RANGE_ENABLE | (tzc.num_regions - 1); 3045544b89dSRouven Czerwinski io_write32(tzc.base + LOCKDOWN_RANGE_OFF, val); 3055544b89dSRouven Czerwinski check = io_read32(tzc.base + LOCKDOWN_RANGE_OFF); 3065544b89dSRouven Czerwinski if (check != val) 3075544b89dSRouven Czerwinski return TEE_ERROR_SECURITY; 3085544b89dSRouven Czerwinski 3095544b89dSRouven Czerwinski val = LOCKDOWN_SELECT_RANGE_ENABLE; 3105544b89dSRouven Czerwinski io_write32(tzc.base + LOCKDOWN_SELECT_OFF, val); 3115544b89dSRouven Czerwinski check = io_read32(tzc.base + LOCKDOWN_SELECT_OFF); 3125544b89dSRouven Czerwinski if (check != val) 3135544b89dSRouven Czerwinski return TEE_ERROR_SECURITY; 3145544b89dSRouven Czerwinski 3155544b89dSRouven Czerwinski return TEE_SUCCESS; 3165544b89dSRouven Czerwinski } 3175544b89dSRouven Czerwinski 3184c56bf5fSPeng Fan #if TRACE_LEVEL >= TRACE_DEBUG 3194c56bf5fSPeng Fan 3204c56bf5fSPeng Fan static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) 3214c56bf5fSPeng Fan { 322918bb3a5SEtienne Carriere return io_read32(base + REGION_SETUP_LOW_OFF(region)); 3234c56bf5fSPeng Fan } 3244c56bf5fSPeng Fan 3254c56bf5fSPeng Fan static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) 3264c56bf5fSPeng Fan { 327918bb3a5SEtienne Carriere return io_read32(base + REGION_SETUP_HIGH_OFF(region)); 3284c56bf5fSPeng Fan } 3294c56bf5fSPeng Fan 3304c56bf5fSPeng Fan #define REGION_MAX 16 3314c56bf5fSPeng Fan void tzc_dump_state(void) 3324c56bf5fSPeng Fan { 3334c56bf5fSPeng Fan uint32_t n; 3344c56bf5fSPeng Fan uint32_t temp_32reg, temp_32reg_h; 3354c56bf5fSPeng Fan 3369fff1a96SRouven Czerwinski DMSG("TZC380 configuration:"); 33765fe41dbSEtienne Carriere DMSG("security_inversion_en %x", 338918bb3a5SEtienne Carriere io_read32(tzc.base + SECURITY_INV_EN_OFF)); 3394c56bf5fSPeng Fan for (n = 0; n <= REGION_MAX; n++) { 3404c56bf5fSPeng Fan temp_32reg = tzc_read_region_attributes(tzc.base, n); 3414c56bf5fSPeng Fan if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK)) 3424c56bf5fSPeng Fan continue; 3434c56bf5fSPeng Fan 34465fe41dbSEtienne Carriere DMSG(""); 3454c56bf5fSPeng Fan DMSG("region %d", n); 3464c56bf5fSPeng Fan temp_32reg = tzc_read_region_base_low(tzc.base, n); 3474c56bf5fSPeng Fan temp_32reg_h = tzc_read_region_base_high(tzc.base, n); 3484c56bf5fSPeng Fan DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); 3494c56bf5fSPeng Fan temp_32reg = tzc_read_region_attributes(tzc.base, n); 3504c56bf5fSPeng Fan DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT); 35165fe41dbSEtienne Carriere DMSG("region size: %x", (temp_32reg & TZC_REGION_SIZE_MASK) >> 3524c56bf5fSPeng Fan TZC_REGION_SIZE_SHIFT); 3534c56bf5fSPeng Fan } 3549fff1a96SRouven Czerwinski DMSG("Lockdown select: %"PRIx32, 3559fff1a96SRouven Czerwinski io_read32(tzc.base + LOCKDOWN_SELECT_OFF)); 3569fff1a96SRouven Czerwinski DMSG("Lockdown range: %"PRIx32, 3579fff1a96SRouven Czerwinski io_read32(tzc.base + LOCKDOWN_RANGE_OFF)); 3589fff1a96SRouven Czerwinski DMSG("Action register: %"PRIx32, tzc_get_action()); 3594c56bf5fSPeng Fan DMSG("exit"); 3604c56bf5fSPeng Fan } 3614c56bf5fSPeng Fan 3624c56bf5fSPeng Fan #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ 363