11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 24c56bf5fSPeng Fan /* 34c56bf5fSPeng Fan * Copyright 2017 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> 354c56bf5fSPeng Fan #include <stddef.h> 364c56bf5fSPeng Fan #include <trace.h> 374c56bf5fSPeng Fan #include <util.h> 384c56bf5fSPeng Fan 394c56bf5fSPeng Fan /* 404c56bf5fSPeng Fan * Implementation defined values used to validate inputs later. 414c56bf5fSPeng Fan * Filters : max of 4 ; 0 to 3 424c56bf5fSPeng Fan * Regions : max of 9 ; 0 to 8 434c56bf5fSPeng Fan * Address width : Values between 32 to 64 444c56bf5fSPeng Fan */ 454c56bf5fSPeng Fan struct tzc_instance { 464c56bf5fSPeng Fan vaddr_t base; 474c56bf5fSPeng Fan uint8_t addr_width; 484c56bf5fSPeng Fan uint8_t num_regions; 494c56bf5fSPeng Fan }; 504c56bf5fSPeng Fan 514c56bf5fSPeng Fan static struct tzc_instance tzc; 524c56bf5fSPeng Fan 534c56bf5fSPeng Fan static uint32_t tzc_read_build_config(vaddr_t base) 544c56bf5fSPeng Fan { 554c56bf5fSPeng Fan return read32(base + BUILD_CONFIG_OFF); 564c56bf5fSPeng Fan } 574c56bf5fSPeng Fan 584c56bf5fSPeng Fan static void tzc_write_action(vaddr_t base, enum tzc_action action) 594c56bf5fSPeng Fan { 604c56bf5fSPeng Fan write32(action, base + ACTION_OFF); 614c56bf5fSPeng Fan } 624c56bf5fSPeng Fan 634c56bf5fSPeng Fan static void tzc_write_region_base_low(vaddr_t base, uint32_t region, 644c56bf5fSPeng Fan uint32_t val) 654c56bf5fSPeng Fan { 664c56bf5fSPeng Fan write32(val, base + REGION_SETUP_LOW_OFF(region)); 674c56bf5fSPeng Fan } 684c56bf5fSPeng Fan 694c56bf5fSPeng Fan static void tzc_write_region_base_high(vaddr_t base, uint32_t region, 704c56bf5fSPeng Fan uint32_t val) 714c56bf5fSPeng Fan { 724c56bf5fSPeng Fan write32(val, base + REGION_SETUP_HIGH_OFF(region)); 734c56bf5fSPeng Fan } 744c56bf5fSPeng Fan 754c56bf5fSPeng Fan static void tzc_write_region_attributes(vaddr_t base, uint32_t region, 764c56bf5fSPeng Fan uint32_t val) 774c56bf5fSPeng Fan { 784c56bf5fSPeng Fan write32(val, base + REGION_ATTRIBUTES_OFF(region)); 794c56bf5fSPeng Fan } 804c56bf5fSPeng Fan 814c56bf5fSPeng Fan void tzc_init(vaddr_t base) 824c56bf5fSPeng Fan { 834c56bf5fSPeng Fan uint32_t tzc_build; 844c56bf5fSPeng Fan 854c56bf5fSPeng Fan assert(base); 864c56bf5fSPeng Fan tzc.base = base; 874c56bf5fSPeng Fan 884c56bf5fSPeng Fan /* Save values we will use later. */ 894c56bf5fSPeng Fan tzc_build = tzc_read_build_config(tzc.base); 904c56bf5fSPeng Fan tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & 914c56bf5fSPeng Fan BUILD_CONFIG_AW_MASK) + 1; 924c56bf5fSPeng Fan tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & 934c56bf5fSPeng Fan BUILD_CONFIG_NR_MASK) + 1; 944c56bf5fSPeng Fan } 954c56bf5fSPeng Fan 964c56bf5fSPeng Fan static uint32_t addr_low(vaddr_t addr) 974c56bf5fSPeng Fan { 984c56bf5fSPeng Fan return (uint32_t)addr; 994c56bf5fSPeng Fan } 1004c56bf5fSPeng Fan 1014c56bf5fSPeng Fan static uint32_t addr_high(vaddr_t addr __maybe_unused) 1024c56bf5fSPeng Fan { 1034c56bf5fSPeng Fan #if (UINTPTR_MAX == UINT64_MAX) 1044c56bf5fSPeng Fan return addr >> 32; 1054c56bf5fSPeng Fan #else 1064c56bf5fSPeng Fan return 0; 1074c56bf5fSPeng Fan #endif 1084c56bf5fSPeng Fan } 1094c56bf5fSPeng Fan 1104c56bf5fSPeng Fan 1114c56bf5fSPeng Fan /* 1124c56bf5fSPeng Fan * `tzc_configure_region` is used to program regions into the TrustZone 1134c56bf5fSPeng Fan * controller. 1144c56bf5fSPeng Fan */ 1154c56bf5fSPeng Fan void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr) 1164c56bf5fSPeng Fan { 1174c56bf5fSPeng Fan assert(tzc.base); 1184c56bf5fSPeng Fan 1194c56bf5fSPeng Fan assert(region < tzc.num_regions); 1204c56bf5fSPeng Fan 121*fe1404daSPeng Fan /* 122*fe1404daSPeng Fan * For region 0, this high/low/size/en field is Read Only (RO). 123*fe1404daSPeng Fan * So should not configure those field for region 0. 124*fe1404daSPeng Fan */ 125*fe1404daSPeng Fan if (region) { 126*fe1404daSPeng Fan tzc_write_region_base_low(tzc.base, region, 127*fe1404daSPeng Fan addr_low(region_base)); 128*fe1404daSPeng Fan tzc_write_region_base_high(tzc.base, region, 129*fe1404daSPeng Fan addr_high(region_base)); 1304c56bf5fSPeng Fan tzc_write_region_attributes(tzc.base, region, attr); 131*fe1404daSPeng Fan } else { 132*fe1404daSPeng Fan tzc_write_region_attributes(tzc.base, region, 133*fe1404daSPeng Fan attr & TZC_ATTR_SP_MASK); 134*fe1404daSPeng Fan } 1354c56bf5fSPeng Fan } 1364c56bf5fSPeng Fan 1374c56bf5fSPeng Fan void tzc_set_action(enum tzc_action action) 1384c56bf5fSPeng Fan { 1394c56bf5fSPeng Fan assert(tzc.base); 1404c56bf5fSPeng Fan 1414c56bf5fSPeng Fan /* 1424c56bf5fSPeng Fan * - Currently no handler is provided to trap an error via interrupt 1434c56bf5fSPeng Fan * or exception. 1444c56bf5fSPeng Fan * - The interrupt action has not been tested. 1454c56bf5fSPeng Fan */ 1464c56bf5fSPeng Fan tzc_write_action(tzc.base, action); 1474c56bf5fSPeng Fan } 1484c56bf5fSPeng Fan 1494c56bf5fSPeng Fan #if TRACE_LEVEL >= TRACE_DEBUG 1504c56bf5fSPeng Fan 1514c56bf5fSPeng Fan static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) 1524c56bf5fSPeng Fan { 1534c56bf5fSPeng Fan return read32(base + REGION_ATTRIBUTES_OFF(region)); 1544c56bf5fSPeng Fan } 1554c56bf5fSPeng Fan 1564c56bf5fSPeng Fan static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) 1574c56bf5fSPeng Fan { 1584c56bf5fSPeng Fan return read32(base + REGION_SETUP_LOW_OFF(region)); 1594c56bf5fSPeng Fan } 1604c56bf5fSPeng Fan 1614c56bf5fSPeng Fan static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) 1624c56bf5fSPeng Fan { 1634c56bf5fSPeng Fan return read32(base + REGION_SETUP_HIGH_OFF(region)); 1644c56bf5fSPeng Fan } 1654c56bf5fSPeng Fan 1664c56bf5fSPeng Fan #define REGION_MAX 16 1674c56bf5fSPeng Fan void tzc_dump_state(void) 1684c56bf5fSPeng Fan { 1694c56bf5fSPeng Fan uint32_t n; 1704c56bf5fSPeng Fan uint32_t temp_32reg, temp_32reg_h; 1714c56bf5fSPeng Fan 1724c56bf5fSPeng Fan DMSG("enter"); 1734c56bf5fSPeng Fan DMSG("security_inversion_en %x\n", 1744c56bf5fSPeng Fan read32(tzc.base + SECURITY_INV_EN_OFF)); 1754c56bf5fSPeng Fan for (n = 0; n <= REGION_MAX; n++) { 1764c56bf5fSPeng Fan temp_32reg = tzc_read_region_attributes(tzc.base, n); 1774c56bf5fSPeng Fan if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK)) 1784c56bf5fSPeng Fan continue; 1794c56bf5fSPeng Fan 1804c56bf5fSPeng Fan DMSG("\n"); 1814c56bf5fSPeng Fan DMSG("region %d", n); 1824c56bf5fSPeng Fan temp_32reg = tzc_read_region_base_low(tzc.base, n); 1834c56bf5fSPeng Fan temp_32reg_h = tzc_read_region_base_high(tzc.base, n); 1844c56bf5fSPeng Fan DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); 1854c56bf5fSPeng Fan temp_32reg = tzc_read_region_attributes(tzc.base, n); 1864c56bf5fSPeng Fan DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT); 1874c56bf5fSPeng Fan DMSG("region size: %x\n", (temp_32reg & TZC_REGION_SIZE_MASK) >> 1884c56bf5fSPeng Fan TZC_REGION_SIZE_SHIFT); 1894c56bf5fSPeng Fan } 1904c56bf5fSPeng Fan DMSG("exit"); 1914c56bf5fSPeng Fan } 1924c56bf5fSPeng Fan 1934c56bf5fSPeng Fan #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ 194