blob: 0584564911ebb49b032c8bf6d075abc2381ba43d [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/hw_random.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/crypto.h>
#include <linux/cryptohash.h>
#include <crypto/scatterwalk.h>
#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
#include "aml-crypto-dma.h"
#define DEBUG (0)
u32 swap_ulong32(u32 val)
{
u32 res = 0;
res = ((val & 0xff) << 24) + (((val >> 8) & 0xff) << 16) +
(((val >> 16) & 0xff) << 8) + ((val >> 24) & 0xff);
return res;
}
EXPORT_SYMBOL_GPL(swap_ulong32);
void aml_write_crypto_reg(u32 addr, u32 data)
{
if (cryptoreg)
writel(data, cryptoreg + (addr << 2));
else
pr_err("crypto reg mapping is not initailized\n");
}
EXPORT_SYMBOL_GPL(aml_write_crypto_reg);
u32 aml_read_crypto_reg(u32 addr)
{
if (!cryptoreg) {
pr_err("crypto reg mapping is not initailized\n");
return 0;
}
return readl(cryptoreg + (addr << 2));
}
EXPORT_SYMBOL_GPL(aml_read_crypto_reg);
void aml_dma_debug(struct dma_dsc *dsc, u32 nents, const char *msg,
u32 thread, u32 status)
{
u32 i = 0;
dbgp(0, "begin %s\n", msg);
dbgp(0, "reg(%u) = 0x%8x\n", thread,
aml_read_crypto_reg(thread));
dbgp(0, "reg(%u) = 0x%8x\n", status,
aml_read_crypto_reg(status));
for (i = 0; i < nents; i++) {
dbgp(0, "desc (%4x) (len) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.length);
dbgp(0, "desc (%4x) (irq) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.irq);
dbgp(0, "desc (%4x) (eoc) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.eoc);
dbgp(0, "desc (%4x) (lop) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.loop);
dbgp(0, "desc (%4x) (mod) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.mode);
dbgp(0, "desc (%4x) (beg) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.begin);
dbgp(0, "desc (%4x) (end) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.end);
dbgp(0, "desc (%4x) (opm) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.op_mode);
dbgp(0, "desc (%4x) (enc) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.enc_sha_only);
dbgp(0, "desc (%4x) (blk) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.block);
dbgp(0, "desc (%4x) (err) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.error);
dbgp(0, "desc (%4x) (own) = 0x%8x\n", i,
dsc[i].dsc_cfg.b.owner);
dbgp(0, "desc (%4x) (src) = 0x%8x\n", i,
dsc[i].src_addr);
dbgp(0, "desc (%4x) (tgt) = 0x%8x\n", i,
dsc[i].tgt_addr);
}
dbgp(0, "end %s\n", msg);
}
EXPORT_SYMBOL_GPL(aml_dma_debug);
u8 aml_dma_do_hw_crypto(struct aml_dma_dev *dd,
struct dma_dsc *dsc,
u32 dsc_len,
dma_addr_t dsc_addr,
u8 polling, u8 dma_flags)
{
u8 status = 0;
spin_lock_irqsave(&dd->dma_lock, dd->irq_flags);
dd->dma_busy |= dma_flags;
aml_write_crypto_reg(dd->thread, (uintptr_t)dsc_addr | 2);
if (polling) {
while (aml_read_crypto_reg(dd->status) == 0)
;
status = aml_read_crypto_reg(dd->status);
WARN_ON(!(dsc[dsc_len - 1].dsc_cfg.b.eoc == 1));
if (dsc[dsc_len - 1].dsc_cfg.b.eoc == 1) {
while (dsc[dsc_len - 1].dsc_cfg.b.owner)
cpu_relax();
}
aml_write_crypto_reg(dd->status, 0xf);
dd->dma_busy &= ~dma_flags;
}
spin_unlock_irqrestore(&dd->dma_lock, dd->irq_flags);
return status;
}
EXPORT_SYMBOL_GPL(aml_dma_do_hw_crypto);
void aml_dma_finish_hw_crypto(struct aml_dma_dev *dd, u8 dma_flags)
{
spin_lock_irqsave(&dd->dma_lock, dd->irq_flags);
aml_write_crypto_reg(dd->status, 0xf);
dd->dma_busy &= ~dma_flags;
spin_unlock_irqrestore(&dd->dma_lock, dd->irq_flags);
}
EXPORT_SYMBOL_GPL(aml_dma_finish_hw_crypto);
int aml_dma_crypto_enqueue_req(struct aml_dma_dev *dd,
struct crypto_async_request *req)
{
s32 ret = 0;
unsigned long flags;
spin_lock_irqsave(&dd->queue_lock, flags);
ret = crypto_enqueue_request(&dd->queue, req);
spin_unlock_irqrestore(&dd->queue_lock, flags);
wake_up_process(dd->kthread);
return ret;
}
EXPORT_SYMBOL_GPL(aml_dma_crypto_enqueue_req);
#if DEBUG
void dump_buf(const s8 *name, u8 *buf, const s32 length)
{
s32 i = 0;
s32 j = length;
pr_err("\nstart dump(%s, %d)================\n", name, length);
while (j >= 8) {
pr_err("%#02x ~ %#02x:\n", i, i + 7);
pr_err("%#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x, %#02x\n",
buf[i], buf[i + 1], buf[i + 2], buf[i + 3],
buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
i += 8;
j -= 8;
};
while (j > 0) {
pr_err("%#02x ", buf[i]);
j--;
i++;
};
pr_err("\nend dump(%s, %d)================\n", name, length);
}
#endif