1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2019, 2023-2024 NXP
4  */
5 #include <caam_common.h>
6 #include <caam_hal_ctrl.h>
7 #include <caam_hal_sm.h>
8 #include <caam_jr.h>
9 #include <caam_status.h>
10 #include <caam_sm.h>
11 #include <tee_api_defines.h>
12 
13 /*
14  * Secure memory module private data
15  */
16 static struct sm_privdata {
17 	vaddr_t baseaddr;  /* Secure memory base address */
18 	vaddr_t ctrl_addr; /* CAAM base address */
19 	vaddr_t jr_addr;   /* Job Ring base address */
20 	paddr_t jr_offset; /* Job Ring offset */
21 } sm_privdata;
22 
caam_sm_alloc(const struct caam_sm_page_desc * page_desc,struct caam_sm_page_addr * page_addr)23 enum caam_status caam_sm_alloc(const struct caam_sm_page_desc *page_desc,
24 			       struct caam_sm_page_addr *page_addr)
25 {
26 	enum caam_status ret = CAAM_FAILURE;
27 
28 	if (!page_desc || !page_addr)
29 		return TEE_ERROR_BAD_PARAMETERS;
30 
31 	ret = caam_hal_sm_check_page_partition(sm_privdata.jr_addr, page_desc);
32 	if (ret != CAAM_NO_ERROR) {
33 		SM_TRACE("Pages %u to %u or partition %u are out of bounds",
34 			 page_desc->page,
35 			 page_desc->page + page_desc->page_count - 1,
36 			 page_desc->partition);
37 		return ret;
38 	}
39 
40 	/* Check if partition is already allocated */
41 	if (!caam_hal_sm_prtn_is_free(sm_privdata.jr_addr,
42 				      page_desc->partition)) {
43 		SM_TRACE("Partition %u not available", page_desc->partition);
44 		return CAAM_BUSY;
45 	}
46 
47 	/* Open secure memory partition to all groups */
48 	caam_hal_sm_open_access_perm(sm_privdata.jr_addr, page_desc->partition);
49 	caam_hal_sm_set_access_all_group(sm_privdata.jr_addr,
50 					 page_desc->partition);
51 
52 	ret = caam_hal_sm_allocate_page(sm_privdata.jr_addr, page_desc);
53 	if (ret != CAAM_NO_ERROR) {
54 		SM_TRACE("Error allocation Pages %u to %u into partition %u",
55 			 page_desc->page,
56 			 page_desc->page + page_desc->page_count - 1,
57 			 page_desc->partition);
58 
59 		/* Free all potientiel pages allocated before failure */
60 		return caam_hal_sm_deallocate_pages(sm_privdata.jr_addr,
61 						    page_desc);
62 	}
63 
64 	page_addr->paddr = caam_hal_ctrl_get_smvaddr(sm_privdata.ctrl_addr,
65 						     sm_privdata.jr_offset) +
66 			   caam_hal_sm_get_pages_size(sm_privdata.jr_addr,
67 						      page_desc->page);
68 	page_addr->vaddr = sm_privdata.baseaddr +
69 			   caam_hal_sm_get_pages_size(sm_privdata.jr_addr,
70 						      page_desc->page);
71 
72 	SM_TRACE("Partition %u Pages %u to %u allocated @0x%" PRIxVA
73 		 " (phys 0x@%" PRIxPA,
74 		 page_desc->partition, page_desc->page,
75 		 page_desc->page + page_desc->page_count - 1, page_addr->vaddr,
76 		 page_addr->paddr);
77 
78 	return CAAM_NO_ERROR;
79 }
80 
caam_sm_free(const struct caam_sm_page_desc * page_desc)81 enum caam_status caam_sm_free(const struct caam_sm_page_desc *page_desc)
82 {
83 	enum caam_status ret = CAAM_FAILURE;
84 
85 	SM_TRACE("Free Secure Memory pages %u to %u from partition %u",
86 		 page_desc->page, page_desc->page + page_desc->page_count,
87 		 page_desc->partition);
88 
89 	/*
90 	 * De-allocate partition. It automatically releases partition's pages
91 	 * to the pool of available pages. if the partition if marked as CSP,
92 	 * pages will be zeroized. If the partition is marked as PSP,
93 	 * partition and pages will not be de-allocated and a PSP will be
94 	 * returned.
95 	 */
96 	if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr,
97 				       page_desc->partition)) {
98 		SM_TRACE("Partition %u not owned by used JR",
99 			 page_desc->partition);
100 		return TEE_ERROR_ACCESS_DENIED;
101 	}
102 
103 	ret = caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, page_desc);
104 	if (ret) {
105 		SM_TRACE("De-alloc pages %u to %u error 0x%" PRIx32,
106 			 page_desc->page,
107 			 page_desc->page + page_desc->page_count, ret);
108 
109 		return ret;
110 	}
111 
112 	ret = caam_hal_sm_deallocate_partition(sm_privdata.jr_addr,
113 					       page_desc->partition);
114 	if (ret) {
115 		SM_TRACE("De-alloc partition %u error 0x%" PRIx32,
116 			 page_desc->partition, ret);
117 		return ret;
118 	}
119 
120 	return CAAM_NO_ERROR;
121 }
122 
123 enum caam_status
caam_sm_set_access_perm(const struct caam_sm_page_desc * page_desc,unsigned int grp1_perm,unsigned int grp2_perm)124 caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc,
125 			unsigned int grp1_perm, unsigned int grp2_perm)
126 {
127 	uint32_t grp1 = 0;
128 	uint32_t grp2 = 0;
129 
130 	if (!page_desc)
131 		return CAAM_BAD_PARAM;
132 
133 	/* Check if the partition is already owned */
134 	if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr,
135 				       page_desc->partition)) {
136 		SM_TRACE("Partition %d not owned by current JR",
137 			 page_desc->partition);
138 		return CAAM_FAILURE;
139 	}
140 
141 	/*
142 	 * Set ourself to access Secure Memory group 1 and/or group 2
143 	 * function if @grp1_perm and/or @grp2_perm not equal 0.
144 	 *
145 	 * The Access Group is related to the Job Ring owner setting without
146 	 * the Secure Bit setting already managed by the Job Ring.
147 	 *
148 	 * If any group permissions are set, need to enable Secure World MID
149 	 * access in SMAG1/2 registers.
150 	 * Since both Non-Secure/Secure world has same MID, using JROWN_ARM_NS
151 	 * and if any grp1_perm/grp2_perm is set, need to enable permission
152 	 * for Secure World for partition in SMAG1/2 Registers.
153 	 */
154 	if (grp1_perm)
155 		grp1 = SHIFT_U32(1, JROWN_ARM_NS);
156 
157 	if (grp2_perm)
158 		grp2 = SHIFT_U32(1, JROWN_ARM_NS);
159 
160 	caam_hal_sm_set_access_group(sm_privdata.jr_addr, page_desc->partition,
161 				     grp1, grp2);
162 	caam_hal_sm_set_access_perm(sm_privdata.jr_addr, page_desc->partition,
163 				    grp1_perm, grp2_perm);
164 
165 	return CAAM_NO_ERROR;
166 }
167 
caam_sm_init(struct caam_jrcfg * jrcfg)168 enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg)
169 {
170 	if (!jrcfg)
171 		return CAAM_FAILURE;
172 
173 	sm_privdata.ctrl_addr = jrcfg->base;
174 	sm_privdata.jr_addr = jrcfg->base + jrcfg->offset;
175 	sm_privdata.jr_offset = jrcfg->offset;
176 	sm_privdata.baseaddr = caam_hal_sm_get_base();
177 
178 	if (!sm_privdata.baseaddr)
179 		return CAAM_FAILURE;
180 
181 	SM_TRACE("Secure Memory Base address = 0x%" PRIxVA,
182 		 sm_privdata.baseaddr);
183 	SM_TRACE("CAAM controller address = 0x%" PRIxVA, sm_privdata.ctrl_addr);
184 	SM_TRACE("CAAM Job Ring address = 0x%" PRIxVA, sm_privdata.jr_addr);
185 
186 	return CAAM_NO_ERROR;
187 }
188