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:
Jason Zhu 2018-12-10 17:01:03 +08:00 committed by Kever Yang
parent 564654eb9c
commit 726087de6e
9 changed files with 475 additions and 1 deletions

View File

@ -1,5 +1,6 @@
menu "Hardware crypto devices"
source drivers/crypto/fsl/Kconfig
source drivers/crypto/rockchip/Kconfig
endmenu

View File

@ -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/

View File

@ -0,0 +1,5 @@
config CRYPTO_ROCKCHIP
bool "Support Rockchip Hardware Crypto"
help
The module supports Rockchip Hardware Crypto.
This accelerates algorithmic operations.

View File

@ -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

View File

@ -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",
};

View File

@ -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),
};

View File

@ -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,
};

View File

@ -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

View File

@ -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