xref: /optee_os/core/drivers/crypto/caam/hal/common/hal_sm.c (revision 461cf006f26c8f9af67271c010f5b838c7479e1f)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2019, 2023 NXP
4  */
5 #include <caam_sm.h>
6 #include <caam_common.h>
7 #include <caam_hal_sm.h>
8 #include <caam_io.h>
9 #include <caam_status.h>
10 #include <kernel/boot.h>
11 #include <kernel/delay.h>
12 #include <kernel/dt.h>
13 #include <mm/core_memprot.h>
14 #include <registers/sm_regs.h>
15 #include <registers/version_regs.h>
16 #include <stdint.h>
17 #include <tee_api_defines.h>
18 #include <tee_api_types.h>
19 
20 /*
21  * Issue a Secure Memory Command to the @page and @partition.
22  * Returns the command status when completed
23  *
24  * @jr_base    JR virtual base address
25  * @page       Memory Page
26  * @partition  Partition
27  * @cmd        Command to sent
28  */
issue_cmd(vaddr_t jr_base,unsigned int page,unsigned int partition,uint8_t cmd)29 static uint32_t issue_cmd(vaddr_t jr_base, unsigned int page,
30 			  unsigned int partition, uint8_t cmd)
31 {
32 	uint32_t status = 0;
33 	uint64_t timeout_ref = timeout_init_us(10000);
34 
35 	assert(jr_base);
36 
37 	/* Send cmd */
38 	io_caam_write32(jr_base + SM_SMCR, SM_SMCR_PAGE(page) |
39 					   SM_SMCR_PRTN(partition) |
40 					   SM_SMCR_CMD(cmd));
41 
42 	/* Wait for the command to complete */
43 	do {
44 		if (timeout_elapsed(timeout_ref))
45 			break;
46 		status = io_caam_read32(jr_base + SM_SMCSR);
47 	} while (SM_SMCSR_CERR(status) == SM_SMCSR_CERR_NOT_COMPLETED);
48 
49 	return io_caam_read32(jr_base + SM_SMCSR);
50 }
51 
52 enum caam_status
caam_hal_sm_check_page_partition(vaddr_t jr_base,const struct caam_sm_page_desc * page_desc)53 caam_hal_sm_check_page_partition(vaddr_t jr_base,
54 				 const struct caam_sm_page_desc *page_desc)
55 {
56 	uint32_t val = 0;
57 
58 	if (!jr_base || !page_desc)
59 		return CAAM_BAD_PARAM;
60 
61 	val = io_caam_read32(jr_base + SMVID_MS);
62 
63 	if (page_desc->page + page_desc->page_count >
64 		    GET_SMVID_MS_MAX_NPAG(val) ||
65 	    page_desc->partition > GET_SMVID_MS_NPRT(val))
66 		return CAAM_BAD_PARAM;
67 
68 	return CAAM_NO_ERROR;
69 }
70 
caam_hal_sm_get_pages_size(vaddr_t jr_base,unsigned int page)71 size_t caam_hal_sm_get_pages_size(vaddr_t jr_base, unsigned int page)
72 {
73 	size_t page_size = 0;
74 
75 	page_size = GET_SMVID_LS_PSIZ(io_caam_read32(jr_base + SMVID_LS));
76 
77 	return SHIFT_U32(1, page_size) * (size_t)page * 1024;
78 }
79 
caam_hal_sm_prtn_is_free(vaddr_t jr_base,unsigned int partition)80 bool caam_hal_sm_prtn_is_free(vaddr_t jr_base, unsigned int partition)
81 {
82 	return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) ==
83 	       SMPO_PO_AVAIL;
84 }
85 
caam_hal_sm_prtn_is_owned(vaddr_t jr_base,unsigned int partition)86 bool caam_hal_sm_prtn_is_owned(vaddr_t jr_base, unsigned int partition)
87 {
88 	return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) ==
89 	       SMPO_PO_OWNED;
90 }
91 
caam_hal_sm_set_access_all_group(vaddr_t jr_base,unsigned int partition)92 void caam_hal_sm_set_access_all_group(vaddr_t jr_base, unsigned int partition)
93 {
94 	io_caam_write32(jr_base + SM_SMAG1(partition), UINT32_MAX);
95 	io_caam_write32(jr_base + SM_SMAG2(partition), UINT32_MAX);
96 }
97 
caam_hal_sm_set_access_group(vaddr_t jr_base,unsigned int partition,uint32_t grp1,uint32_t grp2)98 void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition,
99 				  uint32_t grp1, uint32_t grp2)
100 {
101 	if (!jr_base)
102 		return;
103 
104 	io_caam_write32(jr_base + SM_SMAG1(partition), grp1);
105 	io_caam_write32(jr_base + SM_SMAG2(partition), grp2);
106 }
107 
caam_hal_sm_open_access_perm(vaddr_t jr_base,unsigned int partition)108 void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition)
109 {
110 	io_caam_write32(jr_base + SM_SMAPR(partition),
111 			SM_SMAPR_GRP1(UINT8_MAX) | SM_SMAPR_GRP2(UINT8_MAX));
112 }
113 
caam_hal_sm_set_access_perm(vaddr_t jr_base,unsigned int partition,unsigned int grp1_perm,unsigned int grp2_perm)114 void caam_hal_sm_set_access_perm(vaddr_t jr_base, unsigned int partition,
115 				 unsigned int grp1_perm, unsigned int grp2_perm)
116 {
117 	io_caam_write32(jr_base + SM_SMAPR(partition),
118 			SM_SMAPR_GRP1(grp1_perm) | SM_SMAPR_GRP2(grp2_perm) |
119 			SM_SMAPR_CSP | SM_SMAPR_SMAP_LCK | SM_SMAPR_SMAG_LCK);
120 }
121 
122 enum caam_status
caam_hal_sm_allocate_page(vaddr_t jr_base,const struct caam_sm_page_desc * page_desc)123 caam_hal_sm_allocate_page(vaddr_t jr_base,
124 			  const struct caam_sm_page_desc *page_desc)
125 {
126 	unsigned int page = 0;
127 	uint32_t status = 0;
128 
129 	if (!jr_base || !page_desc)
130 		return CAAM_BAD_PARAM;
131 
132 	/* Check if pages are available */
133 	for (page = page_desc->page;
134 	     page < page_desc->page + page_desc->page_count; page++) {
135 		status = issue_cmd(jr_base, page, page_desc->partition,
136 				   SM_SMCR_PAGE_INQ);
137 		if (SM_SMCSR_PO(status) != SM_SMCSR_PO_AVAILABLE)
138 			return CAAM_BUSY;
139 	}
140 
141 	/* Allocate pages to partition */
142 	for (page = page_desc->page;
143 	     page < page_desc->page + page_desc->page_count; page++) {
144 		status = issue_cmd(jr_base, page, page_desc->partition,
145 				   SM_SMCR_PAGE_ALLOC);
146 		if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR)
147 			return CAAM_FAILURE;
148 	}
149 
150 	/* Check if pages are available */
151 	for (page = page_desc->page;
152 	     page < page_desc->page + page_desc->page_count; page++) {
153 		status = issue_cmd(jr_base, page, page_desc->partition,
154 				   SM_SMCR_PAGE_INQ);
155 		if (SM_SMCSR_PO(status) != SM_SMCSR_PO_OWNED ||
156 		    SM_SMCSR_PRTN(status) != page_desc->partition)
157 			return CAAM_FAILURE;
158 	}
159 
160 	return CAAM_NO_ERROR;
161 }
162 
caam_hal_sm_deallocate_partition(vaddr_t jr_base,unsigned int partition)163 enum caam_status caam_hal_sm_deallocate_partition(vaddr_t jr_base,
164 						  unsigned int partition)
165 {
166 	unsigned int status = 0;
167 
168 	if (!jr_base)
169 		return CAAM_BAD_PARAM;
170 
171 	/* De-Allocate partition and so all partition's page */
172 	status = issue_cmd(jr_base, 0, partition, SM_SMCR_PARTITION_DEALLOC);
173 	if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR)
174 		return CAAM_FAILURE;
175 
176 	return CAAM_NO_ERROR;
177 }
178 
179 enum caam_status
caam_hal_sm_deallocate_pages(vaddr_t jr_base,const struct caam_sm_page_desc * page_desc)180 caam_hal_sm_deallocate_pages(vaddr_t jr_base,
181 			     const struct caam_sm_page_desc *page_desc)
182 {
183 	unsigned int page = 0;
184 	uint32_t status = 0;
185 
186 	if (!jr_base || !page_desc)
187 		return CAAM_BAD_PARAM;
188 
189 	for (page = page_desc->page;
190 	     page < page_desc->page + page_desc->page_count; page++) {
191 		/* Deallocate page, set partition as not used */
192 		status = issue_cmd(jr_base, page, 0, SM_SMCR_PAGE_DEALLOC);
193 		if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR)
194 			return CAAM_FAILURE;
195 	}
196 
197 	return CAAM_NO_ERROR;
198 }
199 
200 register_phys_mem(MEM_AREA_IO_SEC, SECMEM_BASE, SECMEM_SIZE);
caam_hal_sm_get_base(void)201 vaddr_t caam_hal_sm_get_base(void)
202 {
203 	vaddr_t sm_base = 0;
204 	void *fdt = NULL;
205 
206 	fdt = get_dt();
207 	if (fdt)
208 		caam_hal_sm_get_base_dt(fdt, &sm_base);
209 
210 	if (!sm_base)
211 		sm_base = core_mmu_get_va(SECMEM_BASE, MEM_AREA_IO_SEC,
212 					  SECMEM_SIZE);
213 
214 	return sm_base;
215 }
216