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 27*bcf9ecadSFranck LENORMAND #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) 285cd93c5aSClement Faure 29ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) 30ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_ZERO BIT(27) 31ea4f7ad6SClement Faure 32ea4f7ad6SClement Faure #define SNVS_HPLR_MKS_SL BIT32(9) 33ea4f7ad6SClement Faure 34ea4f7ad6SClement Faure #define SNVS_LPLR_MKS_HL BIT32(9) 35ea4f7ad6SClement Faure 36ea4f7ad6SClement Faure #define SNVS_HPCOMR_MKS_EN BIT32(13) 37ea4f7ad6SClement Faure #define SNVS_HPCOMR_NPSWA_EN BIT32(31) 38ea4f7ad6SClement Faure 39ea4f7ad6SClement 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, 49ec93a5a2SClement Faure SNVS_SSM_MODE_SECURE = 15, 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 59ea4f7ad6SClement Faure /* 60ea4f7ad6SClement Faure * Return true if the master key is OTPMK, false otherwise. 61ea4f7ad6SClement Faure */ 62ea4f7ad6SClement Faure static bool is_otpmk_selected(void) 63ea4f7ad6SClement Faure { 64ea4f7ad6SClement Faure uint32_t hp_mks = 0; 65ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 66ea4f7ad6SClement Faure 67ea4f7ad6SClement Faure hp_mks = io_read32(base + SNVS_HPCOMR); 68ea4f7ad6SClement Faure 69ea4f7ad6SClement Faure /* 70ea4f7ad6SClement Faure * The master key selection might be done by the MASTER_KEY_SEL field 71ea4f7ad6SClement Faure * of LPMKCR instead. 72ea4f7ad6SClement Faure */ 73ea4f7ad6SClement Faure if (hp_mks & SNVS_HPCOMR_MKS_EN) { 74ea4f7ad6SClement Faure uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); 75ea4f7ad6SClement Faure 76ea4f7ad6SClement Faure if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) 77ea4f7ad6SClement Faure return false; 78ea4f7ad6SClement Faure } 79ea4f7ad6SClement Faure 80ea4f7ad6SClement Faure return true; 81ea4f7ad6SClement Faure } 82ea4f7ad6SClement Faure 83ea4f7ad6SClement Faure /* 84ea4f7ad6SClement Faure * Return true if the master key selection is locked, false otherwise. 85ea4f7ad6SClement Faure */ 86ea4f7ad6SClement Faure static bool is_mks_locked(void) 87ea4f7ad6SClement Faure { 88ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 89ea4f7ad6SClement Faure 90ea4f7ad6SClement Faure return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || 91ea4f7ad6SClement Faure io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; 92ea4f7ad6SClement Faure } 93ea4f7ad6SClement Faure 94ea4f7ad6SClement Faure /* Set the Master key to use OTPMK and lock it. */ 95ea4f7ad6SClement Faure static void set_mks_otpmk(void) 96ea4f7ad6SClement Faure { 97ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 98ea4f7ad6SClement Faure 99ea4f7ad6SClement Faure io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); 100ea4f7ad6SClement Faure io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); 101ea4f7ad6SClement Faure io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); 102ea4f7ad6SClement Faure io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); 103ea4f7ad6SClement Faure } 104ea4f7ad6SClement Faure 105ea4f7ad6SClement Faure /* 106ea4f7ad6SClement Faure * Return true if OTPMK is valid, false otherwise. 107ea4f7ad6SClement Faure */ 108ea4f7ad6SClement Faure static bool is_otpmk_valid(void) 109ea4f7ad6SClement Faure { 110ea4f7ad6SClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); 111ea4f7ad6SClement Faure uint32_t status = io_read32(base + SNVS_HPSR); 112ea4f7ad6SClement Faure 113ea4f7ad6SClement Faure return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); 114ea4f7ad6SClement Faure } 115ea4f7ad6SClement Faure 1165cd93c5aSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void) 1175cd93c5aSClement Faure { 1185cd93c5aSClement Faure uint32_t val = 0; 1195cd93c5aSClement Faure vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 1205cd93c5aSClement Faure SNVS_SIZE); 1215cd93c5aSClement Faure 122de2fcd34SFranck LENORMAND val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >> 123de2fcd34SFranck LENORMAND SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; 1245cd93c5aSClement Faure 1255cd93c5aSClement Faure switch (val) { 1265cd93c5aSClement Faure case 0b000: 1275cd93c5aSClement Faure return SNVS_SECURITY_CFG_FAB; 1285cd93c5aSClement Faure case 0b001: 1295cd93c5aSClement Faure return SNVS_SECURITY_CFG_OPEN; 1305cd93c5aSClement Faure case 0b011: 1315cd93c5aSClement Faure return SNVS_SECURITY_CFG_CLOSED; 1325cd93c5aSClement Faure default: 1335cd93c5aSClement Faure return SNVS_SECURITY_CFG_FIELD_RETURN; 1345cd93c5aSClement Faure } 1355cd93c5aSClement Faure } 136c6ac89bcSPeng Fan 137ea4f7ad6SClement Faure bool snvs_is_device_closed(void) 138ea4f7ad6SClement Faure { 139ea4f7ad6SClement Faure return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); 140ea4f7ad6SClement Faure } 141ea4f7ad6SClement Faure 142ea4f7ad6SClement Faure #ifdef CFG_RPMB_FS 143916e56edSClement Faure static enum snvs_ssm_mode snvs_get_ssm_mode(void) 144c6ac89bcSPeng Fan { 145c2e4eb43SAnton Rybakov vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 146c2e4eb43SAnton Rybakov SNVS_HPSR + sizeof(uint32_t)); 147599784c7SRouven Czerwinski uint32_t val = 0; 148c6ac89bcSPeng Fan 149599784c7SRouven Czerwinski val = io_read32(snvs + SNVS_HPSR); 150599784c7SRouven Czerwinski val &= HPSR_SSM_ST_MASK; 151599784c7SRouven Czerwinski val = val >> HPSR_SSM_ST_SHIFT; 152599784c7SRouven Czerwinski DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); 153599784c7SRouven Czerwinski return val; 154c6ac89bcSPeng Fan } 155916e56edSClement Faure 156916e56edSClement Faure bool plat_rpmb_key_is_ready(void) 157916e56edSClement Faure { 158916e56edSClement Faure enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; 159916e56edSClement Faure bool ssm_secure = false; 160916e56edSClement Faure 161916e56edSClement Faure mode = snvs_get_ssm_mode(); 162916e56edSClement Faure ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || 163916e56edSClement Faure mode == SNVS_SSM_MODE_SECURE); 164916e56edSClement Faure 165916e56edSClement Faure /* 166916e56edSClement Faure * On i.MX6SDL and i.MX6DQ, the security cfg always returns 167916e56edSClement Faure * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security 168916e56edSClement Faure * configuration for this SoC. 169916e56edSClement Faure */ 170916e56edSClement Faure if (soc_is_imx6sdl() || soc_is_imx6dq()) 171916e56edSClement Faure return ssm_secure; 172916e56edSClement Faure 17348141578SClement Faure return ssm_secure && snvs_is_device_closed(); 174916e56edSClement Faure } 175916e56edSClement Faure #endif /* CFG_RPMB_FS */ 176ea4f7ad6SClement Faure 177ea4f7ad6SClement Faure TEE_Result imx_snvs_set_master_otpmk(void) 178ea4f7ad6SClement Faure { 179332dec4aSFranck LENORMAND if (!is_otpmk_valid()) 180ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 181ea4f7ad6SClement Faure 182ea4f7ad6SClement Faure if (is_mks_locked()) { 183ea4f7ad6SClement Faure if (is_otpmk_selected()) 184ea4f7ad6SClement Faure return TEE_SUCCESS; 185ea4f7ad6SClement Faure 186ea4f7ad6SClement Faure return TEE_ERROR_BAD_STATE; 187ea4f7ad6SClement Faure } 188ea4f7ad6SClement Faure 189ea4f7ad6SClement Faure set_mks_otpmk(); 190ea4f7ad6SClement Faure 191ea4f7ad6SClement Faure return TEE_SUCCESS; 192ea4f7ad6SClement Faure } 193