xref: /optee_os/core/drivers/imx_snvs.c (revision ea4f7ad67de4e1d03729d5a2d393185086cb4aa3)
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