xref: /optee_os/core/drivers/imx_snvs.c (revision 5d5d7d0b1c038a6836be9f0b38585f5aa6a4dd01)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2020 Pengutronix
4  * Rouven Czerwinski <entwicklung@pengutronix.de>
5  * Copyright 2022-2023 NXP
6  */
7 
8 #include <drivers/imx_snvs.h>
9 #include <io.h>
10 #include <mm/core_memprot.h>
11 #include <mm/core_mmu.h>
12 #include <stdint.h>
13 #include <tee/tee_fs.h>
14 #include <types_ext.h>
15 #include <trace.h>
16 
17 #define SNVS_HPLR   0x00
18 #define SNVS_HPCOMR 0x04
19 #define SNVS_HPSR   0x14
20 #define SNVS_LPLR   0x34
21 #define SNVS_LPCR   0x38
22 #define SNVS_LPMKCR 0x3C
23 
24 #define HPSR_SSM_ST_MASK  GENMASK_32(11, 8)
25 #define HPSR_SSM_ST_SHIFT 8
26 
27 #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12
28 #define SNVS_HPSR_SYS_SECURITY_CFG	  GENMASK_32(14, 12)
29 
30 #define SNVS_HPSR_OTPMK_SYND	      GENMASK_32(24, 16)
31 #define SNVS_HPSR_OTPMK_ZERO	      BIT(27)
32 
33 #define SNVS_HPLR_MKS_SL BIT32(9)
34 
35 #define SNVS_LPLR_MKS_HL BIT32(9)
36 
37 #define SNVS_HPCOMR_MKS_EN   BIT32(13)
38 #define SNVS_HPCOMR_NPSWA_EN BIT32(31)
39 
40 #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0)
41 
42 #define SNVS_LPCR_TOP_MASK	BIT(6)
43 #define SNVS_LPCR_DP_EN_MASK	BIT(5)
44 #define SNVS_LPCR_SRTC_ENV_MASK	BIT(1)
45 
46 enum snvs_ssm_mode {
47 	SNVS_SSM_MODE_INIT,
48 	SNVS_SSM_MODE_HARD_FAIL,
49 	SNVS_SSM_MODE_SOFT_FAIL = 3,
50 	SNVS_SSM_MODE_INIT_INTERMEDIATE = 8,
51 	SNVS_SSM_MODE_CHECK,
52 	SNVS_SSM_MODE_NON_SECURE = 11,
53 	SNVS_SSM_MODE_TRUSTED = 13,
54 	SNVS_SSM_MODE_SECURE = 15,
55 };
56 
57 enum snvs_security_cfg {
58 	SNVS_SECURITY_CFG_FAB,
59 	SNVS_SECURITY_CFG_OPEN,
60 	SNVS_SECURITY_CFG_CLOSED,
61 	SNVS_SECURITY_CFG_FIELD_RETURN,
62 };
63 
64 /*
65  * Return true if the master key is OTPMK, false otherwise.
66  */
67 static bool is_otpmk_selected(void)
68 {
69 	uint32_t hp_mks = 0;
70 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
71 
72 	hp_mks = io_read32(base + SNVS_HPCOMR);
73 
74 	/*
75 	 * The master key selection might be done by the MASTER_KEY_SEL field
76 	 * of LPMKCR instead.
77 	 */
78 	if (hp_mks & SNVS_HPCOMR_MKS_EN) {
79 		uint32_t lp_mks = io_read32(base + SNVS_LPMKCR);
80 
81 		if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL)
82 			return false;
83 	}
84 
85 	return true;
86 }
87 
88 /*
89  * Return true if the master key selection is locked, false otherwise.
90  */
91 static bool is_mks_locked(void)
92 {
93 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
94 
95 	return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL ||
96 	       io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL;
97 }
98 
99 /* Set the Master key to use OTPMK and lock it. */
100 static void set_mks_otpmk(void)
101 {
102 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
103 
104 	io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN);
105 	io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL);
106 	io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL);
107 	io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL);
108 }
109 
110 /*
111  * Return true if OTPMK is valid, false otherwise.
112  */
113 static bool is_otpmk_valid(void)
114 {
115 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
116 	uint32_t status = io_read32(base + SNVS_HPSR);
117 
118 	return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND));
119 }
120 
121 static enum snvs_security_cfg snvs_get_security_cfg(void)
122 {
123 	uint32_t val = 0;
124 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
125 				       SNVS_SIZE);
126 
127 	val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >>
128 	      SNVS_HPSR_SYS_SECURITY_CFG_OFFSET;
129 
130 	switch (val) {
131 	case 0b000:
132 		return SNVS_SECURITY_CFG_FAB;
133 	case 0b001:
134 		return SNVS_SECURITY_CFG_OPEN;
135 	case 0b011:
136 		return SNVS_SECURITY_CFG_CLOSED;
137 	default:
138 		return SNVS_SECURITY_CFG_FIELD_RETURN;
139 	}
140 }
141 
142 bool snvs_is_device_closed(void)
143 {
144 	return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED);
145 }
146 
147 #ifdef CFG_RPMB_FS
148 static enum snvs_ssm_mode snvs_get_ssm_mode(void)
149 {
150 	vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC,
151 				       SNVS_HPSR + sizeof(uint32_t));
152 	uint32_t val = 0;
153 
154 	val = io_read32(snvs + SNVS_HPSR);
155 	val &= HPSR_SSM_ST_MASK;
156 	val = val >> HPSR_SSM_ST_SHIFT;
157 	DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val);
158 	return val;
159 }
160 
161 bool plat_rpmb_key_is_ready(void)
162 {
163 	enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT;
164 	bool ssm_secure = false;
165 
166 	mode = snvs_get_ssm_mode();
167 	ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED ||
168 		      mode == SNVS_SSM_MODE_SECURE);
169 
170 	/*
171 	 * On i.MX6SDL and i.MX6DQ, the security cfg always returns
172 	 * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security
173 	 * configuration for this SoC.
174 	 */
175 	if (soc_is_imx6sdl() || soc_is_imx6dq())
176 		return ssm_secure;
177 
178 	return ssm_secure && snvs_is_device_closed();
179 }
180 #endif /* CFG_RPMB_FS */
181 
182 TEE_Result imx_snvs_set_master_otpmk(void)
183 {
184 	if (!is_otpmk_valid())
185 		return TEE_ERROR_BAD_STATE;
186 
187 	if (is_mks_locked()) {
188 		if (is_otpmk_selected())
189 			return TEE_SUCCESS;
190 
191 		return TEE_ERROR_BAD_STATE;
192 	}
193 
194 	set_mks_otpmk();
195 
196 	return TEE_SUCCESS;
197 }
198 
199 void imx_snvs_shutdown(void)
200 {
201 	vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE);
202 
203 	io_write32(base + SNVS_LPCR,
204 		   SNVS_LPCR_TOP_MASK |
205 		   SNVS_LPCR_DP_EN_MASK |
206 		   SNVS_LPCR_SRTC_ENV_MASK);
207 }
208