Commit 7883d1b2 authored by Jia Jie Ho's avatar Jia Jie Ho Committed by Herbert Xu

crypto: starfive - Add hash and HMAC support

Adding hash/HMAC support for SHA-2 and SM3 to StarFive cryptographic
module.
Co-developed-by: default avatarHuan Feng <huan.feng@starfivetech.com>
Signed-off-by: default avatarHuan Feng <huan.feng@starfivetech.com>
Signed-off-by: default avatarJia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 42ef0e94
......@@ -6,6 +6,10 @@ config CRYPTO_DEV_JH7110
tristate "StarFive JH7110 cryptographic engine driver"
depends on SOC_STARFIVE || COMPILE_TEST
select CRYPTO_ENGINE
select CRYPTO_HMAC
select CRYPTO_SHA256
select CRYPTO_SHA512
select CRYPTO_SM3_GENERIC
select ARM_AMBA
select DMADEVICES
select AMBA_PL08X
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o
jh7110-crypto-objs := jh7110-cryp.o
jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o
......@@ -79,10 +79,25 @@ static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp)
dma_release_channel(cryp->rx);
}
static irqreturn_t starfive_cryp_irq(int irq, void *priv)
{
u32 status;
struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv;
status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET);
if (status & STARFIVE_IE_FLAG_HASH_DONE) {
writel(STARFIVE_IE_MASK_HASH_DONE, cryp->base + STARFIVE_IE_MASK_OFFSET);
tasklet_schedule(&cryp->hash_done);
}
return IRQ_HANDLED;
}
static int starfive_cryp_probe(struct platform_device *pdev)
{
struct starfive_cryp_dev *cryp;
struct resource *res;
int irq;
int ret;
cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL);
......@@ -97,6 +112,8 @@ static int starfive_cryp_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base),
"Error remapping memory for platform device\n");
tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp);
cryp->phys_base = res->start;
cryp->dma_maxburst = 32;
......@@ -115,6 +132,16 @@ static int starfive_cryp_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
"Error getting hardware reset line\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
ret = devm_request_irq(&pdev->dev, irq, starfive_cryp_irq, 0, pdev->name,
(void *)cryp);
if (ret)
return dev_err_probe(&pdev->dev, irq,
"Failed to register interrupt handler\n");
clk_prepare_enable(cryp->hclk);
clk_prepare_enable(cryp->ahb);
reset_control_deassert(cryp->rst);
......@@ -142,8 +169,14 @@ static int starfive_cryp_probe(struct platform_device *pdev)
if (ret)
goto err_engine_start;
ret = starfive_hash_register_algs();
if (ret)
goto err_algs_hash;
return 0;
err_algs_hash:
crypto_engine_stop(cryp->engine);
err_engine_start:
crypto_engine_exit(cryp->engine);
err_engine:
......@@ -156,6 +189,8 @@ static int starfive_cryp_probe(struct platform_device *pdev)
clk_disable_unprepare(cryp->hclk);
clk_disable_unprepare(cryp->ahb);
reset_control_assert(cryp->rst);
tasklet_kill(&cryp->hash_done);
err_probe_defer:
return ret;
}
......@@ -164,6 +199,10 @@ static int starfive_cryp_remove(struct platform_device *pdev)
{
struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev);
starfive_hash_unregister_algs();
tasklet_kill(&cryp->hash_done);
crypto_engine_stop(cryp->engine);
crypto_engine_exit(cryp->engine);
......
......@@ -7,6 +7,8 @@
#include <linux/dmaengine.h>
#include <crypto/engine.h>
#include <crypto/sha2.h>
#include <crypto/sm3.h>
#define STARFIVE_ALG_CR_OFFSET 0x0
#define STARFIVE_ALG_FIFO_OFFSET 0x4
......@@ -15,7 +17,43 @@
#define STARFIVE_DMA_IN_LEN_OFFSET 0x10
#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14
#define STARFIVE_IE_MASK_HASH_DONE 0x4
#define STARFIVE_IE_FLAG_HASH_DONE 0x4
#define STARFIVE_MSG_BUFFER_SIZE SZ_16K
#define MAX_KEY_SIZE SHA512_BLOCK_SIZE
union starfive_hash_csr {
u32 v;
struct {
u32 start :1;
u32 reset :1;
u32 ie :1;
u32 firstb :1;
#define STARFIVE_HASH_SM3 0x0
#define STARFIVE_HASH_SHA224 0x3
#define STARFIVE_HASH_SHA256 0x4
#define STARFIVE_HASH_SHA384 0x5
#define STARFIVE_HASH_SHA512 0x6
#define STARFIVE_HASH_MODE_MASK 0x7
u32 mode :3;
u32 rsvd_1 :1;
u32 final :1;
u32 rsvd_2 :2;
#define STARFIVE_HASH_HMAC_FLAGS 0x800
u32 hmac :1;
u32 rsvd_3 :1;
#define STARFIVE_HASH_KEY_DONE BIT(13)
u32 key_done :1;
u32 key_flag :1;
u32 hmac_done :1;
#define STARFIVE_HASH_BUSY BIT(16)
u32 busy :1;
u32 hashdone :1;
u32 rsvd_4 :14;
};
};
union starfive_alg_cr {
u32 v;
......@@ -34,12 +72,18 @@ union starfive_alg_cr {
struct starfive_cryp_ctx {
struct crypto_engine_ctx enginectx;
struct starfive_cryp_dev *cryp;
struct starfive_cryp_request_ctx *rctx;
unsigned int hash_mode;
u8 key[MAX_KEY_SIZE];
int keylen;
bool is_hmac;
struct crypto_ahash *ahash_fbk;
};
struct starfive_cryp_dev {
struct list_head list;
struct device *dev;
struct clk *hclk;
struct clk *ahb;
struct reset_control *rst;
......@@ -52,12 +96,32 @@ struct starfive_cryp_dev {
struct dma_chan *rx;
struct dma_slave_config cfg_in;
struct dma_slave_config cfg_out;
struct crypto_engine *engine;
struct tasklet_struct hash_done;
int err;
union starfive_alg_cr alg_cr;
union {
struct ahash_request *hreq;
} req;
};
struct starfive_cryp_request_ctx {
union {
union starfive_hash_csr hash;
} csr;
struct scatterlist *in_sg;
struct ahash_request ahash_fbk_req;
size_t total;
unsigned int blksize;
unsigned int digsize;
unsigned long in_sg_len;
};
struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx);
int starfive_hash_register_algs(void);
void starfive_hash_unregister_algs(void);
void starfive_hash_done_task(unsigned long param);
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment