@@ -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;
}
@@ -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
};
@@ -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);
}
@@ -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;
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@baylibre.com> --- 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(-)