blob: 5c71e346855056495fa6976927509f1d163a201c [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
34int mtk_pce_cdrt_update_cls_rule(u32 cdrt_idx)
35{
36 struct cdrt_entry *cdrt;
37
38 if (!cdrt_idx || cdrt_idx >= FE_MEM_CDRT_MAX_INDEX)
39 return -EINVAL;
40
41 if (cdrt_idx >= CDRT_ENC_MAX_ENTRY)
42 cdrt = &cdrt_hw.enc_tbl[cdrt_idx - CDRT_ENC_IDX_OFS];
43 else
44 cdrt = &cdrt_hw.dec_tbl[cdrt_idx - CDRT_DEC_IDX_OFS];
45
46 if (cdrt->update_cls_rule)
47 return cdrt->update_cls_rule(cdrt);
48
49 return 0;
50}
51
52int mtk_pce_cdrt_desc_write(struct cdrt_desc *desc, u32 idx)
53{
54 struct fe_mem_msg msg;
55 int ret;
56
57 if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
58 return -EINVAL;
59
60 memset(&msg.raw, 0, sizeof(msg.raw));
61
62 /* write CDR 0 ~ 3 */
63 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
64 3 * idx);
65 memcpy(&msg.raw, &desc->raw1, sizeof(desc->raw1));
66
67 ret = mtk_pce_fe_mem_msg_send(&msg);
68 if (ret)
69 return ret;
70
71 /* write CDR 4 ~ 7 */
72 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
73 3 * idx + 1);
74 memcpy(&msg.raw, &desc->raw2, sizeof(desc->raw2));
75
76 ret = mtk_pce_fe_mem_msg_send(&msg);
77 if (ret)
78 return ret;
79
80 /* write CDR 8 ~ 11 */
81 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
82 3 * idx + 2);
83 memcpy(&msg.raw, &desc->raw3, sizeof(desc->raw3));
84
85 ret = mtk_pce_fe_mem_msg_send(&msg);
86
87 return ret;
88}
89
90int mtk_pce_cdrt_desc_read(struct cdrt_desc *desc, u32 idx)
91{
92 struct fe_mem_msg msg;
93 int ret;
94
95 if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
96 return -EINVAL;
97
98 memset(&msg.raw, 0, sizeof(msg.raw));
99
100 /* read CDR 0 ~ 3 */
101 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
102 3 * idx);
103 ret = mtk_pce_fe_mem_msg_send(&msg);
104 if (ret)
105 return ret;
106
107 memcpy(&desc->raw1, &msg.raw, sizeof(desc->raw1));
108
109 /* read CDR 4 ~ 7 */
110 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
111 3 * idx + 1);
112 ret = mtk_pce_fe_mem_msg_send(&msg);
113 if (ret)
114 return ret;
115
116 memcpy(&desc->raw2, &msg.raw, sizeof(desc->raw2));
117
118 /* read CDR 8 ~ 11 */
119 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
120 3 * idx + 2);
121 ret = mtk_pce_fe_mem_msg_send(&msg);
122 if (ret)
123 return ret;
124
125 memcpy(&desc->raw3, &msg.raw, sizeof(desc->raw3));
126
127 return ret;
128}
129
130int mtk_pce_cdrt_entry_write(struct cdrt_entry *cdrt)
131{
132 if (unlikely(!cdrt))
133 return -EINVAL;
134
135 return mtk_pce_cdrt_desc_write(&cdrt->desc, cdrt->idx);
136}
137EXPORT_SYMBOL(mtk_pce_cdrt_entry_write);
138
139static struct cdrt_entry *mtk_pce_cdrt_entry_encrypt_alloc(void)
140{
141 u32 idx;
142
143 lockdep_assert_held(&cdrt_hw.lock);
144
145 idx = find_first_zero_bit(cdrt_hw.enc_used, CDRT_ENC_MAX_ENTRY);
146 if (idx == CDRT_ENC_MAX_ENTRY)
147 return ERR_PTR(-ENOMEM);
148
149 set_bit(idx, cdrt_hw.enc_used);
150
151 return &cdrt_hw.enc_tbl[idx];
152}
153
154static struct cdrt_entry *mtk_pce_cdrt_entry_decrypt_alloc(void)
155{
156 u32 idx;
157
158 lockdep_assert_held(&cdrt_hw.lock);
159
160 idx = find_first_zero_bit(cdrt_hw.dec_used, CDRT_DEC_MAX_ENTRY);
161 if (idx == CDRT_DEC_MAX_ENTRY)
162 return ERR_PTR(-ENOMEM);
163
164 set_bit(idx, cdrt_hw.dec_used);
165
166 return &cdrt_hw.dec_tbl[idx];
167}
168
169struct cdrt_entry *mtk_pce_cdrt_entry_alloc(enum cdrt_type type)
170{
171 struct cdrt_entry *cdrt;
172 unsigned long flag;
173
174 if (type >= __CDRT_TYPE_MAX)
175 return ERR_PTR(-EINVAL);
176
177 spin_lock_irqsave(&cdrt_hw.lock, flag);
178
179 if (type == CDRT_ENCRYPT)
180 cdrt = mtk_pce_cdrt_entry_encrypt_alloc();
181 else
182 cdrt = mtk_pce_cdrt_entry_decrypt_alloc();
183
184 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
185
186 return cdrt;
187}
188EXPORT_SYMBOL(mtk_pce_cdrt_entry_alloc);
189
190void mtk_pce_cdrt_entry_free(struct cdrt_entry *cdrt)
191{
192 unsigned long flag;
193
194 if (!cdrt)
195 return;
196
197 cdrt->cls = NULL;
198 cdrt->update_cls_rule = NULL;
199
200 memset(&cdrt->desc.raw1, 0, sizeof(cdrt->desc.raw1));
201 memset(&cdrt->desc.raw2, 0, sizeof(cdrt->desc.raw2));
202 memset(&cdrt->desc.raw3, 0, sizeof(cdrt->desc.raw3));
203
204 spin_lock_irqsave(&cdrt_hw.lock, flag);
205
206 if (cdrt->type == CDRT_ENCRYPT)
207 clear_bit(cdrt->idx, cdrt_hw.enc_used);
208 else
209 clear_bit(cdrt->idx, cdrt_hw.dec_used);
210
211 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
212}
213EXPORT_SYMBOL(mtk_pce_cdrt_entry_free);
214
215static void mtk_pce_cdrt_clean_up(void)
216{
217 struct fe_mem_msg msg = {
218 .cmd = FE_MEM_CMD_WRITE,
219 .type = FE_MEM_TYPE_CDRT,
220 };
221 unsigned long flag;
222 int ret = 0;
223 u32 i;
224
225 memset(&msg.raw, 0, sizeof(msg.raw));
226
227 spin_lock_irqsave(&cdrt_hw.lock, flag);
228
229 for (i = 0; i < FE_MEM_CDRT_MAX_INDEX; i++) {
230 msg.index = i;
231
232 ret = mtk_pce_fe_mem_msg_send(&msg);
233 if (ret)
234 return;
235
236 /* TODO: clean up bit map? */
237 }
238
239 spin_unlock_irqrestore(&cdrt_hw.lock, flag);
240}
241
242int mtk_pce_cdrt_enable(void)
243{
244 mtk_pce_netsys_setbits(GLO_MEM_CFG, CDM_CDRT_EN);
245
246 return 0;
247}
248
249void mtk_pce_cdrt_disable(void)
250{
251 mtk_pce_netsys_clrbits(GLO_MEM_CFG, CDM_CDRT_EN);
252}
253
254int mtk_pce_cdrt_init(struct platform_device *pdev)
255{
256 u32 i;
257
258 spin_lock_init(&cdrt_hw.lock);
259
260 mtk_pce_cdrt_clean_up();
261
262 for (i = 0; i < CDRT_DEC_MAX_ENTRY; i++) {
263 cdrt_hw.dec_tbl[i].idx = i + CDRT_DEC_IDX_OFS;
264 cdrt_hw.dec_tbl[i].type = CDRT_DECRYPT;
265 }
266
267 for (i = 0; i < CDRT_ENC_MAX_ENTRY; i++) {
268 cdrt_hw.enc_tbl[i].idx = i + CDRT_ENC_IDX_OFS;
269 cdrt_hw.enc_tbl[i].type = CDRT_ENCRYPT;
270 }
271
272 return 0;
273}
274
275void mtk_pce_cdrt_deinit(struct platform_device *pdev)
276{
277 mtk_pce_cdrt_clean_up();
278}