drivers: crypto: add it51xxx sha256 driver

Implement a crypto sha256 driver for it51xxx series.

Signed-off-by: Yunshao Chiang <Yunshao.Chiang@ite.com.tw>
This commit is contained in:
Yunshao Chiang 2025-04-11 13:23:39 +08:00 committed by Benjamin Cabé
commit 8f8b223ff2
9 changed files with 349 additions and 0 deletions

View file

@ -149,3 +149,7 @@
pinctrl-0 = <&tach0a_gpd6_default>; pinctrl-0 = <&tach0a_gpd6_default>;
pinctrl-names = "default"; pinctrl-names = "default";
}; };
&sha256 {
status = "okay";
};

View file

@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT51XXX_SHA crypto_it51xxx_sha.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2.c)
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c)

View file

@ -80,6 +80,7 @@ source "drivers/crypto/Kconfig.nrf_ecb"
source "drivers/crypto/Kconfig.intel" source "drivers/crypto/Kconfig.intel"
source "drivers/crypto/Kconfig.npcx" source "drivers/crypto/Kconfig.npcx"
source "drivers/crypto/Kconfig.xec" source "drivers/crypto/Kconfig.xec"
source "drivers/crypto/Kconfig.it51xxx"
source "drivers/crypto/Kconfig.it8xxx2" source "drivers/crypto/Kconfig.it8xxx2"
source "drivers/crypto/Kconfig.mcux_dcp" source "drivers/crypto/Kconfig.mcux_dcp"
source "drivers/crypto/Kconfig.si32" source "drivers/crypto/Kconfig.si32"

View file

@ -0,0 +1,11 @@
# Copyright (c) 2025 ITE Corporation.
# SPDX-License-Identifier: Apache-2.0
config CRYPTO_IT51XXX_SHA
bool "ITE IT51XXX SHA driver"
default y
depends on DT_HAS_ITE_IT51XXX_SHA_ENABLED
select SOC_IT51XXX_SHA256_HW_ACCELERATE
help
The IT51XXX hardware supports SHA-256 calculation, which is faster than
the firmware implementation.

View file

