blob: d92369308e447eda9f96096508f6238394f4dce6 [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 <crypto/aes.h>
10#include <crypto/hash.h>
11#include <crypto/hmac.h>
12#include <crypto/md5.h>
13#include <linux/delay.h>
14
15#include <crypto-eip/ddk/slad/api_pcl.h>
16#include <crypto-eip/ddk/slad/api_pcl_dtl.h>
17#include <crypto-eip/ddk/slad/api_pec.h>
18#include <crypto-eip/ddk/slad/api_driver197_init.h>
19
20#include "crypto-eip/crypto-eip.h"
21#include "crypto-eip/ddk-wrapper.h"
22#include "crypto-eip/internal.h"
23#include "crypto-eip/crypto-eip197-inline-ddk.h"
24
25static bool crypto_iotoken_create(IOToken_Input_Dscr_t * const dscr_p,
26 void * const ext_p, u32 *data_p,
27 PEC_CommandDescriptor_t * const pec_cmd_dscr)
28{
29 int IOTokenRc;
30
31 dscr_p->InPacket_ByteCount = pec_cmd_dscr->SrcPkt_ByteCount;
32 dscr_p->Ext_p = ext_p;
33
34 IOTokenRc = IOToken_Create(dscr_p, data_p);
35 if (IOTokenRc < 0) {
36 CRYPTO_ERR("IOToken_Create error %d\n", IOTokenRc);
37 return false;
38 }
39
40 pec_cmd_dscr->InputToken_p = data_p;
41
42 return true;
43}
44
45unsigned int crypto_pe_get_one(IOToken_Output_Dscr_t *const OutTokenDscr_p,
46 u32 *OutTokenData_p,
47 PEC_ResultDescriptor_t *RD_p)
48{
49 int LoopCounter = MTK_EIP197_INLINE_NOF_TRIES;
50 int IOToken_Rc;
51 PEC_Status_t pecres;
52
53 ZEROINIT(*OutTokenDscr_p);
54 ZEROINIT(*RD_p);
55
56 /* Link data structures */
57 RD_p->OutputToken_p = OutTokenData_p;
58
59 while (LoopCounter > 0) {
60 /* Try to get the processed packet from the driver */
61 unsigned int Counter = 0;
62
63 pecres = PEC_Packet_Get(PEC_INTERFACE_ID, RD_p, 1, &Counter);
64 if (pecres != PEC_STATUS_OK) {
65 /* IO error */
66 CRYPTO_ERR("PEC_Packet_Get error %d\n", pecres);
67 return 0;
68 }
69
70 if (Counter) {
71 IOToken_Rc = IOToken_Parse(OutTokenData_p, OutTokenDscr_p);
72 if (IOToken_Rc < 0) {
73 /* IO error */
74 CRYPTO_ERR("IOToken_Parse error %d\n", IOToken_Rc);
75 return 0;
76 }
77
78 if (OutTokenDscr_p->ErrorCode != 0) {
79 /* Packet process error */
80 CRYPTO_ERR("Result descriptor error 0x%x\n",
81 OutTokenDscr_p->ErrorCode);
82 return 0;
83 }
84
85 /* packet received */
86 return Counter;
87 }
88
89 /* Wait for MTK_EIP197_PKT_GET_TIMEOUT_MS milliseconds */
90 udelay(MTK_EIP197_PKT_GET_TIMEOUT_MS * 1000);
91 LoopCounter--;
92 }
93
94 CRYPTO_ERR("Timeout when reading packet\n");
95
96 /* IO error (timeout, not result packet received) */
97 return 0;
98}
99
100
101bool crypto_basic_hash(SABuilder_Auth_t HashAlgo, uint8_t *Input_p,
102 unsigned int InputByteCount, uint8_t *Output_p,
103 unsigned int OutputByteCount, bool fFinalize)
104{
105 SABuilder_Params_Basic_t ProtocolParams;
106 SABuilder_Params_t params;
107 unsigned int SAWords = 0;
108 static uint8_t DummyAuthKey[64];
109 int rc;
110
111 DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
112 DMABuf_HostAddress_t TokenHostAddress;
113 DMABuf_HostAddress_t PktHostAddress;
114 DMABuf_HostAddress_t SAHostAddress;
115 DMABuf_Status_t DMAStatus;
116
117 DMABuf_Handle_t TokenHandle = {0};
118 DMABuf_Handle_t PktHandle = {0};
119 DMABuf_Handle_t SAHandle = {0};
120
121 unsigned int TokenMaxWords = 0;
122 unsigned int TokenHeaderWord;
123 unsigned int TokenWords = 0;
124 unsigned int TCRWords = 0;
125 void *TCRData = 0;
126
127 TokenBuilder_Params_t TokenParams;
128 PEC_CommandDescriptor_t Cmd;
129 PEC_ResultDescriptor_t Res;
130 unsigned int count;
131
132 u32 OutputToken[IOTOKEN_IN_WORD_COUNT];
133 u32 InputToken[IOTOKEN_IN_WORD_COUNT];
134 IOToken_Output_Dscr_t OutTokenDscr;
135 IOToken_Input_Dscr_t InTokenDscr;
136 void *InTokenDscrExt_p = NULL;
137
138#ifdef CRYPTO_IOTOKEN_EXT
139 IOToken_Input_Dscr_Ext_t InTokenDscrExt;
140
141 ZEROINIT(InTokenDscrExt);
142 InTokenDscrExt_p = &InTokenDscrExt;
143#endif
144 ZEROINIT(InTokenDscr);
145 ZEROINIT(OutTokenDscr);
146
147 rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
148 if (rc) {
149 CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
150 goto error_exit;
151 }
152
153 params.AuthAlgo = HashAlgo;
154 params.AuthKey1_p = DummyAuthKey;
155
156 if (!fFinalize)
157 params.flags |= SAB_FLAG_HASH_SAVE | SAB_FLAG_HASH_INTERMEDIATE;
158 params.flags |= SAB_FLAG_SUPPRESS_PAYLOAD;
159 ProtocolParams.ICVByteCount = OutputByteCount;
160
161 rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
162 if (rc) {
163 CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
164 goto error_exit;
165 }
166
167 DMAProperties.fCached = true;
168 DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
169 DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
170 DMAProperties.Size = MAX(4*SAWords, 256);
171
172 DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
173 if (DMAStatus != DMABUF_STATUS_OK) {
174 rc = 1;
175 CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
176 goto error_exit;
177 }
178
179 rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
180 if (rc) {
181 CRYPTO_ERR("SA not created because of errors: %d\n", rc);
182 goto error_exit;
183 }
184
185 rc = TokenBuilder_GetContextSize(&params, &TCRWords);
186 if (rc) {
187 CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
188 goto error_exit;
189 }
190
191 TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
192 if (!TCRData) {
193 rc = 1;
194 CRYPTO_ERR("Allocation of TCR failed\n");
195 goto error_exit;
196 }
197
198 rc = TokenBuilder_BuildContext(&params, TCRData);
199 if (rc) {
200 CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
201 goto error_exit;
202 }
203
204 rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
205 if (rc) {
206 CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
207 goto error_exit;
208 }
209
210 DMAProperties.fCached = true;
211 DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
212 DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
213 DMAProperties.Size = 4*TokenMaxWords;
214
215 DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
216 if (DMAStatus != DMABUF_STATUS_OK) {
217 rc = 1;
218 CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
219 goto error_exit;
220 }
221
222 DMAProperties.fCached = true;
223 DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
224 DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
225 DMAProperties.Size = MAX(InputByteCount, OutputByteCount);
226
227 DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress, &PktHandle);
228 if (DMAStatus != DMABUF_STATUS_OK) {
229 rc = 1;
230 CRYPTO_ERR("Allocation of source packet buffer failed: %d\n",
231 DMAStatus);
232 goto error_exit;
233 }
234
235 rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
236 DMABuf_NULLHandle);
237 if (rc != PEC_STATUS_OK) {
238 CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
239 goto error_exit;
240 }
241
242 memcpy(PktHostAddress.p, Input_p, InputByteCount);
243
244 ZEROINIT(TokenParams);
245 TokenParams.PacketFlags |= (TKB_PACKET_FLAG_HASHFIRST
246 | TKB_PACKET_FLAG_HASHAPPEND);
247 if (fFinalize)
248 TokenParams.PacketFlags |= TKB_PACKET_FLAG_HASHFINAL;
249
250 rc = TokenBuilder_BuildToken(TCRData, (u8 *) PktHostAddress.p,
251 InputByteCount, &TokenParams,
252 (u32 *) TokenHostAddress.p,
253 &TokenWords, &TokenHeaderWord);
254 if (rc != TKB_STATUS_OK) {
255 CRYPTO_ERR("Token builder failed: %d\n", rc);
256 goto error_exit_unregister;
257 }
258
259 ZEROINIT(Cmd);
260 Cmd.Token_Handle = TokenHandle;
261 Cmd.Token_WordCount = TokenWords;
262 Cmd.SrcPkt_Handle = PktHandle;
263 Cmd.SrcPkt_ByteCount = InputByteCount;
264 Cmd.DstPkt_Handle = PktHandle;
265 Cmd.SA_Handle1 = SAHandle;
266 Cmd.SA_Handle2 = DMABuf_NULLHandle;
267
268
269#if defined(CRYPTO_IOTOKEN_EXT)
270 InTokenDscrExt.HW_Services = IOTOKEN_CMD_PKT_LAC;
271#endif
272 InTokenDscr.TknHdrWordInit = TokenHeaderWord;
273
274 if (!crypto_iotoken_create(&InTokenDscr,
275 InTokenDscrExt_p,
276 InputToken,
277 &Cmd)) {
278 rc = 1;
279 goto error_exit_unregister;
280 }
281
282 rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
283 if (rc != PEC_STATUS_OK && count != 1) {
284 rc = 1;
285 CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
286 goto error_exit_unregister;
287 }
288
289 if (crypto_pe_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
290 rc = 1;
291 CRYPTO_ERR("error from crypto_pe_get_one\n");
292 goto error_exit_unregister;
293 }
294 memcpy(Output_p, PktHostAddress.p, OutputByteCount);
295
296error_exit_unregister:
297 PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
298 DMABuf_NULLHandle);
299
300error_exit:
301 DMABuf_Release(SAHandle);
302 DMABuf_Release(TokenHandle);
303 DMABuf_Release(PktHandle);
304
305 if (TCRData != NULL)
306 kfree(TCRData);
307
308 return rc == 0;
309}
310
311bool crypto_hmac_precompute(SABuilder_Auth_t AuthAlgo,
312 uint8_t *AuthKey_p,
313 unsigned int AuthKeyByteCount,
314 uint8_t *Inner_p,
315 uint8_t *Outer_p)
316{
317 SABuilder_Auth_t HashAlgo;
318 unsigned int blocksize, hashsize, digestsize;
319 static uint8_t pad_block[128], hashed_key[128];
320 unsigned int i;
321
322 switch (AuthAlgo) {
323 case SAB_AUTH_HMAC_MD5:
324 HashAlgo = SAB_AUTH_HASH_MD5;
325 blocksize = 64;
326 hashsize = 16;
327 digestsize = 16;
328 break;
329 case SAB_AUTH_HMAC_SHA1:
330 HashAlgo = SAB_AUTH_HASH_SHA1;
331 blocksize = 64;
332 hashsize = 20;
333 digestsize = 20;
334 break;
335 case SAB_AUTH_HMAC_SHA2_224:
336 HashAlgo = SAB_AUTH_HASH_SHA2_224;
337 blocksize = 64;
338 hashsize = 28;
339 digestsize = 32;
340 break;
341 case SAB_AUTH_HMAC_SHA2_256:
342 HashAlgo = SAB_AUTH_HASH_SHA2_256;
343 blocksize = 64;
344 hashsize = 32;
345 digestsize = 32;
346 break;
347 case SAB_AUTH_HMAC_SHA2_384:
348 HashAlgo = SAB_AUTH_HASH_SHA2_384;
349 blocksize = 128;
350 hashsize = 48;
351 digestsize = 64;
352 break;
353 case SAB_AUTH_HMAC_SHA2_512:
354 HashAlgo = SAB_AUTH_HASH_SHA2_512;
355 blocksize = 128;
356 hashsize = 64;
357 digestsize = 64;
358 break;
359 default:
360 CRYPTO_ERR("Unknown HMAC algorithm\n");
361 return false;
362 }
363
364 memset(hashed_key, 0, blocksize);
365 if (AuthKeyByteCount <= blocksize) {
366 memcpy(hashed_key, AuthKey_p, AuthKeyByteCount);
367 } else {
368 if (!crypto_basic_hash(HashAlgo, AuthKey_p, AuthKeyByteCount,
369 hashed_key, hashsize, true))
370 return false;
371 }
372
373 for (i = 0; i < blocksize; i++)
374 pad_block[i] = hashed_key[i] ^ 0x36;
375
376 if (!crypto_basic_hash(HashAlgo, pad_block, blocksize,
377 Inner_p, digestsize, false))
378 return false;
379
380 for (i = 0; i < blocksize; i++)
381 pad_block[i] = hashed_key[i] ^ 0x5c;
382
383 if (!crypto_basic_hash(HashAlgo, pad_block, blocksize,
384 Outer_p, digestsize, false))
385 return false;
386
387 return true;
388}
389
390static SABuilder_Crypto_t set_crypto_algo(struct xfrm_algo *ealg)
391{
392 if (strcmp(ealg->alg_name, "cbc(des)") == 0)
393 return SAB_CRYPTO_DES;
394 else if (strcmp(ealg->alg_name, "cbc(aes)") == 0)
395 return SAB_CRYPTO_AES;
396 else if (strcmp(ealg->alg_name, "cbc(des3_ede)") == 0)
397 return SAB_CRYPTO_3DES;
398
399 return SAB_CRYPTO_NULL;
400}
401
402static bool set_auth_algo(struct xfrm_algo_auth *aalg, SABuilder_Params_t *params,
403 uint8_t *inner, uint8_t *outer)
404{
405 if (strcmp(aalg->alg_name, "hmac(sha1)") == 0) {
406 params->AuthAlgo = SAB_AUTH_HMAC_SHA1;
407 inner = kcalloc(SHA1_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
408 outer = kcalloc(SHA1_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
409 crypto_hmac_precompute(SAB_AUTH_HMAC_SHA1, &aalg->alg_key[0],
410 aalg->alg_key_len / 8, inner, outer);
411
412 params->AuthKey1_p = inner;
413 params->AuthKey2_p = outer;
414 } else if (strcmp(aalg->alg_name, "hmac(sha256)") == 0) {
415 params->AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
416 inner = kcalloc(SHA256_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
417 outer = kcalloc(SHA256_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
418 crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_256, &aalg->alg_key[0],
419 aalg->alg_key_len / 8, inner, outer);
420 params->AuthKey1_p = inner;
421 params->AuthKey2_p = outer;
422 } else if (strcmp(aalg->alg_name, "hmac(sha384)") == 0) {
423 params->AuthAlgo = SAB_AUTH_HMAC_SHA2_384;
424 inner = kcalloc(SHA384_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
425 outer = kcalloc(SHA384_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
426 crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_384, &aalg->alg_key[0],
427 aalg->alg_key_len / 8, inner, outer);
428 params->AuthKey1_p = inner;
429 params->AuthKey2_p = outer;
430 } else if (strcmp(aalg->alg_name, "hmac(sha512)") == 0) {
431 params->AuthAlgo = SAB_AUTH_HMAC_SHA2_512;
432 inner = kcalloc(SHA512_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
433 outer = kcalloc(SHA512_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
434 crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_512, &aalg->alg_key[0],
435 aalg->alg_key_len / 8, inner, outer);
436 params->AuthKey1_p = inner;
437 params->AuthKey2_p = outer;
438 } else if (strcmp(aalg->alg_name, "hmac(md5)") == 0) {
439 params->AuthAlgo = SAB_AUTH_HMAC_MD5;
440 inner = kcalloc(MD5_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
441 outer = kcalloc(MD5_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
442 crypto_hmac_precompute(SAB_AUTH_HMAC_MD5, &aalg->alg_key[0],
443 aalg->alg_key_len / 8, inner, outer);
444 params->AuthKey1_p = inner;
445 params->AuthKey2_p = outer;
446 } else {
447 return false;
448 }
449
450 return true;
451}
452
453u32 *mtk_ddk_tr_ipsec_build(struct mtk_xfrm_params *xfrm_params, u32 ipsec_mode)
454{
455 struct xfrm_state *xs = xfrm_params->xs;
456 SABuilder_Params_IPsec_t ipsec_params;
457 SABuilder_Status_t sa_status;
458 SABuilder_Params_t params;
459 bool set_auth_success = false;
460 unsigned int SAWords = 0;
461 uint8_t *inner, *outer;
462
463 DMABuf_Status_t dma_status;
464 DMABuf_Properties_t dma_properties = {0, 0, 0, 0};
465 DMABuf_HostAddress_t sa_host_addr;
466
467 DMABuf_Handle_t sa_handle = {0};
468
469 sa_status = SABuilder_Init_ESP(&params,
470 &ipsec_params,
471 be32_to_cpu(xs->id.spi),
472 ipsec_mode,
473 SAB_IPSEC_IPV4,
474 xfrm_params->dir);
475
476 if (sa_status != SAB_STATUS_OK) {
477 pr_err("SABuilder_Init_ESP failed\n");
478 sa_handle.p = NULL;
479 return (u32 *) sa_handle.p;
480 }
481
482 /* Add crypto key and parameters */
483 params.CryptoAlgo = set_crypto_algo(xs->ealg);
484 params.CryptoMode = SAB_CRYPTO_MODE_CBC;
485 params.KeyByteCount = xs->ealg->alg_key_len / 8;
486 params.Key_p = xs->ealg->alg_key;
487
488 /* Add authentication key and parameters */
489 set_auth_success = set_auth_algo(xs->aalg, &params, inner, outer);
490 if (set_auth_success != true) {
491 CRYPTO_ERR("Set Auth Algo failed\n");
492 sa_handle.p = NULL;
493 return (u32 *) sa_handle.p;
494 }
495
496 ipsec_params.IPsecFlags |= (SAB_IPSEC_PROCESS_IP_HEADERS
497 | SAB_IPSEC_EXT_PROCESSING);
498 if (ipsec_mode == SAB_IPSEC_TUNNEL) {
499 ipsec_params.SrcIPAddr_p = (uint8_t *) &xs->props.saddr.a4;
500 ipsec_params.DestIPAddr_p = (uint8_t *) &xs->id.daddr.a4;
501 }
502
503 sa_status = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
504 if (sa_status != SAB_STATUS_OK) {
505 CRYPTO_ERR("SA not created because of size errors\n");
506 sa_handle.p = NULL;
507 return (u32 *) sa_handle.p;
508 }
509
510 dma_properties.fCached = true;
511 dma_properties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
512 dma_properties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
513 dma_properties.Size = SAWords * sizeof(u32);
514
515 dma_status = DMABuf_Alloc(dma_properties, &sa_host_addr, &sa_handle);
516 if (dma_status != DMABUF_STATUS_OK) {
517 CRYPTO_ERR("Allocation of SA failed\n");
518 /* goto error_exit; */
519 sa_handle.p = NULL;
520 return (u32 *) sa_handle.p;
521 }
522
523 sa_status = SABuilder_BuildSA(&params, (u32 *) sa_host_addr.p, NULL, NULL);
524 if (sa_status != SAB_STATUS_OK) {
525 CRYPTO_ERR("SA not created because of errors\n");
526 sa_handle.p = NULL;
527 return (u32 *) sa_handle.p;
528 }
529
530 kfree(inner);
531 kfree(outer);
532 return (u32 *) sa_host_addr.p;
533}
534
535int mtk_ddk_pec_init(void)
536{
537 PEC_InitBlock_t pec_init_blk = {0, 0, false};
538 PEC_Capabilities_t pec_cap;
539 PEC_Status_t pec_sta;
540 u32 i = MTK_EIP197_INLINE_NOF_TRIES;
541
542 while (i) {
543 pec_sta = PEC_Init(PEC_INTERFACE_ID, &pec_init_blk);
544 if (pec_sta == PEC_STATUS_OK) {
545 CRYPTO_INFO("PEC_INIT ok!\n");
546 break;
547 } else if (pec_sta != PEC_STATUS_OK && pec_sta != PEC_STATUS_BUSY) {
548 return pec_sta;
549 }
550
551 mdelay(MTK_EIP197_INLINE_RETRY_DELAY_MS);
552 i--;
553 }
554
555 if (!i) {
556 CRYPTO_ERR("PEC could not be initialized: %d\n", pec_sta);
557 return pec_sta;
558 }
559
560 pec_sta = PEC_Capabilities_Get(&pec_cap);
561 if (pec_sta != PEC_STATUS_OK) {
562 CRYPTO_ERR("PEC capability could not be obtained: %d\n", pec_sta);
563 return pec_sta;
564 }
565
566 CRYPTO_INFO("PEC Capabilities: %s\n", pec_cap.szTextDescription);
567
568 return 0;
569}
570
571void mtk_ddk_pec_deinit(void)
572{
573}