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