crypto: support rockchip hardware crypto
Support: rsa & sha algorithm Usage: Set CONFIG_RK_CRYPTO to enable rk crypto. Change-Id: I2b6a920308fcdf46481bcf38fc6be532a02255bd Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
parent
564654eb9c
commit
726087de6e
|
|
@ -1,5 +1,6 @@
|
|||
menu "Hardware crypto devices"
|
||||
|
||||
source drivers/crypto/fsl/Kconfig
|
||||
source drivers/crypto/rockchip/Kconfig
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@
|
|||
obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o
|
||||
obj-y += rsa_mod_exp/
|
||||
obj-y += fsl/
|
||||
obj-$(CONFIG_CRYPTO_ROCKCHIP) += rockchip/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
config CRYPTO_ROCKCHIP
|
||||
bool "Support Rockchip Hardware Crypto"
|
||||
help
|
||||
The module supports Rockchip Hardware Crypto.
|
||||
This accelerates algorithmic operations.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||
#
|
||||
|
||||
obj-y += rockchip_crypto_hd.o
|
||||
obj-y += rockchip_crypto.o
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <errno.h>
|
||||
#include <rockchip_crypto/rockchip_crypto_hd.h>
|
||||
#include <rockchip_crypto/rockchip_crypto.h>
|
||||
|
||||
int get_rk_crypto_desc(struct rk_crypto_desc *crypto_desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_RKCRYPTO, "crypto",
|
||||
&crypto_desc->dev);
|
||||
if (ret) {
|
||||
printf("%s: Can not get crypto dev.\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
crypto_desc->ops = crypto_get_ops(crypto_desc->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rk_crypto_sha_init(struct rk_crypto_desc *rk_crypto, u32 msg_len,
|
||||
int hash_bits)
|
||||
{
|
||||
return rk_crypto->ops->sha_init(rk_crypto->dev, msg_len, msg_len);
|
||||
}
|
||||
|
||||
int rk_crypto_sha_byte_swap(struct rk_crypto_desc *rk_crypto, int en)
|
||||
{
|
||||
return rk_crypto->ops->sha_byte_swap(rk_crypto->dev, en);
|
||||
}
|
||||
|
||||
int rk_crypto_sha_start(struct rk_crypto_desc *rk_crypto, u32 *data,
|
||||
u32 data_len)
|
||||
{
|
||||
return rk_crypto->ops->sha_start(rk_crypto->dev, data, data_len);
|
||||
}
|
||||
|
||||
int rk_crypto_sha_end(struct rk_crypto_desc *rk_crypto, u32 *result)
|
||||
{
|
||||
return rk_crypto->ops->sha_end(rk_crypto->dev, result);
|
||||
}
|
||||
|
||||
int rk_crypto_sha_check(struct rk_crypto_desc *rk_crypto, u32 *in_hash)
|
||||
{
|
||||
int ret;
|
||||
u32 data_hash[8];
|
||||
|
||||
ret = rk_crypto_sha_end(rk_crypto, data_hash);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
return memcmp(in_hash, data_hash, 32);
|
||||
}
|
||||
|
||||
int rk_crypto_rsa_init(struct rk_crypto_desc *rk_crypto)
|
||||
{
|
||||
return rk_crypto->ops->rsa_init(rk_crypto->dev);
|
||||
}
|
||||
|
||||
int rk_crypto_rsa_start(struct rk_crypto_desc *rk_crypto,
|
||||
u32 *m, u32 *n, u32 *e, u32 *c)
|
||||
{
|
||||
return rk_crypto->ops->rsa_start(rk_crypto->dev, m, n, e, c);
|
||||
}
|
||||
|
||||
int rk_crypto_rsa_end(struct rk_crypto_desc *rk_crypto, u32 *result)
|
||||
{
|
||||
return rk_crypto->ops->rsa_end(rk_crypto->dev, result);
|
||||
}
|
||||
|
||||
int rk_crypto_rsa_check(struct rk_crypto_desc *rk_crypto)
|
||||
{
|
||||
u32 datahash[8];
|
||||
u32 rsa_result[8];
|
||||
int ret = 0;
|
||||
|
||||
ret = rk_crypto_sha_end(rk_crypto, datahash);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rk_crypto_rsa_end(rk_crypto, rsa_result);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return memcmp(rsa_result, datahash, 32);
|
||||
}
|
||||
|
||||
int rk_crypto_probe(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_RKCRYPTO, "crypto", &dev);
|
||||
if (ret) {
|
||||
printf("%s: Can not get crypto dev.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = device_probe(dev);
|
||||
if (ret) {
|
||||
printf("%s: Crypto probe error.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(crypto) = {
|
||||
.id = UCLASS_RKCRYPTO,
|
||||
.name = "crypto",
|
||||
};
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bouncebuf.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dt-structs.h>
|
||||
#include <errno.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/periph.h>
|
||||
#include <rockchip_crypto/rockchip_crypto_hd.h>
|
||||
#include <rockchip_crypto/rockchip_crypto.h>
|
||||
|
||||
struct rockchip_crypto_plat {
|
||||
fdt_addr_t base;
|
||||
s32 frequency;
|
||||
};
|
||||
|
||||
struct rockchip_crypto_priv {
|
||||
volatile struct rk_crypto_reg *regbase;
|
||||
struct clk clk;
|
||||
unsigned int max_freq;
|
||||
};
|
||||
|
||||
static int rockchip_crypto_ofdata_to_platdata(struct udevice *bus)
|
||||
{
|
||||
struct rockchip_crypto_plat *plat = dev_get_platdata(bus);
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(bus);
|
||||
int ret = 0;
|
||||
|
||||
plat->base = dev_read_u32_default(bus, "default-addr", 0);
|
||||
debug("Crypto base address is %x\n", (int)(size_t)plat->base);
|
||||
ret = clk_get_by_index(bus, 0, &priv->clk);
|
||||
if (ret < 0) {
|
||||
printf("Could not get clock for %s: %d\n", bus->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
plat->frequency = dev_read_u32_default(bus, "default-frequency",
|
||||
CRYPTO_DEFAULT_CLK);
|
||||
debug("Crypto clock frequency is %x\n", (int)(size_t)plat->frequency);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_probe(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_crypto_plat *plat = dev_get_platdata(dev);
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
priv->regbase = (volatile struct rk_crypto_reg *)
|
||||
(plat->base & 0xffffffff);
|
||||
priv->max_freq = plat->frequency;
|
||||
ret = clk_set_rate(&priv->clk, priv->max_freq);
|
||||
if (ret < 0) {
|
||||
printf("%s: Failed to set clock: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_sha_init(struct udevice *dev, u32 msg_len,
|
||||
int hash_bits)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regbase->crypto_hash_meg_len = msg_len;
|
||||
if (hash_bits == SHA_256_BIT) {
|
||||
priv->regbase->crypto_hash_ctrl = HASH_SWAP_DO | ENGINE_SELECTION_SHA256;
|
||||
priv->regbase->crypto_conf &= ~(BYTESWAP_HRFIFO);
|
||||
} else {
|
||||
printf("Do not support that hash_bits is not equal to 256");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
rk_setreg(&priv->regbase->crypto_ctrl, HASH_FLUSH);
|
||||
do {} while (priv->regbase->crypto_ctrl & HASH_FLUSH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_sha_byte_swap(struct udevice *dev, int en)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (en)
|
||||
priv->regbase->crypto_conf |= BYTESWAP_HRFIFO;
|
||||
else
|
||||
priv->regbase->crypto_conf &= ~BYTESWAP_HRFIFO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_sha_start(struct udevice *dev, u32 *data,
|
||||
u32 data_len)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (data_len == 0)
|
||||
return 0;
|
||||
|
||||
flush_cache((unsigned long)data, data_len);
|
||||
do {} while (priv->regbase->crypto_ctrl & HASH_START);
|
||||
priv->regbase->crypto_intsts = HASH_DONE_INT;
|
||||
priv->regbase->crypto_hrdmas = (u32)(unsigned long)data;
|
||||
priv->regbase->crypto_hrdmal = ((data_len + 3) >> 2);
|
||||
rk_setreg(&priv->regbase->crypto_ctrl, HASH_START);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_sha_end(struct udevice *dev, u32 *result)
|
||||
{
|
||||
int i;
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
do {} while (priv->regbase->crypto_ctrl & HASH_START);
|
||||
do {} while (!priv->regbase->crypto_hash_sts);
|
||||
for (i = 0; i < 8; i++)
|
||||
*result++ = priv->regbase->crypto_hash_dout[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_rsa_init(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regbase->crypto_pka_ctrl = PKA_BLOCK_SIZE_2048;
|
||||
rk_setreg(&priv->regbase->crypto_ctrl, PKA_HASH_CTRL);
|
||||
priv->regbase->crypto_intsts = 0xffffffff;
|
||||
do {} while (priv->regbase->crypto_ctrl & PKA_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_rsa_start(struct udevice *dev, u32 *m,
|
||||
u32 *n, u32 *e, u32 *c)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regbase->crypto_intsts = PKA_DONE_INT;
|
||||
memcpy((void *)&priv->regbase->crypto_pka_m, (void *)m, 256);
|
||||
memcpy((void *)&priv->regbase->crypto_pka_n, (void *)n, 256);
|
||||
memcpy((void *)&priv->regbase->crypto_pka_e, (void *)e, 256);
|
||||
memcpy((void *)&priv->regbase->crypto_pka_c, (void *)c, 256);
|
||||
do {} while (priv->regbase->crypto_ctrl & PKA_START);
|
||||
rk_setreg(&priv->regbase->crypto_ctrl, PKA_START);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_crypto_rsa_end(struct udevice *dev, u32 *result)
|
||||
{
|
||||
struct rockchip_crypto_priv *priv = dev_get_priv(dev);
|
||||
int i;
|
||||
|
||||
do {} while (priv->regbase->crypto_ctrl & PKA_START);
|
||||
for (i = 0; i < 8; i++)
|
||||
*result++ = *((u32 *)(&priv->regbase->crypto_pka_m + i));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_rk_crypto_ops rockchip_crypto_ops = {
|
||||
.sha_init = rockchip_crypto_sha_init,
|
||||
.sha_byte_swap = rockchip_crypto_sha_byte_swap,
|
||||
.sha_start = rockchip_crypto_sha_start,
|
||||
.sha_end = rockchip_crypto_sha_end,
|
||||
.rsa_init = rockchip_crypto_rsa_init,
|
||||
.rsa_start = rockchip_crypto_rsa_start,
|
||||
.rsa_end = rockchip_crypto_rsa_end,
|
||||
};
|
||||
|
||||
static const struct udevice_id rockchip_crypto_ids[] = {
|
||||
{ .compatible = "rockchip,rk3399-crypto" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(rockchip_crypto_drv) = {
|
||||
.name = "rockchip_crypto",
|
||||
.id = UCLASS_RKCRYPTO,
|
||||
.of_match = rockchip_crypto_ids,
|
||||
.ops = &rockchip_crypto_ops,
|
||||
.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
|
||||
.probe = rockchip_crypto_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
|
||||
.platdata_auto_alloc_size = sizeof(struct rockchip_crypto_plat),
|
||||
};
|
||||
|
|
@ -100,7 +100,7 @@ enum uclass_id {
|
|||
UCLASS_CHARGE_DISPLAY, /* Charge display */
|
||||
UCLASS_DVFS, /* DVFS policy */
|
||||
UCLASS_IO_DOMAIN, /* IO domain */
|
||||
|
||||
UCLASS_RKCRYPTO, /* Rockchip Crypto */
|
||||
UCLASS_COUNT,
|
||||
UCLASS_INVALID = -1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#ifndef _ROCKCHIP_CRYPTO_H_
|
||||
#define _ROCKCHIP_CRYPTO_H_
|
||||
|
||||
#define crypto_get_ops(dev) ((struct dm_rk_crypto_ops *)(dev)->driver->ops)
|
||||
|
||||
struct rk_crypto_desc {
|
||||
struct udevice *dev;
|
||||
struct dm_rk_crypto_ops *ops;
|
||||
};
|
||||
|
||||
int get_rk_crypto_desc(struct rk_crypto_desc *crypto_desc);
|
||||
int rk_crypto_sha_init(struct rk_crypto_desc *rk_crypto, u32 msg_len,
|
||||
int hash_bits);
|
||||
int rk_crypto_sha_byte_swap(struct rk_crypto_desc *rk_crypto, int en);
|
||||
int rk_crypto_sha_start(struct rk_crypto_desc *rk_crypto, u32 *data,
|
||||
u32 data_len);
|
||||
int rk_crypto_sha_end(struct rk_crypto_desc *rk_crypto, u32 *result);
|
||||
int rk_crypto_sha_check(struct rk_crypto_desc *rk_crypto, u32 *in_hash);
|
||||
int rk_crypto_rsa_init(struct rk_crypto_desc *rk_crypto);
|
||||
int rk_crypto_rsa_start(struct rk_crypto_desc *rk_crypto, u32 *m,
|
||||
u32 *n, u32 *e, u32 *c);
|
||||
int rk_crypto_rsa_end(struct rk_crypto_desc *rk_crypto, u32 *result);
|
||||
int rk_crypto_rsa_check(struct rk_crypto_desc *rk_crypto);
|
||||
int rk_crypto_probe(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#ifndef _ROCKCHIP_CRYPTO_HD_H_
|
||||
#define _ROCKCHIP_CRYPTO_HD_H_
|
||||
|
||||
struct rk_crypto_reg {
|
||||
u32 crypto_intsts;
|
||||
u32 crypto_intena;
|
||||
u32 crypto_ctrl;
|
||||
u32 crypto_conf;
|
||||
u32 crypto_brdmas;
|
||||
u32 crypto_btdmas;
|
||||
u32 crypto_brdmal;
|
||||
u32 crypto_hrdmas;
|
||||
u32 crypto_hrdmal;
|
||||
u32 reserved0[(0x80 - 0x24) / 4];
|
||||
|
||||
u32 crypto_aes_ctrl;
|
||||
u32 crypto_aes_sts;
|
||||
u32 crypto_aes_din[4];
|
||||
u32 crypto_aes_dout[4];
|
||||
u32 crypto_aes_iv[4];
|
||||
u32 crypto_aes_key[8];
|
||||
u32 crypto_aes_cnt[4];
|
||||
u32 reserved1[(0x100 - 0xe8) / 4];
|
||||
|
||||
u32 crypto_tdes_ctrl;
|
||||
u32 crypto_tdes_sts;
|
||||
u32 crypto_tdes_din[2];
|
||||
u32 crypto_tdes_dout[2];
|
||||
u32 crypto_tdes_iv[2];
|
||||
u32 crypto_tdes_key1[2];
|
||||
u32 crypto_tdes_key2[2];
|
||||
u32 crypto_tdes_key3[2];
|
||||
u32 reserved2[(0x180 - 0x138) / 4];
|
||||
|
||||
u32 crypto_hash_ctrl;
|
||||
u32 crypto_hash_sts;
|
||||
u32 crypto_hash_meg_len;
|
||||
u32 crypto_hash_dout[8];
|
||||
u32 crypto_hash_seed[5];
|
||||
u32 reserved3[(0x200 - 0x1c0) / 4];
|
||||
|
||||
u32 crypto_trng_ctrl;
|
||||
u32 crypto_trng_dout[8];
|
||||
u32 reserved4[(0x280 - 0x224) / 4];
|
||||
|
||||
u32 crypto_pka_ctrl;
|
||||
u32 reserved5[(0x400 - 0x284) / 4];
|
||||
|
||||
u32 crypto_pka_m;
|
||||
u32 reserved6[(0x500 - 0x404) / 4];
|
||||
|
||||
u32 crypto_pka_c;
|
||||
u32 reserved7[(0x600 - 0x504) / 4];
|
||||
|
||||
u32 crypto_pka_n;
|
||||
u32 reserved8[(0x700 - 0x604) / 4];
|
||||
|
||||
u32 crypto_pka_e;
|
||||
};
|
||||
|
||||
#define CRYPTO_DEFAULT_CLK 10000000
|
||||
#define SHA_256_BIT 256
|
||||
/* crypto_hash_ctrl */
|
||||
#define HASH_SWAP_DO 0x8
|
||||
#define ENGINE_SELECTION_SHA256 0x2
|
||||
/* crypto_conf */
|
||||
#define HR_ADDR_MODE (1 << 8)
|
||||
#define BT_ADDR_MODE (1 << 7)
|
||||
#define BR_ADDR_MODE (1 << 6)
|
||||
#define BYTESWAP_HRFIFO (1 << 5)
|
||||
#define BYTESWAP_BTFIFO (1 << 4)
|
||||
#define BYTESWAP_BRFIFO (1 << 3)
|
||||
#define DESSEL (1 << 2)
|
||||
/* crypto_ctrl */
|
||||
#define TRNG_FLUSH (1 << 9)
|
||||
#define TRNG_START (1 << 8)
|
||||
#define PKA_FLUSH (1 << 7)
|
||||
#define HASH_FLUSH (1 << 6)
|
||||
#define BLOCK_FLUSH (1 << 5)
|
||||
#define PKA_START (1 << 4)
|
||||
#define HASH_START (1 << 3)
|
||||
#define BLOCK_START (1 << 2)
|
||||
#define TDES_START (1 << 1)
|
||||
#define AES_START (1 << 0)
|
||||
#define PKA_HASH_CTRL (PKA_FLUSH | HASH_FLUSH)
|
||||
#define PKA_CTRL (PKA_FLUSH | PKA_START)
|
||||
/* crypto_intsts */
|
||||
#define PKA_DONE_INT (1 << 5)
|
||||
#define HASH_DONE_INT (1 << 4)
|
||||
#define HRDMA_ERR_INT (1 << 3)
|
||||
#define HRDMA_DONE_INT (1 << 2)
|
||||
#define BCDMA_ERR_INT (1 << 1)
|
||||
#define BCDMA_DONE_INT (1 << 0)
|
||||
/* crypto_pka_ctrl */
|
||||
#define PKA_BLOCK_SIZE_2048 2
|
||||
|
||||
struct dm_rk_crypto_ops {
|
||||
int (*sha_init)(struct udevice *dev, u32 msg_len, int hash_bits);
|
||||
int (*sha_byte_swap)(struct udevice *dev, int en);
|
||||
int (*sha_start)(struct udevice *dev, u32 *data, u32 data_len);
|
||||
int (*sha_end)(struct udevice *dev, u32 *result);
|
||||
int (*rsa_init)(struct udevice *dev);
|
||||
int (*rsa_start)(struct udevice *dev, u32 *m, u32 *n, u32 *e, u32 *c);
|
||||
int (*rsa_end)(struct udevice *dev, u32 *result);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue