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 26*5cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12 27*5cd93c5aSClement 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, 48916e56edSClement Faure SNVS_SSM_MODE_SECURE, 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 115*5cd93c5aSClement Faure #ifdef CFG_MX8M 116*5cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(15, 12) 117*5cd93c5aSClement Faure 118916e56edSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 119c6ac89bcSPeng Fan { 120599784c7SRouven Czerwinski uint32_t val = 0; 121*5cd93c5aSClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 122*5cd93c5aSClement Faure SNVS_SIZE); 123c6ac89bcSPeng Fan 124*5cd93c5aSClement Faure val = io_read32(base + SNVS_HPSR) & 125*5cd93c5aSClement Faure SNVS_HPSR_SYS_SECURITY_CFG >> SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 126c6ac89bcSPeng Fan 127*5cd93c5aSClement Faure switch (val) { 128*5cd93c5aSClement Faure case 0b0000: 129*5cd93c5aSClement Faure case 0b1000: 130599784c7SRouven Czerwinski return SNVS_SECURITY_CFG_FAB; 131*5cd93c5aSClement Faure case 0b0001: 132*5cd93c5aSClement Faure case 0b0010: 133*5cd93c5aSClement Faure case 0b0011: 134*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_OPEN; 135*5cd93c5aSClement Faure case 0b1010: 136*5cd93c5aSClement Faure case 0b1001: 137*5cd93c5aSClement Faure case 0b1011: 138*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_CLOSED; 139*5cd93c5aSClement Faure default: 140*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_FIELD_RETURN; 141c6ac89bcSPeng Fan } 142*5cd93c5aSClement Faure } 143*5cd93c5aSClement Faure #else 144*5cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) 145*5cd93c5aSClement Faure 146*5cd93c5aSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 147*5cd93c5aSClement Faure { 148*5cd93c5aSClement Faure uint32_t val = 0; 149*5cd93c5aSClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 150*5cd93c5aSClement Faure SNVS_SIZE); 151*5cd93c5aSClement Faure 152*5cd93c5aSClement Faure val = io_read32(base + SNVS_HPSR) & 153*5cd93c5aSClement Faure SNVS_HPSR_SYS_SECURITY_CFG >> SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 154*5cd93c5aSClement Faure 155*5cd93c5aSClement Faure switch (val) { 156*5cd93c5aSClement Faure case 0b000: 157*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_FAB; 158*5cd93c5aSClement Faure case 0b001: 159*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_OPEN; 160*5cd93c5aSClement Faure case 0b011: 161*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_CLOSED; 162*5cd93c5aSClement Faure default: 163*5cd93c5aSClement Faure return SNVS_SECURITY_CFG_FIELD_RETURN; 164*5cd93c5aSClement Faure } 165*5cd93c5aSClement Faure } 166*5cd93c5aSClement 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