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 8*ea4f7ad6SClement 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 17*ea4f7ad6SClement Faure #define SNVS_HPLR 0x00 18*ea4f7ad6SClement Faure #define SNVS_HPCOMR 0x04 19916e56edSClement Faure #define SNVS_HPSR 0x14 20*ea4f7ad6SClement Faure #define SNVS_LPLR 0x34 21*ea4f7ad6SClement 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 26916e56edSClement Faure #define SNVS_HPSR_SYS_SECURITY_BAD BIT(14) 27916e56edSClement Faure #define SNVS_HPSR_SYS_SECURITY_CLOSED BIT(13) 28916e56edSClement Faure #define SNVS_HPSR_SYS_SECURITY_OPEN BIT(12) 29*ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) 30*ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_ZERO BIT(27) 31*ea4f7ad6SClement Faure 32*ea4f7ad6SClement Faure #define SNVS_HPLR_MKS_SL BIT32(9) 33*ea4f7ad6SClement Faure 34*ea4f7ad6SClement Faure #define SNVS_LPLR_MKS_HL BIT32(9) 35*ea4f7ad6SClement Faure 36*ea4f7ad6SClement Faure #define SNVS_HPCOMR_MKS_EN BIT32(13) 37*ea4f7ad6SClement Faure #define SNVS_HPCOMR_NPSWA_EN BIT32(31) 38*ea4f7ad6SClement Faure 39*ea4f7ad6SClement Faure #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0) 40916e56edSClement Faure 41916e56edSClement Faure enum snvs_ssm_mode { 42916e56edSClement Faure SNVS_SSM_MODE_INIT, 43916e56edSClement Faure SNVS_SSM_MODE_HARD_FAIL, 44916e56edSClement Faure SNVS_SSM_MODE_SOFT_FAIL = 3, 45916e56edSClement Faure SNVS_SSM_MODE_INIT_INTERMEDIATE = 8, 46916e56edSClement Faure SNVS_SSM_MODE_CHECK, 47916e56edSClement Faure SNVS_SSM_MODE_NON_SECURE = 11, 48916e56edSClement Faure SNVS_SSM_MODE_TRUSTED = 13, 49916e56edSClement Faure SNVS_SSM_MODE_SECURE, 50916e56edSClement Faure }; 51916e56edSClement Faure 52916e56edSClement Faure enum snvs_security_cfg { 53916e56edSClement Faure SNVS_SECURITY_CFG_FAB, 54916e56edSClement Faure SNVS_SECURITY_CFG_OPEN, 55916e56edSClement Faure SNVS_SECURITY_CFG_CLOSED, 56916e56edSClement Faure SNVS_SECURITY_CFG_FIELD_RETURN, 57916e56edSClement Faure }; 58916e56edSClement Faure 59*ea4f7ad6SClement Faure /* 60*ea4f7ad6SClement Faure * Return true if the master key is OTPMK, false otherwise. 61*ea4f7ad6SClement Faure */ 62*ea4f7ad6SClement Faure static bool is_otpmk_selected(void) 63*ea4f7ad6SClement Faure { 64*ea4f7ad6SClement Faure uint32_t hp_mks = 0; 65*ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 66*ea4f7ad6SClement Faure 67*ea4f7ad6SClement Faure hp_mks = io_read32(base + SNVS_HPCOMR); 68*ea4f7ad6SClement Faure 69*ea4f7ad6SClement Faure /* 70*ea4f7ad6SClement Faure * The master key selection might be done by the MASTER_KEY_SEL field 71*ea4f7ad6SClement Faure * of LPMKCR instead. 72*ea4f7ad6SClement Faure */ 73*ea4f7ad6SClement Faure if (hp_mks & SNVS_HPCOMR_MKS_EN) { 74*ea4f7ad6SClement Faure uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); 75*ea4f7ad6SClement Faure 76*ea4f7ad6SClement Faure if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) 77*ea4f7ad6SClement Faure return false; 78*ea4f7ad6SClement Faure } 79*ea4f7ad6SClement Faure 80*ea4f7ad6SClement Faure return true; 81*ea4f7ad6SClement Faure } 82*ea4f7ad6SClement Faure 83*ea4f7ad6SClement Faure /* 84*ea4f7ad6SClement Faure * Return true if the master key selection is locked, false otherwise. 85*ea4f7ad6SClement Faure */ 86*ea4f7ad6SClement Faure static bool is_mks_locked(void) 87*ea4f7ad6SClement Faure { 88*ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 89*ea4f7ad6SClement Faure 90*ea4f7ad6SClement Faure return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || 91*ea4f7ad6SClement Faure io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; 92*ea4f7ad6SClement Faure } 93*ea4f7ad6SClement Faure 94*ea4f7ad6SClement Faure /* Set the Master key to use OTPMK and lock it. */ 95*ea4f7ad6SClement Faure static void set_mks_otpmk(void) 96*ea4f7ad6SClement Faure { 97*ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 98*ea4f7ad6SClement Faure 99*ea4f7ad6SClement Faure io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); 100*ea4f7ad6SClement Faure io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); 101*ea4f7ad6SClement Faure io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); 102*ea4f7ad6SClement Faure io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); 103*ea4f7ad6SClement Faure } 104*ea4f7ad6SClement Faure 105*ea4f7ad6SClement Faure /* 106*ea4f7ad6SClement Faure * Return true if OTPMK is valid, false otherwise. 107*ea4f7ad6SClement Faure */ 108*ea4f7ad6SClement Faure static bool is_otpmk_valid(void) 109*ea4f7ad6SClement Faure { 110*ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 111*ea4f7ad6SClement Faure uint32_t status = io_read32(base + SNVS_HPSR); 112*ea4f7ad6SClement Faure 113*ea4f7ad6SClement Faure return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); 114*ea4f7ad6SClement Faure } 115*ea4f7ad6SClement Faure 116916e56edSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 117c6ac89bcSPeng Fan { 118c2e4eb43SAnton Rybakov vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 119c2e4eb43SAnton Rybakov SNVS_HPSR + sizeof(uint32_t)); 120599784c7SRouven Czerwinski uint32_t val = 0; 121c6ac89bcSPeng Fan 122599784c7SRouven Czerwinski val = io_read32(snvs + SNVS_HPSR); 123599784c7SRouven Czerwinski DMSG("HPSR: 0x%"PRIx32, val); 124599784c7SRouven Czerwinski if (val & SNVS_HPSR_SYS_SECURITY_BAD) 125599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_FIELD_RETURN; 126599784c7SRouven Czerwinski else if (val & SNVS_HPSR_SYS_SECURITY_CLOSED) 127599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_CLOSED; 128599784c7SRouven Czerwinski else if (val & SNVS_HPSR_SYS_SECURITY_OPEN) 129599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_OPEN; 130599784c7SRouven Czerwinski else if (val > 4 && val < 8) 131599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_OPEN; 132c6ac89bcSPeng Fan 133599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_FAB; 134c6ac89bcSPeng Fan } 135c6ac89bcSPeng Fan 136*ea4f7ad6SClement Faure bool snvs_is_device_closed(void) 137*ea4f7ad6SClement Faure { 138*ea4f7ad6SClement Faure return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); 139*ea4f7ad6SClement Faure } 140*ea4f7ad6SClement Faure 141*ea4f7ad6SClement Faure #ifdef CFG_RPMB_FS 142916e56edSClement Faure static enum snvs_ssm_mode snvs_get_ssm_mode(void) 143c6ac89bcSPeng Fan { 144c2e4eb43SAnton Rybakov vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 145c2e4eb43SAnton Rybakov SNVS_HPSR + sizeof(uint32_t)); 146599784c7SRouven Czerwinski uint32_t val = 0; 147c6ac89bcSPeng Fan 148599784c7SRouven Czerwinski val = io_read32(snvs + SNVS_HPSR); 149599784c7SRouven Czerwinski val &= HPSR_SSM_ST_MASK; 150599784c7SRouven Czerwinski val = val >> HPSR_SSM_ST_SHIFT; 151599784c7SRouven Czerwinski DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); 152599784c7SRouven Czerwinski return val; 153c6ac89bcSPeng Fan } 154916e56edSClement Faure 155916e56edSClement Faure bool plat_rpmb_key_is_ready(void) 156916e56edSClement Faure { 157916e56edSClement Faure enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; 158916e56edSClement Faure enum snvs_security_cfg security = SNVS_SECURITY_CFG_OPEN; 159916e56edSClement Faure bool ssm_secure = false; 160916e56edSClement Faure 161916e56edSClement Faure mode = snvs_get_ssm_mode(); 162916e56edSClement Faure security = snvs_get_security_cfg(); 163916e56edSClement Faure ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || 164916e56edSClement Faure mode == SNVS_SSM_MODE_SECURE); 165916e56edSClement Faure 166916e56edSClement Faure /* 167916e56edSClement Faure * On i.MX6SDL and i.MX6DQ, the security cfg always returns 168916e56edSClement Faure * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security 169916e56edSClement Faure * configuration for this SoC. 170916e56edSClement Faure */ 171916e56edSClement Faure if (soc_is_imx6sdl() || soc_is_imx6dq()) 172916e56edSClement Faure return ssm_secure; 173916e56edSClement Faure 174916e56edSClement Faure return ssm_secure && (security == SNVS_SECURITY_CFG_CLOSED); 175916e56edSClement Faure } 176916e56edSClement Faure #endif /* CFG_RPMB_FS */ 177*ea4f7ad6SClement Faure 178*ea4f7ad6SClement Faure TEE_Result imx_snvs_set_master_otpmk(void) 179*ea4f7ad6SClement Faure { 180*ea4f7ad6SClement Faure if (is_otpmk_valid()) 181*ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 182*ea4f7ad6SClement Faure 183*ea4f7ad6SClement Faure if (is_mks_locked()) { 184*ea4f7ad6SClement Faure if (is_otpmk_selected()) 185*ea4f7ad6SClement Faure return TEE_SUCCESS; 186*ea4f7ad6SClement Faure 187*ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 188*ea4f7ad6SClement Faure } 189*ea4f7ad6SClement Faure 190*ea4f7ad6SClement Faure set_mks_otpmk(); 191*ea4f7ad6SClement Faure 192*ea4f7ad6SClement Faure return TEE_SUCCESS; 193*ea4f7ad6SClement Faure } 194