From 8f8b223ff2c3fe33358c584f8b87506fb2432b26 Mon Sep 17 00:00:00 2001 From: Yunshao Chiang Date: Fri, 11 Apr 2025 13:23:39 +0800 Subject: [PATCH] drivers: crypto: add it51xxx sha256 driver Implement a crypto sha256 driver for it51xxx series. Signed-off-by: Yunshao Chiang --- boards/ite/it515xx_evb/it515xx_evb.dts | 4 + drivers/crypto/CMakeLists.txt | 1 + drivers/crypto/Kconfig | 1 + drivers/crypto/Kconfig.it51xxx | 11 + drivers/crypto/crypto_it51xxx_sha.c | 276 +++++++++++++++++++++++ dts/bindings/crypto/ite,it51xxx-sha.yaml | 12 + dts/riscv/ite/it51xxx.dtsi | 6 + soc/ite/ec/it51xxx/Kconfig | 13 ++ soc/ite/ec/it51xxx/linker.ld | 25 ++ 9 files changed, 349 insertions(+) create mode 100644 drivers/crypto/Kconfig.it51xxx create mode 100644 drivers/crypto/crypto_it51xxx_sha.c create mode 100644 dts/bindings/crypto/ite,it51xxx-sha.yaml diff --git a/boards/ite/it515xx_evb/it515xx_evb.dts b/boards/ite/it515xx_evb/it515xx_evb.dts index f55af4d8ee0..926c93bd921 100644 --- a/boards/ite/it515xx_evb/it515xx_evb.dts +++ b/boards/ite/it515xx_evb/it515xx_evb.dts @@ -149,3 +149,7 @@ pinctrl-0 = <&tach0a_gpd6_default>; pinctrl-names = "default"; }; + +&sha256 { + status = "okay"; +}; diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 5094377abb1..a84a191642b 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -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_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_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_V2 crypto_it8xxx2_sha_v2.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 9a7bdb89b54..0a609e3fce5 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -80,6 +80,7 @@ source "drivers/crypto/Kconfig.nrf_ecb" source "drivers/crypto/Kconfig.intel" source "drivers/crypto/Kconfig.npcx" source "drivers/crypto/Kconfig.xec" +source "drivers/crypto/Kconfig.it51xxx" source "drivers/crypto/Kconfig.it8xxx2" source "drivers/crypto/Kconfig.mcux_dcp" source "drivers/crypto/Kconfig.si32" diff --git a/drivers/crypto/Kconfig.it51xxx b/drivers/crypto/Kconfig.it51xxx new file mode 100644 index 00000000000..8cda3a77887 --- /dev/null +++ b/drivers/crypto/Kconfig.it51xxx @@ -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. diff --git a/drivers/crypto/crypto_it51xxx_sha.c b/drivers/crypto/crypto_it51xxx_sha.c new file mode 100644 index 00000000000..bd20c29b25f --- /dev/null +++ b/drivers/crypto/crypto_it51xxx_sha.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2025 ITE Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it51xxx_sha + +#include +#include +#include +#include +#include + +#include +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"); diff --git a/dts/bindings/crypto/ite,it51xxx-sha.yaml b/dts/bindings/crypto/ite,it51xxx-sha.yaml new file mode 100644 index 00000000000..ec4ab0170ca --- /dev/null +++ b/dts/bindings/crypto/ite,it51xxx-sha.yaml @@ -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 diff --git a/dts/riscv/ite/it51xxx.dtsi b/dts/riscv/ite/it51xxx.dtsi index b75bb286367..8f3b008276e 100644 --- a/dts/riscv/ite/it51xxx.dtsi +++ b/dts/riscv/ite/it51xxx.dtsi @@ -1315,5 +1315,11 @@ io-channel = <3>; extern-enable = <0xf016de 1>; }; + + sha256: crypto@f03b00 { + compatible = "ite,it51xxx-sha"; + reg = <0x00f03b00 0x6>; + status = "disabled"; + }; }; }; diff --git a/soc/ite/ec/it51xxx/Kconfig b/soc/ite/ec/it51xxx/Kconfig index 1b910657b69..83096116742 100644 --- a/soc/ite/ec/it51xxx/Kconfig +++ b/soc/ite/ec/it51xxx/Kconfig @@ -40,6 +40,19 @@ config SOC_IT51XXX_USE_ILM predictable than executing from Flash directly, and some code (such as code 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 int "ILM Size in kB" default 4 diff --git a/soc/ite/ec/it51xxx/linker.ld b/soc/ite/ec/it51xxx/linker.ld index ec3feb5ee8a..219f6118db8 100644 --- a/soc/ite/ec/it51xxx/linker.ld +++ b/soc/ite/ec/it51xxx/linker.ld @@ -79,6 +79,12 @@ #define RAM_BASE CONFIG_SRAM_BASE_ADDRESS #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 #define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY #define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE); @@ -104,6 +110,10 @@ MEMORY #endif 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) DEVNULL_ROM (rx) : ORIGIN = DEVNULL_ADDR, LENGTH = DEVNULL_SIZE #endif @@ -443,6 +453,21 @@ GROUP_END(DTCM) 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 /DISCARD/ : { *(.note.GNU-stack) }