11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2c6ac89bcSPeng Fan /* 3599784c7SRouven Czerwinski * Copyright (C) 2020 Pengutronix 4599784c7SRouven Czerwinski * Rouven Czerwinski <entwicklung@pengutronix.de> 5916e56edSClement Faure * Copyright 2022 NXP 6c6ac89bcSPeng Fan */ 7c6ac89bcSPeng Fan 8ea4f7ad6SClement Faure #include <drivers/imx_snvs.h> 9c6ac89bcSPeng Fan #include <io.h> 10c6ac89bcSPeng Fan #include <mm/core_memprot.h> 11c6ac89bcSPeng Fan #include <mm/core_mmu.h> 12c6ac89bcSPeng Fan #include <stdint.h> 13916e56edSClement Faure #include <tee/tee_fs.h> 14c6ac89bcSPeng Fan #include <types_ext.h> 15c6ac89bcSPeng Fan #include <trace.h> 16c6ac89bcSPeng Fan 17ea4f7ad6SClement Faure #define SNVS_HPLR 0x00 18ea4f7ad6SClement Faure #define SNVS_HPCOMR 0x04 19916e56edSClement Faure #define SNVS_HPSR 0x14 20ea4f7ad6SClement Faure #define SNVS_LPLR 0x34 21ea4f7ad6SClement Faure #define SNVS_LPMKCR 0x3C 22916e56edSClement Faure 23916e56edSClement Faure #define HPSR_SSM_ST_MASK GENMASK_32(11, 8) 24916e56edSClement Faure #define HPSR_SSM_ST_SHIFT 8 25916e56edSClement Faure 265cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12 275cd93c5aSClement Faure 28ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) 29ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_ZERO BIT(27) 30ea4f7ad6SClement Faure 31ea4f7ad6SClement Faure #define SNVS_HPLR_MKS_SL BIT32(9) 32ea4f7ad6SClement Faure 33ea4f7ad6SClement Faure #define SNVS_LPLR_MKS_HL BIT32(9) 34ea4f7ad6SClement Faure 35ea4f7ad6SClement Faure #define SNVS_HPCOMR_MKS_EN BIT32(13) 36ea4f7ad6SClement Faure #define SNVS_HPCOMR_NPSWA_EN BIT32(31) 37ea4f7ad6SClement Faure 38ea4f7ad6SClement Faure #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0) 39916e56edSClement Faure 40916e56edSClement Faure enum snvs_ssm_mode { 41916e56edSClement Faure SNVS_SSM_MODE_INIT, 42916e56edSClement Faure SNVS_SSM_MODE_HARD_FAIL, 43916e56edSClement Faure SNVS_SSM_MODE_SOFT_FAIL = 3, 44916e56edSClement Faure SNVS_SSM_MODE_INIT_INTERMEDIATE = 8, 45916e56edSClement Faure SNVS_SSM_MODE_CHECK, 46916e56edSClement Faure SNVS_SSM_MODE_NON_SECURE = 11, 47916e56edSClement Faure SNVS_SSM_MODE_TRUSTED = 13, 48*ec93a5a2SClement Faure SNVS_SSM_MODE_SECURE = 15, 49916e56edSClement Faure }; 50916e56edSClement Faure 51916e56edSClement Faure enum snvs_security_cfg { 52916e56edSClement Faure SNVS_SECURITY_CFG_FAB, 53916e56edSClement Faure SNVS_SECURITY_CFG_OPEN, 54916e56edSClement Faure SNVS_SECURITY_CFG_CLOSED, 55916e56edSClement Faure SNVS_SECURITY_CFG_FIELD_RETURN, 56916e56edSClement Faure }; 57916e56edSClement Faure 58ea4f7ad6SClement Faure /* 59ea4f7ad6SClement Faure * Return true if the master key is OTPMK, false otherwise. 60ea4f7ad6SClement Faure */ 61ea4f7ad6SClement Faure static bool is_otpmk_selected(void) 62ea4f7ad6SClement Faure { 63ea4f7ad6SClement Faure uint32_t hp_mks = 0; 64ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 65ea4f7ad6SClement Faure 66ea4f7ad6SClement Faure hp_mks = io_read32(base + SNVS_HPCOMR); 67ea4f7ad6SClement Faure 68ea4f7ad6SClement Faure /* 69ea4f7ad6SClement Faure * The master key selection might be done by the MASTER_KEY_SEL field 70ea4f7ad6SClement Faure * of LPMKCR instead. 71ea4f7ad6SClement Faure */ 72ea4f7ad6SClement Faure if (hp_mks & SNVS_HPCOMR_MKS_EN) { 73ea4f7ad6SClement Faure uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); 74ea4f7ad6SClement Faure 75ea4f7ad6SClement Faure if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) 76ea4f7ad6SClement Faure return false; 77ea4f7ad6SClement Faure } 78ea4f7ad6SClement Faure 79ea4f7ad6SClement Faure return true; 80ea4f7ad6SClement Faure } 81ea4f7ad6SClement Faure 82ea4f7ad6SClement Faure /* 83ea4f7ad6SClement Faure * Return true if the master key selection is locked, false otherwise. 84ea4f7ad6SClement Faure */ 85ea4f7ad6SClement Faure static bool is_mks_locked(void) 86ea4f7ad6SClement Faure { 87ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 88ea4f7ad6SClement Faure 89ea4f7ad6SClement Faure return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || 90ea4f7ad6SClement Faure io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; 91ea4f7ad6SClement Faure } 92ea4f7ad6SClement Faure 93ea4f7ad6SClement Faure /* Set the Master key to use OTPMK and lock it. */ 94ea4f7ad6SClement Faure static void set_mks_otpmk(void) 95ea4f7ad6SClement Faure { 96ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 97ea4f7ad6SClement Faure 98ea4f7ad6SClement Faure io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); 99ea4f7ad6SClement Faure io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); 100ea4f7ad6SClement Faure io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); 101ea4f7ad6SClement Faure io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); 102ea4f7ad6SClement Faure } 103ea4f7ad6SClement Faure 104ea4f7ad6SClement Faure /* 105ea4f7ad6SClement Faure * Return true if OTPMK is valid, false otherwise. 106ea4f7ad6SClement Faure */ 107ea4f7ad6SClement Faure static bool is_otpmk_valid(void) 108ea4f7ad6SClement Faure { 109ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 110ea4f7ad6SClement Faure uint32_t status = io_read32(base + SNVS_HPSR); 111ea4f7ad6SClement Faure 112ea4f7ad6SClement Faure return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); 113ea4f7ad6SClement Faure } 114ea4f7ad6SClement Faure 1155cd93c5aSClement Faure #ifdef CFG_MX8M 1165cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(15, 12) 1175cd93c5aSClement Faure 118916e56edSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 119c6ac89bcSPeng Fan { 120599784c7SRouven Czerwinski uint32_t val = 0; 1215cd93c5aSClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 1225cd93c5aSClement Faure SNVS_SIZE); 123c6ac89bcSPeng Fan 1245cd93c5aSClement Faure val = io_read32(base + SNVS_HPSR) & 1255cd93c5aSClement Faure SNVS_HPSR_SYS_SECURITY_CFG >> SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 126c6ac89bcSPeng Fan 1275cd93c5aSClement Faure switch (val) { 1285cd93c5aSClement Faure case 0b0000: 1295cd93c5aSClement Faure case 0b1000: 130599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_FAB; 1315cd93c5aSClement Faure case 0b0001: 1325cd93c5aSClement Faure case 0b0010: 1335cd93c5aSClement Faure case 0b0011: 1345cd93c5aSClement Faure return SNVS_SECURITY_CFG_OPEN; 1355cd93c5aSClement Faure case 0b1010: 1365cd93c5aSClement Faure case 0b1001: 1375cd93c5aSClement Faure case 0b1011: 1385cd93c5aSClement Faure return SNVS_SECURITY_CFG_CLOSED; 1395cd93c5aSClement Faure default: 1405cd93c5aSClement Faure return SNVS_SECURITY_CFG_FIELD_RETURN; 141c6ac89bcSPeng Fan } 1425cd93c5aSClement Faure } 1435cd93c5aSClement Faure #else 1445cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) 1455cd93c5aSClement Faure 1465cd93c5aSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 1475cd93c5aSClement Faure { 1485cd93c5aSClement Faure uint32_t val = 0; 1495cd93c5aSClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 1505cd93c5aSClement Faure SNVS_SIZE); 1515cd93c5aSClement Faure 1525cd93c5aSClement Faure val = io_read32(base + SNVS_HPSR) & 1535cd93c5aSClement Faure SNVS_HPSR_SYS_SECURITY_CFG >> SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 1545cd93c5aSClement Faure 1555cd93c5aSClement Faure switch (val) { 1565cd93c5aSClement Faure case 0b000: 1575cd93c5aSClement Faure return SNVS_SECURITY_CFG_FAB; 1585cd93c5aSClement Faure case 0b001: 1595cd93c5aSClement Faure return SNVS_SECURITY_CFG_OPEN; 1605cd93c5aSClement Faure case 0b011: 1615cd93c5aSClement Faure return SNVS_SECURITY_CFG_CLOSED; 1625cd93c5aSClement Faure default: 1635cd93c5aSClement Faure return SNVS_SECURITY_CFG_FIELD_RETURN; 1645cd93c5aSClement Faure } 1655cd93c5aSClement Faure } 1665cd93c5aSClement Faure #endif 167c6ac89bcSPeng Fan 168ea4f7ad6SClement Faure bool snvs_is_device_closed(void) 169ea4f7ad6SClement Faure { 170ea4f7ad6SClement Faure return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); 171ea4f7ad6SClement Faure } 172ea4f7ad6SClement Faure 173ea4f7ad6SClement Faure #ifdef CFG_RPMB_FS 174916e56edSClement Faure static enum snvs_ssm_mode snvs_get_ssm_mode(void) 175c6ac89bcSPeng Fan { 176c2e4eb43SAnton Rybakov vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 177c2e4eb43SAnton Rybakov SNVS_HPSR + sizeof(uint32_t)); 178599784c7SRouven Czerwinski uint32_t val = 0; 179c6ac89bcSPeng Fan 180599784c7SRouven Czerwinski val = io_read32(snvs + SNVS_HPSR); 181599784c7SRouven Czerwinski val &= HPSR_SSM_ST_MASK; 182599784c7SRouven Czerwinski val = val >> HPSR_SSM_ST_SHIFT; 183599784c7SRouven Czerwinski DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); 184599784c7SRouven Czerwinski return val; 185c6ac89bcSPeng Fan } 186916e56edSClement Faure 187916e56edSClement Faure bool plat_rpmb_key_is_ready(void) 188916e56edSClement Faure { 189916e56edSClement Faure enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; 190916e56edSClement Faure enum snvs_security_cfg security = SNVS_SECURITY_CFG_OPEN; 191916e56edSClement Faure bool ssm_secure = false; 192916e56edSClement Faure 193916e56edSClement Faure mode = snvs_get_ssm_mode(); 194916e56edSClement Faure security = snvs_get_security_cfg(); 195916e56edSClement Faure ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || 196916e56edSClement Faure mode == SNVS_SSM_MODE_SECURE); 197916e56edSClement Faure 198916e56edSClement Faure /* 199916e56edSClement Faure * On i.MX6SDL and i.MX6DQ, the security cfg always returns 200916e56edSClement Faure * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security 201916e56edSClement Faure * configuration for this SoC. 202916e56edSClement Faure */ 203916e56edSClement Faure if (soc_is_imx6sdl() || soc_is_imx6dq()) 204916e56edSClement Faure return ssm_secure; 205916e56edSClement Faure 206916e56edSClement Faure return ssm_secure && (security == SNVS_SECURITY_CFG_CLOSED); 207916e56edSClement Faure } 208916e56edSClement Faure #endif /* CFG_RPMB_FS */ 209ea4f7ad6SClement Faure 210ea4f7ad6SClement Faure TEE_Result imx_snvs_set_master_otpmk(void) 211ea4f7ad6SClement Faure { 212ea4f7ad6SClement Faure if (is_otpmk_valid()) 213ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 214ea4f7ad6SClement Faure 215ea4f7ad6SClement Faure if (is_mks_locked()) { 216ea4f7ad6SClement Faure if (is_otpmk_selected()) 217ea4f7ad6SClement Faure return TEE_SUCCESS; 218ea4f7ad6SClement Faure 219ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 220ea4f7ad6SClement Faure } 221ea4f7ad6SClement Faure 222ea4f7ad6SClement Faure set_mks_otpmk(); 223ea4f7ad6SClement Faure 224ea4f7ad6SClement Faure return TEE_SUCCESS; 225ea4f7ad6SClement Faure } 226