// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "aml-crypto-dma.h" #define AML_CRYPTO_DMA_DBG (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(struct aml_dma_dev *dd, u32 addr, u64 data) { if (dd && cryptoreg) { u32 low = (u32)(0xffffffff & data); /* If 64 bits mode and wants to write thread reg */ if (dd->dma_bus64 && addr == dd->thread) { u32 high = (u32)(0xff & (data >> 32)); writel(high, cryptoreg + (addr << 2) + 0x80); } writel(low, cryptoreg + (addr << 2)); } else { pr_err("crypto reg mapping is not initialized\n"); } } EXPORT_SYMBOL_GPL(aml_write_crypto_reg); u32 aml_read_crypto_reg(u32 addr) { if (!cryptoreg) { pr_err("crypto reg mapping is not initialized\n"); return 0; } return readl(cryptoreg + (addr << 2)); } EXPORT_SYMBOL_GPL(aml_read_crypto_reg); void aml_dma_debug_v1(void *descriptor, u32 nents, const char *msg, u32 thread, u32 status, u8 dma_bus64) { u32 i = 0; struct dma_dsc *dsc = descriptor; struct dma_dsc_64 *dsc_64 = descriptor; 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)); dbgp(0, "bus64 = %u\n", dma_bus64); if (dma_bus64) { for (i = 0; i < nents; i++) { dbgp(0, "desc (%4x) (len) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.length); dbgp(0, "desc (%4x) (irq) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.irq); dbgp(0, "desc (%4x) (eoc) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.eoc); dbgp(0, "desc (%4x) (lop) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.loop); dbgp(0, "desc (%4x) (mod) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.mode); dbgp(0, "desc (%4x) (beg) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.begin); dbgp(0, "desc (%4x) (end) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.end); dbgp(0, "desc (%4x) (opm) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.op_mode); dbgp(0, "desc (%4x) (enc) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.enc_sha_only); dbgp(0, "desc (%4x) (blk) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.block); dbgp(0, "desc (%4x) (lnk_err) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.link_error); dbgp(0, "desc (%4x) (own) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.owner); dbgp(0, "desc (%4x) (src) = 0x%16llx\n", i, dsc_64[i].src_addr); dbgp(0, "desc (%4x) (tgt) = 0x%16llx\n", i, dsc_64[i].tgt_addr); } } else { 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) (lnk_err) = 0x%8x\n", i, dsc[i].dsc_cfg.b.link_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); } void aml_dma_debug_v2(void *descriptor, u32 nents, const char *msg, u32 thread, u32 status, u8 dma_bus64) { u32 i = 0; struct dma_dsc_v2 *dsc = descriptor; struct dma_dsc_v2_64 *dsc_64 = descriptor; 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)); dbgp(0, "bus64 = %u\n", dma_bus64); if (dma_bus64) { for (i = 0; i < nents; i++) { dbgp(0, "desc (%4x) (len) = 0x%8x\n", i, dsc_64[i].length); dbgp(0, "desc (%4x) (skp) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.skip_block_count); dbgp(0, "desc (%4x) (crp) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.crypt_block_count); dbgp(0, "desc (%4x) (irq) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.irq); dbgp(0, "desc (%4x) (eoc) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.eoc); dbgp(0, "desc (%4x) (lop) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.loop); dbgp(0, "desc (%4x) (mod) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.mode); dbgp(0, "desc (%4x) (beg) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.begin); dbgp(0, "desc (%4x) (end) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.end); dbgp(0, "desc (%4x) (opm) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.op_mode); dbgp(0, "desc (%4x) (enc) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.enc_sha_only); dbgp(0, "desc (%4x) (lnk_err) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.link_error); dbgp(0, "desc (%4x) (own) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.owner); dbgp(0, "desc (%4x) (src) = 0x%16llx\n", i, dsc_64[i].src_addr); dbgp(0, "desc (%4x) (tgt) = 0x%16llx\n", i, dsc_64[i].tgt_addr); } } else { for (i = 0; i < nents; i++) { dbgp(0, "desc (%4x) (len) = 0x%8x\n", i, dsc[i].length); dbgp(0, "desc (%4x) (skp) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.skip_block_count); dbgp(0, "desc (%4x) (crp) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.crypt_block_count); 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) (lnk_err) = 0x%8x\n", i, dsc[i].dsc_cfg.b.link_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); } void aml_dma_debug(void *descriptor, u32 nents, const char *msg, u32 thread, u32 status, struct aml_dma_dev *dma) { if (dma->dma_version == DMA_VERSION_1) return aml_dma_debug_v1(descriptor, nents, msg, thread, status, dma->dma_bus64); else if (dma->dma_version == DMA_VERSION_2) return aml_dma_debug_v2(descriptor, nents, msg, thread, status, dma->dma_bus64); else return; } EXPORT_SYMBOL_GPL(aml_dma_debug); void aml_dma_link_debug(void *descriptor, dma_addr_t dma_dsc, u32 nents, const char *msg, u8 dma_bus64) { struct dma_sg_dsc *dsc = descriptor; struct dma_sg_dsc_64 *dsc_64 = descriptor; u32 i = 0; dbgp(0, "link begin %s\n", msg); dbgp(0, "link dma_addr 0x%lx\n", (unsigned long)dma_dsc); if (dma_bus64) { for (i = 0; i < nents; i++) { dbgp(0, "sg desc (%4x) (vld) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.valid); dbgp(0, "sg desc (%4x) (eoc) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.eoc); dbgp(0, "sg desc (%4x) (int) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.intr); dbgp(0, "sg desc (%4x) (act) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.act); dbgp(0, "sg desc (%4x) (len) = 0x%8x\n", i, dsc_64[i].dsc_cfg.b.length); dbgp(0, "sg desc (%4x) (adr) = 0x%16llx\n", i, dsc_64[i].addr); } } else { for (i = 0; i < nents; i++) { dbgp(0, "sg desc (%4x) (vld) = 0x%8x\n", i, dsc[i].dsc_cfg.b.valid); dbgp(0, "sg desc (%4x) (eoc) = 0x%8x\n", i, dsc[i].dsc_cfg.b.eoc); dbgp(0, "sg desc (%4x) (int) = 0x%8x\n", i, dsc[i].dsc_cfg.b.intr); dbgp(0, "sg desc (%4x) (act) = 0x%8x\n", i, dsc[i].dsc_cfg.b.act); dbgp(0, "sg desc (%4x) (len) = 0x%8x\n", i, dsc[i].dsc_cfg.b.length); dbgp(0, "sg desc (%4x) (adr) = 0x%8x\n", i, dsc[i].addr); } } dbgp(0, "link end %s\n", msg); } EXPORT_SYMBOL_GPL(aml_dma_link_debug); irqreturn_t aml_crypto_dma_irq(int irq, void *dev_id) { struct aml_dma_dev *dd = dev_id; struct device *dev = dd->dev; u32 status = aml_read_crypto_reg(dd->status); if (status) { if (status == 0x1) dev_err(dev, "irq overwrite\n"); if (dd->dma_busy) { complete(&dd->done); return IRQ_HANDLED; } else { return IRQ_NONE; } } return IRQ_NONE; } u32 aml_dma_do_hw_crypto(struct aml_dma_dev *dd, void *descriptor, u32 dsc_len, dma_addr_t dsc_addr, u8 polling, u8 dma_flags) { u32 status = 0; struct dma_dsc_v2_64 dsc; spin_lock_irqsave(&dd->dma_lock, dd->irq_flags); dd->dma_busy |= dma_flags; reinit_completion(&dd->done); spin_unlock_irqrestore(&dd->dma_lock, dd->irq_flags); aml_write_crypto_reg(dd, dd->status, 0xffff); aml_write_crypto_reg(dd, dd->thread, (uintptr_t)dsc_addr | 2); if (polling) { while (aml_read_crypto_reg(dd->status) == 0) ; } else { wait_for_completion(&dd->done); } status = aml_read_crypto_reg(dd->status); if (status & DMA_STATUS_KEY_ERROR) { /* If error occurs, report it and don't wait owner bit */ pr_err("Error returned by DMA(0x%8x)\n", status); } else { aml_dma_dsc_reader(descriptor, dsc_len - 1, &dsc, 0, dd); WARN_ON(!dsc.dsc_cfg.b.eoc); if (dsc.dsc_cfg.b.eoc == 1) { while (dsc.dsc_cfg.b.owner != 0) { cpu_relax(); aml_dma_dsc_reader(descriptor, dsc_len - 1, &dsc, 0, dd); } } } spin_lock_irqsave(&dd->dma_lock, dd->irq_flags); 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, dd->status, 0xffff); 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); noinline int aml_dma_call_smc(u64 func_id, u64 arg0, u64 arg1, u64 arg2) { struct arm_smccc_res res; arm_smccc_smc((unsigned long)func_id, (unsigned long)arg0, (unsigned long)arg1, (unsigned long)arg2, 0, 0, 0, 0, &res); return res.a0; } EXPORT_SYMBOL_GPL(aml_dma_call_smc); inline void aml_dma_dsc_writer_v1(void *base, u32 i, void *dsc, u8 dma_bus64, u8 is_sg_dsc) { u8 use_block_mode = 0; if (dma_bus64) { if (!is_sg_dsc) { struct dma_dsc_64 *dsc_base = base; struct dma_dsc_v2_64 *dsc_to_write = dsc; if (!(dsc_to_write->length % DMA_BLOCK_MODE_SIZE)) use_block_mode = 1; dsc_base[i].src_addr = dsc_to_write->src_addr; dsc_base[i].tgt_addr = dsc_to_write->tgt_addr; dsc_base[i].dsc_cfg.d32 = 0; dsc_base[i].dsc_cfg.b.irq = dsc_to_write->dsc_cfg.b.irq; dsc_base[i].dsc_cfg.b.eoc = dsc_to_write->dsc_cfg.b.eoc; dsc_base[i].dsc_cfg.b.loop = dsc_to_write->dsc_cfg.b.loop; dsc_base[i].dsc_cfg.b.mode = dsc_to_write->dsc_cfg.b.mode; dsc_base[i].dsc_cfg.b.begin = dsc_to_write->dsc_cfg.b.begin; dsc_base[i].dsc_cfg.b.end = dsc_to_write->dsc_cfg.b.end; dsc_base[i].dsc_cfg.b.op_mode = dsc_to_write->dsc_cfg.b.op_mode; dsc_base[i].dsc_cfg.b.enc_sha_only = dsc_to_write->dsc_cfg.b.enc_sha_only; if (use_block_mode) { dsc_base[i].dsc_cfg.b.length = dsc_to_write->length / DMA_BLOCK_MODE_SIZE; dsc_base[i].dsc_cfg.b.block = 1; } else { dsc_base[i].dsc_cfg.b.length = dsc_to_write->length; WARN_ON(dsc_base[i].dsc_cfg.b.length != dsc_to_write->length); } dsc_base[i].dsc_cfg.b.link_error = dsc_to_write->dsc_cfg.b.link_error; dsc_base[i].dsc_cfg.b.owner = dsc_to_write->dsc_cfg.b.owner; } else { struct dma_sg_dsc_64 *dsc_base = base; struct dma_sg_dsc_64 *dsc_to_write = dsc; dsc_base[i] = *dsc_to_write; } } else { if (!is_sg_dsc) { struct dma_dsc *dsc_base = base; struct dma_dsc_v2_64 *dsc_to_write = dsc; if (!(dsc_to_write->length % DMA_BLOCK_MODE_SIZE)) use_block_mode = 1; dsc_base[i].src_addr = dsc_to_write->src_addr; dsc_base[i].tgt_addr = dsc_to_write->tgt_addr; dsc_base[i].dsc_cfg.d32 = 0; dsc_base[i].dsc_cfg.b.length = dsc_to_write->length; dsc_base[i].dsc_cfg.b.irq = dsc_to_write->dsc_cfg.b.irq; dsc_base[i].dsc_cfg.b.eoc = dsc_to_write->dsc_cfg.b.eoc; dsc_base[i].dsc_cfg.b.loop = dsc_to_write->dsc_cfg.b.loop; dsc_base[i].dsc_cfg.b.mode = dsc_to_write->dsc_cfg.b.mode; dsc_base[i].dsc_cfg.b.begin = dsc_to_write->dsc_cfg.b.begin; dsc_base[i].dsc_cfg.b.end = dsc_to_write->dsc_cfg.b.end; dsc_base[i].dsc_cfg.b.op_mode = dsc_to_write->dsc_cfg.b.op_mode; dsc_base[i].dsc_cfg.b.enc_sha_only = dsc_to_write->dsc_cfg.b.enc_sha_only; if (use_block_mode) { dsc_base[i].dsc_cfg.b.length = dsc_to_write->length / DMA_BLOCK_MODE_SIZE; dsc_base[i].dsc_cfg.b.block = 1; } else { dsc_base[i].dsc_cfg.b.length = dsc_to_write->length; } dsc_base[i].dsc_cfg.b.link_error = dsc_to_write->dsc_cfg.b.link_error; dsc_base[i].dsc_cfg.b.owner = dsc_to_write->dsc_cfg.b.owner; } else { struct dma_sg_dsc *dsc_base = base; struct dma_sg_dsc_64 *dsc_to_write = dsc; dsc_base[i].dsc_cfg = dsc_to_write->dsc_cfg; dsc_base[i].addr = dsc_to_write->addr; } } } inline void aml_dma_dsc_writer_v2(void *base, u32 i, void *dsc, u8 dma_bus64, u8 is_sg_dsc) { if (dma_bus64) { if (!is_sg_dsc) { struct dma_dsc_v2_64 *dsc_base = base; struct dma_dsc_v2_64 *dsc_to_write = dsc; dsc_base[i] = *dsc_to_write; } else { struct dma_sg_dsc_64 *dsc_base = base; struct dma_sg_dsc_64 *dsc_to_write = dsc; dsc_base[i] = *dsc_to_write; } } else { if (!is_sg_dsc) { struct dma_dsc_v2 *dsc_base = base; struct dma_dsc_v2_64 *dsc_to_write = dsc; dsc_base[i].dsc_cfg = dsc_to_write->dsc_cfg; dsc_base[i].src_addr = dsc_to_write->src_addr; dsc_base[i].tgt_addr = dsc_to_write->tgt_addr; } else { struct dma_sg_dsc *dsc_base = base; struct dma_sg_dsc_64 *dsc_to_write = dsc; dsc_base[i].dsc_cfg = dsc_to_write->dsc_cfg; dsc_base[i].addr = dsc_to_write->addr; } } } inline void aml_dma_dsc_writer(void *base, u32 i, void *dsc, u8 is_sg_dsc, struct aml_dma_dev *dma) { if (dma->dma_version == DMA_VERSION_1) return aml_dma_dsc_writer_v1(base, i, dsc, dma->dma_bus64, is_sg_dsc); else if (dma->dma_version == DMA_VERSION_2) return aml_dma_dsc_writer_v2(base, i, dsc, dma->dma_bus64, is_sg_dsc); else return; } EXPORT_SYMBOL_GPL(aml_dma_dsc_writer); inline void aml_dma_dsc_reader_v1(void *base, u32 i, void *dsc, u8 dma_bus64, u8 is_sg_dsc) { if (dma_bus64) { if (!is_sg_dsc) { struct dma_dsc_64 *dsc_base = base; struct dma_dsc_v2_64 *dsc_read = dsc; if (dsc_base[i].dsc_cfg.b.block) dsc_read->length = dsc_base[i].dsc_cfg.b.length * DMA_BLOCK_MODE_SIZE; else dsc_read->length = dsc_base[i].dsc_cfg.b.length; dsc_read->src_addr = dsc_base[i].src_addr; dsc_read->tgt_addr = dsc_base[i].tgt_addr; dsc_read->dsc_cfg.d32 = 0; dsc_read->dsc_cfg.b.irq = dsc_base[i].dsc_cfg.b.irq; dsc_read->dsc_cfg.b.eoc = dsc_base[i].dsc_cfg.b.eoc; dsc_read->dsc_cfg.b.loop = dsc_base[i].dsc_cfg.b.loop; dsc_read->dsc_cfg.b.mode = dsc_base[i].dsc_cfg.b.mode; dsc_read->dsc_cfg.b.begin = dsc_base[i].dsc_cfg.b.begin; dsc_read->dsc_cfg.b.end = dsc_base[i].dsc_cfg.b.end; dsc_read->dsc_cfg.b.op_mode = dsc_base[i].dsc_cfg.b.op_mode; dsc_read->dsc_cfg.b.enc_sha_only = dsc_base[i].dsc_cfg.b.enc_sha_only; dsc_read->dsc_cfg.b.link_error = dsc_base[i].dsc_cfg.b.link_error; dsc_read->dsc_cfg.b.owner = dsc_base[i].dsc_cfg.b.owner; } else { struct dma_sg_dsc_64 *dsc_base = base; struct dma_sg_dsc_64 *dsc_read = dsc; *dsc_read = dsc_base[i]; } } else { if (!is_sg_dsc) { struct dma_dsc *dsc_base = base; struct dma_dsc_v2_64 *dsc_read = dsc; if (dsc_base[i].dsc_cfg.b.block) dsc_read->length = dsc_base[i].dsc_cfg.b.length * DMA_BLOCK_MODE_SIZE; else dsc_read->length = dsc_base[i].dsc_cfg.b.length; dsc_read->src_addr = dsc_base[i].src_addr; dsc_read->tgt_addr = dsc_base[i].tgt_addr; dsc_read->dsc_cfg.d32 = 0; dsc_read->dsc_cfg.b.irq = dsc_base[i].dsc_cfg.b.irq; dsc_read->dsc_cfg.b.eoc = dsc_base[i].dsc_cfg.b.eoc; dsc_read->dsc_cfg.b.loop = dsc_base[i].dsc_cfg.b.loop; dsc_read->dsc_cfg.b.mode = dsc_base[i].dsc_cfg.b.mode; dsc_read->dsc_cfg.b.begin = dsc_base[i].dsc_cfg.b.begin; dsc_read->dsc_cfg.b.end = dsc_base[i].dsc_cfg.b.end; dsc_read->dsc_cfg.b.op_mode = dsc_base[i].dsc_cfg.b.op_mode; dsc_read->dsc_cfg.b.enc_sha_only = dsc_base[i].dsc_cfg.b.enc_sha_only; dsc_read->dsc_cfg.b.link_error = dsc_base[i].dsc_cfg.b.link_error; dsc_read->dsc_cfg.b.owner = dsc_base[i].dsc_cfg.b.owner; } else { struct dma_sg_dsc *dsc_base = base; struct dma_sg_dsc_64 *dsc_read = dsc; dsc_read->dsc_cfg = dsc_base[i].dsc_cfg; dsc_read->addr = dsc_base[i].addr; } } } inline void aml_dma_dsc_reader_v2(void *base, u32 i, void *dsc, u8 dma_bus64, u8 is_sg_dsc) { if (dma_bus64) { if (!is_sg_dsc) { struct dma_dsc_v2_64 *dsc_base = base; struct dma_dsc_v2_64 *dsc_read = dsc; *dsc_read = dsc_base[i]; } else { struct dma_sg_dsc_64 *dsc_base = base; struct dma_sg_dsc_64 *dsc_read = dsc; *dsc_read = dsc_base[i]; } } else { if (!is_sg_dsc) { struct dma_dsc_v2 *dsc_base = base; struct dma_dsc_v2_64 *dsc_read = dsc; dsc_read->dsc_cfg = dsc_base[i].dsc_cfg; dsc_read->src_addr = dsc_base[i].src_addr; dsc_read->tgt_addr = dsc_base[i].tgt_addr; } else { struct dma_sg_dsc *dsc_base = base; struct dma_sg_dsc_64 *dsc_read = dsc; dsc_read->dsc_cfg = dsc_base[i].dsc_cfg; dsc_read->addr = dsc_base[i].addr; } } } inline void aml_dma_dsc_reader(void *base, u32 i, void *dsc, u8 is_sg_dsc, struct aml_dma_dev *dma) { if (dma->dma_version == DMA_VERSION_1) return aml_dma_dsc_reader_v1(base, i, dsc, dma->dma_bus64, is_sg_dsc); else if (dma->dma_version == DMA_VERSION_2) return aml_dma_dsc_reader_v2(base, i, dsc, dma->dma_bus64, is_sg_dsc); else return; } EXPORT_SYMBOL_GPL(aml_dma_dsc_reader); inline u32 aml_dma_get_dsc_sz(u8 is_sg_dsc, struct aml_dma_dev *dma) { if (dma->dma_version == DMA_VERSION_1) { if (!is_sg_dsc) return dma->dma_bus64 ? sizeof(struct dma_dsc_64) : sizeof(struct dma_dsc); else return dma->dma_bus64 ? sizeof(struct dma_sg_dsc_64) : sizeof(struct dma_sg_dsc); } else if (dma->dma_version == DMA_VERSION_2) { if (!is_sg_dsc) return dma->dma_bus64 ? sizeof(struct dma_dsc_v2_64) : sizeof(struct dma_dsc_v2); else return dma->dma_bus64 ? sizeof(struct dma_sg_dsc_64) : sizeof(struct dma_sg_dsc); } else { return 0; } } EXPORT_SYMBOL_GPL(aml_dma_get_dsc_sz); #if AML_CRYPTO_DMA_DBG 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