blob: 7a7ec27f28d9d26a0661dc1f0a49433e1fb05f8d [file] [log] [blame]
developer94c513e2023-08-21 17:33:25 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2023 MediaTek Inc.
4 *
5 * Author: Chris.Chou <chris.chou@mediatek.com>
6 * Ren-Ting Wang <ren-ting.wang@mediatek.com>
7 */
8
9#include <linux/module.h>
10#include <linux/netdevice.h>
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/of_platform.h>
developerebe38fd2024-03-22 14:36:06 +080014#include <linux/crypto.h>
developer94c513e2023-08-21 17:33:25 +080015#include <linux/platform_device.h>
developerebe38fd2024-03-22 14:36:06 +080016#include <crypto/internal/skcipher.h>
17#include <crypto/internal/aead.h>
18#include <crypto/internal/hash.h>
developer94c513e2023-08-21 17:33:25 +080019
20#include <mtk_eth_soc.h>
21#include <mtk_hnat/hnat.h>
22
developer94c513e2023-08-21 17:33:25 +080023#include "crypto-eip/crypto-eip.h"
24#include "crypto-eip/ddk-wrapper.h"
developerebe38fd2024-03-22 14:36:06 +080025#include "crypto-eip/lookaside.h"
developer94c513e2023-08-21 17:33:25 +080026#include "crypto-eip/internal.h"
developer1baf13c2024-07-05 15:43:05 +080027#include "crypto-eip/debugfs.h"
developer94c513e2023-08-21 17:33:25 +080028
29#define DRIVER_AUTHOR "Ren-Ting Wang <ren-ting.wang@mediatek.com, " \
30 "Chris.Chou <chris.chou@mediatek.com"
31
32struct mtk_crypto mcrypto;
33struct device *crypto_dev;
developerebe38fd2024-03-22 14:36:06 +080034struct mtk_crypto_priv *priv;
developerebe38fd2024-03-22 14:36:06 +080035
36static struct mtk_crypto_alg_template *mtk_crypto_algs[] = {
37 &mtk_crypto_cbc_aes,
38 &mtk_crypto_ecb_aes,
39 &mtk_crypto_cfb_aes,
40 &mtk_crypto_ofb_aes,
41 &mtk_crypto_ctr_aes,
42 &mtk_crypto_cbc_des,
43 &mtk_crypto_ecb_des,
44 &mtk_crypto_cbc_des3_ede,
45 &mtk_crypto_ecb_des3_ede,
46 &mtk_crypto_sha1,
47 &mtk_crypto_hmac_sha1,
48 &mtk_crypto_sha224,
49 &mtk_crypto_hmac_sha224,
50 &mtk_crypto_sha256,
51 &mtk_crypto_hmac_sha256,
52 &mtk_crypto_sha384,
53 &mtk_crypto_hmac_sha384,
54 &mtk_crypto_sha512,
55 &mtk_crypto_hmac_sha512,
56 &mtk_crypto_md5,
57 &mtk_crypto_hmac_md5,
58 &mtk_crypto_xcbcmac,
59 &mtk_crypto_cmac,
60 &mtk_crypto_hmac_sha1_cbc_aes,
61 &mtk_crypto_hmac_sha224_cbc_aes,
62 &mtk_crypto_hmac_sha256_cbc_aes,
63 &mtk_crypto_hmac_sha384_cbc_aes,
64 &mtk_crypto_hmac_sha512_cbc_aes,
65 &mtk_crypto_hmac_md5_cbc_aes,
66 &mtk_crypto_hmac_sha1_cbc_des3_ede,
67 &mtk_crypto_hmac_sha224_cbc_des3_ede,
68 &mtk_crypto_hmac_sha256_cbc_des3_ede,
69 &mtk_crypto_hmac_sha384_cbc_des3_ede,
70 &mtk_crypto_hmac_sha512_cbc_des3_ede,
71 &mtk_crypto_hmac_md5_cbc_des3_ede,
72 &mtk_crypto_hmac_sha1_cbc_des,
73 &mtk_crypto_hmac_sha224_cbc_des,
74 &mtk_crypto_hmac_sha256_cbc_des,
75 &mtk_crypto_hmac_sha384_cbc_des,
76 &mtk_crypto_hmac_sha512_cbc_des,
77 //&mtk_crypto_hmac_sha1_ctr_aes, /* no testcase, todo */
78 //&mtk_crypto_hmac_sha256_ctr_aes, /* no testcase, todo */
79 &mtk_crypto_gcm,
80 &mtk_crypto_rfc4106_gcm,
81 &mtk_crypto_rfc4543_gcm,
82 &mtk_crypto_rfc4309_ccm,
83};
developer94c513e2023-08-21 17:33:25 +080084
85inline void crypto_eth_write(u32 reg, u32 val)
86{
87 writel(val, mcrypto.eth_base + reg);
88}
89
90static inline void crypto_eip_write(u32 reg, u32 val)
91{
92 writel(val, mcrypto.crypto_base + reg);
93}
94
95static inline void crypto_eip_set(u32 reg, u32 mask)
96{
97 setbits(mcrypto.crypto_base + reg, mask);
98}
99
100static inline void crypto_eip_clr(u32 reg, u32 mask)
101{
102 clrbits(mcrypto.crypto_base + reg, mask);
103}
104
105static inline void crypto_eip_rmw(u32 reg, u32 mask, u32 val)
106{
107 clrsetbits(mcrypto.crypto_base + reg, mask, val);
108}
109
110static inline u32 crypto_eip_read(u32 reg)
111{
112 return readl(mcrypto.crypto_base + reg);
113}
114
developer49489b82024-03-28 15:18:08 +0800115#if IS_ENABLED(CONFIG_NET_MEDIATEK_HNAT)
developer94c513e2023-08-21 17:33:25 +0800116static bool mtk_crypto_eip_offloadable(struct sk_buff *skb)
117{
118 /* TODO: check is esp */
119 return true;
120}
developer49489b82024-03-28 15:18:08 +0800121#endif // HNAT
developer94c513e2023-08-21 17:33:25 +0800122
developer5922d4d2024-02-26 19:01:58 +0800123u32 mtk_crypto_ppe_get_num(void)
124{
125 return mcrypto.ppe_num;
126}
127
developer94c513e2023-08-21 17:33:25 +0800128static const struct xfrmdev_ops mtk_xfrmdev_ops = {
129 .xdo_dev_state_add = mtk_xfrm_offload_state_add,
130 .xdo_dev_state_delete = mtk_xfrm_offload_state_delete,
131 .xdo_dev_state_free = mtk_xfrm_offload_state_free,
132 .xdo_dev_offload_ok = mtk_xfrm_offload_ok,
133
134 /* Not support at v5.4*/
135 .xdo_dev_policy_add = mtk_xfrm_offload_policy_add,
developer6ad3f362024-10-28 11:19:49 +0800136 .xdo_dev_policy_delete = mtk_xfrm_offload_policy_delete,
137 .xdo_dev_policy_free = mtk_xfrm_offload_policy_free,
developer94c513e2023-08-21 17:33:25 +0800138};
139
developerebe38fd2024-03-22 14:36:06 +0800140static int mtk_crypto_register_algorithms(struct mtk_crypto_priv *priv)
141{
142 int i;
143 int j;
144 int ret;
145
146 for (i = 0; i < ARRAY_SIZE(mtk_crypto_algs); i++) {
147 mtk_crypto_algs[i]->priv = priv;
148
149 if (mtk_crypto_algs[i]->type == MTK_CRYPTO_ALG_TYPE_SKCIPHER)
150 ret = crypto_register_skcipher(&mtk_crypto_algs[i]->alg.skcipher);
151 else if (mtk_crypto_algs[i]->type == MTK_CRYPTO_ALG_TYPE_AEAD)
152 ret = crypto_register_aead(&mtk_crypto_algs[i]->alg.aead);
153 else
154 ret = crypto_register_ahash(&mtk_crypto_algs[i]->alg.ahash);
155
156 if (ret)
157 goto fail;
158 }
159
160 return 0;
161
162fail:
163 for (j = 0; j < i; j++) {
164 if (mtk_crypto_algs[j]->type == MTK_CRYPTO_ALG_TYPE_SKCIPHER)
165 crypto_unregister_skcipher(&mtk_crypto_algs[j]->alg.skcipher);
166 else if (mtk_crypto_algs[j]->type == MTK_CRYPTO_ALG_TYPE_AEAD)
167 crypto_unregister_aead(&mtk_crypto_algs[j]->alg.aead);
168 else
169 crypto_unregister_ahash(&mtk_crypto_algs[j]->alg.ahash);
170 }
171
172 return ret;
173}
174
175static void mtk_crypto_unregister_algorithms(void)
176{
177 int i;
178
179 for (i = 0; i < ARRAY_SIZE(mtk_crypto_algs); i++) {
180 if (mtk_crypto_algs[i]->type == MTK_CRYPTO_ALG_TYPE_SKCIPHER)
181 crypto_unregister_skcipher(&mtk_crypto_algs[i]->alg.skcipher);
182 else if (mtk_crypto_algs[i]->type == MTK_CRYPTO_ALG_TYPE_AEAD)
183 crypto_unregister_aead(&mtk_crypto_algs[i]->alg.aead);
184 else
185 crypto_unregister_ahash(&mtk_crypto_algs[i]->alg.ahash);
186 }
187}
188
developer94c513e2023-08-21 17:33:25 +0800189static void mtk_crypto_xfrm_offload_deinit(struct mtk_eth *eth)
190{
191 int i;
192
developer49489b82024-03-28 15:18:08 +0800193#if IS_ENABLED(CONFIG_NET_MEDIATEK_HNAT)
developer94c513e2023-08-21 17:33:25 +0800194 mtk_crypto_offloadable = NULL;
developer49489b82024-03-28 15:18:08 +0800195#endif // HNAT
developer94c513e2023-08-21 17:33:25 +0800196
197 for (i = 0; i < MTK_MAC_COUNT; i++) {
198 eth->netdev[i]->xfrmdev_ops = NULL;
199 eth->netdev[i]->features &= (~NETIF_F_HW_ESP);
200 eth->netdev[i]->hw_enc_features &= (~NETIF_F_HW_ESP);
201 rtnl_lock();
202 netdev_change_features(eth->netdev[i]);
203 rtnl_unlock();
204 }
205}
206
207static void mtk_crypto_xfrm_offload_init(struct mtk_eth *eth)
208{
209 int i;
210
211 for (i = 0; i < MTK_MAC_COUNT; i++) {
212 eth->netdev[i]->xfrmdev_ops = &mtk_xfrmdev_ops;
213 eth->netdev[i]->features |= NETIF_F_HW_ESP;
214 eth->netdev[i]->hw_enc_features |= NETIF_F_HW_ESP;
215 rtnl_lock();
216 netdev_change_features(eth->netdev[i]);
217 rtnl_unlock();
218 }
219
developer49489b82024-03-28 15:18:08 +0800220#if IS_ENABLED(CONFIG_NET_MEDIATEK_HNAT)
developer94c513e2023-08-21 17:33:25 +0800221 mtk_crypto_offloadable = mtk_crypto_eip_offloadable;
developer49489b82024-03-28 15:18:08 +0800222#endif // HNAT
developer94c513e2023-08-21 17:33:25 +0800223}
224
225static int __init mtk_crypto_eth_dts_init(struct platform_device *pdev)
226{
227 struct platform_device *eth_pdev;
228 struct device_node *crypto_node;
229 struct device_node *eth_node;
230 struct resource res;
231 int ret = 0;
232
233 crypto_node = pdev->dev.of_node;
234
235 eth_node = of_parse_phandle(crypto_node, "eth", 0);
236 if (!eth_node)
237 return -ENODEV;
238
239 eth_pdev = of_find_device_by_node(eth_node);
240 if (!eth_pdev) {
241 ret = -ENODEV;
242 goto out;
243 }
244
245 if (!eth_pdev->dev.driver) {
246 ret = -EFAULT;
247 goto out;
248 }
249
250 if (of_address_to_resource(eth_node, 0, &res)) {
251 ret = -ENXIO;
252 goto out;
253 }
254
255 mcrypto.eth_base = devm_ioremap(&pdev->dev,
256 res.start, resource_size(&res));
257 if (!mcrypto.eth_base) {
258 ret = -ENOMEM;
259 goto out;
260 }
261
262 mcrypto.eth = platform_get_drvdata(eth_pdev);
263
264out:
265 of_node_put(eth_node);
266
267 return ret;
268}
269
developer5922d4d2024-02-26 19:01:58 +0800270static int __init mtk_crypto_ppe_num_dts_init(struct platform_device *pdev)
271{
272 struct device_node *hnat = NULL;
273 u32 val = 0;
274 int ret = 0;
275
276 hnat = of_parse_phandle(pdev->dev.of_node, "hnat", 0);
277 if (!hnat) {
278 CRYPTO_ERR("can not find hnat node\n");
279 return -ENODEV;
280 }
281
282 ret = of_property_read_u32(hnat, "mtketh-ppe-num", &val);
283 if (ret)
284 mcrypto.ppe_num = 1;
285 else
286 mcrypto.ppe_num = val;
287
288 of_node_put(hnat);
289
290 return 0;
291}
292
developerebe38fd2024-03-22 14:36:06 +0800293static int __init mtk_crypto_lookaside_data_init(struct platform_device *pdev)
294{
295 struct device *dev = &pdev->dev;
developerb3c41cd2024-06-04 17:52:08 +0800296 int i;
developerebe38fd2024-03-22 14:36:06 +0800297
298 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
299 if (!priv)
300 return -ENOMEM;
301
302 platform_set_drvdata(pdev, priv);
303
developerb3c41cd2024-06-04 17:52:08 +0800304 priv->mtk_eip_ring = devm_kcalloc(dev, PEC_MAX_INTERFACE_NUM,
305 sizeof(*priv->mtk_eip_ring), GFP_KERNEL);
306 if (!priv->mtk_eip_ring)
developerebe38fd2024-03-22 14:36:06 +0800307 return -ENOMEM;
308
developerb3c41cd2024-06-04 17:52:08 +0800309 for (i = 0; i < PEC_MAX_INTERFACE_NUM; i++) {
310 char wq_name[17] = {0};
311 char irq_name[6] = {0};
312 int irq, cpu;
313
314 // init workqueue for all rings
315 priv->mtk_eip_ring[i].work_data.priv = priv;
316 priv->mtk_eip_ring[i].work_data.ring = i;
317 INIT_WORK(&priv->mtk_eip_ring[i].work_data.work, mtk_crypto_dequeue_work);
318
319 snprintf(wq_name, 17, "mtk_crypto_work%d", i);
320 priv->mtk_eip_ring[i].workqueue = create_singlethread_workqueue(wq_name);
321 if (!priv->mtk_eip_ring[i].workqueue)
322 return -ENOMEM;
developerebe38fd2024-03-22 14:36:06 +0800323
developerb3c41cd2024-06-04 17:52:08 +0800324 crypto_init_queue(&priv->mtk_eip_ring[i].queue, EIP197_DEFAULT_RING_SIZE);
325
326 spin_lock_init(&priv->mtk_eip_ring[i].ring_lock);
327 spin_lock_init(&priv->mtk_eip_ring[i].queue_lock);
328 INIT_LIST_HEAD(&priv->mtk_eip_ring[i].list);
329
330 // setup irq affinity
331 snprintf(irq_name, 6, "ring%d", i);
332 irq = platform_get_irq_byname(pdev, irq_name);
333 if (irq < 0)
334 return irq;
335
336 cpu = cpumask_local_spread(i, NUMA_NO_NODE);
337 irq_set_affinity_hint(irq, get_cpu_mask(cpu));
338 }
developerebe38fd2024-03-22 14:36:06 +0800339
340 return 0;
341};
342
developer94c513e2023-08-21 17:33:25 +0800343static int __init mtk_crypto_eip_dts_init(void)
344{
345 struct platform_device *crypto_pdev;
346 struct device_node *crypto_node;
347 struct resource res;
348 int ret;
349
350 crypto_node = of_find_compatible_node(NULL, NULL, HWPAL_PLATFORM_DEVICE_NAME);
351 if (!crypto_node)
352 return -ENODEV;
353
354 crypto_pdev = of_find_device_by_node(crypto_node);
355 if (!crypto_pdev) {
356 ret = -ENODEV;
357 goto out;
358 }
359
360 /* check crypto platform device is ready */
361 if (!crypto_pdev->dev.driver) {
362 ret = -EFAULT;
363 goto out;
364 }
365
366 if (of_address_to_resource(crypto_node, 0, &res)) {
367 ret = -ENXIO;
368 goto out;
369 }
370
371 mcrypto.crypto_base = devm_ioremap(&crypto_pdev->dev,
372 res.start, resource_size(&res));
373 if (!mcrypto.crypto_base) {
374 ret = -ENOMEM;
375 goto out;
376 }
377
378 ret = mtk_crypto_eth_dts_init(crypto_pdev);
379 if (ret)
380 goto out;
381
developer5922d4d2024-02-26 19:01:58 +0800382 ret = mtk_crypto_ppe_num_dts_init(crypto_pdev);
383 if (ret)
384 goto out;
385
developer94c513e2023-08-21 17:33:25 +0800386 crypto_dev = &crypto_pdev->dev;
387
developerebe38fd2024-03-22 14:36:06 +0800388 ret = mtk_crypto_lookaside_data_init(crypto_pdev);
389 if (ret)
390 goto out;
391
developer94c513e2023-08-21 17:33:25 +0800392out:
393 of_node_put(crypto_node);
394
395 return ret;
396}
397
398static int __init mtk_crypto_eip_hw_init(void)
399{
400 crypto_eip_write(EIP197_FORCE_CLK_ON, 0xffffffff);
401
402 crypto_eip_write(EIP197_FORCE_CLK_ON2, 0xffffffff);
403
404 /* TODO: adjust AXI burst? */
405
406 mtk_ddk_pec_init();
407
408 return 0;
409}
410
411static void __exit mtk_crypto_eip_hw_deinit(void)
412{
413 mtk_ddk_pec_deinit();
414
415 crypto_eip_write(EIP197_FORCE_CLK_ON, 0);
416
417 crypto_eip_write(EIP197_FORCE_CLK_ON2, 0);
418}
419
420static int __init mtk_crypto_eip_init(void)
421{
422 int ret;
423
424 ret = mtk_crypto_eip_dts_init();
425 if (ret) {
426 CRYPTO_ERR("crypto-eip dts init failed: %d\n", ret);
427 return ret;
428 }
429
430 ret = mtk_crypto_eip_hw_init();
431 if (ret) {
432 CRYPTO_ERR("crypto-eip hw init failed: %d\n", ret);
433 return ret;
434 }
435
436 mtk_crypto_xfrm_offload_init(mcrypto.eth);
developer1baf13c2024-07-05 15:43:05 +0800437 mtk_crypto_debugfs_init();
developerebe38fd2024-03-22 14:36:06 +0800438 mtk_crypto_register_algorithms(priv);
developer49489b82024-03-28 15:18:08 +0800439#if defined(CONFIG_MTK_TOPS_CAPWAP_DTLS)
440 mtk_dtls_capwap_init();
441#endif
developer94c513e2023-08-21 17:33:25 +0800442
443 CRYPTO_INFO("crypto-eip init done\n");
444
445 return ret;
446}
447
448static void __exit mtk_crypto_eip_exit(void)
449{
450 /* TODO: deactivate all tunnel */
developer49489b82024-03-28 15:18:08 +0800451#if defined(CONFIG_MTK_TOPS_CAPWAP_DTLS)
452 mtk_dtls_capwap_deinit();
453#endif
developerebe38fd2024-03-22 14:36:06 +0800454 mtk_crypto_unregister_algorithms();
developer94c513e2023-08-21 17:33:25 +0800455 mtk_crypto_xfrm_offload_deinit(mcrypto.eth);
456
457 mtk_crypto_eip_hw_deinit();
developerebe38fd2024-03-22 14:36:06 +0800458
developer94c513e2023-08-21 17:33:25 +0800459}
460
461module_init(mtk_crypto_eip_init);
462module_exit(mtk_crypto_eip_exit);
463
464MODULE_LICENSE("GPL");
465MODULE_DESCRIPTION("MediaTek Crypto EIP Control Driver");
466MODULE_AUTHOR(DRIVER_AUTHOR);