@ -0,0 +1,276 @@
/*
* Copyright (c) 2025 ITE Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT ite_it51xxx_sha
#include <errno.h>
#include <it51xxx/chip_chipregs.h>
#include <zephyr/crypto/crypto.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(crypto_it51xxx_sha, CONFIG_CRYPTO_LOG_LEVEL);
#define IT51XXX_SHA_REGS_BASE DT_REG_ADDR(DT_NODELABEL(sha256))
/* 0x00: SHA Control Register (SHACR) */
#define IT51XXX_SHACR (IT51XXX_SHA_REGS_BASE + 0x00)
#define IT51XXX_SHAWB BIT(2)
#define IT51XXX_SHAINI BIT(1)
#define IT51XXX_SHAEXE BIT(0)
/* 0x01: SHA Status Register (SHASR)*/
#define IT51XXX_SHASR (IT51XXX_SHA_REGS_BASE + 0x01)
#define IT51XXX_SHAIE BIT(3)
#define IT51XXX_SHAIS BIT(2)
#define IT51XXX_SHABUSY BIT(0)
/* 0x02: SHA Execution Counter Register (SHAECR) */
#define IT51XXX_SHAECR (IT51XXX_SHA_REGS_BASE + 0x02)
#define IT51XXX_SHAEXEC_64_BYTE 0x00
#define IT51XXX_SHAEXEC_1K_BYTE 0x0F
/* 0x03: SHA DLM Base Address 0 Register (SHADBA0R) */
#define IT51XXX_SHADBA0R (IT51XXX_SHA_REGS_BASE + 0x03)
/* 0x04: SHA DLM Base Address 1 Register (SHADBA1R) */
#define IT51XXX_SHADBA1R (IT51XXX_SHA_REGS_BASE + 0x04)
/* 0x05: SHA Setting Register (SHASETR) */
#define IT51XXX_SHASETR (IT51XXX_SHA_REGS_BASE + 0x05)
#define IT51XXX_SHA256 0x00
/* 0x06: SHA DLM Base Address 2 Register (SHADBA2R) */
#define IT51XXX_SHADBA2R (IT51XXX_SHA_REGS_BASE + 0x06)
#define SHA_SHA256_HASH_LEN 32
#define SHA_SHA256_BLOCK_LEN 64
#define SHA_SHA256_HASH_LEN_WORDS (SHA_SHA256_HASH_LEN / sizeof(uint32_t))
#define SHA_SHA256_BLOCK_LEN_WORDS (SHA_SHA256_BLOCK_LEN / sizeof(uint32_t))
/*
* If the input message is more than 1K bytes, taking 10K bytes for example,
* it should run 10 times SHA hardwired loading and execution, and process 1K bytes each time.
*/
#define SHA_HW_MAX_INPUT_LEN 1024
#define SHA_HW_MAX_INPUT_LEN_WORDS (SHA_HW_MAX_INPUT_LEN / sizeof(uint32_t))
/*
* This struct is used by the hardware and must be stored in RAM first 4k-byte
* and aligned on a 256-byte boundary.
*/
struct chip_sha256_ctx {
union {
/* SHA data buffer */
uint32_t w_sha[SHA_HW_MAX_INPUT_LEN_WORDS];
uint8_t w_input[SHA_HW_MAX_INPUT_LEN];
};
/* H[0] ~ H[7] */
uint32_t h[SHA_SHA256_HASH_LEN_WORDS];
uint32_t sha_init;
uint32_t w_input_index;
uint32_t total_len;
} __aligned(256);
Z_GENERIC_SECTION(.__sha256_ram_block) struct chip_sha256_ctx chip_ctx;
static void it51xxx_sha256_init(bool init_k)
{
chip_ctx.sha_init = init_k;
chip_ctx.total_len = 0;
chip_ctx.w_input_index = 0;
/* Set DLM address for input data */
sys_write8(((uint32_t)&chip_ctx) & 0xC0, IT51XXX_SHADBA0R);
sys_write8(((uint32_t)&chip_ctx) >> 8, IT51XXX_SHADBA1R);
sys_write8(((uint32_t)&chip_ctx) >> 16, IT51XXX_SHADBA2R);
}
static void it51xxx_sha256_module_calculation(void)
{
uint32_t key;
/*
* Global interrupt is disabled because the CPU cannot access memory
* via the DLM (Data Local Memory) bus while HW module is computing
* hash.
*/
key = irq_lock();
if (chip_ctx.sha_init) {
chip_ctx.sha_init = 0;
sys_write8(IT51XXX_SHAINI | IT51XXX_SHAEXE, IT51XXX_SHACR);
} else {
sys_write8(IT51XXX_SHAEXE, IT51XXX_SHACR);
}
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
sys_write8(IT51XXX_SHAIS, IT51XXX_SHASR);
irq_unlock(key);
chip_ctx.w_input_index = 0;
}
static int it51xxx_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish)
{
uint32_t i;
uint32_t in_buf_idx = 0;
uint32_t key;
uint32_t rem_len = pkt->in_len;
/* data length >= 1KiB */
while (rem_len >= SHA_HW_MAX_INPUT_LEN) {
rem_len = rem_len - SHA_HW_MAX_INPUT_LEN;
for (i = 0; i < SHA_HW_MAX_INPUT_LEN; i++) {
chip_ctx.w_input[chip_ctx.w_input_index++] = pkt->in_buf[in_buf_idx++];
}
/* HW automatically load 1KB data from DLM */
sys_write8(IT51XXX_SHAEXEC_1K_BYTE, IT51XXX_SHAECR);
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
it51xxx_sha256_module_calculation();
}
/* 0 <= data length < 1KiB */
while (rem_len) {
rem_len--;
chip_ctx.w_input[chip_ctx.w_input_index++] = pkt->in_buf[in_buf_idx++];
/*
* If fill full 64byte then execute HW calculation.
* If not, will execute in later finish block.
*/
if (chip_ctx.w_input_index >= SHA_SHA256_BLOCK_LEN) {
/* HW automatically load 64 bytes data from DLM */
sys_write8(IT51XXX_SHAEXEC_64_BYTE, IT51XXX_SHAECR);
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
it51xxx_sha256_module_calculation();
}
}
chip_ctx.total_len += pkt->in_len;
if (finish) {
uint32_t *out_buf_ptr = (uint32_t *)pkt->out_buf;
/* Pre-processing (Padding) */
chip_ctx.w_input[chip_ctx.w_input_index++] = 0x80;
memset(&chip_ctx.w_input[chip_ctx.w_input_index], 0,
SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
/*
* Handles the boundary case of rest data:
* Because the last eight bytes are bit length field of SHA256 rule.
* If the data index >= 56, it needs to trigger HW to calculate,
* then fill 0 data and the last eight bytes bit length, and calculate
* again.
*/
if (chip_ctx.w_input_index >= 56) {
/* HW automatically load 64Bytes data from DLM */
sys_write8(IT51XXX_SHAEXEC_64_BYTE, IT51XXX_SHAECR);
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
it51xxx_sha256_module_calculation();
memset(&chip_ctx.w_input[chip_ctx.w_input_index], 0,
SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
}
/*
* Since input data (big-endian) are copied 1byte by 1byte to
* it51xxx memory (little-endian), so the bit length needs to
* be transformed into big-endian format and then write to memory.
*/
chip_ctx.w_sha[15] = sys_cpu_to_be32(chip_ctx.total_len * 8);
/* HW automatically load 64Bytes data from DLM */
sys_write8(IT51XXX_SHAEXEC_64_BYTE, IT51XXX_SHAECR);
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
it51xxx_sha256_module_calculation();
/* HW write back the hash result to DLM */
/* Set DLM address for input data */
sys_write8(((uint32_t)&chip_ctx.h) & 0xC0, IT51XXX_SHADBA0R);
sys_write8(((uint32_t)&chip_ctx.h) >> 8, IT51XXX_SHADBA1R);
key = irq_lock();
sys_write8(IT51XXX_SHAWB, IT51XXX_SHACR);
while (sys_read8(IT51XXX_SHASR) & IT51XXX_SHABUSY) {
};
sys_write8(IT51XXX_SHAIS, IT51XXX_SHASR);
irq_unlock(key);
for (i = 0; i < SHA_SHA256_HASH_LEN_WORDS; i++) {
out_buf_ptr[i] = chip_ctx.h[i];
}
it51xxx_sha256_init(true);
}
return 0;
}
static int it51xxx_hash_session_free(const struct device *dev, struct hash_ctx *ctx)
{
it51xxx_sha256_init(true);
return 0;
}
static inline int it51xxx_query_hw_caps(const struct device *dev)
{
return (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
}
static int it51xxx_hash_begin_session(const struct device *dev, struct hash_ctx *ctx,
enum hash_algo algo)
{
if (algo != CRYPTO_HASH_ALGO_SHA256) {
LOG_ERR("Unsupported algorithm");
return -EINVAL;
}
if (ctx->flags & ~(it51xxx_query_hw_caps(dev))) {
LOG_ERR("Unsupported flag");
return -EINVAL;
}
it51xxx_sha256_init(true);
ctx->hash_hndlr = it51xxx_hash_handler;
return 0;
}
static int it51xxx_sha_init(const struct device *dev)
{
it51xxx_sha256_init(true);
/* Select SHA-2 Family, SHA-256 */
sys_write8(IT51XXX_SHA256, IT51XXX_SHASETR);
/* SHA interrupt disable */
sys_write8(sys_read8(IT51XXX_SHASR) & ~IT51XXX_SHAIE, IT51XXX_SHASR);
return 0;
}
static DEVICE_API(crypto, it51xxx_crypto_api) = {
.hash_begin_session = it51xxx_hash_begin_session,
.hash_free_session = it51xxx_hash_session_free,
.query_hw_caps = it51xxx_query_hw_caps,
};
DEVICE_DT_INST_DEFINE(0, &it51xxx_sha_init, NULL, NULL, NULL, POST_KERNEL,
CONFIG_CRYPTO_INIT_PRIORITY, &it51xxx_crypto_api);
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "support only one sha compatible node");

View file

@ -0,0 +1,12 @@
# Copyright (c) 2025 ITE Corporation
# SPDX-License-Identifier: Apache-2.0
description: ITE IT51XXX Crypto SHA accelerator.
compatible: "ite,it51xxx-sha"
include: base.yaml
properties:
reg:
required: true

View file

@ -1315,5 +1315,11 @@
io-channel = <3>; io-channel = <3>;
extern-enable = <0xf016de 1>; extern-enable = <0xf016de 1>;
}; };
sha256: crypto@f03b00 {
compatible = "ite,it51xxx-sha";
reg = <0x00f03b00 0x6>;
status = "disabled";
};
}; };
}; };

