From: Chia-Wei Wang <chiawei_wang@aspeedtech.com>
To: <lukma@denx.de>, <maxims@google.com>, <sjg@chromium.org>,
<u-boot@lists.denx.de>
Cc: <ryan_chen@aspeedtech.com>
Subject: [PATCH 03/14] crypto: aspeed: Add AST2600 HACE support
Date: Tue, 13 Jul 2021 17:00:05 +0800 [thread overview]
Message-ID: <20210713090016.2729-4-chiawei_wang@aspeedtech.com> (raw)
In-Reply-To: <20210713090016.2729-1-chiawei_wang@aspeedtech.com>
Hash and Crypto Engine (HACE) is designed to accelerate the
throughput of hash data digest, and symmetric-key encryption.
Signed-off-by: Chia-Wei Wang <chiawei_wang@aspeedtech.com>
---
drivers/crypto/Kconfig | 2 +
drivers/crypto/Makefile | 1 +
drivers/crypto/aspeed/Kconfig | 12 ++
drivers/crypto/aspeed/Makefile | 1 +
drivers/crypto/aspeed/aspeed_hace.c | 288 ++++++++++++++++++++++++++++
5 files changed, 304 insertions(+)
create mode 100644 drivers/crypto/aspeed/Kconfig
create mode 100644 drivers/crypto/aspeed/Makefile
create mode 100644 drivers/crypto/aspeed/aspeed_hace.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 1ea116be75..422d01403e 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -2,4 +2,6 @@ menu "Hardware crypto devices"
source drivers/crypto/fsl/Kconfig
+source drivers/crypto/aspeed/Kconfig
+
endmenu
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index efbd1d3fca..0442067e5e 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o
obj-y += rsa_mod_exp/
obj-y += fsl/
+obj-y += aspeed/
diff --git a/drivers/crypto/aspeed/Kconfig b/drivers/crypto/aspeed/Kconfig
new file mode 100644
index 0000000000..299efc223f
--- /dev/null
+++ b/drivers/crypto/aspeed/Kconfig
@@ -0,0 +1,12 @@
+config ASPEED_HACE
+ bool "ASPEED Hash and Crypto Engine"
+ depends on ASPEED_AST2600
+ imply SHA_HW_ACCEL
+ imply SHA_PROG_HW_ACCEL
+ imply CMD_HASH
+ help
+ Select this option to enable a driver for using the SHA engine in
+ the ASPEED BMC SoCs.
+
+ Enabling this allows the use of SHA operations in hardware without requiring the
+ SHA software implementations. It also improves performance and saves code size.
diff --git a/drivers/crypto/aspeed/Makefile b/drivers/crypto/aspeed/Makefile
new file mode 100644
index 0000000000..84e6bfe82a
--- /dev/null
+++ b/drivers/crypto/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASPEED_HACE) += aspeed_hace.o
diff --git a/drivers/crypto/aspeed/aspeed_hace.c b/drivers/crypto/aspeed/aspeed_hace.c
new file mode 100644
index 0000000000..34e68c07f4
--- /dev/null
+++ b/drivers/crypto/aspeed/aspeed_hace.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2021 IBM Corp.
+ * Copyright 2021 ASPEED Technology Inc.
+ */
+#include <common.h>
+#include <clk.h>
+#include <log.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <hash.h>
+#include <dm/uclass.h>
+#include <dm/device.h>
+#include <dm/fdtaddr.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/iopoll.h>
+
+/* register offsets*/
+#define HACE_STS 0x1C
+#define HACE_HASH_INT BIT(9)
+#define HACE_HASH_BUSY BIT(0)
+#define HACE_HASH_DATA 0x20
+#define HACE_HASH_DIGEST 0x24
+#define HACE_HASH_HMAC_KEY 0x28
+#define HACE_HASH_DATA_LEN 0x2C
+#define HACE_SG_LAST BIT(31)
+#define HACE_HASH_CMD 0x30
+#define HACE_SG_EN BIT(18)
+#define HACE_ALGO_SHA384 (BIT(10) | BIT(6) | BIT(5))
+#define HACE_ALGO_SHA512 (BIT(6) | BIT(5))
+#define HACE_ALGO_SHA256 (BIT(6) | BIT(4))
+#define HACE_ALGO_SHA224 BIT(6)
+#define HACE_ALGO_SHA1 BIT(5)
+#define HACE_SHA_BE_EN BIT(3)
+#define HACE_MD5_LE_EN BIT(2)
+
+#define HACE_MAX_SG 32
+
+struct aspeed_sg {
+ u32 len;
+ u32 addr;
+};
+
+struct aspeed_hash_ctx {
+ u32 method;
+ u32 digest_size;
+ u32 len;
+ u32 count;
+ struct aspeed_sg list[HACE_MAX_SG]; /* Must be 8 byte aligned */
+};
+
+struct aspeed_hace {
+ phys_addr_t base;
+ struct clk clk;
+};
+
+static phys_addr_t aspeed_hace_get_base(void)
+{
+ int rc;
+ struct udevice *dev;
+ struct aspeed_hace *hace;
+
+ rc = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_DRIVER_GET(aspeed_hace),
+ &dev);
+ if (rc) {
+ printf("Cannot get HACE device, rc=%d\n", rc);
+ return 0;
+ }
+
+ hace = dev_get_priv(dev);
+
+ return hace->base;
+}
+
+static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us)
+{
+ u32 val;
+
+ return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us);
+}
+
+static int digest_object(const void *data, unsigned int length, void *digest,
+ u32 method)
+{
+ phys_addr_t base = aspeed_hace_get_base();
+
+ if (!((u32)data & BIT(31))) {
+ debug("HACE src out of bounds: can only copy from SDRAM\n");
+ return -EINVAL;
+ }
+
+ if (!((u32)digest & BIT(31))) {
+ debug("HACE dst out of bounds: can only copy to SDRAM\n");
+ return -EINVAL;
+ }
+
+ if ((u32)digest & 0x7) {
+ debug("HACE dst alignment incorrect: %p\n", digest);
+ return -EINVAL;
+ }
+
+ if (readl(base + HACE_STS) & HACE_HASH_BUSY) {
+ debug("HACE error: engine busy\n");
+ return -EBUSY;
+ }
+
+ /* Clear pending completion status */
+ writel(HACE_HASH_INT, base + HACE_STS);
+ writel((u32)data, base + HACE_HASH_DATA);
+ writel((u32)digest, base + HACE_HASH_DIGEST);
+ writel(length, base + HACE_HASH_DATA_LEN);
+ writel(HACE_SHA_BE_EN | method, base + HACE_HASH_CMD);
+
+ /* SHA512 hashing appears to have a througput of about 12MB/s */
+ return aspeed_hace_wait_completion(base + HACE_STS,
+ HACE_HASH_INT,
+ 1000 + (length >> 3));
+}
+
+void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
+ unsigned char *pout, unsigned int chunk_size)
+{
+ int rc;
+
+ rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA1);
+ if (rc)
+ debug("HACE failure: %d\n", rc);
+}
+
+void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
+ unsigned char *pout, unsigned int chunk_size)
+{
+ int rc;
+
+ rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA256);
+ if (rc)
+ debug("HACE failure: %d\n", rc);
+}
+
+void hw_sha384(const unsigned char *pbuf, unsigned int buf_len,
+ unsigned char *pout, unsigned int chunk_size)
+{
+ int rc;
+
+ rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA384);
+ if (rc)
+ debug("HACE failure: %d\n", rc);
+}
+
+void hw_sha512(const unsigned char *pbuf, unsigned int buf_len,
+ unsigned char *pout, unsigned int chunk_size)
+{
+ int rc;
+
+ rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA512);
+ if (rc)
+ debug("HACE failure: %d\n", rc);
+}
+
+int hw_sha_init(struct hash_algo *algo, void **ctxp)
+{
+ struct aspeed_hash_ctx *ctx;
+ u32 method;
+
+ if (!strcmp(algo->name, "sha1"))
+ method = HACE_ALGO_SHA1;
+ else if (!strcmp(algo->name, "sha256"))
+ method = HACE_ALGO_SHA256;
+ else if (!strcmp(algo->name, "sha384"))
+ method = HACE_ALGO_SHA384;
+ else if (!strcmp(algo->name, "sha512"))
+ method = HACE_ALGO_SHA512;
+ else
+ return -ENOTSUPP;
+
+ ctx = memalign(8, sizeof(*ctx));
+ if (!ctx) {
+ debug("HACE error: Cannot allocate memory for context\n");
+ return -ENOMEM;
+ }
+
+ memset(ctx, '\0', sizeof(*ctx));
+
+ if (((uintptr_t)ctx->list & 0x3) != 0) {
+ printf("HACE error: Invalid alignment for input data\n");
+ return -EINVAL;
+ }
+
+ ctx->method = method | HACE_SG_EN;
+ ctx->digest_size = algo->digest_size;
+
+ *ctxp = ctx;
+
+ return 0;
+}
+
+int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf,
+ unsigned int size, int is_last)
+{
+ struct aspeed_hash_ctx *ctx = hash_ctx;
+ struct aspeed_sg *sg = &ctx->list[ctx->count];
+
+ if (ctx->count >= ARRAY_SIZE(ctx->list)) {
+ debug("HACE error: Reached maximum number of hash segments\n");
+ free(ctx);
+ return -EINVAL;
+ }
+
+ sg->addr = (u32)buf;
+ sg->len = size;
+
+ if (is_last)
+ sg->len |= HACE_SG_LAST;
+
+ ctx->count++;
+ ctx->len += size;
+
+ return 0;
+}
+
+int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size)
+{
+ struct aspeed_hash_ctx *ctx = hash_ctx;
+ int rc;
+
+ if (size < ctx->digest_size) {
+ debug("HACE error: insufficient size on destination buffer\n");
+ free(ctx);
+ return -EINVAL;
+ }
+
+ rc = digest_object(ctx->list, ctx->len, dest_buf, ctx->method);
+ if (rc)
+ debug("HACE Scatter-Gather failure\n");
+
+ free(ctx);
+
+ return rc;
+}
+
+static int aspeed_hace_probe(struct udevice *dev)
+{
+ struct aspeed_hace *hace = dev_get_priv(dev);
+ int ret;
+
+ ret = clk_get_by_index(dev, 0, &hace->clk);
+ if (ret < 0) {
+ debug("Can't get clock for %s: %d\n", dev->name, ret);
+ return ret;
+ }
+
+ ret = clk_enable(&hace->clk);
+ if (ret) {
+ debug("Failed to enable fsi clock (%d)\n", ret);
+ return ret;
+ }
+
+ hace->base = devfdt_get_addr(dev);
+
+ return ret;
+}
+
+static int aspeed_hace_remove(struct udevice *dev)
+{
+ struct aspeed_hace *hace = dev_get_priv(dev);
+
+ clk_disable(&hace->clk);
+
+ return 0;
+}
+
+static const struct udevice_id aspeed_hace_ids[] = {
+ { .compatible = "aspeed,ast2600-hace" },
+ { }
+};
+
+U_BOOT_DRIVER(aspeed_hace) = {
+ .name = "aspeed_hace",
+ .id = UCLASS_MISC,
+ .of_match = aspeed_hace_ids,
+ .probe = aspeed_hace_probe,
+ .remove = aspeed_hace_remove,
+ .priv_auto = sizeof(struct aspeed_hace),
+ .flags = DM_FLAG_PRE_RELOC,
+};
--
2.17.1
next prev parent reply other threads:[~2021-07-13 9:00 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-13 9:00 [PATCH 00/14] aspeed: Support secure boot chain with FIT image verification Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 01/14] aspeed: ast2600: Enlarge SRAM size Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 02/14] clk: ast2600: Add YCLK control for HACE Chia-Wei Wang
2021-07-13 9:00 ` Chia-Wei Wang [this message]
2021-07-13 9:00 ` [PATCH 04/14] ast2600: spl: Add HACE probing Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 05/14] ARM: dts: ast2600: Add HACE to device tree Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 06/14] common: fit: Use hash.c to call CRC/SHA function Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 07/14] clk: ast2600: Add RSACLK control for ARCY Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 08/14] crypto: aspeed: Add AST2600 ARCY support Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 09/14] ast2600: spl: Add ARCY probing Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 10/14] ARM: dts: ast2600: Add ARCY to device tree Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 11/14] ast2600: spl: Locate load buffer in DRAM space Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 12/14] configs: ast2600-evb: Enable SPL FIT support Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 13/14] configs: aspeed: Make EXTRA_ENV_SETTINGS board specific Chia-Wei Wang
2021-07-13 9:00 ` [PATCH 14/14] configs: ast2600: Boot kernel FIT in DRAM Chia-Wei Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210713090016.2729-4-chiawei_wang@aspeedtech.com \
--to=chiawei_wang@aspeedtech.com \
--cc=lukma@denx.de \
--cc=maxims@google.com \
--cc=ryan_chen@aspeedtech.com \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox