Skip to content

Commit

Permalink
crypto: marvell/cesa - add TDMA support
Browse files Browse the repository at this point in the history
The CESA IP supports CPU offload through a dedicated DMA engine (TDMA)
which can control the crypto block.
When you use this mode, all the required data (operation metadata and
payload data) are transferred using DMA, and the results are retrieved
through DMA when possible (hash results are not retrieved through DMA yet),
thus reducing the involvement of the CPU and providing better performances
in most cases (for small requests, the cost of DMA preparation might
exceed the performance gain).

Note that some CESA IPs do not embed this dedicated DMA, hence the
activation of this feature on a per platform basis.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Boris BREZILLON authored and Herbert Xu committed Jun 19, 2015
1 parent f63601f commit db509a4
Show file tree
Hide file tree
Showing 7 changed files with 1,101 additions and 16 deletions.
1 change: 1 addition & 0 deletions drivers/crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ config CRYPTO_DEV_MARVELL_CESA
help
This driver allows you to utilize the Cryptographic Engines and
Security Accelerator (CESA) which can be found on the Armada 370.
This driver supports CPU offload through DMA transfers.

This driver is aimed at replacing the mv_cesa driver. This will only
happen once it has received proper testing.
Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/marvell/Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
obj-$(CONFIG_CRYPTO_DEV_MARVELL_CESA) += marvell-cesa.o
marvell-cesa-objs := cesa.o cipher.o hash.o
marvell-cesa-objs := cesa.o cipher.o hash.o tdma.o
68 changes: 68 additions & 0 deletions drivers/crypto/marvell/cesa.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ static const struct mv_cesa_caps armada_370_caps = {
.ncipher_algs = ARRAY_SIZE(armada_370_cipher_algs),
.ahash_algs = armada_370_ahash_algs,
.nahash_algs = ARRAY_SIZE(armada_370_ahash_algs),
.has_tdma = true,
};

static const struct of_device_id mv_cesa_of_match_table[] = {
Expand All @@ -192,6 +193,66 @@ static const struct of_device_id mv_cesa_of_match_table[] = {
};
MODULE_DEVICE_TABLE(of, mv_cesa_of_match_table);

static void
mv_cesa_conf_mbus_windows(struct mv_cesa_engine *engine,
const struct mbus_dram_target_info *dram)
{
void __iomem *iobase = engine->regs;
int i;

for (i = 0; i < 4; i++) {
writel(0, iobase + CESA_TDMA_WINDOW_CTRL(i));
writel(0, iobase + CESA_TDMA_WINDOW_BASE(i));
}

for (i = 0; i < dram->num_cs; i++) {
const struct mbus_dram_window *cs = dram->cs + i;

writel(((cs->size - 1) & 0xffff0000) |
(cs->mbus_attr << 8) |
(dram->mbus_dram_target_id << 4) | 1,
iobase + CESA_TDMA_WINDOW_CTRL(i));
writel(cs->base, iobase + CESA_TDMA_WINDOW_BASE(i));
}
}

static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa)
{
struct device *dev = cesa->dev;
struct mv_cesa_dev_dma *dma;

if (!cesa->caps->has_tdma)
return 0;

dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;

dma->tdma_desc_pool = dmam_pool_create("tdma_desc", dev,
sizeof(struct mv_cesa_tdma_desc),
16, 0);
if (!dma->tdma_desc_pool)
return -ENOMEM;

dma->op_pool = dmam_pool_create("cesa_op", dev,
sizeof(struct mv_cesa_op_ctx), 16, 0);
if (!dma->op_pool)
return -ENOMEM;

dma->cache_pool = dmam_pool_create("cesa_cache", dev,
CESA_MAX_HASH_BLOCK_SIZE, 1, 0);
if (!dma->cache_pool)
return -ENOMEM;

dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0);
if (!dma->cache_pool)
return -ENOMEM;

cesa->dma = dma;

return 0;
}

static int mv_cesa_get_sram(struct platform_device *pdev, int idx)
{
struct mv_cesa_dev *cesa = platform_get_drvdata(pdev);
Expand Down Expand Up @@ -299,6 +360,10 @@ static int mv_cesa_probe(struct platform_device *pdev)
if (IS_ERR(cesa->regs))
return -ENOMEM;

ret = mv_cesa_dev_dma_init(cesa);
if (ret)
return ret;

dram = mv_mbus_dram_info_nooverlap();

platform_set_drvdata(pdev, cesa);
Expand Down Expand Up @@ -347,6 +412,9 @@ static int mv_cesa_probe(struct platform_device *pdev)

engine->regs = cesa->regs + CESA_ENGINE_OFF(i);

if (dram && cesa->caps->has_tdma)
mv_cesa_conf_mbus_windows(&cesa->engines[i], dram);

writel(0, cesa->engines[i].regs + CESA_SA_INT_STATUS);
writel(CESA_SA_CFG_STOP_DIG_ERR,
cesa->engines[i].regs + CESA_SA_CFG);
Expand Down
Loading

0 comments on commit db509a4

Please sign in to comment.