diff options
author | Tom Rini <trini@konsulko.com> | 2021-07-27 09:11:25 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-07-27 09:11:25 -0400 |
commit | 0d4823fbebae6ebbf558a9325d86b37c67d848d9 (patch) | |
tree | 46c84c5039fc1d2ce0ff441e32603de406976db5 /arch/arm/mach-stm32mp/tzc400.c | |
parent | df59b7d23be71db03275e4c1b243e67397b50f9a (diff) | |
parent | 65b3f56d42e5ddc9183843723cf735950f062410 (diff) |
Merge tag 'u-boot-stm32-20210727' of https://source.denx.de/u-boot/custodians/u-boot-stm
- FIP Enable OP-TEE and TZC support in SPL for STM32MP15 SoC
- Add stm32mp15 missing SPI clock support
- Manage pull-up on gpio button STM32MP15 boards
- Correct STM32MP15 boot when TAMPER registers are invalid
- Fix EMMC pinmux on STM32MP15 Avenger96 board
Diffstat (limited to 'arch/arm/mach-stm32mp/tzc400.c')
-rw-r--r-- | arch/arm/mach-stm32mp/tzc400.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/arch/arm/mach-stm32mp/tzc400.c b/arch/arm/mach-stm32mp/tzc400.c new file mode 100644 index 0000000000..cdc4a40eda --- /dev/null +++ b/arch/arm/mach-stm32mp/tzc400.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Simple API for configuring TrustZone memory restrictions for TZC400 + */ + +#define LOG_CATEGORY LOGC_ARCH + +#include <linux/iopoll.h> +#include <mach/tzc.h> + +#define TZC_TIMEOUT_US 100 + +#define TZC_BUILD_CONFIG 0x00 +#define TZC_ACTION 0x04 +#define TZC_ACTION_NONE 0 +#define TZC_ACTION_ERR 1 +#define TZC_ACTION_INT 2 +#define TZC_ACTION_INT_ERR 3 +#define TZC_GATE_KEEPER 0x08 + +#define TZC_REGION0_OFFSET 0x100 +#define TZC_REGION_CFG_SIZE 0x20 +#define TZC_REGION1_OFFSET 0x120 +#define TZC_REGION_BASE 0x00 +#define TZC_REGION_TOP 0x08 +#define TZC_REGION_ATTRIBUTE 0x10 +#define TZC_REGION_ACCESS 0x14 + +static uint32_t tzc_read(uintptr_t tzc, size_t reg) +{ + return readl(tzc + reg); +} + +static void tzc_write(uintptr_t tzc, size_t reg, uint32_t val) +{ + writel(val, tzc + reg); +} + +static uint16_t tzc_config_get_active_filters(const struct tzc_region *cfg) +{ + uint16_t active_filters = 0; + + for ( ; cfg->top != 0; cfg++) + active_filters |= cfg->filters_mask; + + return active_filters; +} + +int tzc_configure(uintptr_t tzc, const struct tzc_region *cfg) +{ + uintptr_t region = tzc + TZC_REGION1_OFFSET; + uint32_t nsid, attr_reg, active_filters; + int ret; + + active_filters = tzc_config_get_active_filters(cfg); + if (active_filters == 0) + return -EINVAL; + + ret = tzc_disable_filters(tzc, active_filters); + if (ret < 0) + return ret; + + for ( ; cfg->top != 0; cfg++, region += TZC_REGION_CFG_SIZE) { + attr_reg = (cfg->sec_mode & 0x03) << 30; + attr_reg |= (cfg->filters_mask & 0x03) << 0; + nsid = cfg->nsec_id & 0xffff; + nsid |= nsid << 16; + + tzc_write(region, TZC_REGION_BASE, cfg->base); + tzc_write(region, TZC_REGION_TOP, cfg->top); + tzc_write(region, TZC_REGION_ACCESS, nsid); + tzc_write(region, TZC_REGION_ATTRIBUTE, attr_reg); + } + + tzc_write(tzc, TZC_ACTION, TZC_ACTION_ERR); + return tzc_enable_filters(tzc, active_filters); +} + +int tzc_disable_filters(uintptr_t tzc, uint16_t filters_mask) +{ + uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER); + uint32_t filter_status = filters_mask << 16; + + gate &= ~filters_mask; + tzc_write(tzc, TZC_GATE_KEEPER, gate); + + return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate, + (gate & filter_status) == 0, TZC_TIMEOUT_US); +} + +int tzc_enable_filters(uintptr_t tzc, uint16_t filters_mask) +{ + uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER); + uint32_t filter_status = filters_mask << 16; + + gate |= filters_mask; + tzc_write(tzc, TZC_GATE_KEEPER, gate); + + return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate, + (gate & filter_status) == filter_status, + TZC_TIMEOUT_US); +} + +static const char *sec_access_str_from_attr(uint32_t attr) +{ + const char *const sec_mode[] = { "none", "RO ", "WO ", "RW " }; + + return sec_mode[(attr >> 30) & 0x03]; +} + +void tzc_dump_config(uintptr_t tzc) +{ + uint32_t build_config, base, top, attr, nsaid; + int num_regions, i; + uintptr_t region; + + build_config = tzc_read(tzc, TZC_BUILD_CONFIG); + num_regions = ((build_config >> 0) & 0x1f) + 1; + + for (i = 0; i < num_regions; i++) { + region = tzc + TZC_REGION0_OFFSET + i * TZC_REGION_CFG_SIZE; + + base = tzc_read(region, TZC_REGION_BASE); + top = tzc_read(region, TZC_REGION_TOP); + attr = tzc_read(region, TZC_REGION_ATTRIBUTE); + nsaid = tzc_read(region, TZC_REGION_ACCESS); + + if (attr == 0 && nsaid == 0) + continue; + + log_info("TZC region %u: %08x->%08x - filters 0x%x\n", + i, base, top, (attr >> 0) & 0xf); + log_info("\t Secure access %s NSAID %08x\n", + sec_access_str_from_attr(attr), nsaid); + } +} |