mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
crypto: starfive - Add hash and HMAC support
Adding hash/HMAC support for SHA-2 and SM3 to StarFive cryptographic module. Co-developed-by: Huan Feng <huan.feng@starfivetech.com> Signed-off-by: Huan Feng <huan.feng@starfivetech.com> Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 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 @@ err_dma_init:
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user