284 lines
6.9 KiB
C
284 lines
6.9 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <FreeRTOS.h>
|
|
#include <semphr.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "common.h"
|
|
//#include "printf.h"
|
|
#include "hwcrypto.h"
|
|
#include "interrupt.h"
|
|
|
|
SemaphoreHandle_t dma_mutex;
|
|
uint8_t dma_init_done;
|
|
struct dma_dsc g_dsc[MAX_DESCRIPTORS] __section(".dma_buffer") __aligned(64);
|
|
|
|
#if configCryptoDmaUseIsr
|
|
SemaphoreHandle_t isr_binary_semaphore;
|
|
|
|
static inline void prvCryptoDmaInterruptHandler(uint32_t thread __unused)
|
|
{
|
|
if (thread == cryptCRYPTO_THREAD_IDX) {
|
|
BaseType_t xTaskWoken = pdFALSE;
|
|
|
|
REG32(cryptDMA_STATUS_REG(thread)) = 0xf;
|
|
xSemaphoreGiveFromISR(isr_binary_semaphore, &xTaskWoken);
|
|
portYIELD_FROM_ISR(xTaskWoken);
|
|
} else {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Error: Isr is called with thread(%d), but actual is (%d)\n",
|
|
thread, cryptCRYPTO_THREAD_IDX);
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void vDmaInit(void)
|
|
{
|
|
dma_mutex = xSemaphoreCreateMutex();
|
|
|
|
REG32(cryptDMA_STATUS_REG(cryptCRYPTO_THREAD_IDX)) = 0xffff;
|
|
|
|
#if configCryptoDmaUseIsr
|
|
//TODO: Register ISR
|
|
#endif
|
|
|
|
if (dma_mutex)
|
|
dma_init_done = 1;
|
|
|
|
if (!dma_init_done)
|
|
printf("dma init failed\n");
|
|
}
|
|
|
|
#if AML_CRYPTO_DEBUG
|
|
static void prvAmlDmaDebug(struct dma_dsc *dsc __unused,
|
|
uint8_t threadidx __unused,
|
|
uint32_t nents __unused, const char *msg __unused)
|
|
{
|
|
|
|
uint32_t i = 0;
|
|
|
|
printf("begin %s\n", msg);
|
|
printf("thread reg(%x) = 0x%x\n",
|
|
(uintptr_t) (cryptDMA_THREAD_REG(threadidx)),
|
|
REG32(cryptDMA_THREAD_REG(threadidx)));
|
|
printf("status reg(%x) = 0x%x\n",
|
|
(uintptr_t) (cryptDMA_STATUS_REG(threadidx)),
|
|
REG32(cryptDMA_STATUS_REG(threadidx)));
|
|
|
|
printf("main dsc: 0x%x\n", (uintptr_t)dsc);
|
|
for (i = 0; i < nents; i++) {
|
|
printf("desc (%x) (len) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.length);
|
|
printf("desc (%x) (irq) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.irq);
|
|
printf("desc (%x) (eoc) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.eoc);
|
|
printf("desc (%x) (lop) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.loop);
|
|
printf("desc (%x) (mod) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.mode);
|
|
printf("desc (%x) (beg) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.begin);
|
|
printf("desc (%x) (end) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.end);
|
|
printf("desc (%x) (opm) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.op_mode);
|
|
printf("desc (%x) (enc) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.enc_sha_only);
|
|
printf("desc (%x) (blk) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.block);
|
|
printf("desc (%x) (lnk_err) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.link_error);
|
|
printf("desc (%x) (own) = 0x%x\n", i,
|
|
(int)dsc[i].dsc_cfg.b.owner);
|
|
#if DMA_64_BIT
|
|
printf("desc (%x) (src) = 0x%llx\n", i, (int)dsc[i].src_addr);
|
|
printf("desc (%x) (tgt) = 0x%llx\n", i, (int)dsc[i].tgt_addr);
|
|
#else
|
|
printf("desc (%x) (src) = 0x%x\n", i, (int)dsc[i].src_addr);
|
|
printf("desc (%x) (tgt) = 0x%x\n", i, (int)dsc[i].tgt_addr);
|
|
#endif
|
|
}
|
|
printf("end %s\n", msg);
|
|
}
|
|
#endif
|
|
|
|
static int xAmlMemcpyWithDSC(void *dest, const void *src, size_t n)
|
|
{
|
|
uint32_t i = 0;
|
|
uint32_t cnt = 0;
|
|
uint32_t nb, b;
|
|
const uint32_t thread = cryptCRYPTO_THREAD_IDX;
|
|
|
|
//printf("%s:%d: main dsc: 0x%x\n", __func__, __LINE__, (uintptr_t)g_dsc);
|
|
/* sanity check */
|
|
if (!dest || !src || !n)
|
|
return -pdFREERTOS_ERRNO_EINVAL;
|
|
|
|
if ((uintptr_t)dest >= UNSUPPORT_ADDR_START && (uintptr_t)dest < UNSUPPORT_ADDR_END) {
|
|
printf("dst(%p) unsupported.\n", dest);
|
|
return -pdFREERTOS_ERRNO_EINVAL;
|
|
}
|
|
|
|
if ((uintptr_t)src >= UNSUPPORT_ADDR_START && (uintptr_t)src < UNSUPPORT_ADDR_END) {
|
|
printf("src(%p) unsupported.\n", src);
|
|
return -pdFREERTOS_ERRNO_EINVAL;
|
|
}
|
|
|
|
if (n > MAX_BYTES_TRANSFER) {
|
|
printf("size(%u) too big.\n", n);
|
|
return -pdFREERTOS_ERRNO_EINVAL;
|
|
}
|
|
|
|
xSemaphoreTake(dma_mutex, portMAX_DELAY);
|
|
|
|
memset(&g_dsc, 0, sizeof(g_dsc));
|
|
|
|
nb = n & (cryptDMA_BLOCK_SIZE - 1);
|
|
b = (n - nb) >> cryptDMA_BLOCK_SIZE_SHIFT;
|
|
|
|
//printf("%s:%d: b(%u) nb(%u)\n", __func__, __LINE__, b, nb);
|
|
if (b) {
|
|
g_dsc[i].src_addr = (uintptr_t)src;
|
|
g_dsc[i].tgt_addr = (uintptr_t)dest;
|
|
g_dsc[i].dsc_cfg.d32 = 0;
|
|
g_dsc[i].dsc_cfg.b.block = 1; /* block mode */
|
|
g_dsc[i].dsc_cfg.b.length = b;
|
|
g_dsc[i].dsc_cfg.b.mode = cryptDMA_MODE_DMA; /* copy */
|
|
g_dsc[i].dsc_cfg.b.owner = 1;
|
|
i++;
|
|
}
|
|
|
|
if (nb) {
|
|
g_dsc[i].src_addr = (uintptr_t)((uint8_t *)src + b * cryptDMA_BLOCK_SIZE);
|
|
g_dsc[i].tgt_addr = (uintptr_t)((uint8_t *)dest + b * cryptDMA_BLOCK_SIZE);
|
|
g_dsc[i].dsc_cfg.d32 = 0;
|
|
g_dsc[i].dsc_cfg.b.length = nb;
|
|
g_dsc[i].dsc_cfg.b.mode = cryptDMA_MODE_DMA; /* copy */
|
|
g_dsc[i].dsc_cfg.b.owner = 1;
|
|
i++;
|
|
}
|
|
g_dsc[i-1].dsc_cfg.b.eoc = 1;
|
|
|
|
REG32(cryptDMA_STATUS_REG(thread)) = 0xffff;
|
|
#if AML_CRYPTO_DEBUG
|
|
prvAmlDmaDebug(g_dsc, thread, i, "memcpy start");
|
|
#endif
|
|
REG32(cryptDMA_THREAD_REG(thread)) = (uintptr_t)&g_dsc | 2;
|
|
|
|
while ((REG32(cryptDMA_STATUS_REG(thread)) == 0) && cnt < DMA_TIME_OUT)
|
|
cnt++;
|
|
|
|
xSemaphoreGive(dma_mutex);
|
|
#if AML_CRYPTO_DEBUG
|
|
prvAmlDmaDebug(g_dsc, thread, i, "memcpy end");
|
|
#endif
|
|
if (REG32(cryptDMA_STATUS_REG(thread)) &
|
|
(cryptoDMA_STS_ERROR | cryptoDMA_STS_ERROR_REASON)) {
|
|
printf("DMA failed(%x)\n", REG32(cryptDMA_STATUS_REG(thread)));
|
|
return -pdFREERTOS_ERRNO_ENXIO;
|
|
}
|
|
|
|
if (cnt >= DMA_TIME_OUT) {
|
|
printf("DMA timeout\n");
|
|
return -pdFREERTOS_ERRNO_ETIMEDOUT;
|
|
}
|
|
|
|
return pdFREERTOS_ERRNO_NONE;
|
|
}
|
|
|
|
#if AML_CRYPTO_TEST
|
|
enum {
|
|
SRAM_TO_SRAM = 0,
|
|
SRAM_TO_DDR = 1,
|
|
DDR_TO_DDR = 2,
|
|
DDR_TO_SRAM = 3,
|
|
};
|
|
static uint8_t from[SZ], to[SZ];
|
|
|
|
void xDmaTest(uint32_t dir)
|
|
{
|
|
uint8_t i = 0;
|
|
uint8_t *f, *t;
|
|
uint32_t printed = 0;
|
|
uint32_t ret = 0;
|
|
|
|
if (dir == SRAM_TO_SRAM) {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Test DMA(SRAM -> SRAM)\n");
|
|
#endif
|
|
f = from;
|
|
t = to;
|
|
memset(from, MAGIC, SZ);
|
|
memset(to, 0x0, SZ);
|
|
} else if (dir == SRAM_TO_DDR) {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Test DMA(sram -> DDR)\n");
|
|
#endif
|
|
f = from;
|
|
t = (uint8_t *)TEST_DDR_OUT;
|
|
memset(from, MAGIC, SZ);
|
|
} else if (dir == DDR_TO_DDR) {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Test DMA(DDR -> DDR)\n");
|
|
#endif
|
|
f = (uint8_t *)TEST_DDR_IN;
|
|
t = (uint8_t *)TEST_DDR_OUT;
|
|
} else if (dir == DDR_TO_SRAM) {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Test DMA(DDR -> SRAM)\n");
|
|
#endif
|
|
f = (uint8_t *)TEST_DDR_IN;
|
|
t = to;
|
|
memset(to, 0x0, SZ);
|
|
memset(from, MAGIC, SZ);
|
|
} else {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("Invalid direction %u\n", dir);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (xAmlMemcpyWithDSC(t, f, SZ) < 0) {
|
|
#if AML_CRYPTO_DEBUG
|
|
printf("xAmlMemcpyWithDSC failed.\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (dir == SRAM_TO_SRAM)
|
|
ret = memcmp(t, f, SZ);
|
|
else if (dir == DDR_TO_SRAM)
|
|
ret = memcmp(from, t, SZ);
|
|
#if AML_CRYPTO_DEBUG
|
|
if (ret) {
|
|
printf("DMA memcpy failed\n");
|
|
} else {
|
|
if (dir == SRAM_TO_DDR || dir == DDR_TO_DDR)
|
|
printf("Pls check content at addr(%x)\n", TEST_DDR_OUT);
|
|
else
|
|
printf("DMA memcpy successful.\n");
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void vVDMAInit(void)
|
|
{
|
|
vDmaInit();
|
|
}
|
|
|
|
int xVDMATransfer(struct vdma_info *info)
|
|
{
|
|
if (!info)
|
|
return -pdFREERTOS_ERRNO_EINVAL;
|
|
|
|
return xAmlMemcpyWithDSC(info->dest, info->src, info->size);
|
|
}
|
|
|