blob: 260008223775c1d0c03338549fd3b94bc80c77b2 [file] [log] [blame]
developer1966afb2023-08-08 16:02:18 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 Mediatek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
8#include <linux/bitmap.h>
9#include <linux/bitops.h>
10#include <linux/err.h>
11#include <linux/lockdep.h>
12#include <linux/spinlock.h>
13
14#include "pce/cdrt.h"
15#include "pce/internal.h"
16#include "pce/netsys.h"
17
18/* decrypt use cdrt idx 1 ~ 15, encrypt use cdrt idx 16 ~ 31 */
19#define CDRT_ENC_MAX_ENTRY 16
20#define CDRT_ENC_IDX_OFS 16
21#define CDRT_DEC_MAX_ENTRY 15
22#define CDRT_DEC_IDX_OFS 1
23
24struct cdrt_hardware {
25 DECLARE_BITMAP(enc_used, CDRT_ENC_MAX_ENTRY);
26 DECLARE_BITMAP(dec_used, CDRT_DEC_MAX_ENTRY);
27 struct cdrt_entry enc_tbl[CDRT_ENC_MAX_ENTRY];
28 struct cdrt_entry dec_tbl[CDRT_DEC_MAX_ENTRY];
29 spinlock_t lock;
30};
31
32struct cdrt_hardware cdrt_hw;
33
developer1966afb2023-08-08 16:02:18 +080034int mtk_pce_cdrt_desc_write(struct cdrt_desc *desc, u32 idx)
35{
36 struct fe_mem_msg msg;
37 int ret;
38
39 if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
40 return -EINVAL;
41
42 memset(&msg.raw, 0, sizeof(msg.raw));
43
44 /* write CDR 0 ~ 3 */
45 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
46 3 * idx);
47 memcpy(&msg.raw, &desc->raw1, sizeof(desc->raw1));
48
49 ret = mtk_pce_fe_mem_msg_send(&msg);
50 if (ret)
51 return ret;
52
53 /* write CDR 4 ~ 7 */
54 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
55 3 * idx + 1);
56 memcpy(&msg.raw, &desc->raw2, sizeof(desc->raw2));
57
58 ret = mtk_pce_fe_mem_msg_send(&msg);
59 if (ret)
60 return ret;
61
62 /* write CDR 8 ~ 11 */
63 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
64 3 * idx + 2);
65 memcpy(&msg.raw, &desc->raw3, sizeof(desc->raw3));
66
67 ret = mtk_pce_fe_mem_msg_send(&msg);
68
69 return ret;
70}
71
72int mtk_pce_cdrt_desc_read(struct cdrt_desc *desc, u32 idx)
73{
74 struct fe_mem_msg msg;
75 int ret;
76
77 if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
78 return -EINVAL;
79
80 memset(&msg.raw, 0, sizeof(msg.raw));
81
82 /* read CDR 0 ~ 3 */
83 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
84 3 * idx);
85 ret = mtk_pce_fe_mem_msg_send(&msg);
86 if (ret)
87 return ret;
88
89 memcpy(&desc->raw1, &msg.raw, sizeof(desc->raw1));
90
91 /* read CDR 4 ~ 7 */
92 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
93 3 * idx + 1);
94 ret = mtk_pce_fe_mem_msg_send(&msg);
95 if (ret)
96 return ret;
97
98 memcpy(&desc->raw2, &msg.raw, sizeof(desc->raw2));
99
100 /* read CDR 8 ~ 11 */
101 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
102 3 * idx + 2);
103 ret = mtk_pce_fe_mem_msg_send(&msg);
104 if (ret)
105 return ret;
106
107 memcpy(&desc->raw3, &msg.raw, sizeof(desc->raw3));
108
109 return ret;
110}
111
112int mtk_pce_cdrt_entry_write(struct cdrt_entry *cdrt)
113{
114 if (unlikely(!cdrt))
115 return -EINVAL;
116
117 return mtk_pce_cdrt_desc_write(&cdrt->desc, cdrt->idx);
118}
119EXPORT_SYMBOL(mtk_pce_cdrt_entry_write);
120
developerd3e8ce32023-08-24 17:41:43 +0800121struct cdrt_entry *mtk_pce_cdrt_entry_find(u32 cdrt_idx)
122{
123 struct cdrt_entry *cdrt;
124 unsigned long flag;
125 u32 idx;
126
developereff2b952023-11-17 09:44:29 +0800127 if (unlikely(!cdrt_idx || cdrt_idx > CDRT_DEC_MAX_ENTRY + CDRT_ENC_MAX_ENTRY))
developerd3e8ce32023-08-24 17:41:43 +0800128 return ERR_PTR(-EINVAL);
129
130 spin_lock_irqsave(&cdrt_hw.lock, flag);
131
132 if (cdrt_idx < CDRT_DEC_IDX_OFS + CDRT_DEC_MAX_ENTRY) {
133 idx = cdrt_idx - CDRT_DEC_IDX_OFS;
134 if (!test_bit(idx, cdrt_hw.dec_used))
135 return ERR_PTR(-ENODEV);
136
137 cdrt = &cdrt_hw.dec_tbl[idx];
138 } else {
139 idx = cdrt_idx - CDRT_ENC_IDX_OFS;
140 if (!test_bit(idx, cdrt_hw.enc_used))
141 return ERR_PTR(-ENODEV);
142
143 cdrt = &cdrt_hw.enc_tbl[idx];
144 }
145
146 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
147
148 return cdrt;
149}
150EXPORT_SYMBOL(mtk_pce_cdrt_entry_find);
151
developer1966afb2023-08-08 16:02:18 +0800152static struct cdrt_entry *mtk_pce_cdrt_entry_encrypt_alloc(void)
153{
154 u32 idx;
155
156 lockdep_assert_held(&cdrt_hw.lock);
157
158 idx = find_first_zero_bit(cdrt_hw.enc_used, CDRT_ENC_MAX_ENTRY);
159 if (idx == CDRT_ENC_MAX_ENTRY)
160 return ERR_PTR(-ENOMEM);
161
162 set_bit(idx, cdrt_hw.enc_used);
163
164 return &cdrt_hw.enc_tbl[idx];
165}
166
167static struct cdrt_entry *mtk_pce_cdrt_entry_decrypt_alloc(void)
168{
169 u32 idx;
170
171 lockdep_assert_held(&cdrt_hw.lock);
172
173 idx = find_first_zero_bit(cdrt_hw.dec_used, CDRT_DEC_MAX_ENTRY);
174 if (idx == CDRT_DEC_MAX_ENTRY)
175 return ERR_PTR(-ENOMEM);
176
177 set_bit(idx, cdrt_hw.dec_used);
178
179 return &cdrt_hw.dec_tbl[idx];
180}
181
182struct cdrt_entry *mtk_pce_cdrt_entry_alloc(enum cdrt_type type)
183{
184 struct cdrt_entry *cdrt;
185 unsigned long flag;
186
187 if (type >= __CDRT_TYPE_MAX)
188 return ERR_PTR(-EINVAL);
189
190 spin_lock_irqsave(&cdrt_hw.lock, flag);
191
192 if (type == CDRT_ENCRYPT)
193 cdrt = mtk_pce_cdrt_entry_encrypt_alloc();
194 else
195 cdrt = mtk_pce_cdrt_entry_decrypt_alloc();
196
197 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
198
199 return cdrt;
200}
201EXPORT_SYMBOL(mtk_pce_cdrt_entry_alloc);
202
203void mtk_pce_cdrt_entry_free(struct cdrt_entry *cdrt)
204{
205 unsigned long flag;
206
207 if (!cdrt)
208 return;
209
210 cdrt->cls = NULL;
developer1966afb2023-08-08 16:02:18 +0800211
212 memset(&cdrt->desc.raw1, 0, sizeof(cdrt->desc.raw1));
213 memset(&cdrt->desc.raw2, 0, sizeof(cdrt->desc.raw2));
214 memset(&cdrt->desc.raw3, 0, sizeof(cdrt->desc.raw3));
215
216 spin_lock_irqsave(&cdrt_hw.lock, flag);
217
218 if (cdrt->type == CDRT_ENCRYPT)
219 clear_bit(cdrt->idx, cdrt_hw.enc_used);
220 else
221 clear_bit(cdrt->idx, cdrt_hw.dec_used);
222
223 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
224}
225EXPORT_SYMBOL(mtk_pce_cdrt_entry_free);
226
227static void mtk_pce_cdrt_clean_up(void)
228{
229 struct fe_mem_msg msg = {
230 .cmd = FE_MEM_CMD_WRITE,
231 .type = FE_MEM_TYPE_CDRT,
232 };
233 unsigned long flag;
234 int ret = 0;
235 u32 i;
236
237 memset(&msg.raw, 0, sizeof(msg.raw));
238
239 spin_lock_irqsave(&cdrt_hw.lock, flag);
240
241 for (i = 0; i < FE_MEM_CDRT_MAX_INDEX; i++) {
242 msg.index = i;
243
244 ret = mtk_pce_fe_mem_msg_send(&msg);
245 if (ret)
246 return;
247
248 /* TODO: clean up bit map? */
249 }
250
251 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
252}
253
254int mtk_pce_cdrt_enable(void)
255{
256 mtk_pce_netsys_setbits(GLO_MEM_CFG, CDM_CDRT_EN);
257
258 return 0;
259}
260
261void mtk_pce_cdrt_disable(void)
262{
263 mtk_pce_netsys_clrbits(GLO_MEM_CFG, CDM_CDRT_EN);
264}
265
266int mtk_pce_cdrt_init(struct platform_device *pdev)
267{
268 u32 i;
269
270 spin_lock_init(&cdrt_hw.lock);
271
272 mtk_pce_cdrt_clean_up();
273
274 for (i = 0; i < CDRT_DEC_MAX_ENTRY; i++) {
275 cdrt_hw.dec_tbl[i].idx = i + CDRT_DEC_IDX_OFS;
276 cdrt_hw.dec_tbl[i].type = CDRT_DECRYPT;
277 }
278
279 for (i = 0; i < CDRT_ENC_MAX_ENTRY; i++) {
280 cdrt_hw.enc_tbl[i].idx = i + CDRT_ENC_IDX_OFS;
281 cdrt_hw.enc_tbl[i].type = CDRT_ENCRYPT;
282 }
283
284 return 0;
285}
286
287void mtk_pce_cdrt_deinit(struct platform_device *pdev)
288{
289 mtk_pce_cdrt_clean_up();
290}