The RK3399 has 2 crypto identical IP, so let's add support for both. We need also to handle all rk3399-cryto's resets. Signed-off-by: Corentin Labbe <clabbe@xxxxxxxxxxxx> --- drivers/crypto/rockchip/rk3288_crypto.c | 111 +++++++++++------- drivers/crypto/rockchip/rk3288_crypto.h | 32 +++-- drivers/crypto/rockchip/rk3288_crypto_ahash.c | 65 +++++----- .../crypto/rockchip/rk3288_crypto_skcipher.c | 51 ++++---- 4 files changed, 160 insertions(+), 99 deletions(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index 97ef59a36be6..5f1422094a7f 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -14,10 +14,19 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/clk.h> #include <linux/crypto.h> #include <linux/reset.h> +static const struct rk_variant rk3288_variant = { + .num_instance = 1 +}; + +static const struct rk_variant rk3399_variant = { + .num_instance = 2 +}; + static int rk_crypto_enable_clk(struct rk_crypto_info *dev) { int err; @@ -82,19 +91,25 @@ static void rk_crypto_pm_exit(struct rk_crypto_info *rkdev) static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) { - struct rk_crypto_info *dev = platform_get_drvdata(dev_id); + struct rk_crypto_info *dev = platform_get_drvdata(dev_id); + void __iomem *reg; u32 interrupt_status; + int i; - interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS); - CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, interrupt_status); + for (i = 0; i < dev->variant->num_instance; i++) { + if (dev->rki[i].irq != irq) + continue; + reg = dev->rki[i].reg; + interrupt_status = readl(reg + RK_CRYPTO_INTSTS); + writel(interrupt_status, reg + RK_CRYPTO_INTSTS); - dev->status = 1; - if (interrupt_status & 0x0a) { - dev_warn(dev->dev, "DMA Error\n"); - dev->status = 0; + dev->rki[i].status = 1; + if (interrupt_status & 0x0a) { + dev->rki[i].status = 0; + } + complete(&dev->rki[i].complete); + return IRQ_HANDLED; } - complete(&dev->complete); - return IRQ_HANDLED; } @@ -152,6 +167,7 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) { rk_cipher_algs[i]->dev = crypto_info; + switch (rk_cipher_algs[i]->type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(crypto_info->dev, "Register %s as %s\n", @@ -196,7 +212,12 @@ static void rk_crypto_unregister(void) } static const struct of_device_id crypto_of_id_table[] = { - { .compatible = "rockchip,rk3288-crypto" }, + { .compatible = "rockchip,rk3288-crypto", + .data = &rk3288_variant, + }, + { .compatible = "rockchip,rk3399-crypto", + .data = &rk3399_variant, + }, {} }; MODULE_DEVICE_TABLE(of, crypto_of_id_table); @@ -206,6 +227,7 @@ static int rk_crypto_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rk_crypto_info *crypto_info; int err = 0; + int i; crypto_info = devm_kzalloc(&pdev->dev, sizeof(*crypto_info), GFP_KERNEL); @@ -214,48 +236,54 @@ static int rk_crypto_probe(struct platform_device *pdev) goto err_crypto; } - crypto_info->rst = devm_reset_control_get(dev, "crypto-rst"); - if (IS_ERR(crypto_info->rst)) { - err = PTR_ERR(crypto_info->rst); - goto err_crypto; + crypto_info->variant = of_device_get_match_data(&pdev->dev); + if (!crypto_info->variant) { + dev_err(&pdev->dev, "Missing variant\n"); + return -EINVAL; } - crypto_info->reg = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(crypto_info->reg)) { - err = PTR_ERR(crypto_info->reg); - goto err_crypto; - } + for (i = 0; i < crypto_info->variant->num_instance; i++) { + crypto_info->rki[i].reg = devm_platform_ioremap_resource(pdev, i); + if (IS_ERR(crypto_info->rki[i].reg)) { + err = PTR_ERR(crypto_info->rki[i].reg); + goto err_crypto; + } + crypto_info->rki[i].irq = platform_get_irq(pdev, i); + if (crypto_info->rki[i].irq < 0) { + dev_err(&pdev->dev, "control Interrupt is not available.\n"); + err = crypto_info->rki[i].irq; + goto err_crypto; + } - crypto_info->num_clks = devm_clk_bulk_get_all(&pdev->dev, - &crypto_info->clks); - if (crypto_info->num_clks < 3) { - err = -EINVAL; - goto err_crypto; + err = devm_request_irq(&pdev->dev, crypto_info->rki[i].irq, + rk_crypto_irq_handle, IRQF_SHARED, + "rk-crypto", pdev); + + if (err) { + dev_err(&pdev->dev, "irq request failed.\n"); + goto err_crypto; + } + init_completion(&crypto_info->rki[i].complete); + crypto_info->rki[i].engine = crypto_engine_alloc_init(&pdev->dev, true); + crypto_engine_start(crypto_info->rki[i].engine); } - crypto_info->irq = platform_get_irq(pdev, 0); - if (crypto_info->irq < 0) { - dev_err(&pdev->dev, "control Interrupt is not available.\n"); - err = crypto_info->irq; + crypto_info->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(crypto_info->rst)) { + err = PTR_ERR(crypto_info->rst); goto err_crypto; } - err = devm_request_irq(&pdev->dev, crypto_info->irq, - rk_crypto_irq_handle, IRQF_SHARED, - "rk-crypto", pdev); - - if (err) { - dev_err(&pdev->dev, "irq request failed.\n"); + crypto_info->num_clks = devm_clk_bulk_get_all(&pdev->dev, + &crypto_info->clks); + if (crypto_info->num_clks < 3) { + err = -EINVAL; goto err_crypto; } crypto_info->dev = &pdev->dev; platform_set_drvdata(pdev, crypto_info); - crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true); - crypto_engine_start(crypto_info->engine); - init_completion(&crypto_info->complete); - err = rk_crypto_pm_init(crypto_info); if (err) goto err_pm; @@ -281,7 +309,8 @@ static int rk_crypto_probe(struct platform_device *pdev) err_register_alg: rk_crypto_pm_exit(crypto_info); err_pm: - crypto_engine_exit(crypto_info->engine); + for (i = 0; i < crypto_info->variant->num_instance; i++) + crypto_engine_exit(crypto_info->rki[i].engine); err_crypto: dev_err(dev, "Crypto Accelerator not successfully registered\n"); return err; @@ -290,13 +319,15 @@ static int rk_crypto_probe(struct platform_device *pdev) static int rk_crypto_remove(struct platform_device *pdev) { struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev); + int i; #ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG debugfs_remove_recursive(crypto_tmp->dbgfs_dir); #endif rk_crypto_unregister(); rk_crypto_pm_exit(crypto_tmp); - crypto_engine_exit(crypto_tmp->engine); + for (i = 0; i < crypto_tmp->variant->num_instance; i++) + crypto_engine_exit(crypto_tmp->rki[i].engine); return 0; } diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h index b6cd67d1d0cb..e1dac351bc64 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.h +++ b/drivers/crypto/rockchip/rk3288_crypto.h @@ -183,28 +183,38 @@ #define RK_CRYPTO_HASH_DOUT_6 0x01a4 #define RK_CRYPTO_HASH_DOUT_7 0x01a8 -#define CRYPTO_READ(dev, offset) \ - readl_relaxed(((dev)->reg + (offset))) -#define CRYPTO_WRITE(dev, offset, val) \ - writel_relaxed((val), ((dev)->reg + (offset))) +struct rk_variant { + int num_instance; +}; + +struct rk_instance { + void __iomem *reg; + int irq; + struct completion complete; + struct crypto_engine *engine; + int status; +}; struct rk_crypto_info { struct device *dev; struct clk_bulk_data *clks; int num_clks; struct reset_control *rst; - void __iomem *reg; - int irq; - - struct crypto_engine *engine; - struct completion complete; - int status; + struct rk_instance rki[2]; + int numinst; + const struct rk_variant *variant; + atomic_t flow; #ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG struct dentry *dbgfs_dir; struct dentry *dbgfs_stats; #endif }; +static inline int rk_get_engine_number(struct rk_crypto_info *rk) +{ + return atomic_inc_return(&rk->flow) % rk->variant->num_instance; +} + /* the private variable of hash */ struct rk_ahash_ctx { struct crypto_engine_ctx enginectx; @@ -218,6 +228,7 @@ struct rk_ahash_rctx { struct ahash_request fallback_req; u32 mode; int nrsg; + int ninst; }; /* the private variable of cipher */ @@ -233,6 +244,7 @@ struct rk_cipher_ctx { struct rk_cipher_rctx { u8 backup_iv[AES_BLOCK_SIZE]; u32 mode; + int ninst; struct skcipher_request fallback_req; // keep at the end }; diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c index 137013bd4410..28f4a7124683 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c +++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c @@ -83,33 +83,33 @@ static void rk_ahash_reg_init(struct ahash_request *req) struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); struct rk_crypto_info *dev = tctx->dev; + void __iomem *reg = dev->rki[rctx->ninst].reg; int reg_status; - reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL) | + reg_status = readl(reg + RK_CRYPTO_CTRL) | RK_CRYPTO_HASH_FLUSH | _SBF(0xffff, 16); - CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status); + writel(reg_status, reg + RK_CRYPTO_CTRL); - reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL); + reg_status = readl(reg + RK_CRYPTO_CTRL); reg_status &= (~RK_CRYPTO_HASH_FLUSH); reg_status |= _SBF(0xffff, 16); - CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status); + writel(reg_status, reg + RK_CRYPTO_CTRL); - memset_io(dev->reg + RK_CRYPTO_HASH_DOUT_0, 0, 32); + memset_io(reg + RK_CRYPTO_HASH_DOUT_0, 0, 32); - CRYPTO_WRITE(dev, RK_CRYPTO_INTENA, RK_CRYPTO_HRDMA_ERR_ENA | - RK_CRYPTO_HRDMA_DONE_ENA); + writel(RK_CRYPTO_HRDMA_ERR_ENA | RK_CRYPTO_HRDMA_DONE_ENA, + reg + RK_CRYPTO_INTENA); - CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, RK_CRYPTO_HRDMA_ERR_INT | - RK_CRYPTO_HRDMA_DONE_INT); + writel(RK_CRYPTO_HRDMA_ERR_INT | RK_CRYPTO_HRDMA_DONE_INT, + reg + RK_CRYPTO_INTSTS); - CRYPTO_WRITE(dev, RK_CRYPTO_HASH_CTRL, rctx->mode | - RK_CRYPTO_HASH_SWAP_DO); + writel(rctx->mode | RK_CRYPTO_HASH_SWAP_DO, + reg + RK_CRYPTO_HASH_CTRL); - CRYPTO_WRITE(dev, RK_CRYPTO_CONF, RK_CRYPTO_BYTESWAP_HRFIFO | - RK_CRYPTO_BYTESWAP_BRFIFO | - RK_CRYPTO_BYTESWAP_BTFIFO); + writel(RK_CRYPTO_BYTESWAP_HRFIFO | RK_CRYPTO_BYTESWAP_BRFIFO | + RK_CRYPTO_BYTESWAP_BTFIFO, reg + RK_CRYPTO_CONF); - CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, req->nbytes); + writel(req->nbytes, reg + RK_CRYPTO_HASH_MSG_LEN); } static int rk_ahash_init(struct ahash_request *req) @@ -200,7 +200,9 @@ static int rk_ahash_export(struct ahash_request *req, void *out) static int rk_ahash_digest(struct ahash_request *req) { struct rk_ahash_ctx *tctx = crypto_tfm_ctx(req->base.tfm); + struct rk_ahash_rctx *rctx = ahash_request_ctx(req); struct rk_crypto_info *dev = tctx->dev; + struct crypto_engine *engine; if (rk_ahash_need_fallback(req)) return rk_ahash_digest_fb(req); @@ -208,15 +210,20 @@ static int rk_ahash_digest(struct ahash_request *req) if (!req->nbytes) return zero_message_process(req); - return crypto_transfer_hash_request_to_engine(dev->engine, req); + rctx->ninst = rk_get_engine_number(dev); + engine = dev->rki[rctx->ninst].engine; + return crypto_transfer_hash_request_to_engine(engine, req); } -static void crypto_ahash_dma_start(struct rk_crypto_info *dev, struct scatterlist *sg) +static void crypto_ahash_dma_start(struct rk_crypto_info *dev, int ninst, + struct scatterlist *sg) { - CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, sg_dma_address(sg)); - CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, sg_dma_len(sg) / 4); - CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_HASH_START | - (RK_CRYPTO_HASH_START << 16)); + void __iomem *reg = dev->rki[ninst].reg; + + writel(sg_dma_address(sg), reg + RK_CRYPTO_HRDMAS); + writel(sg_dma_len(sg) / 4, reg + RK_CRYPTO_HRDMAL); + writel(RK_CRYPTO_HASH_START | (RK_CRYPTO_HASH_START << 16), + reg + RK_CRYPTO_CTRL); } static int rk_hash_prepare(struct crypto_engine *engine, void *breq) @@ -255,6 +262,8 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + struct rk_instance *rki = &tctx->dev->rki[rctx->ninst]; + void __iomem *reg = tctx->dev->rki[rctx->ninst].reg; struct scatterlist *sg = areq->src; int err = 0; int i; @@ -282,12 +291,12 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) rk_ahash_reg_init(areq); while (sg) { - reinit_completion(&tctx->dev->complete); - tctx->dev->status = 0; - crypto_ahash_dma_start(tctx->dev, sg); - wait_for_completion_interruptible_timeout(&tctx->dev->complete, + reinit_completion(&rki->complete); + rki->status = 0; + crypto_ahash_dma_start(tctx->dev, rctx->ninst, sg); + wait_for_completion_interruptible_timeout(&rki->complete, msecs_to_jiffies(2000)); - if (!tctx->dev->status) { + if (!rki->status) { dev_err(tctx->dev->dev, "DMA timeout\n"); err = -EFAULT; goto theend; @@ -305,11 +314,11 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) * efficiency, and make it response quickly when dma * complete. */ - while (!CRYPTO_READ(tctx->dev, RK_CRYPTO_HASH_STS)) + while (!readl(reg + RK_CRYPTO_HASH_STS)) udelay(10); for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { - v = readl(tctx->dev->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); + v = readl(reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); put_unaligned_le32(v, areq->result + i * 4); } diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c index 8d3a60db0cf6..f386ebb32e7c 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c @@ -95,11 +95,15 @@ static int rk_cipher_fallback(struct skcipher_request *areq) static int rk_handle_req(struct rk_crypto_info *dev, struct skcipher_request *req) { - struct crypto_engine *engine = dev->engine; + struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct crypto_engine *engine; if (rk_cipher_need_fallback(req)) return rk_cipher_fallback(req); + rctx->ninst = rk_get_engine_number(dev); + engine = dev->rki[rctx->ninst].engine; + return crypto_transfer_skcipher_request_to_engine(engine, req); } @@ -290,6 +294,7 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev, struct skcipher_request struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher); u32 block, conf_reg = 0; + void __iomem *reg = dev->rki[rctx->ninst].reg; block = crypto_tfm_alg_blocksize(tfm); @@ -297,8 +302,8 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev, struct skcipher_request rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | RK_CRYPTO_TDES_BYTESWAP_KEY | RK_CRYPTO_TDES_BYTESWAP_IV; - CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode); - memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen); + writel(rctx->mode, reg + RK_CRYPTO_TDES_CTRL); + memcpy_toio(reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen); conf_reg = RK_CRYPTO_DESSEL; } else { rctx->mode |= RK_CRYPTO_AES_FIFO_MODE | @@ -309,25 +314,27 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev, struct skcipher_request rctx->mode |= RK_CRYPTO_AES_192BIT_key; else if (ctx->keylen == AES_KEYSIZE_256) rctx->mode |= RK_CRYPTO_AES_256BIT_key; - CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode); - memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen); + writel(rctx->mode, reg + RK_CRYPTO_AES_CTRL); + memcpy_toio(reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen); } conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO | RK_CRYPTO_BYTESWAP_BRFIFO; - CRYPTO_WRITE(dev, RK_CRYPTO_CONF, conf_reg); - CRYPTO_WRITE(dev, RK_CRYPTO_INTENA, - RK_CRYPTO_BCDMA_ERR_ENA | RK_CRYPTO_BCDMA_DONE_ENA); + writel(conf_reg, reg + RK_CRYPTO_CONF); + writel(RK_CRYPTO_BCDMA_ERR_ENA | RK_CRYPTO_BCDMA_DONE_ENA, + reg + RK_CRYPTO_INTENA); } -static void crypto_dma_start(struct rk_crypto_info *dev, +static void crypto_dma_start(struct rk_crypto_info *dev, int ninst, struct scatterlist *sgs, struct scatterlist *sgd, unsigned int todo) { - CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, sg_dma_address(sgs)); - CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, todo); - CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, sg_dma_address(sgd)); - CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_BLOCK_START | - _SBF(RK_CRYPTO_BLOCK_START, 16)); + void __iomem *reg = dev->rki[ninst].reg; + + writel(sg_dma_address(sgs), reg + RK_CRYPTO_BRDMAS); + writel(todo, reg + RK_CRYPTO_BRDMAL); + writel(sg_dma_address(sgd), reg + RK_CRYPTO_BTDMAS); + writel(RK_CRYPTO_BLOCK_START | _SBF(RK_CRYPTO_BLOCK_START, 16), + reg + RK_CRYPTO_CTRL); } static int rk_cipher_run(struct crypto_engine *engine, void *async_req) @@ -348,6 +355,8 @@ static int rk_cipher_run(struct crypto_engine *engine, void *async_req) unsigned int todo; struct skcipher_alg *alg = crypto_skcipher_alg(tfm); struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + struct rk_instance *rki = &ctx->dev->rki[rctx->ninst]; + void __iomem *reg = ctx->dev->rki[rctx->ninst].reg; algt->stat_req++; @@ -396,19 +405,19 @@ static int rk_cipher_run(struct crypto_engine *engine, void *async_req) rk_ablk_hw_init(ctx->dev, areq); if (ivsize) { if (ivsize == DES_BLOCK_SIZE) - memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_IV_0, ivtouse, ivsize); + memcpy_toio(reg + RK_CRYPTO_TDES_IV_0, ivtouse, ivsize); else - memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_IV_0, ivtouse, ivsize); + memcpy_toio(reg + RK_CRYPTO_AES_IV_0, ivtouse, ivsize); } - reinit_completion(&ctx->dev->complete); - ctx->dev->status = 0; + reinit_completion(&rki->complete); + rki->status = 0; todo = min(sg_dma_len(sgs), len); len -= todo; - crypto_dma_start(ctx->dev, sgs, sgd, todo / 4); - wait_for_completion_interruptible_timeout(&ctx->dev->complete, + crypto_dma_start(ctx->dev, rctx->ninst, sgs, sgd, todo / 4); + wait_for_completion_interruptible_timeout(&rki->complete, msecs_to_jiffies(2000)); - if (!ctx->dev->status) { + if (!rki->status) { dev_err(ctx->dev->dev, "DMA timeout\n"); err = -EFAULT; goto theend; -- 2.34.1