162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of STM32 Crypto driver for Linux. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 662306a36Sopenharmony_ci * Author(s): Lionel DEBIEVE <lionel.debieve@st.com> for STMicroelectronics. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <crypto/engine.h> 1062306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1162306a36Sopenharmony_ci#include <crypto/md5.h> 1262306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1362306a36Sopenharmony_ci#include <crypto/sha1.h> 1462306a36Sopenharmony_ci#include <crypto/sha2.h> 1562306a36Sopenharmony_ci#include <crypto/sha3.h> 1662306a36Sopenharmony_ci#include <linux/clk.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1962306a36Sopenharmony_ci#include <linux/dmaengine.h> 2062306a36Sopenharmony_ci#include <linux/interrupt.h> 2162306a36Sopenharmony_ci#include <linux/iopoll.h> 2262306a36Sopenharmony_ci#include <linux/kernel.h> 2362306a36Sopenharmony_ci#include <linux/module.h> 2462306a36Sopenharmony_ci#include <linux/of.h> 2562306a36Sopenharmony_ci#include <linux/platform_device.h> 2662306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2762306a36Sopenharmony_ci#include <linux/reset.h> 2862306a36Sopenharmony_ci#include <linux/string.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define HASH_CR 0x00 3162306a36Sopenharmony_ci#define HASH_DIN 0x04 3262306a36Sopenharmony_ci#define HASH_STR 0x08 3362306a36Sopenharmony_ci#define HASH_UX500_HREG(x) (0x0c + ((x) * 0x04)) 3462306a36Sopenharmony_ci#define HASH_IMR 0x20 3562306a36Sopenharmony_ci#define HASH_SR 0x24 3662306a36Sopenharmony_ci#define HASH_CSR(x) (0x0F8 + ((x) * 0x04)) 3762306a36Sopenharmony_ci#define HASH_HREG(x) (0x310 + ((x) * 0x04)) 3862306a36Sopenharmony_ci#define HASH_HWCFGR 0x3F0 3962306a36Sopenharmony_ci#define HASH_VER 0x3F4 4062306a36Sopenharmony_ci#define HASH_ID 0x3F8 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* Control Register */ 4362306a36Sopenharmony_ci#define HASH_CR_INIT BIT(2) 4462306a36Sopenharmony_ci#define HASH_CR_DMAE BIT(3) 4562306a36Sopenharmony_ci#define HASH_CR_DATATYPE_POS 4 4662306a36Sopenharmony_ci#define HASH_CR_MODE BIT(6) 4762306a36Sopenharmony_ci#define HASH_CR_ALGO_POS 7 4862306a36Sopenharmony_ci#define HASH_CR_MDMAT BIT(13) 4962306a36Sopenharmony_ci#define HASH_CR_DMAA BIT(14) 5062306a36Sopenharmony_ci#define HASH_CR_LKEY BIT(16) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Interrupt */ 5362306a36Sopenharmony_ci#define HASH_DINIE BIT(0) 5462306a36Sopenharmony_ci#define HASH_DCIE BIT(1) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Interrupt Mask */ 5762306a36Sopenharmony_ci#define HASH_MASK_CALC_COMPLETION BIT(0) 5862306a36Sopenharmony_ci#define HASH_MASK_DATA_INPUT BIT(1) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* Status Flags */ 6162306a36Sopenharmony_ci#define HASH_SR_DATA_INPUT_READY BIT(0) 6262306a36Sopenharmony_ci#define HASH_SR_OUTPUT_READY BIT(1) 6362306a36Sopenharmony_ci#define HASH_SR_DMA_ACTIVE BIT(2) 6462306a36Sopenharmony_ci#define HASH_SR_BUSY BIT(3) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* STR Register */ 6762306a36Sopenharmony_ci#define HASH_STR_NBLW_MASK GENMASK(4, 0) 6862306a36Sopenharmony_ci#define HASH_STR_DCAL BIT(8) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* HWCFGR Register */ 7162306a36Sopenharmony_ci#define HASH_HWCFG_DMA_MASK GENMASK(3, 0) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* Context swap register */ 7462306a36Sopenharmony_ci#define HASH_CSR_NB_SHA256_HMAC 54 7562306a36Sopenharmony_ci#define HASH_CSR_NB_SHA256 38 7662306a36Sopenharmony_ci#define HASH_CSR_NB_SHA512_HMAC 103 7762306a36Sopenharmony_ci#define HASH_CSR_NB_SHA512 91 7862306a36Sopenharmony_ci#define HASH_CSR_NB_SHA3_HMAC 88 7962306a36Sopenharmony_ci#define HASH_CSR_NB_SHA3 72 8062306a36Sopenharmony_ci#define HASH_CSR_NB_MAX HASH_CSR_NB_SHA512_HMAC 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define HASH_FLAGS_INIT BIT(0) 8362306a36Sopenharmony_ci#define HASH_FLAGS_OUTPUT_READY BIT(1) 8462306a36Sopenharmony_ci#define HASH_FLAGS_CPU BIT(2) 8562306a36Sopenharmony_ci#define HASH_FLAGS_DMA_ACTIVE BIT(3) 8662306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_INIT BIT(4) 8762306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_FINAL BIT(5) 8862306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_KEY BIT(6) 8962306a36Sopenharmony_ci#define HASH_FLAGS_SHA3_MODE BIT(7) 9062306a36Sopenharmony_ci#define HASH_FLAGS_FINAL BIT(15) 9162306a36Sopenharmony_ci#define HASH_FLAGS_FINUP BIT(16) 9262306a36Sopenharmony_ci#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17) 9362306a36Sopenharmony_ci#define HASH_FLAGS_ALGO_SHIFT 17 9462306a36Sopenharmony_ci#define HASH_FLAGS_ERRORS BIT(21) 9562306a36Sopenharmony_ci#define HASH_FLAGS_EMPTY BIT(22) 9662306a36Sopenharmony_ci#define HASH_FLAGS_HMAC BIT(23) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#define HASH_OP_UPDATE 1 9962306a36Sopenharmony_ci#define HASH_OP_FINAL 2 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define HASH_BURST_LEVEL 4 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cienum stm32_hash_data_format { 10462306a36Sopenharmony_ci HASH_DATA_32_BITS = 0x0, 10562306a36Sopenharmony_ci HASH_DATA_16_BITS = 0x1, 10662306a36Sopenharmony_ci HASH_DATA_8_BITS = 0x2, 10762306a36Sopenharmony_ci HASH_DATA_1_BIT = 0x3 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define HASH_BUFLEN (SHA3_224_BLOCK_SIZE + 4) 11162306a36Sopenharmony_ci#define HASH_MAX_KEY_SIZE (SHA512_BLOCK_SIZE * 8) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cienum stm32_hash_algo { 11462306a36Sopenharmony_ci HASH_SHA1 = 0, 11562306a36Sopenharmony_ci HASH_MD5 = 1, 11662306a36Sopenharmony_ci HASH_SHA224 = 2, 11762306a36Sopenharmony_ci HASH_SHA256 = 3, 11862306a36Sopenharmony_ci HASH_SHA3_224 = 4, 11962306a36Sopenharmony_ci HASH_SHA3_256 = 5, 12062306a36Sopenharmony_ci HASH_SHA3_384 = 6, 12162306a36Sopenharmony_ci HASH_SHA3_512 = 7, 12262306a36Sopenharmony_ci HASH_SHA384 = 12, 12362306a36Sopenharmony_ci HASH_SHA512 = 15, 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cienum ux500_hash_algo { 12762306a36Sopenharmony_ci HASH_SHA256_UX500 = 0, 12862306a36Sopenharmony_ci HASH_SHA1_UX500 = 1, 12962306a36Sopenharmony_ci}; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define HASH_AUTOSUSPEND_DELAY 50 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistruct stm32_hash_ctx { 13462306a36Sopenharmony_ci struct stm32_hash_dev *hdev; 13562306a36Sopenharmony_ci struct crypto_shash *xtfm; 13662306a36Sopenharmony_ci unsigned long flags; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci u8 key[HASH_MAX_KEY_SIZE]; 13962306a36Sopenharmony_ci int keylen; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistruct stm32_hash_state { 14362306a36Sopenharmony_ci u32 flags; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci u16 bufcnt; 14662306a36Sopenharmony_ci u16 blocklen; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci u8 buffer[HASH_BUFLEN] __aligned(4); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* hash state */ 15162306a36Sopenharmony_ci u32 hw_context[3 + HASH_CSR_NB_MAX]; 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistruct stm32_hash_request_ctx { 15562306a36Sopenharmony_ci struct stm32_hash_dev *hdev; 15662306a36Sopenharmony_ci unsigned long op; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32)); 15962306a36Sopenharmony_ci size_t digcnt; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* DMA */ 16262306a36Sopenharmony_ci struct scatterlist *sg; 16362306a36Sopenharmony_ci unsigned int offset; 16462306a36Sopenharmony_ci unsigned int total; 16562306a36Sopenharmony_ci struct scatterlist sg_key; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci dma_addr_t dma_addr; 16862306a36Sopenharmony_ci size_t dma_ct; 16962306a36Sopenharmony_ci int nents; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci u8 data_type; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci struct stm32_hash_state state; 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistruct stm32_hash_algs_info { 17762306a36Sopenharmony_ci struct ahash_engine_alg *algs_list; 17862306a36Sopenharmony_ci size_t size; 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistruct stm32_hash_pdata { 18262306a36Sopenharmony_ci const int alg_shift; 18362306a36Sopenharmony_ci const struct stm32_hash_algs_info *algs_info; 18462306a36Sopenharmony_ci size_t algs_info_size; 18562306a36Sopenharmony_ci bool has_sr; 18662306a36Sopenharmony_ci bool has_mdmat; 18762306a36Sopenharmony_ci bool broken_emptymsg; 18862306a36Sopenharmony_ci bool ux500; 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistruct stm32_hash_dev { 19262306a36Sopenharmony_ci struct list_head list; 19362306a36Sopenharmony_ci struct device *dev; 19462306a36Sopenharmony_ci struct clk *clk; 19562306a36Sopenharmony_ci struct reset_control *rst; 19662306a36Sopenharmony_ci void __iomem *io_base; 19762306a36Sopenharmony_ci phys_addr_t phys_base; 19862306a36Sopenharmony_ci u32 dma_mode; 19962306a36Sopenharmony_ci bool polled; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci struct ahash_request *req; 20262306a36Sopenharmony_ci struct crypto_engine *engine; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci unsigned long flags; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci struct dma_chan *dma_lch; 20762306a36Sopenharmony_ci struct completion dma_completion; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci const struct stm32_hash_pdata *pdata; 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistruct stm32_hash_drv { 21362306a36Sopenharmony_ci struct list_head dev_list; 21462306a36Sopenharmony_ci spinlock_t lock; /* List protection access */ 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic struct stm32_hash_drv stm32_hash = { 21862306a36Sopenharmony_ci .dev_list = LIST_HEAD_INIT(stm32_hash.dev_list), 21962306a36Sopenharmony_ci .lock = __SPIN_LOCK_UNLOCKED(stm32_hash.lock), 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic void stm32_hash_dma_callback(void *param); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic inline u32 stm32_hash_read(struct stm32_hash_dev *hdev, u32 offset) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci return readl_relaxed(hdev->io_base + offset); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline void stm32_hash_write(struct stm32_hash_dev *hdev, 23062306a36Sopenharmony_ci u32 offset, u32 value) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci writel_relaxed(value, hdev->io_base + offset); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline int stm32_hash_wait_busy(struct stm32_hash_dev *hdev) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci u32 status; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* The Ux500 lacks the special status register, we poll the DCAL bit instead */ 24062306a36Sopenharmony_ci if (!hdev->pdata->has_sr) 24162306a36Sopenharmony_ci return readl_relaxed_poll_timeout(hdev->io_base + HASH_STR, status, 24262306a36Sopenharmony_ci !(status & HASH_STR_DCAL), 10, 10000); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return readl_relaxed_poll_timeout(hdev->io_base + HASH_SR, status, 24562306a36Sopenharmony_ci !(status & HASH_SR_BUSY), 10, 10000); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci u32 reg; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_STR); 25362306a36Sopenharmony_ci reg &= ~(HASH_STR_NBLW_MASK); 25462306a36Sopenharmony_ci reg |= (8U * ((length) % 4U)); 25562306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_STR, reg); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int stm32_hash_write_key(struct stm32_hash_dev *hdev) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); 26162306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); 26262306a36Sopenharmony_ci u32 reg; 26362306a36Sopenharmony_ci int keylen = ctx->keylen; 26462306a36Sopenharmony_ci void *key = ctx->key; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (keylen) { 26762306a36Sopenharmony_ci stm32_hash_set_nblw(hdev, keylen); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci while (keylen > 0) { 27062306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_DIN, *(u32 *)key); 27162306a36Sopenharmony_ci keylen -= 4; 27262306a36Sopenharmony_ci key += 4; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_STR); 27662306a36Sopenharmony_ci reg |= HASH_STR_DCAL; 27762306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_STR, reg); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return -EINPROGRESS; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci return 0; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 28862306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); 28962306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); 29062306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 29162306a36Sopenharmony_ci u32 alg = (state->flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci u32 reg = HASH_CR_INIT; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (!(hdev->flags & HASH_FLAGS_INIT)) { 29662306a36Sopenharmony_ci if (hdev->pdata->ux500) { 29762306a36Sopenharmony_ci reg |= ((alg & BIT(0)) << HASH_CR_ALGO_POS); 29862306a36Sopenharmony_ci } else { 29962306a36Sopenharmony_ci if (hdev->pdata->alg_shift == HASH_CR_ALGO_POS) 30062306a36Sopenharmony_ci reg |= ((alg & BIT(1)) << 17) | 30162306a36Sopenharmony_ci ((alg & BIT(0)) << HASH_CR_ALGO_POS); 30262306a36Sopenharmony_ci else 30362306a36Sopenharmony_ci reg |= alg << hdev->pdata->alg_shift; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_HMAC) { 30962306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_HMAC; 31062306a36Sopenharmony_ci reg |= HASH_CR_MODE; 31162306a36Sopenharmony_ci if (ctx->keylen > crypto_ahash_blocksize(tfm)) 31262306a36Sopenharmony_ci reg |= HASH_CR_LKEY; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (!hdev->polled) 31662306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CR, reg); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_INIT; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* 32362306a36Sopenharmony_ci * After first block + 1 words are fill up, 32462306a36Sopenharmony_ci * we only need to fill 1 block to start partial computation 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_ci rctx->state.blocklen -= sizeof(u32); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci dev_dbg(hdev->dev, "Write Control %x\n", reg); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 33562306a36Sopenharmony_ci size_t count; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci while ((state->bufcnt < state->blocklen) && rctx->total) { 33862306a36Sopenharmony_ci count = min(rctx->sg->length - rctx->offset, rctx->total); 33962306a36Sopenharmony_ci count = min_t(size_t, count, state->blocklen - state->bufcnt); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (count <= 0) { 34262306a36Sopenharmony_ci if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) { 34362306a36Sopenharmony_ci rctx->sg = sg_next(rctx->sg); 34462306a36Sopenharmony_ci continue; 34562306a36Sopenharmony_ci } else { 34662306a36Sopenharmony_ci break; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci scatterwalk_map_and_copy(state->buffer + state->bufcnt, 35162306a36Sopenharmony_ci rctx->sg, rctx->offset, count, 0); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci state->bufcnt += count; 35462306a36Sopenharmony_ci rctx->offset += count; 35562306a36Sopenharmony_ci rctx->total -= count; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (rctx->offset == rctx->sg->length) { 35862306a36Sopenharmony_ci rctx->sg = sg_next(rctx->sg); 35962306a36Sopenharmony_ci if (rctx->sg) 36062306a36Sopenharmony_ci rctx->offset = 0; 36162306a36Sopenharmony_ci else 36262306a36Sopenharmony_ci rctx->total = 0; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, 36862306a36Sopenharmony_ci const u8 *buf, size_t length, int final) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 37162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 37262306a36Sopenharmony_ci unsigned int count, len32; 37362306a36Sopenharmony_ci const u32 *buffer = (const u32 *)buf; 37462306a36Sopenharmony_ci u32 reg; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (final) { 37762306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_FINAL; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* Do not process empty messages if hw is buggy. */ 38062306a36Sopenharmony_ci if (!(hdev->flags & HASH_FLAGS_INIT) && !length && 38162306a36Sopenharmony_ci hdev->pdata->broken_emptymsg) { 38262306a36Sopenharmony_ci state->flags |= HASH_FLAGS_EMPTY; 38362306a36Sopenharmony_ci return 0; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci len32 = DIV_ROUND_UP(length, sizeof(u32)); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci dev_dbg(hdev->dev, "%s: length: %zd, final: %x len32 %i\n", 39062306a36Sopenharmony_ci __func__, length, final, len32); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_CPU; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci stm32_hash_write_ctrl(hdev); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 39762306a36Sopenharmony_ci return -ETIMEDOUT; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if ((hdev->flags & HASH_FLAGS_HMAC) && 40062306a36Sopenharmony_ci (!(hdev->flags & HASH_FLAGS_HMAC_KEY))) { 40162306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_HMAC_KEY; 40262306a36Sopenharmony_ci stm32_hash_write_key(hdev); 40362306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 40462306a36Sopenharmony_ci return -ETIMEDOUT; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci for (count = 0; count < len32; count++) 40862306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_DIN, buffer[count]); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (final) { 41162306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 41262306a36Sopenharmony_ci return -ETIMEDOUT; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci stm32_hash_set_nblw(hdev, length); 41562306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_STR); 41662306a36Sopenharmony_ci reg |= HASH_STR_DCAL; 41762306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_STR, reg); 41862306a36Sopenharmony_ci if (hdev->flags & HASH_FLAGS_HMAC) { 41962306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 42062306a36Sopenharmony_ci return -ETIMEDOUT; 42162306a36Sopenharmony_ci stm32_hash_write_key(hdev); 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci return -EINPROGRESS; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return 0; 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic int hash_swap_reg(struct stm32_hash_request_ctx *rctx) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci switch ((state->flags & HASH_FLAGS_ALGO_MASK) >> 43462306a36Sopenharmony_ci HASH_FLAGS_ALGO_SHIFT) { 43562306a36Sopenharmony_ci case HASH_MD5: 43662306a36Sopenharmony_ci case HASH_SHA1: 43762306a36Sopenharmony_ci case HASH_SHA224: 43862306a36Sopenharmony_ci case HASH_SHA256: 43962306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_HMAC) 44062306a36Sopenharmony_ci return HASH_CSR_NB_SHA256_HMAC; 44162306a36Sopenharmony_ci else 44262306a36Sopenharmony_ci return HASH_CSR_NB_SHA256; 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci case HASH_SHA384: 44662306a36Sopenharmony_ci case HASH_SHA512: 44762306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_HMAC) 44862306a36Sopenharmony_ci return HASH_CSR_NB_SHA512_HMAC; 44962306a36Sopenharmony_ci else 45062306a36Sopenharmony_ci return HASH_CSR_NB_SHA512; 45162306a36Sopenharmony_ci break; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci case HASH_SHA3_224: 45462306a36Sopenharmony_ci case HASH_SHA3_256: 45562306a36Sopenharmony_ci case HASH_SHA3_384: 45662306a36Sopenharmony_ci case HASH_SHA3_512: 45762306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_HMAC) 45862306a36Sopenharmony_ci return HASH_CSR_NB_SHA3_HMAC; 45962306a36Sopenharmony_ci else 46062306a36Sopenharmony_ci return HASH_CSR_NB_SHA3; 46162306a36Sopenharmony_ci break; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci default: 46462306a36Sopenharmony_ci return -EINVAL; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cistatic int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 47162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 47262306a36Sopenharmony_ci u32 *preg = state->hw_context; 47362306a36Sopenharmony_ci int bufcnt, err = 0, final; 47462306a36Sopenharmony_ci int i, swap_reg; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci dev_dbg(hdev->dev, "%s flags %x\n", __func__, state->flags); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci final = state->flags & HASH_FLAGS_FINAL; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci while ((rctx->total >= state->blocklen) || 48162306a36Sopenharmony_ci (state->bufcnt + rctx->total >= state->blocklen)) { 48262306a36Sopenharmony_ci stm32_hash_append_sg(rctx); 48362306a36Sopenharmony_ci bufcnt = state->bufcnt; 48462306a36Sopenharmony_ci state->bufcnt = 0; 48562306a36Sopenharmony_ci err = stm32_hash_xmit_cpu(hdev, state->buffer, bufcnt, 0); 48662306a36Sopenharmony_ci if (err) 48762306a36Sopenharmony_ci return err; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci stm32_hash_append_sg(rctx); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (final) { 49362306a36Sopenharmony_ci bufcnt = state->bufcnt; 49462306a36Sopenharmony_ci state->bufcnt = 0; 49562306a36Sopenharmony_ci return stm32_hash_xmit_cpu(hdev, state->buffer, bufcnt, 1); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (!(hdev->flags & HASH_FLAGS_INIT)) 49962306a36Sopenharmony_ci return 0; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 50262306a36Sopenharmony_ci return -ETIMEDOUT; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci swap_reg = hash_swap_reg(rctx); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (!hdev->pdata->ux500) 50762306a36Sopenharmony_ci *preg++ = stm32_hash_read(hdev, HASH_IMR); 50862306a36Sopenharmony_ci *preg++ = stm32_hash_read(hdev, HASH_STR); 50962306a36Sopenharmony_ci *preg++ = stm32_hash_read(hdev, HASH_CR); 51062306a36Sopenharmony_ci for (i = 0; i < swap_reg; i++) 51162306a36Sopenharmony_ci *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci state->flags |= HASH_FLAGS_INIT; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return err; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev, 51962306a36Sopenharmony_ci struct scatterlist *sg, int length, int mdma) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct dma_async_tx_descriptor *in_desc; 52262306a36Sopenharmony_ci dma_cookie_t cookie; 52362306a36Sopenharmony_ci u32 reg; 52462306a36Sopenharmony_ci int err; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci in_desc = dmaengine_prep_slave_sg(hdev->dma_lch, sg, 1, 52762306a36Sopenharmony_ci DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | 52862306a36Sopenharmony_ci DMA_CTRL_ACK); 52962306a36Sopenharmony_ci if (!in_desc) { 53062306a36Sopenharmony_ci dev_err(hdev->dev, "dmaengine_prep_slave error\n"); 53162306a36Sopenharmony_ci return -ENOMEM; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci reinit_completion(&hdev->dma_completion); 53562306a36Sopenharmony_ci in_desc->callback = stm32_hash_dma_callback; 53662306a36Sopenharmony_ci in_desc->callback_param = hdev; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_FINAL; 53962306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_DMA_ACTIVE; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_CR); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (hdev->pdata->has_mdmat) { 54462306a36Sopenharmony_ci if (mdma) 54562306a36Sopenharmony_ci reg |= HASH_CR_MDMAT; 54662306a36Sopenharmony_ci else 54762306a36Sopenharmony_ci reg &= ~HASH_CR_MDMAT; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci reg |= HASH_CR_DMAE; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CR, reg); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci stm32_hash_set_nblw(hdev, length); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci cookie = dmaengine_submit(in_desc); 55662306a36Sopenharmony_ci err = dma_submit_error(cookie); 55762306a36Sopenharmony_ci if (err) 55862306a36Sopenharmony_ci return -ENOMEM; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci dma_async_issue_pending(hdev->dma_lch); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (!wait_for_completion_timeout(&hdev->dma_completion, 56362306a36Sopenharmony_ci msecs_to_jiffies(100))) 56462306a36Sopenharmony_ci err = -ETIMEDOUT; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (dma_async_is_tx_complete(hdev->dma_lch, cookie, 56762306a36Sopenharmony_ci NULL, NULL) != DMA_COMPLETE) 56862306a36Sopenharmony_ci err = -ETIMEDOUT; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci if (err) { 57162306a36Sopenharmony_ci dev_err(hdev->dev, "DMA Error %i\n", err); 57262306a36Sopenharmony_ci dmaengine_terminate_all(hdev->dma_lch); 57362306a36Sopenharmony_ci return err; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci return -EINPROGRESS; 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic void stm32_hash_dma_callback(void *param) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci struct stm32_hash_dev *hdev = param; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci complete(&hdev->dma_completion); 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 58962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); 59062306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); 59162306a36Sopenharmony_ci int err; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (ctx->keylen < rctx->state.blocklen || hdev->dma_mode == 1) { 59462306a36Sopenharmony_ci err = stm32_hash_write_key(hdev); 59562306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 59662306a36Sopenharmony_ci return -ETIMEDOUT; 59762306a36Sopenharmony_ci } else { 59862306a36Sopenharmony_ci if (!(hdev->flags & HASH_FLAGS_HMAC_KEY)) 59962306a36Sopenharmony_ci sg_init_one(&rctx->sg_key, ctx->key, 60062306a36Sopenharmony_ci ALIGN(ctx->keylen, sizeof(u32))); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci rctx->dma_ct = dma_map_sg(hdev->dev, &rctx->sg_key, 1, 60362306a36Sopenharmony_ci DMA_TO_DEVICE); 60462306a36Sopenharmony_ci if (rctx->dma_ct == 0) { 60562306a36Sopenharmony_ci dev_err(hdev->dev, "dma_map_sg error\n"); 60662306a36Sopenharmony_ci return -ENOMEM; 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci err = stm32_hash_xmit_dma(hdev, &rctx->sg_key, ctx->keylen, 0); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci dma_unmap_sg(hdev->dev, &rctx->sg_key, 1, DMA_TO_DEVICE); 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return err; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic int stm32_hash_dma_init(struct stm32_hash_dev *hdev) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci struct dma_slave_config dma_conf; 62062306a36Sopenharmony_ci struct dma_chan *chan; 62162306a36Sopenharmony_ci int err; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci memset(&dma_conf, 0, sizeof(dma_conf)); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci dma_conf.direction = DMA_MEM_TO_DEV; 62662306a36Sopenharmony_ci dma_conf.dst_addr = hdev->phys_base + HASH_DIN; 62762306a36Sopenharmony_ci dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 62862306a36Sopenharmony_ci dma_conf.src_maxburst = HASH_BURST_LEVEL; 62962306a36Sopenharmony_ci dma_conf.dst_maxburst = HASH_BURST_LEVEL; 63062306a36Sopenharmony_ci dma_conf.device_fc = false; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci chan = dma_request_chan(hdev->dev, "in"); 63362306a36Sopenharmony_ci if (IS_ERR(chan)) 63462306a36Sopenharmony_ci return PTR_ERR(chan); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci hdev->dma_lch = chan; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci err = dmaengine_slave_config(hdev->dma_lch, &dma_conf); 63962306a36Sopenharmony_ci if (err) { 64062306a36Sopenharmony_ci dma_release_channel(hdev->dma_lch); 64162306a36Sopenharmony_ci hdev->dma_lch = NULL; 64262306a36Sopenharmony_ci dev_err(hdev->dev, "Couldn't configure DMA slave.\n"); 64362306a36Sopenharmony_ci return err; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci init_completion(&hdev->dma_completion); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci return 0; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic int stm32_hash_dma_send(struct stm32_hash_dev *hdev) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 65462306a36Sopenharmony_ci u32 *buffer = (void *)rctx->state.buffer; 65562306a36Sopenharmony_ci struct scatterlist sg[1], *tsg; 65662306a36Sopenharmony_ci int err = 0, reg, ncp = 0; 65762306a36Sopenharmony_ci unsigned int i, len = 0, bufcnt = 0; 65862306a36Sopenharmony_ci bool is_last = false; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci rctx->sg = hdev->req->src; 66162306a36Sopenharmony_ci rctx->total = hdev->req->nbytes; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci rctx->nents = sg_nents(rctx->sg); 66462306a36Sopenharmony_ci if (rctx->nents < 0) 66562306a36Sopenharmony_ci return -EINVAL; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci stm32_hash_write_ctrl(hdev); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci if (hdev->flags & HASH_FLAGS_HMAC) { 67062306a36Sopenharmony_ci err = stm32_hash_hmac_dma_send(hdev); 67162306a36Sopenharmony_ci if (err != -EINPROGRESS) 67262306a36Sopenharmony_ci return err; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci for_each_sg(rctx->sg, tsg, rctx->nents, i) { 67662306a36Sopenharmony_ci sg[0] = *tsg; 67762306a36Sopenharmony_ci len = sg->length; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci if (sg_is_last(sg) || (bufcnt + sg[0].length) >= rctx->total) { 68062306a36Sopenharmony_ci sg->length = rctx->total - bufcnt; 68162306a36Sopenharmony_ci is_last = true; 68262306a36Sopenharmony_ci if (hdev->dma_mode == 1) { 68362306a36Sopenharmony_ci len = (ALIGN(sg->length, 16) - 16); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci ncp = sg_pcopy_to_buffer( 68662306a36Sopenharmony_ci rctx->sg, rctx->nents, 68762306a36Sopenharmony_ci rctx->state.buffer, sg->length - len, 68862306a36Sopenharmony_ci rctx->total - sg->length + len); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci sg->length = len; 69162306a36Sopenharmony_ci } else { 69262306a36Sopenharmony_ci if (!(IS_ALIGNED(sg->length, sizeof(u32)))) { 69362306a36Sopenharmony_ci len = sg->length; 69462306a36Sopenharmony_ci sg->length = ALIGN(sg->length, 69562306a36Sopenharmony_ci sizeof(u32)); 69662306a36Sopenharmony_ci } 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci rctx->dma_ct = dma_map_sg(hdev->dev, sg, 1, 70162306a36Sopenharmony_ci DMA_TO_DEVICE); 70262306a36Sopenharmony_ci if (rctx->dma_ct == 0) { 70362306a36Sopenharmony_ci dev_err(hdev->dev, "dma_map_sg error\n"); 70462306a36Sopenharmony_ci return -ENOMEM; 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci err = stm32_hash_xmit_dma(hdev, sg, len, !is_last); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci bufcnt += sg[0].length; 71062306a36Sopenharmony_ci dma_unmap_sg(hdev->dev, sg, 1, DMA_TO_DEVICE); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci if (err == -ENOMEM) 71362306a36Sopenharmony_ci return err; 71462306a36Sopenharmony_ci if (is_last) 71562306a36Sopenharmony_ci break; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci if (hdev->dma_mode == 1) { 71962306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 72062306a36Sopenharmony_ci return -ETIMEDOUT; 72162306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_CR); 72262306a36Sopenharmony_ci reg &= ~HASH_CR_DMAE; 72362306a36Sopenharmony_ci reg |= HASH_CR_DMAA; 72462306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CR, reg); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (ncp) { 72762306a36Sopenharmony_ci memset(buffer + ncp, 0, 72862306a36Sopenharmony_ci DIV_ROUND_UP(ncp, sizeof(u32)) - ncp); 72962306a36Sopenharmony_ci writesl(hdev->io_base + HASH_DIN, buffer, 73062306a36Sopenharmony_ci DIV_ROUND_UP(ncp, sizeof(u32))); 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci stm32_hash_set_nblw(hdev, ncp); 73362306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_STR); 73462306a36Sopenharmony_ci reg |= HASH_STR_DCAL; 73562306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_STR, reg); 73662306a36Sopenharmony_ci err = -EINPROGRESS; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (hdev->flags & HASH_FLAGS_HMAC) { 74062306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 74162306a36Sopenharmony_ci return -ETIMEDOUT; 74262306a36Sopenharmony_ci err = stm32_hash_hmac_dma_send(hdev); 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci return err; 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct stm32_hash_dev *hdev = NULL, *tmp; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci spin_lock_bh(&stm32_hash.lock); 75362306a36Sopenharmony_ci if (!ctx->hdev) { 75462306a36Sopenharmony_ci list_for_each_entry(tmp, &stm32_hash.dev_list, list) { 75562306a36Sopenharmony_ci hdev = tmp; 75662306a36Sopenharmony_ci break; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci ctx->hdev = hdev; 75962306a36Sopenharmony_ci } else { 76062306a36Sopenharmony_ci hdev = ctx->hdev; 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci spin_unlock_bh(&stm32_hash.lock); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci return hdev; 76662306a36Sopenharmony_ci} 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_cistatic bool stm32_hash_dma_aligned_data(struct ahash_request *req) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci struct scatterlist *sg; 77162306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 77262306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 77362306a36Sopenharmony_ci struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); 77462306a36Sopenharmony_ci int i; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci if (!hdev->dma_lch || req->nbytes <= rctx->state.blocklen) 77762306a36Sopenharmony_ci return false; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci if (sg_nents(req->src) > 1) { 78062306a36Sopenharmony_ci if (hdev->dma_mode == 1) 78162306a36Sopenharmony_ci return false; 78262306a36Sopenharmony_ci for_each_sg(req->src, sg, sg_nents(req->src), i) { 78362306a36Sopenharmony_ci if ((!IS_ALIGNED(sg->length, sizeof(u32))) && 78462306a36Sopenharmony_ci (!sg_is_last(sg))) 78562306a36Sopenharmony_ci return false; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (req->src->offset % 4) 79062306a36Sopenharmony_ci return false; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci return true; 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_cistatic int stm32_hash_init(struct ahash_request *req) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 79862306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); 79962306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 80062306a36Sopenharmony_ci struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); 80162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 80262306a36Sopenharmony_ci bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci rctx->hdev = hdev; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci state->flags = HASH_FLAGS_CPU; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci if (sha3_mode) 80962306a36Sopenharmony_ci state->flags |= HASH_FLAGS_SHA3_MODE; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci rctx->digcnt = crypto_ahash_digestsize(tfm); 81262306a36Sopenharmony_ci switch (rctx->digcnt) { 81362306a36Sopenharmony_ci case MD5_DIGEST_SIZE: 81462306a36Sopenharmony_ci state->flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT; 81562306a36Sopenharmony_ci break; 81662306a36Sopenharmony_ci case SHA1_DIGEST_SIZE: 81762306a36Sopenharmony_ci if (hdev->pdata->ux500) 81862306a36Sopenharmony_ci state->flags |= HASH_SHA1_UX500 << HASH_FLAGS_ALGO_SHIFT; 81962306a36Sopenharmony_ci else 82062306a36Sopenharmony_ci state->flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT; 82162306a36Sopenharmony_ci break; 82262306a36Sopenharmony_ci case SHA224_DIGEST_SIZE: 82362306a36Sopenharmony_ci if (sha3_mode) 82462306a36Sopenharmony_ci state->flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT; 82562306a36Sopenharmony_ci else 82662306a36Sopenharmony_ci state->flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT; 82762306a36Sopenharmony_ci break; 82862306a36Sopenharmony_ci case SHA256_DIGEST_SIZE: 82962306a36Sopenharmony_ci if (sha3_mode) { 83062306a36Sopenharmony_ci state->flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT; 83162306a36Sopenharmony_ci } else { 83262306a36Sopenharmony_ci if (hdev->pdata->ux500) 83362306a36Sopenharmony_ci state->flags |= HASH_SHA256_UX500 << HASH_FLAGS_ALGO_SHIFT; 83462306a36Sopenharmony_ci else 83562306a36Sopenharmony_ci state->flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci break; 83862306a36Sopenharmony_ci case SHA384_DIGEST_SIZE: 83962306a36Sopenharmony_ci if (sha3_mode) 84062306a36Sopenharmony_ci state->flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT; 84162306a36Sopenharmony_ci else 84262306a36Sopenharmony_ci state->flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT; 84362306a36Sopenharmony_ci break; 84462306a36Sopenharmony_ci case SHA512_DIGEST_SIZE: 84562306a36Sopenharmony_ci if (sha3_mode) 84662306a36Sopenharmony_ci state->flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT; 84762306a36Sopenharmony_ci else 84862306a36Sopenharmony_ci state->flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT; 84962306a36Sopenharmony_ci break; 85062306a36Sopenharmony_ci default: 85162306a36Sopenharmony_ci return -EINVAL; 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci rctx->state.bufcnt = 0; 85562306a36Sopenharmony_ci rctx->state.blocklen = crypto_ahash_blocksize(tfm) + sizeof(u32); 85662306a36Sopenharmony_ci if (rctx->state.blocklen > HASH_BUFLEN) { 85762306a36Sopenharmony_ci dev_err(hdev->dev, "Error, block too large"); 85862306a36Sopenharmony_ci return -EINVAL; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci rctx->total = 0; 86162306a36Sopenharmony_ci rctx->offset = 0; 86262306a36Sopenharmony_ci rctx->data_type = HASH_DATA_8_BITS; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci if (ctx->flags & HASH_FLAGS_HMAC) 86562306a36Sopenharmony_ci state->flags |= HASH_FLAGS_HMAC; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci dev_dbg(hdev->dev, "%s Flags %x\n", __func__, state->flags); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci return 0; 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int stm32_hash_update_req(struct stm32_hash_dev *hdev) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); 87562306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if (!(state->flags & HASH_FLAGS_CPU)) 87862306a36Sopenharmony_ci return stm32_hash_dma_send(hdev); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci return stm32_hash_update_cpu(hdev); 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic int stm32_hash_final_req(struct stm32_hash_dev *hdev) 88462306a36Sopenharmony_ci{ 88562306a36Sopenharmony_ci struct ahash_request *req = hdev->req; 88662306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 88762306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 88862306a36Sopenharmony_ci int buflen = state->bufcnt; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_FINUP) 89162306a36Sopenharmony_ci return stm32_hash_update_req(hdev); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci state->bufcnt = 0; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci return stm32_hash_xmit_cpu(hdev, state->buffer, buflen, 1); 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic void stm32_hash_emptymsg_fallback(struct ahash_request *req) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 90162306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(ahash); 90262306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 90362306a36Sopenharmony_ci struct stm32_hash_dev *hdev = rctx->hdev; 90462306a36Sopenharmony_ci int ret; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci dev_dbg(hdev->dev, "use fallback message size 0 key size %d\n", 90762306a36Sopenharmony_ci ctx->keylen); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (!ctx->xtfm) { 91062306a36Sopenharmony_ci dev_err(hdev->dev, "no fallback engine\n"); 91162306a36Sopenharmony_ci return; 91262306a36Sopenharmony_ci } 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci if (ctx->keylen) { 91562306a36Sopenharmony_ci ret = crypto_shash_setkey(ctx->xtfm, ctx->key, ctx->keylen); 91662306a36Sopenharmony_ci if (ret) { 91762306a36Sopenharmony_ci dev_err(hdev->dev, "failed to set key ret=%d\n", ret); 91862306a36Sopenharmony_ci return; 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci ret = crypto_shash_tfm_digest(ctx->xtfm, NULL, 0, rctx->digest); 92362306a36Sopenharmony_ci if (ret) 92462306a36Sopenharmony_ci dev_err(hdev->dev, "shash digest error\n"); 92562306a36Sopenharmony_ci} 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_cistatic void stm32_hash_copy_hash(struct ahash_request *req) 92862306a36Sopenharmony_ci{ 92962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 93062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 93162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 93262306a36Sopenharmony_ci struct stm32_hash_dev *hdev = rctx->hdev; 93362306a36Sopenharmony_ci __be32 *hash = (void *)rctx->digest; 93462306a36Sopenharmony_ci unsigned int i, hashsize; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (hdev->pdata->broken_emptymsg && (state->flags & HASH_FLAGS_EMPTY)) 93762306a36Sopenharmony_ci return stm32_hash_emptymsg_fallback(req); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci hashsize = crypto_ahash_digestsize(tfm); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci for (i = 0; i < hashsize / sizeof(u32); i++) { 94262306a36Sopenharmony_ci if (hdev->pdata->ux500) 94362306a36Sopenharmony_ci hash[i] = cpu_to_be32(stm32_hash_read(hdev, 94462306a36Sopenharmony_ci HASH_UX500_HREG(i))); 94562306a36Sopenharmony_ci else 94662306a36Sopenharmony_ci hash[i] = cpu_to_be32(stm32_hash_read(hdev, 94762306a36Sopenharmony_ci HASH_HREG(i))); 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic int stm32_hash_finish(struct ahash_request *req) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 95462306a36Sopenharmony_ci u32 reg; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci reg = stm32_hash_read(rctx->hdev, HASH_SR); 95762306a36Sopenharmony_ci reg &= ~HASH_SR_OUTPUT_READY; 95862306a36Sopenharmony_ci stm32_hash_write(rctx->hdev, HASH_SR, reg); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (!req->result) 96162306a36Sopenharmony_ci return -EINVAL; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci memcpy(req->result, rctx->digest, rctx->digcnt); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci return 0; 96662306a36Sopenharmony_ci} 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_cistatic void stm32_hash_finish_req(struct ahash_request *req, int err) 96962306a36Sopenharmony_ci{ 97062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 97162306a36Sopenharmony_ci struct stm32_hash_dev *hdev = rctx->hdev; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (!err && (HASH_FLAGS_FINAL & hdev->flags)) { 97462306a36Sopenharmony_ci stm32_hash_copy_hash(req); 97562306a36Sopenharmony_ci err = stm32_hash_finish(req); 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci pm_runtime_mark_last_busy(hdev->dev); 97962306a36Sopenharmony_ci pm_runtime_put_autosuspend(hdev->dev); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci crypto_finalize_hash_request(hdev->engine, req, err); 98262306a36Sopenharmony_ci} 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_cistatic int stm32_hash_handle_queue(struct stm32_hash_dev *hdev, 98562306a36Sopenharmony_ci struct ahash_request *req) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci return crypto_transfer_hash_request_to_engine(hdev->engine, req); 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_cistatic int stm32_hash_one_request(struct crypto_engine *engine, void *areq) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci struct ahash_request *req = container_of(areq, struct ahash_request, 99362306a36Sopenharmony_ci base); 99462306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 99562306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 99662306a36Sopenharmony_ci struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); 99762306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 99862306a36Sopenharmony_ci int swap_reg; 99962306a36Sopenharmony_ci int err = 0; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci if (!hdev) 100262306a36Sopenharmony_ci return -ENODEV; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci dev_dbg(hdev->dev, "processing new req, op: %lu, nbytes %d\n", 100562306a36Sopenharmony_ci rctx->op, req->nbytes); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci pm_runtime_get_sync(hdev->dev); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci hdev->req = req; 101062306a36Sopenharmony_ci hdev->flags = 0; 101162306a36Sopenharmony_ci swap_reg = hash_swap_reg(rctx); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_INIT) { 101462306a36Sopenharmony_ci u32 *preg = rctx->state.hw_context; 101562306a36Sopenharmony_ci u32 reg; 101662306a36Sopenharmony_ci int i; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci if (!hdev->pdata->ux500) 101962306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_IMR, *preg++); 102062306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_STR, *preg++); 102162306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CR, *preg); 102262306a36Sopenharmony_ci reg = *preg++ | HASH_CR_INIT; 102362306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CR, reg); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci for (i = 0; i < swap_reg; i++) 102662306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_CSR(i), *preg++); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_INIT; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (state->flags & HASH_FLAGS_HMAC) 103162306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_HMAC | 103262306a36Sopenharmony_ci HASH_FLAGS_HMAC_KEY; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci if (rctx->op == HASH_OP_UPDATE) 103662306a36Sopenharmony_ci err = stm32_hash_update_req(hdev); 103762306a36Sopenharmony_ci else if (rctx->op == HASH_OP_FINAL) 103862306a36Sopenharmony_ci err = stm32_hash_final_req(hdev); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci /* If we have an IRQ, wait for that, else poll for completion */ 104162306a36Sopenharmony_ci if (err == -EINPROGRESS && hdev->polled) { 104262306a36Sopenharmony_ci if (stm32_hash_wait_busy(hdev)) 104362306a36Sopenharmony_ci err = -ETIMEDOUT; 104462306a36Sopenharmony_ci else { 104562306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_OUTPUT_READY; 104662306a36Sopenharmony_ci err = 0; 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci } 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if (err != -EINPROGRESS) 105162306a36Sopenharmony_ci /* done task will not finish it, so do it here */ 105262306a36Sopenharmony_ci stm32_hash_finish_req(req, err); 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci return 0; 105562306a36Sopenharmony_ci} 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_cistatic int stm32_hash_enqueue(struct ahash_request *req, unsigned int op) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 106062306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 106162306a36Sopenharmony_ci struct stm32_hash_dev *hdev = ctx->hdev; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci rctx->op = op; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci return stm32_hash_handle_queue(hdev, req); 106662306a36Sopenharmony_ci} 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_cistatic int stm32_hash_update(struct ahash_request *req) 106962306a36Sopenharmony_ci{ 107062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 107162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci if (!req->nbytes || !(state->flags & HASH_FLAGS_CPU)) 107462306a36Sopenharmony_ci return 0; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci rctx->total = req->nbytes; 107762306a36Sopenharmony_ci rctx->sg = req->src; 107862306a36Sopenharmony_ci rctx->offset = 0; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci if ((state->bufcnt + rctx->total < state->blocklen)) { 108162306a36Sopenharmony_ci stm32_hash_append_sg(rctx); 108262306a36Sopenharmony_ci return 0; 108362306a36Sopenharmony_ci } 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci return stm32_hash_enqueue(req, HASH_OP_UPDATE); 108662306a36Sopenharmony_ci} 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_cistatic int stm32_hash_final(struct ahash_request *req) 108962306a36Sopenharmony_ci{ 109062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 109162306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci state->flags |= HASH_FLAGS_FINAL; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci return stm32_hash_enqueue(req, HASH_OP_FINAL); 109662306a36Sopenharmony_ci} 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic int stm32_hash_finup(struct ahash_request *req) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 110162306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 110262306a36Sopenharmony_ci struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); 110362306a36Sopenharmony_ci struct stm32_hash_state *state = &rctx->state; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci if (!req->nbytes) 110662306a36Sopenharmony_ci goto out; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci state->flags |= HASH_FLAGS_FINUP; 110962306a36Sopenharmony_ci rctx->total = req->nbytes; 111062306a36Sopenharmony_ci rctx->sg = req->src; 111162306a36Sopenharmony_ci rctx->offset = 0; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci if (hdev->dma_lch && stm32_hash_dma_aligned_data(req)) 111462306a36Sopenharmony_ci state->flags &= ~HASH_FLAGS_CPU; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ciout: 111762306a36Sopenharmony_ci return stm32_hash_final(req); 111862306a36Sopenharmony_ci} 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_cistatic int stm32_hash_digest(struct ahash_request *req) 112162306a36Sopenharmony_ci{ 112262306a36Sopenharmony_ci return stm32_hash_init(req) ?: stm32_hash_finup(req); 112362306a36Sopenharmony_ci} 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_cistatic int stm32_hash_export(struct ahash_request *req, void *out) 112662306a36Sopenharmony_ci{ 112762306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci memcpy(out, &rctx->state, sizeof(rctx->state)); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci return 0; 113262306a36Sopenharmony_ci} 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_cistatic int stm32_hash_import(struct ahash_request *req, const void *in) 113562306a36Sopenharmony_ci{ 113662306a36Sopenharmony_ci struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci stm32_hash_init(req); 113962306a36Sopenharmony_ci memcpy(&rctx->state, in, sizeof(rctx->state)); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return 0; 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_cistatic int stm32_hash_setkey(struct crypto_ahash *tfm, 114562306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 114662306a36Sopenharmony_ci{ 114762306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci if (keylen <= HASH_MAX_KEY_SIZE) { 115062306a36Sopenharmony_ci memcpy(ctx->key, key, keylen); 115162306a36Sopenharmony_ci ctx->keylen = keylen; 115262306a36Sopenharmony_ci } else { 115362306a36Sopenharmony_ci return -ENOMEM; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci return 0; 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_cistatic int stm32_hash_init_fallback(struct crypto_tfm *tfm) 116062306a36Sopenharmony_ci{ 116162306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); 116262306a36Sopenharmony_ci struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); 116362306a36Sopenharmony_ci const char *name = crypto_tfm_alg_name(tfm); 116462306a36Sopenharmony_ci struct crypto_shash *xtfm; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci /* The fallback is only needed on Ux500 */ 116762306a36Sopenharmony_ci if (!hdev->pdata->ux500) 116862306a36Sopenharmony_ci return 0; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci xtfm = crypto_alloc_shash(name, 0, CRYPTO_ALG_NEED_FALLBACK); 117162306a36Sopenharmony_ci if (IS_ERR(xtfm)) { 117262306a36Sopenharmony_ci dev_err(hdev->dev, "failed to allocate %s fallback\n", 117362306a36Sopenharmony_ci name); 117462306a36Sopenharmony_ci return PTR_ERR(xtfm); 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci dev_info(hdev->dev, "allocated %s fallback\n", name); 117762306a36Sopenharmony_ci ctx->xtfm = xtfm; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci return 0; 118062306a36Sopenharmony_ci} 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_cistatic int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 118762306a36Sopenharmony_ci sizeof(struct stm32_hash_request_ctx)); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci ctx->keylen = 0; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (algs_flags) 119262306a36Sopenharmony_ci ctx->flags |= algs_flags; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci return stm32_hash_init_fallback(tfm); 119562306a36Sopenharmony_ci} 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_cistatic int stm32_hash_cra_init(struct crypto_tfm *tfm) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci return stm32_hash_cra_init_algs(tfm, 0); 120062306a36Sopenharmony_ci} 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_cistatic int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm) 120362306a36Sopenharmony_ci{ 120462306a36Sopenharmony_ci return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC); 120562306a36Sopenharmony_ci} 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_cistatic int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE); 121062306a36Sopenharmony_ci} 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_cistatic int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm) 121362306a36Sopenharmony_ci{ 121462306a36Sopenharmony_ci return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE | 121562306a36Sopenharmony_ci HASH_FLAGS_HMAC); 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_cistatic void stm32_hash_cra_exit(struct crypto_tfm *tfm) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci if (ctx->xtfm) 122462306a36Sopenharmony_ci crypto_free_shash(ctx->xtfm); 122562306a36Sopenharmony_ci} 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_cistatic irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) 122862306a36Sopenharmony_ci{ 122962306a36Sopenharmony_ci struct stm32_hash_dev *hdev = dev_id; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci if (HASH_FLAGS_CPU & hdev->flags) { 123262306a36Sopenharmony_ci if (HASH_FLAGS_OUTPUT_READY & hdev->flags) { 123362306a36Sopenharmony_ci hdev->flags &= ~HASH_FLAGS_OUTPUT_READY; 123462306a36Sopenharmony_ci goto finish; 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci } else if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) { 123762306a36Sopenharmony_ci hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE; 123862306a36Sopenharmony_ci goto finish; 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci return IRQ_HANDLED; 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_cifinish: 124462306a36Sopenharmony_ci /* Finish current request */ 124562306a36Sopenharmony_ci stm32_hash_finish_req(hdev->req, 0); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci return IRQ_HANDLED; 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_cistatic irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) 125162306a36Sopenharmony_ci{ 125262306a36Sopenharmony_ci struct stm32_hash_dev *hdev = dev_id; 125362306a36Sopenharmony_ci u32 reg; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci reg = stm32_hash_read(hdev, HASH_SR); 125662306a36Sopenharmony_ci if (reg & HASH_SR_OUTPUT_READY) { 125762306a36Sopenharmony_ci hdev->flags |= HASH_FLAGS_OUTPUT_READY; 125862306a36Sopenharmony_ci /* Disable IT*/ 125962306a36Sopenharmony_ci stm32_hash_write(hdev, HASH_IMR, 0); 126062306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci return IRQ_NONE; 126462306a36Sopenharmony_ci} 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_cistatic struct ahash_engine_alg algs_md5[] = { 126762306a36Sopenharmony_ci { 126862306a36Sopenharmony_ci .base.init = stm32_hash_init, 126962306a36Sopenharmony_ci .base.update = stm32_hash_update, 127062306a36Sopenharmony_ci .base.final = stm32_hash_final, 127162306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 127262306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 127362306a36Sopenharmony_ci .base.export = stm32_hash_export, 127462306a36Sopenharmony_ci .base.import = stm32_hash_import, 127562306a36Sopenharmony_ci .base.halg = { 127662306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 127762306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 127862306a36Sopenharmony_ci .base = { 127962306a36Sopenharmony_ci .cra_name = "md5", 128062306a36Sopenharmony_ci .cra_driver_name = "stm32-md5", 128162306a36Sopenharmony_ci .cra_priority = 200, 128262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 128362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 128462306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 128562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 128662306a36Sopenharmony_ci .cra_alignmask = 3, 128762306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 128862306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 128962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci }, 129262306a36Sopenharmony_ci .op = { 129362306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 129462306a36Sopenharmony_ci }, 129562306a36Sopenharmony_ci }, 129662306a36Sopenharmony_ci { 129762306a36Sopenharmony_ci .base.init = stm32_hash_init, 129862306a36Sopenharmony_ci .base.update = stm32_hash_update, 129962306a36Sopenharmony_ci .base.final = stm32_hash_final, 130062306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 130162306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 130262306a36Sopenharmony_ci .base.export = stm32_hash_export, 130362306a36Sopenharmony_ci .base.import = stm32_hash_import, 130462306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 130562306a36Sopenharmony_ci .base.halg = { 130662306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 130762306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 130862306a36Sopenharmony_ci .base = { 130962306a36Sopenharmony_ci .cra_name = "hmac(md5)", 131062306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-md5", 131162306a36Sopenharmony_ci .cra_priority = 200, 131262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 131362306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 131462306a36Sopenharmony_ci .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 131562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 131662306a36Sopenharmony_ci .cra_alignmask = 3, 131762306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 131862306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 131962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 132062306a36Sopenharmony_ci } 132162306a36Sopenharmony_ci }, 132262306a36Sopenharmony_ci .op = { 132362306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 132462306a36Sopenharmony_ci }, 132562306a36Sopenharmony_ci } 132662306a36Sopenharmony_ci}; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha1[] = { 132962306a36Sopenharmony_ci { 133062306a36Sopenharmony_ci .base.init = stm32_hash_init, 133162306a36Sopenharmony_ci .base.update = stm32_hash_update, 133262306a36Sopenharmony_ci .base.final = stm32_hash_final, 133362306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 133462306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 133562306a36Sopenharmony_ci .base.export = stm32_hash_export, 133662306a36Sopenharmony_ci .base.import = stm32_hash_import, 133762306a36Sopenharmony_ci .base.halg = { 133862306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 133962306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 134062306a36Sopenharmony_ci .base = { 134162306a36Sopenharmony_ci .cra_name = "sha1", 134262306a36Sopenharmony_ci .cra_driver_name = "stm32-sha1", 134362306a36Sopenharmony_ci .cra_priority = 200, 134462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 134562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 134662306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 134762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 134862306a36Sopenharmony_ci .cra_alignmask = 3, 134962306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 135062306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 135162306a36Sopenharmony_ci .cra_module = THIS_MODULE, 135262306a36Sopenharmony_ci } 135362306a36Sopenharmony_ci }, 135462306a36Sopenharmony_ci .op = { 135562306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 135662306a36Sopenharmony_ci }, 135762306a36Sopenharmony_ci }, 135862306a36Sopenharmony_ci { 135962306a36Sopenharmony_ci .base.init = stm32_hash_init, 136062306a36Sopenharmony_ci .base.update = stm32_hash_update, 136162306a36Sopenharmony_ci .base.final = stm32_hash_final, 136262306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 136362306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 136462306a36Sopenharmony_ci .base.export = stm32_hash_export, 136562306a36Sopenharmony_ci .base.import = stm32_hash_import, 136662306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 136762306a36Sopenharmony_ci .base.halg = { 136862306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 136962306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 137062306a36Sopenharmony_ci .base = { 137162306a36Sopenharmony_ci .cra_name = "hmac(sha1)", 137262306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha1", 137362306a36Sopenharmony_ci .cra_priority = 200, 137462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 137562306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 137662306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 137762306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 137862306a36Sopenharmony_ci .cra_alignmask = 3, 137962306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 138062306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 138162306a36Sopenharmony_ci .cra_module = THIS_MODULE, 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci }, 138462306a36Sopenharmony_ci .op = { 138562306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 138662306a36Sopenharmony_ci }, 138762306a36Sopenharmony_ci }, 138862306a36Sopenharmony_ci}; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha224[] = { 139162306a36Sopenharmony_ci { 139262306a36Sopenharmony_ci .base.init = stm32_hash_init, 139362306a36Sopenharmony_ci .base.update = stm32_hash_update, 139462306a36Sopenharmony_ci .base.final = stm32_hash_final, 139562306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 139662306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 139762306a36Sopenharmony_ci .base.export = stm32_hash_export, 139862306a36Sopenharmony_ci .base.import = stm32_hash_import, 139962306a36Sopenharmony_ci .base.halg = { 140062306a36Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 140162306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 140262306a36Sopenharmony_ci .base = { 140362306a36Sopenharmony_ci .cra_name = "sha224", 140462306a36Sopenharmony_ci .cra_driver_name = "stm32-sha224", 140562306a36Sopenharmony_ci .cra_priority = 200, 140662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 140762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 140862306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 140962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 141062306a36Sopenharmony_ci .cra_alignmask = 3, 141162306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 141262306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 141362306a36Sopenharmony_ci .cra_module = THIS_MODULE, 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci }, 141662306a36Sopenharmony_ci .op = { 141762306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 141862306a36Sopenharmony_ci }, 141962306a36Sopenharmony_ci }, 142062306a36Sopenharmony_ci { 142162306a36Sopenharmony_ci .base.init = stm32_hash_init, 142262306a36Sopenharmony_ci .base.update = stm32_hash_update, 142362306a36Sopenharmony_ci .base.final = stm32_hash_final, 142462306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 142562306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 142662306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 142762306a36Sopenharmony_ci .base.export = stm32_hash_export, 142862306a36Sopenharmony_ci .base.import = stm32_hash_import, 142962306a36Sopenharmony_ci .base.halg = { 143062306a36Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 143162306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 143262306a36Sopenharmony_ci .base = { 143362306a36Sopenharmony_ci .cra_name = "hmac(sha224)", 143462306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha224", 143562306a36Sopenharmony_ci .cra_priority = 200, 143662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 143762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 143862306a36Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 143962306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 144062306a36Sopenharmony_ci .cra_alignmask = 3, 144162306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 144262306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 144362306a36Sopenharmony_ci .cra_module = THIS_MODULE, 144462306a36Sopenharmony_ci } 144562306a36Sopenharmony_ci }, 144662306a36Sopenharmony_ci .op = { 144762306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 144862306a36Sopenharmony_ci }, 144962306a36Sopenharmony_ci }, 145062306a36Sopenharmony_ci}; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha256[] = { 145362306a36Sopenharmony_ci { 145462306a36Sopenharmony_ci .base.init = stm32_hash_init, 145562306a36Sopenharmony_ci .base.update = stm32_hash_update, 145662306a36Sopenharmony_ci .base.final = stm32_hash_final, 145762306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 145862306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 145962306a36Sopenharmony_ci .base.export = stm32_hash_export, 146062306a36Sopenharmony_ci .base.import = stm32_hash_import, 146162306a36Sopenharmony_ci .base.halg = { 146262306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 146362306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 146462306a36Sopenharmony_ci .base = { 146562306a36Sopenharmony_ci .cra_name = "sha256", 146662306a36Sopenharmony_ci .cra_driver_name = "stm32-sha256", 146762306a36Sopenharmony_ci .cra_priority = 200, 146862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 146962306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 147062306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 147162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 147262306a36Sopenharmony_ci .cra_alignmask = 3, 147362306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 147462306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 147562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 147662306a36Sopenharmony_ci } 147762306a36Sopenharmony_ci }, 147862306a36Sopenharmony_ci .op = { 147962306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 148062306a36Sopenharmony_ci }, 148162306a36Sopenharmony_ci }, 148262306a36Sopenharmony_ci { 148362306a36Sopenharmony_ci .base.init = stm32_hash_init, 148462306a36Sopenharmony_ci .base.update = stm32_hash_update, 148562306a36Sopenharmony_ci .base.final = stm32_hash_final, 148662306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 148762306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 148862306a36Sopenharmony_ci .base.export = stm32_hash_export, 148962306a36Sopenharmony_ci .base.import = stm32_hash_import, 149062306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 149162306a36Sopenharmony_ci .base.halg = { 149262306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 149362306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 149462306a36Sopenharmony_ci .base = { 149562306a36Sopenharmony_ci .cra_name = "hmac(sha256)", 149662306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha256", 149762306a36Sopenharmony_ci .cra_priority = 200, 149862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 149962306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 150062306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 150162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 150262306a36Sopenharmony_ci .cra_alignmask = 3, 150362306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 150462306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 150562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 150662306a36Sopenharmony_ci } 150762306a36Sopenharmony_ci }, 150862306a36Sopenharmony_ci .op = { 150962306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 151062306a36Sopenharmony_ci }, 151162306a36Sopenharmony_ci }, 151262306a36Sopenharmony_ci}; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha384_sha512[] = { 151562306a36Sopenharmony_ci { 151662306a36Sopenharmony_ci .base.init = stm32_hash_init, 151762306a36Sopenharmony_ci .base.update = stm32_hash_update, 151862306a36Sopenharmony_ci .base.final = stm32_hash_final, 151962306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 152062306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 152162306a36Sopenharmony_ci .base.export = stm32_hash_export, 152262306a36Sopenharmony_ci .base.import = stm32_hash_import, 152362306a36Sopenharmony_ci .base.halg = { 152462306a36Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 152562306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 152662306a36Sopenharmony_ci .base = { 152762306a36Sopenharmony_ci .cra_name = "sha384", 152862306a36Sopenharmony_ci .cra_driver_name = "stm32-sha384", 152962306a36Sopenharmony_ci .cra_priority = 200, 153062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 153162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 153262306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 153362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 153462306a36Sopenharmony_ci .cra_alignmask = 3, 153562306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 153662306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 153762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci }, 154062306a36Sopenharmony_ci .op = { 154162306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 154262306a36Sopenharmony_ci }, 154362306a36Sopenharmony_ci }, 154462306a36Sopenharmony_ci { 154562306a36Sopenharmony_ci .base.init = stm32_hash_init, 154662306a36Sopenharmony_ci .base.update = stm32_hash_update, 154762306a36Sopenharmony_ci .base.final = stm32_hash_final, 154862306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 154962306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 155062306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 155162306a36Sopenharmony_ci .base.export = stm32_hash_export, 155262306a36Sopenharmony_ci .base.import = stm32_hash_import, 155362306a36Sopenharmony_ci .base.halg = { 155462306a36Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 155562306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 155662306a36Sopenharmony_ci .base = { 155762306a36Sopenharmony_ci .cra_name = "hmac(sha384)", 155862306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha384", 155962306a36Sopenharmony_ci .cra_priority = 200, 156062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 156162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 156262306a36Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 156362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 156462306a36Sopenharmony_ci .cra_alignmask = 3, 156562306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 156662306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 156762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 156862306a36Sopenharmony_ci } 156962306a36Sopenharmony_ci }, 157062306a36Sopenharmony_ci .op = { 157162306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 157262306a36Sopenharmony_ci }, 157362306a36Sopenharmony_ci }, 157462306a36Sopenharmony_ci { 157562306a36Sopenharmony_ci .base.init = stm32_hash_init, 157662306a36Sopenharmony_ci .base.update = stm32_hash_update, 157762306a36Sopenharmony_ci .base.final = stm32_hash_final, 157862306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 157962306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 158062306a36Sopenharmony_ci .base.export = stm32_hash_export, 158162306a36Sopenharmony_ci .base.import = stm32_hash_import, 158262306a36Sopenharmony_ci .base.halg = { 158362306a36Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 158462306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 158562306a36Sopenharmony_ci .base = { 158662306a36Sopenharmony_ci .cra_name = "sha512", 158762306a36Sopenharmony_ci .cra_driver_name = "stm32-sha512", 158862306a36Sopenharmony_ci .cra_priority = 200, 158962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 159062306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 159162306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 159262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 159362306a36Sopenharmony_ci .cra_alignmask = 3, 159462306a36Sopenharmony_ci .cra_init = stm32_hash_cra_init, 159562306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 159662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci }, 159962306a36Sopenharmony_ci .op = { 160062306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 160162306a36Sopenharmony_ci }, 160262306a36Sopenharmony_ci }, 160362306a36Sopenharmony_ci { 160462306a36Sopenharmony_ci .base.init = stm32_hash_init, 160562306a36Sopenharmony_ci .base.update = stm32_hash_update, 160662306a36Sopenharmony_ci .base.final = stm32_hash_final, 160762306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 160862306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 160962306a36Sopenharmony_ci .base.export = stm32_hash_export, 161062306a36Sopenharmony_ci .base.import = stm32_hash_import, 161162306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 161262306a36Sopenharmony_ci .base.halg = { 161362306a36Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 161462306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 161562306a36Sopenharmony_ci .base = { 161662306a36Sopenharmony_ci .cra_name = "hmac(sha512)", 161762306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha512", 161862306a36Sopenharmony_ci .cra_priority = 200, 161962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 162062306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 162162306a36Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 162262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 162362306a36Sopenharmony_ci .cra_alignmask = 3, 162462306a36Sopenharmony_ci .cra_init = stm32_hash_cra_hmac_init, 162562306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 162662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 162762306a36Sopenharmony_ci } 162862306a36Sopenharmony_ci }, 162962306a36Sopenharmony_ci .op = { 163062306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 163162306a36Sopenharmony_ci }, 163262306a36Sopenharmony_ci }, 163362306a36Sopenharmony_ci}; 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha3[] = { 163662306a36Sopenharmony_ci { 163762306a36Sopenharmony_ci .base.init = stm32_hash_init, 163862306a36Sopenharmony_ci .base.update = stm32_hash_update, 163962306a36Sopenharmony_ci .base.final = stm32_hash_final, 164062306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 164162306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 164262306a36Sopenharmony_ci .base.export = stm32_hash_export, 164362306a36Sopenharmony_ci .base.import = stm32_hash_import, 164462306a36Sopenharmony_ci .base.halg = { 164562306a36Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 164662306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 164762306a36Sopenharmony_ci .base = { 164862306a36Sopenharmony_ci .cra_name = "sha3-224", 164962306a36Sopenharmony_ci .cra_driver_name = "stm32-sha3-224", 165062306a36Sopenharmony_ci .cra_priority = 200, 165162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 165262306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 165362306a36Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 165462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 165562306a36Sopenharmony_ci .cra_alignmask = 3, 165662306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_init, 165762306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 165862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci }, 166162306a36Sopenharmony_ci .op = { 166262306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 166362306a36Sopenharmony_ci }, 166462306a36Sopenharmony_ci }, 166562306a36Sopenharmony_ci { 166662306a36Sopenharmony_ci .base.init = stm32_hash_init, 166762306a36Sopenharmony_ci .base.update = stm32_hash_update, 166862306a36Sopenharmony_ci .base.final = stm32_hash_final, 166962306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 167062306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 167162306a36Sopenharmony_ci .base.export = stm32_hash_export, 167262306a36Sopenharmony_ci .base.import = stm32_hash_import, 167362306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 167462306a36Sopenharmony_ci .base.halg = { 167562306a36Sopenharmony_ci .digestsize = SHA3_224_DIGEST_SIZE, 167662306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 167762306a36Sopenharmony_ci .base = { 167862306a36Sopenharmony_ci .cra_name = "hmac(sha3-224)", 167962306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha3-224", 168062306a36Sopenharmony_ci .cra_priority = 200, 168162306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 168262306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 168362306a36Sopenharmony_ci .cra_blocksize = SHA3_224_BLOCK_SIZE, 168462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 168562306a36Sopenharmony_ci .cra_alignmask = 3, 168662306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_hmac_init, 168762306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 168862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 168962306a36Sopenharmony_ci } 169062306a36Sopenharmony_ci }, 169162306a36Sopenharmony_ci .op = { 169262306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 169362306a36Sopenharmony_ci }, 169462306a36Sopenharmony_ci }, 169562306a36Sopenharmony_ci { 169662306a36Sopenharmony_ci .base.init = stm32_hash_init, 169762306a36Sopenharmony_ci .base.update = stm32_hash_update, 169862306a36Sopenharmony_ci .base.final = stm32_hash_final, 169962306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 170062306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 170162306a36Sopenharmony_ci .base.export = stm32_hash_export, 170262306a36Sopenharmony_ci .base.import = stm32_hash_import, 170362306a36Sopenharmony_ci .base.halg = { 170462306a36Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 170562306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 170662306a36Sopenharmony_ci .base = { 170762306a36Sopenharmony_ci .cra_name = "sha3-256", 170862306a36Sopenharmony_ci .cra_driver_name = "stm32-sha3-256", 170962306a36Sopenharmony_ci .cra_priority = 200, 171062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 171162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 171262306a36Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 171362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 171462306a36Sopenharmony_ci .cra_alignmask = 3, 171562306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_init, 171662306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 171762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci }, 172062306a36Sopenharmony_ci .op = { 172162306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 172262306a36Sopenharmony_ci }, 172362306a36Sopenharmony_ci }, 172462306a36Sopenharmony_ci { 172562306a36Sopenharmony_ci .base.init = stm32_hash_init, 172662306a36Sopenharmony_ci .base.update = stm32_hash_update, 172762306a36Sopenharmony_ci .base.final = stm32_hash_final, 172862306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 172962306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 173062306a36Sopenharmony_ci .base.export = stm32_hash_export, 173162306a36Sopenharmony_ci .base.import = stm32_hash_import, 173262306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 173362306a36Sopenharmony_ci .base.halg = { 173462306a36Sopenharmony_ci .digestsize = SHA3_256_DIGEST_SIZE, 173562306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 173662306a36Sopenharmony_ci .base = { 173762306a36Sopenharmony_ci .cra_name = "hmac(sha3-256)", 173862306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha3-256", 173962306a36Sopenharmony_ci .cra_priority = 200, 174062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 174162306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 174262306a36Sopenharmony_ci .cra_blocksize = SHA3_256_BLOCK_SIZE, 174362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 174462306a36Sopenharmony_ci .cra_alignmask = 3, 174562306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_hmac_init, 174662306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 174762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci }, 175062306a36Sopenharmony_ci .op = { 175162306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 175262306a36Sopenharmony_ci }, 175362306a36Sopenharmony_ci }, 175462306a36Sopenharmony_ci { 175562306a36Sopenharmony_ci .base.init = stm32_hash_init, 175662306a36Sopenharmony_ci .base.update = stm32_hash_update, 175762306a36Sopenharmony_ci .base.final = stm32_hash_final, 175862306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 175962306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 176062306a36Sopenharmony_ci .base.export = stm32_hash_export, 176162306a36Sopenharmony_ci .base.import = stm32_hash_import, 176262306a36Sopenharmony_ci .base.halg = { 176362306a36Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 176462306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 176562306a36Sopenharmony_ci .base = { 176662306a36Sopenharmony_ci .cra_name = "sha3-384", 176762306a36Sopenharmony_ci .cra_driver_name = "stm32-sha3-384", 176862306a36Sopenharmony_ci .cra_priority = 200, 176962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 177062306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 177162306a36Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 177262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 177362306a36Sopenharmony_ci .cra_alignmask = 3, 177462306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_init, 177562306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 177662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci }, 177962306a36Sopenharmony_ci .op = { 178062306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 178162306a36Sopenharmony_ci }, 178262306a36Sopenharmony_ci }, 178362306a36Sopenharmony_ci { 178462306a36Sopenharmony_ci .base.init = stm32_hash_init, 178562306a36Sopenharmony_ci .base.update = stm32_hash_update, 178662306a36Sopenharmony_ci .base.final = stm32_hash_final, 178762306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 178862306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 178962306a36Sopenharmony_ci .base.export = stm32_hash_export, 179062306a36Sopenharmony_ci .base.import = stm32_hash_import, 179162306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 179262306a36Sopenharmony_ci .base.halg = { 179362306a36Sopenharmony_ci .digestsize = SHA3_384_DIGEST_SIZE, 179462306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 179562306a36Sopenharmony_ci .base = { 179662306a36Sopenharmony_ci .cra_name = "hmac(sha3-384)", 179762306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha3-384", 179862306a36Sopenharmony_ci .cra_priority = 200, 179962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 180062306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 180162306a36Sopenharmony_ci .cra_blocksize = SHA3_384_BLOCK_SIZE, 180262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 180362306a36Sopenharmony_ci .cra_alignmask = 3, 180462306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_hmac_init, 180562306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 180662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 180762306a36Sopenharmony_ci } 180862306a36Sopenharmony_ci }, 180962306a36Sopenharmony_ci .op = { 181062306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 181162306a36Sopenharmony_ci }, 181262306a36Sopenharmony_ci }, 181362306a36Sopenharmony_ci { 181462306a36Sopenharmony_ci .base.init = stm32_hash_init, 181562306a36Sopenharmony_ci .base.update = stm32_hash_update, 181662306a36Sopenharmony_ci .base.final = stm32_hash_final, 181762306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 181862306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 181962306a36Sopenharmony_ci .base.export = stm32_hash_export, 182062306a36Sopenharmony_ci .base.import = stm32_hash_import, 182162306a36Sopenharmony_ci .base.halg = { 182262306a36Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 182362306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 182462306a36Sopenharmony_ci .base = { 182562306a36Sopenharmony_ci .cra_name = "sha3-512", 182662306a36Sopenharmony_ci .cra_driver_name = "stm32-sha3-512", 182762306a36Sopenharmony_ci .cra_priority = 200, 182862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 182962306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 183062306a36Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 183162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 183262306a36Sopenharmony_ci .cra_alignmask = 3, 183362306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_init, 183462306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 183562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 183662306a36Sopenharmony_ci } 183762306a36Sopenharmony_ci }, 183862306a36Sopenharmony_ci .op = { 183962306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 184062306a36Sopenharmony_ci }, 184162306a36Sopenharmony_ci }, 184262306a36Sopenharmony_ci { 184362306a36Sopenharmony_ci .base.init = stm32_hash_init, 184462306a36Sopenharmony_ci .base.update = stm32_hash_update, 184562306a36Sopenharmony_ci .base.final = stm32_hash_final, 184662306a36Sopenharmony_ci .base.finup = stm32_hash_finup, 184762306a36Sopenharmony_ci .base.digest = stm32_hash_digest, 184862306a36Sopenharmony_ci .base.export = stm32_hash_export, 184962306a36Sopenharmony_ci .base.import = stm32_hash_import, 185062306a36Sopenharmony_ci .base.setkey = stm32_hash_setkey, 185162306a36Sopenharmony_ci .base.halg = { 185262306a36Sopenharmony_ci .digestsize = SHA3_512_DIGEST_SIZE, 185362306a36Sopenharmony_ci .statesize = sizeof(struct stm32_hash_state), 185462306a36Sopenharmony_ci .base = { 185562306a36Sopenharmony_ci .cra_name = "hmac(sha3-512)", 185662306a36Sopenharmony_ci .cra_driver_name = "stm32-hmac-sha3-512", 185762306a36Sopenharmony_ci .cra_priority = 200, 185862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 185962306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY, 186062306a36Sopenharmony_ci .cra_blocksize = SHA3_512_BLOCK_SIZE, 186162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct stm32_hash_ctx), 186262306a36Sopenharmony_ci .cra_alignmask = 3, 186362306a36Sopenharmony_ci .cra_init = stm32_hash_cra_sha3_hmac_init, 186462306a36Sopenharmony_ci .cra_exit = stm32_hash_cra_exit, 186562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ci }, 186862306a36Sopenharmony_ci .op = { 186962306a36Sopenharmony_ci .do_one_request = stm32_hash_one_request, 187062306a36Sopenharmony_ci }, 187162306a36Sopenharmony_ci } 187262306a36Sopenharmony_ci}; 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_cistatic int stm32_hash_register_algs(struct stm32_hash_dev *hdev) 187562306a36Sopenharmony_ci{ 187662306a36Sopenharmony_ci unsigned int i, j; 187762306a36Sopenharmony_ci int err; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci for (i = 0; i < hdev->pdata->algs_info_size; i++) { 188062306a36Sopenharmony_ci for (j = 0; j < hdev->pdata->algs_info[i].size; j++) { 188162306a36Sopenharmony_ci err = crypto_engine_register_ahash( 188262306a36Sopenharmony_ci &hdev->pdata->algs_info[i].algs_list[j]); 188362306a36Sopenharmony_ci if (err) 188462306a36Sopenharmony_ci goto err_algs; 188562306a36Sopenharmony_ci } 188662306a36Sopenharmony_ci } 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci return 0; 188962306a36Sopenharmony_cierr_algs: 189062306a36Sopenharmony_ci dev_err(hdev->dev, "Algo %d : %d failed\n", i, j); 189162306a36Sopenharmony_ci for (; i--; ) { 189262306a36Sopenharmony_ci for (; j--;) 189362306a36Sopenharmony_ci crypto_engine_unregister_ahash( 189462306a36Sopenharmony_ci &hdev->pdata->algs_info[i].algs_list[j]); 189562306a36Sopenharmony_ci } 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci return err; 189862306a36Sopenharmony_ci} 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_cistatic int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev) 190162306a36Sopenharmony_ci{ 190262306a36Sopenharmony_ci unsigned int i, j; 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci for (i = 0; i < hdev->pdata->algs_info_size; i++) { 190562306a36Sopenharmony_ci for (j = 0; j < hdev->pdata->algs_info[i].size; j++) 190662306a36Sopenharmony_ci crypto_engine_unregister_ahash( 190762306a36Sopenharmony_ci &hdev->pdata->algs_info[i].algs_list[j]); 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci return 0; 191162306a36Sopenharmony_ci} 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_ux500[] = { 191462306a36Sopenharmony_ci { 191562306a36Sopenharmony_ci .algs_list = algs_sha1, 191662306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1), 191762306a36Sopenharmony_ci }, 191862306a36Sopenharmony_ci { 191962306a36Sopenharmony_ci .algs_list = algs_sha256, 192062306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha256), 192162306a36Sopenharmony_ci }, 192262306a36Sopenharmony_ci}; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_ux500 = { 192562306a36Sopenharmony_ci .alg_shift = 7, 192662306a36Sopenharmony_ci .algs_info = stm32_hash_algs_info_ux500, 192762306a36Sopenharmony_ci .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_ux500), 192862306a36Sopenharmony_ci .broken_emptymsg = true, 192962306a36Sopenharmony_ci .ux500 = true, 193062306a36Sopenharmony_ci}; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = { 193362306a36Sopenharmony_ci { 193462306a36Sopenharmony_ci .algs_list = algs_md5, 193562306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_md5), 193662306a36Sopenharmony_ci }, 193762306a36Sopenharmony_ci { 193862306a36Sopenharmony_ci .algs_list = algs_sha1, 193962306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1), 194062306a36Sopenharmony_ci }, 194162306a36Sopenharmony_ci}; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = { 194462306a36Sopenharmony_ci .alg_shift = 7, 194562306a36Sopenharmony_ci .algs_info = stm32_hash_algs_info_stm32f4, 194662306a36Sopenharmony_ci .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4), 194762306a36Sopenharmony_ci .has_sr = true, 194862306a36Sopenharmony_ci .has_mdmat = true, 194962306a36Sopenharmony_ci}; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { 195262306a36Sopenharmony_ci { 195362306a36Sopenharmony_ci .algs_list = algs_md5, 195462306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_md5), 195562306a36Sopenharmony_ci }, 195662306a36Sopenharmony_ci { 195762306a36Sopenharmony_ci .algs_list = algs_sha1, 195862306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1), 195962306a36Sopenharmony_ci }, 196062306a36Sopenharmony_ci { 196162306a36Sopenharmony_ci .algs_list = algs_sha224, 196262306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha224), 196362306a36Sopenharmony_ci }, 196462306a36Sopenharmony_ci { 196562306a36Sopenharmony_ci .algs_list = algs_sha256, 196662306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha256), 196762306a36Sopenharmony_ci }, 196862306a36Sopenharmony_ci}; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = { 197162306a36Sopenharmony_ci .alg_shift = 7, 197262306a36Sopenharmony_ci .algs_info = stm32_hash_algs_info_stm32f7, 197362306a36Sopenharmony_ci .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7), 197462306a36Sopenharmony_ci .has_sr = true, 197562306a36Sopenharmony_ci .has_mdmat = true, 197662306a36Sopenharmony_ci}; 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = { 197962306a36Sopenharmony_ci { 198062306a36Sopenharmony_ci .algs_list = algs_sha1, 198162306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1), 198262306a36Sopenharmony_ci }, 198362306a36Sopenharmony_ci { 198462306a36Sopenharmony_ci .algs_list = algs_sha224, 198562306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha224), 198662306a36Sopenharmony_ci }, 198762306a36Sopenharmony_ci { 198862306a36Sopenharmony_ci .algs_list = algs_sha256, 198962306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha256), 199062306a36Sopenharmony_ci }, 199162306a36Sopenharmony_ci { 199262306a36Sopenharmony_ci .algs_list = algs_sha384_sha512, 199362306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha384_sha512), 199462306a36Sopenharmony_ci }, 199562306a36Sopenharmony_ci { 199662306a36Sopenharmony_ci .algs_list = algs_sha3, 199762306a36Sopenharmony_ci .size = ARRAY_SIZE(algs_sha3), 199862306a36Sopenharmony_ci }, 199962306a36Sopenharmony_ci}; 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = { 200262306a36Sopenharmony_ci .alg_shift = 17, 200362306a36Sopenharmony_ci .algs_info = stm32_hash_algs_info_stm32mp13, 200462306a36Sopenharmony_ci .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32mp13), 200562306a36Sopenharmony_ci .has_sr = true, 200662306a36Sopenharmony_ci .has_mdmat = true, 200762306a36Sopenharmony_ci}; 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_cistatic const struct of_device_id stm32_hash_of_match[] = { 201062306a36Sopenharmony_ci { .compatible = "stericsson,ux500-hash", .data = &stm32_hash_pdata_ux500 }, 201162306a36Sopenharmony_ci { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 }, 201262306a36Sopenharmony_ci { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 }, 201362306a36Sopenharmony_ci { .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 }, 201462306a36Sopenharmony_ci {}, 201562306a36Sopenharmony_ci}; 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_hash_of_match); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_cistatic int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, 202062306a36Sopenharmony_ci struct device *dev) 202162306a36Sopenharmony_ci{ 202262306a36Sopenharmony_ci hdev->pdata = of_device_get_match_data(dev); 202362306a36Sopenharmony_ci if (!hdev->pdata) { 202462306a36Sopenharmony_ci dev_err(dev, "no compatible OF match\n"); 202562306a36Sopenharmony_ci return -EINVAL; 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci return 0; 202962306a36Sopenharmony_ci} 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_cistatic int stm32_hash_probe(struct platform_device *pdev) 203262306a36Sopenharmony_ci{ 203362306a36Sopenharmony_ci struct stm32_hash_dev *hdev; 203462306a36Sopenharmony_ci struct device *dev = &pdev->dev; 203562306a36Sopenharmony_ci struct resource *res; 203662306a36Sopenharmony_ci int ret, irq; 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci hdev = devm_kzalloc(dev, sizeof(*hdev), GFP_KERNEL); 203962306a36Sopenharmony_ci if (!hdev) 204062306a36Sopenharmony_ci return -ENOMEM; 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci hdev->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 204362306a36Sopenharmony_ci if (IS_ERR(hdev->io_base)) 204462306a36Sopenharmony_ci return PTR_ERR(hdev->io_base); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci hdev->phys_base = res->start; 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci ret = stm32_hash_get_of_match(hdev, dev); 204962306a36Sopenharmony_ci if (ret) 205062306a36Sopenharmony_ci return ret; 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci irq = platform_get_irq_optional(pdev, 0); 205362306a36Sopenharmony_ci if (irq < 0 && irq != -ENXIO) 205462306a36Sopenharmony_ci return irq; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci if (irq > 0) { 205762306a36Sopenharmony_ci ret = devm_request_threaded_irq(dev, irq, 205862306a36Sopenharmony_ci stm32_hash_irq_handler, 205962306a36Sopenharmony_ci stm32_hash_irq_thread, 206062306a36Sopenharmony_ci IRQF_ONESHOT, 206162306a36Sopenharmony_ci dev_name(dev), hdev); 206262306a36Sopenharmony_ci if (ret) { 206362306a36Sopenharmony_ci dev_err(dev, "Cannot grab IRQ\n"); 206462306a36Sopenharmony_ci return ret; 206562306a36Sopenharmony_ci } 206662306a36Sopenharmony_ci } else { 206762306a36Sopenharmony_ci dev_info(dev, "No IRQ, use polling mode\n"); 206862306a36Sopenharmony_ci hdev->polled = true; 206962306a36Sopenharmony_ci } 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci hdev->clk = devm_clk_get(&pdev->dev, NULL); 207262306a36Sopenharmony_ci if (IS_ERR(hdev->clk)) 207362306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(hdev->clk), 207462306a36Sopenharmony_ci "failed to get clock for hash\n"); 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci ret = clk_prepare_enable(hdev->clk); 207762306a36Sopenharmony_ci if (ret) { 207862306a36Sopenharmony_ci dev_err(dev, "failed to enable hash clock (%d)\n", ret); 207962306a36Sopenharmony_ci return ret; 208062306a36Sopenharmony_ci } 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, HASH_AUTOSUSPEND_DELAY); 208362306a36Sopenharmony_ci pm_runtime_use_autosuspend(dev); 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci pm_runtime_get_noresume(dev); 208662306a36Sopenharmony_ci pm_runtime_set_active(dev); 208762306a36Sopenharmony_ci pm_runtime_enable(dev); 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci hdev->rst = devm_reset_control_get(&pdev->dev, NULL); 209062306a36Sopenharmony_ci if (IS_ERR(hdev->rst)) { 209162306a36Sopenharmony_ci if (PTR_ERR(hdev->rst) == -EPROBE_DEFER) { 209262306a36Sopenharmony_ci ret = -EPROBE_DEFER; 209362306a36Sopenharmony_ci goto err_reset; 209462306a36Sopenharmony_ci } 209562306a36Sopenharmony_ci } else { 209662306a36Sopenharmony_ci reset_control_assert(hdev->rst); 209762306a36Sopenharmony_ci udelay(2); 209862306a36Sopenharmony_ci reset_control_deassert(hdev->rst); 209962306a36Sopenharmony_ci } 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci hdev->dev = dev; 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci platform_set_drvdata(pdev, hdev); 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci ret = stm32_hash_dma_init(hdev); 210662306a36Sopenharmony_ci switch (ret) { 210762306a36Sopenharmony_ci case 0: 210862306a36Sopenharmony_ci break; 210962306a36Sopenharmony_ci case -ENOENT: 211062306a36Sopenharmony_ci case -ENODEV: 211162306a36Sopenharmony_ci dev_info(dev, "DMA mode not available\n"); 211262306a36Sopenharmony_ci break; 211362306a36Sopenharmony_ci default: 211462306a36Sopenharmony_ci dev_err(dev, "DMA init error %d\n", ret); 211562306a36Sopenharmony_ci goto err_dma; 211662306a36Sopenharmony_ci } 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci spin_lock(&stm32_hash.lock); 211962306a36Sopenharmony_ci list_add_tail(&hdev->list, &stm32_hash.dev_list); 212062306a36Sopenharmony_ci spin_unlock(&stm32_hash.lock); 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci /* Initialize crypto engine */ 212362306a36Sopenharmony_ci hdev->engine = crypto_engine_alloc_init(dev, 1); 212462306a36Sopenharmony_ci if (!hdev->engine) { 212562306a36Sopenharmony_ci ret = -ENOMEM; 212662306a36Sopenharmony_ci goto err_engine; 212762306a36Sopenharmony_ci } 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci ret = crypto_engine_start(hdev->engine); 213062306a36Sopenharmony_ci if (ret) 213162306a36Sopenharmony_ci goto err_engine_start; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci if (hdev->pdata->ux500) 213462306a36Sopenharmony_ci /* FIXME: implement DMA mode for Ux500 */ 213562306a36Sopenharmony_ci hdev->dma_mode = 0; 213662306a36Sopenharmony_ci else 213762306a36Sopenharmony_ci hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & HASH_HWCFG_DMA_MASK; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci /* Register algos */ 214062306a36Sopenharmony_ci ret = stm32_hash_register_algs(hdev); 214162306a36Sopenharmony_ci if (ret) 214262306a36Sopenharmony_ci goto err_algs; 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci dev_info(dev, "Init HASH done HW ver %x DMA mode %u\n", 214562306a36Sopenharmony_ci stm32_hash_read(hdev, HASH_VER), hdev->dma_mode); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ci pm_runtime_put_sync(dev); 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci return 0; 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_cierr_algs: 215262306a36Sopenharmony_cierr_engine_start: 215362306a36Sopenharmony_ci crypto_engine_exit(hdev->engine); 215462306a36Sopenharmony_cierr_engine: 215562306a36Sopenharmony_ci spin_lock(&stm32_hash.lock); 215662306a36Sopenharmony_ci list_del(&hdev->list); 215762306a36Sopenharmony_ci spin_unlock(&stm32_hash.lock); 215862306a36Sopenharmony_cierr_dma: 215962306a36Sopenharmony_ci if (hdev->dma_lch) 216062306a36Sopenharmony_ci dma_release_channel(hdev->dma_lch); 216162306a36Sopenharmony_cierr_reset: 216262306a36Sopenharmony_ci pm_runtime_disable(dev); 216362306a36Sopenharmony_ci pm_runtime_put_noidle(dev); 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci clk_disable_unprepare(hdev->clk); 216662306a36Sopenharmony_ci 216762306a36Sopenharmony_ci return ret; 216862306a36Sopenharmony_ci} 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_cistatic void stm32_hash_remove(struct platform_device *pdev) 217162306a36Sopenharmony_ci{ 217262306a36Sopenharmony_ci struct stm32_hash_dev *hdev = platform_get_drvdata(pdev); 217362306a36Sopenharmony_ci int ret; 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_ci ret = pm_runtime_get_sync(hdev->dev); 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci stm32_hash_unregister_algs(hdev); 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci crypto_engine_exit(hdev->engine); 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci spin_lock(&stm32_hash.lock); 218262306a36Sopenharmony_ci list_del(&hdev->list); 218362306a36Sopenharmony_ci spin_unlock(&stm32_hash.lock); 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci if (hdev->dma_lch) 218662306a36Sopenharmony_ci dma_release_channel(hdev->dma_lch); 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci pm_runtime_disable(hdev->dev); 218962306a36Sopenharmony_ci pm_runtime_put_noidle(hdev->dev); 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci if (ret >= 0) 219262306a36Sopenharmony_ci clk_disable_unprepare(hdev->clk); 219362306a36Sopenharmony_ci} 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci#ifdef CONFIG_PM 219662306a36Sopenharmony_cistatic int stm32_hash_runtime_suspend(struct device *dev) 219762306a36Sopenharmony_ci{ 219862306a36Sopenharmony_ci struct stm32_hash_dev *hdev = dev_get_drvdata(dev); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci clk_disable_unprepare(hdev->clk); 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci return 0; 220362306a36Sopenharmony_ci} 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_cistatic int stm32_hash_runtime_resume(struct device *dev) 220662306a36Sopenharmony_ci{ 220762306a36Sopenharmony_ci struct stm32_hash_dev *hdev = dev_get_drvdata(dev); 220862306a36Sopenharmony_ci int ret; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci ret = clk_prepare_enable(hdev->clk); 221162306a36Sopenharmony_ci if (ret) { 221262306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to prepare_enable clock\n"); 221362306a36Sopenharmony_ci return ret; 221462306a36Sopenharmony_ci } 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci return 0; 221762306a36Sopenharmony_ci} 221862306a36Sopenharmony_ci#endif 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_cistatic const struct dev_pm_ops stm32_hash_pm_ops = { 222162306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 222262306a36Sopenharmony_ci pm_runtime_force_resume) 222362306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(stm32_hash_runtime_suspend, 222462306a36Sopenharmony_ci stm32_hash_runtime_resume, NULL) 222562306a36Sopenharmony_ci}; 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_cistatic struct platform_driver stm32_hash_driver = { 222862306a36Sopenharmony_ci .probe = stm32_hash_probe, 222962306a36Sopenharmony_ci .remove_new = stm32_hash_remove, 223062306a36Sopenharmony_ci .driver = { 223162306a36Sopenharmony_ci .name = "stm32-hash", 223262306a36Sopenharmony_ci .pm = &stm32_hash_pm_ops, 223362306a36Sopenharmony_ci .of_match_table = stm32_hash_of_match, 223462306a36Sopenharmony_ci } 223562306a36Sopenharmony_ci}; 223662306a36Sopenharmony_ci 223762306a36Sopenharmony_cimodule_platform_driver(stm32_hash_driver); 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ciMODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver"); 224062306a36Sopenharmony_ciMODULE_AUTHOR("Lionel Debieve <lionel.debieve@st.com>"); 224162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2242