xref: /optee_os/core/drivers/imx_snvs.c (revision 11c218dbfdab949c36ff48c44e13862ab3d78581)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2c6ac89bcSPeng Fan /*
3599784c7SRouven Czerwinski  * Copyright (C) 2020 Pengutronix
4599784c7SRouven Czerwinski  * Rouven Czerwinski <entwicklung@pengutronix.de>
5*11c218dbSClement Faure  * Copyright 2022-2023 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
21*11c218dbSClement Faure #define SNVS_LPCR   0x38
22ea4f7ad6SClement Faure #define SNVS_LPMKCR 0x3C
23916e56edSClement Faure 
24916e56edSClement Faure #define HPSR_SSM_ST_MASK  GENMASK_32(11, 8)
25916e56edSClement Faure #define HPSR_SSM_ST_SHIFT 8
26916e56edSClement Faure 
275cd93c5aSClement Faure #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12
28bcf9ecadSFranck LENORMAND #define SNVS_HPSR_SYS_SECURITY_CFG	  GENMASK_32(14, 12)
295cd93c5aSClement Faure 
30ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_SYND	      GENMASK_32(24, 16)
31ea4f7ad6SClement Faure #define SNVS_HPSR_OTPMK_ZERO	      BIT(27)
32ea4f7ad6SClement Faure 
33ea4f7ad6SClement Faure #define SNVS_HPLR_MKS_SL BIT32(9)
34ea4f7ad6SClement Faure 
35ea4f7ad6SClement Faure #define SNVS_LPLR_MKS_HL BIT32(9)
36ea4f7ad6SClement Faure 
37ea4f7ad6SClement Faure #define SNVS_HPCOMR_MKS_EN   BIT32(13)
38ea4f7ad6SClement Faure #define SNVS_HPCOMR_NPSWA_EN BIT32(31)
39ea4f7ad6SClement Faure 
40ea4f7ad6SClement Faure #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0)
41916e56edSClement Faure 
42*11c218dbSClement Faure #define SNVS_LPCR_TOP_MASK	BIT(6)
43*11c218dbSClement Faure #define SNVS_LPCR_DP_EN_MASK	BIT(5)
44*11c218dbSClement Faure #define SNVS_LPCR_SRTC_ENV_MASK	BIT(1)
45*11c218dbSClement Faure 
46916e56edSClement Faure enum snvs_ssm_mode {
47916e56edSClement Faure 	SNVS_SSM_MODE_INIT,
48916e56edSClement Faure 	SNVS_SSM_MODE_HARD_FAIL,
49916e56edSClement Faure 	SNVS_SSM_MODE_SOFT_FAIL = 3,
50916e56edSClement Faure 	SNVS_SSM_MODE_INIT_INTERMEDIATE = 8,
51916e56edSClement Faure 	SNVS_SSM_MODE_CHECK,
52916e56edSClement Faure 	SNVS_SSM_MODE_NON_SECURE = 11,
53916e56edSClement Faure 	SNVS_SSM_MODE_TRUSTED = 13,
54ec93a5a2SClement Faure 	SNVS_SSM_MODE_SECURE = 15,
55916e56edSClement Faure };
56916e56edSClement Faure 
57916e56edSClement Faure enum snvs_security_cfg {
58916e56edSClement Faure 	SNVS_SECURITY_CFG_FAB,
59916e56edSClement Faure 	SNVS_SECURITY_CFG_OPEN,
60916e56edSClement Faure 	SNVS_SECURITY_CFG_CLOSED,
61916e56edSClement Faure 	SNVS_SECURITY_CFG_FIELD_RETURN,
62916e56edSClement Faure };
63916e56edSClement Faure 
64ea4f7ad6SClement Faure /*
65ea4f7ad6SClement Faure  * Return true if the master key is OTPMK, false otherwise.
66ea4f7ad6SClement Faure  */
is_otpmk_selected(void)67ea4f7ad6SClement Faure static bool is_otpmk_selected(void)
68ea4f7ad6SClement Faure {
69ea4f7ad6SClement Faure 	uint32_t hp_mks = 0;
70ea4f7ad6SClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
71ea4f7ad6SClement Faure 
72ea4f7ad6SClement Faure 	hp_mks = io_read32(base + SNVS_HPCOMR);
73ea4f7ad6SClement Faure 
74ea4f7ad6SClement Faure 	/*
75ea4f7ad6SClement Faure 	 * The master key selection might be done by the MASTER_KEY_SEL field
76ea4f7ad6SClement Faure 	 * of LPMKCR instead.
77ea4f7ad6SClement Faure 	 */
78ea4f7ad6SClement Faure 	if (hp_mks & SNVS_HPCOMR_MKS_EN) {
79ea4f7ad6SClement Faure 		uint32_t lp_mks = io_read32(base + SNVS_LPMKCR);
80ea4f7ad6SClement Faure 
81ea4f7ad6SClement Faure 		if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL)
82ea4f7ad6SClement Faure 			return false;
83ea4f7ad6SClement Faure 	}
84ea4f7ad6SClement Faure 
85ea4f7ad6SClement Faure 	return true;
86ea4f7ad6SClement Faure }
87ea4f7ad6SClement Faure 
88ea4f7ad6SClement Faure /*
89ea4f7ad6SClement Faure  * Return true if the master key selection is locked, false otherwise.
90ea4f7ad6SClement Faure  */
is_mks_locked(void)91ea4f7ad6SClement Faure static bool is_mks_locked(void)
92ea4f7ad6SClement Faure {
93ea4f7ad6SClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
94ea4f7ad6SClement Faure 
95ea4f7ad6SClement Faure 	return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL ||
96ea4f7ad6SClement Faure 	       io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL;
97ea4f7ad6SClement Faure }
98ea4f7ad6SClement Faure 
99ea4f7ad6SClement Faure /* Set the Master key to use OTPMK and lock it. */
set_mks_otpmk(void)100ea4f7ad6SClement Faure static void set_mks_otpmk(void)
101ea4f7ad6SClement Faure {
102ea4f7ad6SClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
103ea4f7ad6SClement Faure 
104ea4f7ad6SClement Faure 	io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN);
105ea4f7ad6SClement Faure 	io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL);
106ea4f7ad6SClement Faure 	io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL);
107ea4f7ad6SClement Faure 	io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL);
108ea4f7ad6SClement Faure }
109ea4f7ad6SClement Faure 
110ea4f7ad6SClement Faure /*
111ea4f7ad6SClement Faure  * Return true if OTPMK is valid, false otherwise.
112ea4f7ad6SClement Faure  */
is_otpmk_valid(void)113ea4f7ad6SClement Faure static bool is_otpmk_valid(void)
114ea4f7ad6SClement Faure {
115ea4f7ad6SClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
116ea4f7ad6SClement Faure 	uint32_t status = io_read32(base + SNVS_HPSR);
117ea4f7ad6SClement Faure 
118ea4f7ad6SClement Faure 	return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND));
119ea4f7ad6SClement Faure }
120ea4f7ad6SClement Faure 
snvs_get_security_cfg(void)1215cd93c5aSClement Faure static enum snvs_security_cfg snvs_get_security_cfg(void)
1225cd93c5aSClement Faure {
1235cd93c5aSClement Faure 	uint32_t val = 0;
1245cd93c5aSClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
1255cd93c5aSClement Faure 				       SNVS_SIZE);
1265cd93c5aSClement Faure 
127de2fcd34SFranck LENORMAND 	val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >>
128de2fcd34SFranck LENORMAND 	      SNVS_HPSR_SYS_SECURITY_CFG_OFFSET;
1295cd93c5aSClement Faure 
1305cd93c5aSClement Faure 	switch (val) {
1315cd93c5aSClement Faure 	case 0b000:
1325cd93c5aSClement Faure 		return SNVS_SECURITY_CFG_FAB;
1335cd93c5aSClement Faure 	case 0b001:
1345cd93c5aSClement Faure 		return SNVS_SECURITY_CFG_OPEN;
1355cd93c5aSClement Faure 	case 0b011:
1365cd93c5aSClement Faure 		return SNVS_SECURITY_CFG_CLOSED;
1375cd93c5aSClement Faure 	default:
1385cd93c5aSClement Faure 		return SNVS_SECURITY_CFG_FIELD_RETURN;
1395cd93c5aSClement Faure 	}
1405cd93c5aSClement Faure }
141c6ac89bcSPeng Fan 
snvs_is_device_closed(void)142ea4f7ad6SClement Faure bool snvs_is_device_closed(void)
143ea4f7ad6SClement Faure {
144ea4f7ad6SClement Faure 	return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED);
145ea4f7ad6SClement Faure }
146ea4f7ad6SClement Faure 
147ea4f7ad6SClement Faure #ifdef CFG_RPMB_FS
snvs_get_ssm_mode(void)148916e56edSClement Faure static enum snvs_ssm_mode snvs_get_ssm_mode(void)
149c6ac89bcSPeng Fan {
150c2e4eb43SAnton Rybakov 	vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
151c2e4eb43SAnton Rybakov 				       SNVS_HPSR + sizeof(uint32_t));
152599784c7SRouven Czerwinski 	uint32_t val = 0;
153c6ac89bcSPeng Fan 
154599784c7SRouven Czerwinski 	val = io_read32(snvs + SNVS_HPSR);
155599784c7SRouven Czerwinski 	val &= HPSR_SSM_ST_MASK;
156599784c7SRouven Czerwinski 	val = val >> HPSR_SSM_ST_SHIFT;
157599784c7SRouven Czerwinski 	DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val);
158599784c7SRouven Czerwinski 	return val;
159c6ac89bcSPeng Fan }
160916e56edSClement Faure 
plat_rpmb_key_is_ready(void)161916e56edSClement Faure bool plat_rpmb_key_is_ready(void)
162916e56edSClement Faure {
163916e56edSClement Faure 	enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT;
164916e56edSClement Faure 	bool ssm_secure = false;
165916e56edSClement Faure 
166916e56edSClement Faure 	mode = snvs_get_ssm_mode();
167916e56edSClement Faure 	ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED ||
168916e56edSClement Faure 		      mode == SNVS_SSM_MODE_SECURE);
169916e56edSClement Faure 
170916e56edSClement Faure 	/*
171916e56edSClement Faure 	 * On i.MX6SDL and i.MX6DQ, the security cfg always returns
172916e56edSClement Faure 	 * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security
173916e56edSClement Faure 	 * configuration for this SoC.
174916e56edSClement Faure 	 */
175916e56edSClement Faure 	if (soc_is_imx6sdl() || soc_is_imx6dq())
176916e56edSClement Faure 		return ssm_secure;
177916e56edSClement Faure 
17848141578SClement Faure 	return ssm_secure && snvs_is_device_closed();
179916e56edSClement Faure }
180916e56edSClement Faure #endif /* CFG_RPMB_FS */
181ea4f7ad6SClement Faure 
imx_snvs_set_master_otpmk(void)182ea4f7ad6SClement Faure TEE_Result imx_snvs_set_master_otpmk(void)
183ea4f7ad6SClement Faure {
184332dec4aSFranck LENORMAND 	if (!is_otpmk_valid())
185ea4f7ad6SClement Faure 		return TEE_ERROR_BAD_STATE;
186ea4f7ad6SClement Faure 
187ea4f7ad6SClement Faure 	if (is_mks_locked()) {
188ea4f7ad6SClement Faure 		if (is_otpmk_selected())
189ea4f7ad6SClement Faure 			return TEE_SUCCESS;
190ea4f7ad6SClement Faure 
191ea4f7ad6SClement Faure 		return TEE_ERROR_BAD_STATE;
192ea4f7ad6SClement Faure 	}
193ea4f7ad6SClement Faure 
194ea4f7ad6SClement Faure 	set_mks_otpmk();
195ea4f7ad6SClement Faure 
196ea4f7ad6SClement Faure 	return TEE_SUCCESS;
197ea4f7ad6SClement Faure }
198*11c218dbSClement Faure 
imx_snvs_shutdown(void)199*11c218dbSClement Faure void imx_snvs_shutdown(void)
200*11c218dbSClement Faure {
201*11c218dbSClement Faure 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
202*11c218dbSClement Faure 
203*11c218dbSClement Faure 	io_write32(base + SNVS_LPCR,
204*11c218dbSClement Faure 		   SNVS_LPCR_TOP_MASK |
205*11c218dbSClement Faure 		   SNVS_LPCR_DP_EN_MASK |
206*11c218dbSClement Faure 		   SNVS_LPCR_SRTC_ENV_MASK);
207*11c218dbSClement Faure }
208