View file

@ -40,6 +40,19 @@ config SOC_IT51XXX_USE_ILM
predictable than executing from Flash directly, and some code (such as code predictable than executing from Flash directly, and some code (such as code
that writes to the internal Flash) must execute out of RAM. that writes to the internal Flash) must execute out of RAM.
config SOC_IT51XXX_SHA256_HW_ACCELERATE
bool "HW SHA256 calculation"
help
IT51XXX HW support sha256 calculation, and its calculation is faster than FW.
config SOC_IT515XX_SHA256_DLM_OFFSET
hex
default 0x03E000
depends on SOC_IT51XXX_SHA256_HW_ACCELERATE
help
Due to the hardware requirements of the IT515XX, the SHA-256 data must be
placed within the specific address range (0x83E000 to 0x83EFFF by default).
config ILM_MAX_SIZE config ILM_MAX_SIZE
int "ILM Size in kB" int "ILM Size in kB"
default 4 default 4

View file

@ -79,6 +79,12 @@
#define RAM_BASE CONFIG_SRAM_BASE_ADDRESS #define RAM_BASE CONFIG_SRAM_BASE_ADDRESS
#define RAM_SIZE KB(CONFIG_SRAM_SIZE) #define RAM_SIZE KB(CONFIG_SRAM_SIZE)
/* The IT515XX series must use the address range 0x83E000 to 0x83EFFF to calculate SHA */
#ifdef CONFIG_SOC_IT51XXX_SHA256_HW_ACCELERATE
#define SHA256_DLM_BASE (RAM_BASE + CONFIG_SOC_IT515XX_SHA256_DLM_OFFSET)
#define SHA256_DLM_LENGTH KB(4)
#endif
#ifdef CONFIG_RISCV_PMP #ifdef CONFIG_RISCV_PMP
#define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY #define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY
#define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE); #define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE);
@ -104,6 +110,10 @@ MEMORY
#endif #endif
RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE
#ifdef CONFIG_SOC_IT51XXX_SHA256_HW_ACCELERATE
SHA256_DLM (rw) : ORIGIN = SHA256_DLM_BASE, LENGTH = SHA256_DLM_LENGTH
#endif
#if defined(CONFIG_LINKER_DEVNULL_MEMORY) #if defined(CONFIG_LINKER_DEVNULL_MEMORY)
DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE
#endif #endif
@ -443,6 +453,21 @@ GROUP_END(DTCM)
GROUP_END(RAMABLE_REGION) GROUP_END(RAMABLE_REGION)
#ifdef CONFIG_SOC_IT51XXX_SHA256_HW_ACCELERATE
GROUP_START(SHA256_DLM)
SECTION_PROLOGUE(it515xx_sha256_ram, (NOLOAD),)
{
__sha256_ram_block_start = .;
KEEP(*(.__sha256_ram_block))
ASSERT((ABSOLUTE(__sha256_ram_block_start) & 0xfff) == 0, \
"SHA256 DLM block must be 4KB aligned");
} GROUP_LINK_IN(SHA256_DLM)
GROUP_END(SHA256_DLM)
#endif
#include <zephyr/linker/debug-sections.ld> #include <zephyr/linker/debug-sections.ld>
/DISCARD/ : { *(.note.GNU-stack) } /DISCARD/ : { *(.note.GNU-stack) }