-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: starfive - Add crypto engine support
Adding device probe and DMA init for 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>
- Loading branch information
Showing
7 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# | ||
# StarFive crypto drivers configuration | ||
# | ||
|
||
config CRYPTO_DEV_JH7110 | ||
tristate "StarFive JH7110 cryptographic engine driver" | ||
depends on SOC_STARFIVE || COMPILE_TEST | ||
select CRYPTO_ENGINE | ||
select ARM_AMBA | ||
select DMADEVICES | ||
select AMBA_PL08X | ||
help | ||
Support for StarFive JH7110 crypto hardware acceleration engine. | ||
This module provides acceleration for public key algo, | ||
skciphers, AEAD and hash functions. | ||
|
||
If you choose 'M' here, this module will be called jh7110-crypto. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
|
||
obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o | ||
jh7110-crypto-objs := jh7110-cryp.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Cryptographic API. | ||
* | ||
* Support for StarFive hardware cryptographic engine. | ||
* Copyright (c) 2022 StarFive Technology | ||
* | ||
*/ | ||
|
||
#include <linux/clk.h> | ||
#include <linux/delay.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/iopoll.h> | ||
#include <linux/module.h> | ||
#include <linux/of_device.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/pm_runtime.h> | ||
#include <linux/reset.h> | ||
|
||
#include "jh7110-cryp.h" | ||
|
||
#define DRIVER_NAME "jh7110-crypto" | ||
|
||
struct starfive_dev_list { | ||
struct list_head dev_list; | ||
spinlock_t lock; /* protect dev_list */ | ||
}; | ||
|
||
static struct starfive_dev_list dev_list = { | ||
.dev_list = LIST_HEAD_INIT(dev_list.dev_list), | ||
.lock = __SPIN_LOCK_UNLOCKED(dev_list.lock), | ||
}; | ||
|
||
struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) | ||
{ | ||
struct starfive_cryp_dev *cryp = NULL, *tmp; | ||
|
||
spin_lock_bh(&dev_list.lock); | ||
if (!ctx->cryp) { | ||
list_for_each_entry(tmp, &dev_list.dev_list, list) { | ||
cryp = tmp; | ||
break; | ||
} | ||
ctx->cryp = cryp; | ||
} else { | ||
cryp = ctx->cryp; | ||
} | ||
|
||
spin_unlock_bh(&dev_list.lock); | ||
|
||
return cryp; | ||
} | ||
|
||
static int starfive_dma_init(struct starfive_cryp_dev *cryp) | ||
{ | ||
dma_cap_mask_t mask; | ||
|
||
dma_cap_zero(mask); | ||
dma_cap_set(DMA_SLAVE, mask); | ||
|
||
cryp->tx = dma_request_chan(cryp->dev, "tx"); | ||
if (IS_ERR(cryp->tx)) | ||
return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx), | ||
"Error requesting tx dma channel.\n"); | ||
|
||
cryp->rx = dma_request_chan(cryp->dev, "rx"); | ||
if (IS_ERR(cryp->rx)) { | ||
dma_release_channel(cryp->tx); | ||
return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx), | ||
"Error requesting rx dma channel.\n"); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp) | ||
{ | ||
dma_release_channel(cryp->tx); | ||
dma_release_channel(cryp->rx); | ||
} | ||
|
||
static int starfive_cryp_probe(struct platform_device *pdev) | ||
{ | ||
struct starfive_cryp_dev *cryp; | ||
struct resource *res; | ||
int ret; | ||
|
||
cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL); | ||
if (!cryp) | ||
return -ENOMEM; | ||
|
||
platform_set_drvdata(pdev, cryp); | ||
cryp->dev = &pdev->dev; | ||
|
||
cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | ||
if (IS_ERR(cryp->base)) | ||
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base), | ||
"Error remapping memory for platform device\n"); | ||
|
||
cryp->phys_base = res->start; | ||
cryp->dma_maxburst = 32; | ||
|
||
cryp->hclk = devm_clk_get(&pdev->dev, "hclk"); | ||
if (IS_ERR(cryp->hclk)) | ||
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk), | ||
"Error getting hardware reference clock\n"); | ||
|
||
cryp->ahb = devm_clk_get(&pdev->dev, "ahb"); | ||
if (IS_ERR(cryp->ahb)) | ||
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb), | ||
"Error getting ahb reference clock\n"); | ||
|
||
cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL); | ||
if (IS_ERR(cryp->rst)) | ||
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst), | ||
"Error getting hardware reset line\n"); | ||
|
||
clk_prepare_enable(cryp->hclk); | ||
clk_prepare_enable(cryp->ahb); | ||
reset_control_deassert(cryp->rst); | ||
|
||
spin_lock(&dev_list.lock); | ||
list_add(&cryp->list, &dev_list.dev_list); | ||
spin_unlock(&dev_list.lock); | ||
|
||
ret = starfive_dma_init(cryp); | ||
if (ret) { | ||
if (ret == -EPROBE_DEFER) | ||
goto err_probe_defer; | ||
else | ||
goto err_dma_init; | ||
} | ||
|
||
/* Initialize crypto engine */ | ||
cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1); | ||
if (!cryp->engine) { | ||
ret = -ENOMEM; | ||
goto err_engine; | ||
} | ||
|
||
ret = crypto_engine_start(cryp->engine); | ||
if (ret) | ||
goto err_engine_start; | ||
|
||
return 0; | ||
|
||
err_engine_start: | ||
crypto_engine_exit(cryp->engine); | ||
err_engine: | ||
starfive_dma_cleanup(cryp); | ||
err_dma_init: | ||
spin_lock(&dev_list.lock); | ||
list_del(&cryp->list); | ||
spin_unlock(&dev_list.lock); | ||
|
||
clk_disable_unprepare(cryp->hclk); | ||
clk_disable_unprepare(cryp->ahb); | ||
reset_control_assert(cryp->rst); | ||
err_probe_defer: | ||
return ret; | ||
} | ||
|
||
static int starfive_cryp_remove(struct platform_device *pdev) | ||
{ | ||
struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev); | ||
|
||
crypto_engine_stop(cryp->engine); | ||
crypto_engine_exit(cryp->engine); | ||
|
||
starfive_dma_cleanup(cryp); | ||
|
||
spin_lock(&dev_list.lock); | ||
list_del(&cryp->list); | ||
spin_unlock(&dev_list.lock); | ||
|
||
clk_disable_unprepare(cryp->hclk); | ||
clk_disable_unprepare(cryp->ahb); | ||
reset_control_assert(cryp->rst); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct of_device_id starfive_dt_ids[] __maybe_unused = { | ||
{ .compatible = "starfive,jh7110-crypto", .data = NULL}, | ||
{}, | ||
}; | ||
MODULE_DEVICE_TABLE(of, starfive_dt_ids); | ||
|
||
static struct platform_driver starfive_cryp_driver = { | ||
.probe = starfive_cryp_probe, | ||
.remove = starfive_cryp_remove, | ||
.driver = { | ||
.name = DRIVER_NAME, | ||
.of_match_table = starfive_dt_ids, | ||
}, | ||
}; | ||
|
||
module_platform_driver(starfive_cryp_driver); | ||
|
||
MODULE_LICENSE("GPL"); | ||
MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __STARFIVE_STR_H__ | ||
#define __STARFIVE_STR_H__ | ||
|
||
#include <linux/delay.h> | ||
#include <linux/dma-mapping.h> | ||
#include <linux/dmaengine.h> | ||
|
||
#include <crypto/engine.h> | ||
|
||
#define STARFIVE_ALG_CR_OFFSET 0x0 | ||
#define STARFIVE_ALG_FIFO_OFFSET 0x4 | ||
#define STARFIVE_IE_MASK_OFFSET 0x8 | ||
#define STARFIVE_IE_FLAG_OFFSET 0xc | ||
#define STARFIVE_DMA_IN_LEN_OFFSET 0x10 | ||
#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14 | ||
|
||
#define STARFIVE_MSG_BUFFER_SIZE SZ_16K | ||
|
||
union starfive_alg_cr { | ||
u32 v; | ||
struct { | ||
u32 start :1; | ||
u32 aes_dma_en :1; | ||
u32 rsvd_0 :1; | ||
u32 hash_dma_en :1; | ||
u32 alg_done :1; | ||
u32 rsvd_1 :3; | ||
u32 clear :1; | ||
u32 rsvd_2 :23; | ||
}; | ||
}; | ||
|
||
struct starfive_cryp_ctx { | ||
struct crypto_engine_ctx enginectx; | ||
struct starfive_cryp_dev *cryp; | ||
}; | ||
|
||
struct starfive_cryp_dev { | ||
struct list_head list; | ||
struct device *dev; | ||
|
||
struct clk *hclk; | ||
struct clk *ahb; | ||
struct reset_control *rst; | ||
|
||
void __iomem *base; | ||
phys_addr_t phys_base; | ||
|
||
u32 dma_maxburst; | ||
struct dma_chan *tx; | ||
struct dma_chan *rx; | ||
struct dma_slave_config cfg_in; | ||
struct dma_slave_config cfg_out; | ||
|
||
struct crypto_engine *engine; | ||
|
||
union starfive_alg_cr alg_cr; | ||
}; | ||
|
||
struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx); | ||
|
||
#endif |