cregit-Linux how code gets into the kernel

Release 4.16 drivers/crypto/stm32/stm32-hash.c

/*
 * This file is part of STM32 Crypto driver for Linux.
 *
 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
 * Author(s): Lionel DEBIEVE <lionel.debieve@st.com> for STMicroelectronics.
 *
 * License terms: GPL V2.0.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <linux/clk.h>
#include <linux/crypto.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>

#include <crypto/engine.h>
#include <crypto/hash.h>
#include <crypto/md5.h>
#include <crypto/scatterwalk.h>
#include <crypto/sha.h>
#include <crypto/internal/hash.h>


#define HASH_CR				0x00

#define HASH_DIN			0x04

#define HASH_STR			0x08

#define HASH_IMR			0x20

#define HASH_SR				0x24

#define HASH_CSR(x)			(0x0F8 + ((x) * 0x04))

#define HASH_HREG(x)			(0x310 + ((x) * 0x04))

#define HASH_HWCFGR			0x3F0

#define HASH_VER			0x3F4

#define HASH_ID				0x3F8

/* Control Register */

#define HASH_CR_INIT			BIT(2)

#define HASH_CR_DMAE			BIT(3)

#define HASH_CR_DATATYPE_POS		4

#define HASH_CR_MODE			BIT(6)

#define HASH_CR_MDMAT			BIT(13)

#define HASH_CR_DMAA			BIT(14)

#define HASH_CR_LKEY			BIT(16)


#define HASH_CR_ALGO_SHA1		0x0

#define HASH_CR_ALGO_MD5		0x80

#define HASH_CR_ALGO_SHA224		0x40000

#define HASH_CR_ALGO_SHA256		0x40080

/* Interrupt */

#define HASH_DINIE			BIT(0)

#define HASH_DCIE			BIT(1)

/* Interrupt Mask */

#define HASH_MASK_CALC_COMPLETION	BIT(0)

#define HASH_MASK_DATA_INPUT		BIT(1)

/* Context swap register */

#define HASH_CSR_REGISTER_NUMBER	53

/* Status Flags */

#define HASH_SR_DATA_INPUT_READY	BIT(0)

#define HASH_SR_OUTPUT_READY		BIT(1)

#define HASH_SR_DMA_ACTIVE		BIT(2)

#define HASH_SR_BUSY			BIT(3)

/* STR Register */

#define HASH_STR_NBLW_MASK		GENMASK(4, 0)

#define HASH_STR_DCAL			BIT(8)


#define HASH_FLAGS_INIT			BIT(0)

#define HASH_FLAGS_OUTPUT_READY		BIT(1)

#define HASH_FLAGS_CPU			BIT(2)

#define HASH_FLAGS_DMA_READY		BIT(3)

#define HASH_FLAGS_DMA_ACTIVE		BIT(4)

#define HASH_FLAGS_HMAC_INIT		BIT(5)

#define HASH_FLAGS_HMAC_FINAL		BIT(6)

#define HASH_FLAGS_HMAC_KEY		BIT(7)


#define HASH_FLAGS_FINAL		BIT(15)

#define HASH_FLAGS_FINUP		BIT(16)

#define HASH_FLAGS_ALGO_MASK		GENMASK(21, 18)

#define HASH_FLAGS_MD5			BIT(18)

#define HASH_FLAGS_SHA1			BIT(19)

#define HASH_FLAGS_SHA224		BIT(20)

#define HASH_FLAGS_SHA256		BIT(21)

#define HASH_FLAGS_ERRORS		BIT(22)

#define HASH_FLAGS_HMAC			BIT(23)


#define HASH_OP_UPDATE			1

#define HASH_OP_FINAL			2


enum stm32_hash_data_format {
	
HASH_DATA_32_BITS		= 0x0,
	
HASH_DATA_16_BITS		= 0x1,
	
HASH_DATA_8_BITS		= 0x2,
	
HASH_DATA_1_BIT			= 0x3
};


#define HASH_BUFLEN			256

#define HASH_LONG_KEY			64

#define HASH_MAX_KEY_SIZE		(SHA256_BLOCK_SIZE * 8)

#define HASH_QUEUE_LENGTH		16

#define HASH_DMA_THRESHOLD		50


struct stm32_hash_ctx {
	
struct stm32_hash_dev	*hdev;
	
unsigned long		flags;

	
u8			key[HASH_MAX_KEY_SIZE];
	
int			keylen;
};


struct stm32_hash_request_ctx {
	
struct stm32_hash_dev	*hdev;
	
unsigned long		flags;
	
unsigned long		op;

	u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32));
	
size_t			digcnt;
	
size_t			bufcnt;
	
size_t			buflen;

	/* DMA */
	
struct scatterlist	*sg;
	
unsigned int		offset;
	
unsigned int		total;
	
struct scatterlist	sg_key;

	
dma_addr_t		dma_addr;
	
size_t			dma_ct;
	
int			nents;

	
u8			data_type;

	u8 buffer[HASH_BUFLEN] __aligned(sizeof(u32));

	/* Export Context */
	
u32			*hw_context;
};


struct stm32_hash_algs_info {
	
struct ahash_alg	*algs_list;
	
size_t			size;
};


struct stm32_hash_pdata {
	
struct stm32_hash_algs_info	*algs_info;
	
size_t				algs_info_size;
};


struct stm32_hash_dev {
	
struct list_head	list;
	
struct device		*dev;
	
struct clk		*clk;
	
struct reset_control	*rst;
	
void __iomem		*io_base;
	
phys_addr_t		phys_base;
	
u32			dma_mode;
	
u32			dma_maxburst;

	
spinlock_t		lock; /* lock to protect queue */

	
struct ahash_request	*req;
	
struct crypto_engine	*engine;

	
int			err;
	
unsigned long		flags;

	
struct dma_chan		*dma_lch;
	
struct completion	dma_completion;

	
const struct stm32_hash_pdata	*pdata;
};


struct stm32_hash_drv {
	
struct list_head	dev_list;
	
spinlock_t		lock; /* List protection access */
};


static struct stm32_hash_drv stm32_hash = {
	.dev_list = LIST_HEAD_INIT(stm32_hash.dev_list),
	.lock = __SPIN_LOCK_UNLOCKED(stm32_hash.lock),
};

static void stm32_hash_dma_callback(void *param);


static inline u32 stm32_hash_read(struct stm32_hash_dev *hdev, u32 offset) { return readl_relaxed(hdev->io_base + offset); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve25100.00%1100.00%
Total25100.00%1100.00%


static inline void stm32_hash_write(struct stm32_hash_dev *hdev, u32 offset, u32 value) { writel_relaxed(value, hdev->io_base + offset); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve29100.00%1100.00%
Total29100.00%1100.00%


static inline int stm32_hash_wait_busy(struct stm32_hash_dev *hdev) { u32 status; return readl_relaxed_poll_timeout(hdev->io_base + HASH_SR, status, !(status & HASH_SR_BUSY), 10, 10000); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve38100.00%1100.00%
Total38100.00%1100.00%


static void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length) { u32 reg; reg = stm32_hash_read(hdev, HASH_STR); reg &= ~(HASH_STR_NBLW_MASK); reg |= (8U * ((length) % 4U)); stm32_hash_write(hdev, HASH_STR, reg); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve56100.00%1100.00%
Total56100.00%1100.00%


static int stm32_hash_write_key(struct stm32_hash_dev *hdev) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 reg; int keylen = ctx->keylen; void *key = ctx->key; if (keylen) { stm32_hash_set_nblw(hdev, keylen); while (keylen > 0) { stm32_hash_write(hdev, HASH_DIN, *(u32 *)key); keylen -= 4; key += 4; } reg = stm32_hash_read(hdev, HASH_STR); reg |= HASH_STR_DCAL; stm32_hash_write(hdev, HASH_STR, reg); return -EINPROGRESS; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve123100.00%1100.00%
Total123100.00%1100.00%


static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 reg = HASH_CR_INIT; if (!(hdev->flags & HASH_FLAGS_INIT)) { switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { case HASH_FLAGS_MD5: reg |= HASH_CR_ALGO_MD5; break; case HASH_FLAGS_SHA1: reg |= HASH_CR_ALGO_SHA1; break; case HASH_FLAGS_SHA224: reg |= HASH_CR_ALGO_SHA224; break; case HASH_FLAGS_SHA256: reg |= HASH_CR_ALGO_SHA256; break; default: reg |= HASH_CR_ALGO_MD5; } reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); if (rctx->flags & HASH_FLAGS_HMAC) { hdev->flags |= HASH_FLAGS_HMAC; reg |= HASH_CR_MODE; if (ctx->keylen > HASH_LONG_KEY) reg |= HASH_CR_LKEY; } stm32_hash_write(hdev, HASH_IMR, HASH_DCIE); stm32_hash_write(hdev, HASH_CR, reg); hdev->flags |= HASH_FLAGS_INIT; dev_dbg(hdev->dev, "Write Control %x\n", reg); } }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve187100.00%1100.00%
Total187100.00%1100.00%


static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) { size_t count; while ((rctx->bufcnt < rctx->buflen) && rctx->total) { count = min(rctx->sg->length - rctx->offset, rctx->total); count = min(count, rctx->buflen - rctx->bufcnt); if (count <= 0) { if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) { rctx->sg = sg_next(rctx->sg); continue; } else { break; } } scatterwalk_map_and_copy(rctx->buffer + rctx->bufcnt, rctx->sg, rctx->offset, count, 0); rctx->bufcnt += count; rctx->offset += count; rctx->total -= count; if (rctx->offset == rctx->sg->length) { rctx->sg = sg_next(rctx->sg); if (rctx->sg) rctx->offset = 0; else rctx->total = 0; } } }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve197100.00%1100.00%
Total197100.00%1100.00%


static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, const u8 *buf, size_t length, int final) { unsigned int count, len32; const u32 *buffer = (const u32 *)buf; u32 reg; if (final) hdev->flags |= HASH_FLAGS_FINAL; len32 = DIV_ROUND_UP(length, sizeof(u32)); dev_dbg(hdev->dev, "%s: length: %d, final: %x len32 %i\n", __func__, length, final, len32); hdev->flags |= HASH_FLAGS_CPU; stm32_hash_write_ctrl(hdev); if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; if ((hdev->flags & HASH_FLAGS_HMAC) && (hdev->flags & ~HASH_FLAGS_HMAC_KEY)) { hdev->flags |= HASH_FLAGS_HMAC_KEY; stm32_hash_write_key(hdev); if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; } for (count = 0; count < len32; count++) stm32_hash_write(hdev, HASH_DIN, buffer[count]); if (final) { stm32_hash_set_nblw(hdev, length); reg = stm32_hash_read(hdev, HASH_STR); reg |= HASH_STR_DCAL; stm32_hash_write(hdev, HASH_STR, reg); if (hdev->flags & HASH_FLAGS_HMAC) { if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; stm32_hash_write_key(hdev); } return -EINPROGRESS; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve240100.00%1100.00%
Total240100.00%1100.00%


static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); int bufcnt, err = 0, final; dev_dbg(hdev->dev, "%s flags %lx\n", __func__, rctx->flags); final = (rctx->flags & HASH_FLAGS_FINUP); while ((rctx->total >= rctx->buflen) || (rctx->bufcnt + rctx->total >= rctx->buflen)) { stm32_hash_append_sg(rctx); bufcnt = rctx->bufcnt; rctx->bufcnt = 0; err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, 0); } stm32_hash_append_sg(rctx); if (final) { bufcnt = rctx->bufcnt; rctx->bufcnt = 0; err = stm32_hash_xmit_cpu(hdev, rctx->buffer, bufcnt, (rctx->flags & HASH_FLAGS_FINUP)); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve164100.00%1100.00%
Total164100.00%1100.00%


static int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev, struct scatterlist *sg, int length, int mdma) { struct dma_async_tx_descriptor *in_desc; dma_cookie_t cookie; u32 reg; int err; in_desc = dmaengine_prep_slave_sg(hdev->dma_lch, sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!in_desc) { dev_err(hdev->dev, "dmaengine_prep_slave error\n"); return -ENOMEM; } reinit_completion(&hdev->dma_completion); in_desc->callback = stm32_hash_dma_callback; in_desc->callback_param = hdev; hdev->flags |= HASH_FLAGS_FINAL; hdev->flags |= HASH_FLAGS_DMA_ACTIVE; reg = stm32_hash_read(hdev, HASH_CR); if (mdma) reg |= HASH_CR_MDMAT; else reg &= ~HASH_CR_MDMAT; reg |= HASH_CR_DMAE; stm32_hash_write(hdev, HASH_CR, reg); stm32_hash_set_nblw(hdev, length); cookie = dmaengine_submit(in_desc); err = dma_submit_error(cookie); if (err) return -ENOMEM; dma_async_issue_pending(hdev->dma_lch); if (!wait_for_completion_interruptible_timeout(&hdev->dma_completion, msecs_to_jiffies(100))) err = -ETIMEDOUT; if (dma_async_is_tx_complete(hdev->dma_lch, cookie, NULL, NULL) != DMA_COMPLETE) err = -ETIMEDOUT; if (err) { dev_err(hdev->dev, "DMA Error %i\n", err); dmaengine_terminate_all(hdev->dma_lch); return err; } return -EINPROGRESS; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve253100.00%1100.00%
Total253100.00%1100.00%


static void stm32_hash_dma_callback(void *param) { struct stm32_hash_dev *hdev = param; complete(&hdev->dma_completion); hdev->flags |= HASH_FLAGS_DMA_READY; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve31100.00%1100.00%
Total31100.00%1100.00%


static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); int err; if (ctx->keylen < HASH_DMA_THRESHOLD || (hdev->dma_mode == 1)) { err = stm32_hash_write_key(hdev); if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; } else { if (!(hdev->flags & HASH_FLAGS_HMAC_KEY)) sg_init_one(&rctx->sg_key, ctx->key, ALIGN(ctx->keylen, sizeof(u32))); rctx->dma_ct = dma_map_sg(hdev->dev, &rctx->sg_key, 1, DMA_TO_DEVICE); if (rctx->dma_ct == 0) { dev_err(hdev->dev, "dma_map_sg error\n"); return -ENOMEM; } err = stm32_hash_xmit_dma(hdev, &rctx->sg_key, ctx->keylen, 0); dma_unmap_sg(hdev->dev, &rctx->sg_key, 1, DMA_TO_DEVICE); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve202100.00%1100.00%
Total202100.00%1100.00%


static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) { struct dma_slave_config dma_conf; int err; memset(&dma_conf, 0, sizeof(dma_conf)); dma_conf.direction = DMA_MEM_TO_DEV; dma_conf.dst_addr = hdev->phys_base + HASH_DIN; dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_conf.src_maxburst = hdev->dma_maxburst; dma_conf.dst_maxburst = hdev->dma_maxburst; dma_conf.device_fc = false; hdev->dma_lch = dma_request_slave_channel(hdev->dev, "in"); if (!hdev->dma_lch) { dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n"); return -EBUSY; } err = dmaengine_slave_config(hdev->dma_lch, &dma_conf); if (err) { dma_release_channel(hdev->dma_lch); hdev->dma_lch = NULL; dev_err(hdev->dev, "Couldn't configure DMA slave.\n"); return err; } init_completion(&hdev->dma_completion); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve164100.00%1100.00%
Total164100.00%1100.00%


static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct scatterlist sg[1], *tsg; int err = 0, len = 0, reg, ncp = 0; unsigned int i; u32 *buffer = (void *)rctx->buffer; rctx->sg = hdev->req->src; rctx->total = hdev->req->nbytes; rctx->nents = sg_nents(rctx->sg); if (rctx->nents < 0) return -EINVAL; stm32_hash_write_ctrl(hdev); if (hdev->flags & HASH_FLAGS_HMAC) { err = stm32_hash_hmac_dma_send(hdev); if (err != -EINPROGRESS) return err; } for_each_sg(rctx->sg, tsg, rctx->nents, i) { len = sg->length; sg[0] = *tsg; if (sg_is_last(sg)) { if (hdev->dma_mode == 1) { len = (ALIGN(sg->length, 16) - 16); ncp = sg_pcopy_to_buffer( rctx->sg, rctx->nents, rctx->buffer, sg->length - len, rctx->total - sg->length + len); sg->length = len; } else { if (!(IS_ALIGNED(sg->length, sizeof(u32)))) { len = sg->length; sg->length = ALIGN(sg->length, sizeof(u32)); } } } rctx->dma_ct = dma_map_sg(hdev->dev, sg, 1, DMA_TO_DEVICE); if (rctx->dma_ct == 0) { dev_err(hdev->dev, "dma_map_sg error\n"); return -ENOMEM; } err = stm32_hash_xmit_dma(hdev, sg, len, !sg_is_last(sg)); dma_unmap_sg(hdev->dev, sg, 1, DMA_TO_DEVICE); if (err == -ENOMEM) return err; } if (hdev->dma_mode == 1) { if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; reg = stm32_hash_read(hdev, HASH_CR); reg &= ~HASH_CR_DMAE; reg |= HASH_CR_DMAA; stm32_hash_write(hdev, HASH_CR, reg); if (ncp) { memset(buffer + ncp, 0, DIV_ROUND_UP(ncp, sizeof(u32)) - ncp); writesl(hdev->io_base + HASH_DIN, buffer, DIV_ROUND_UP(ncp, sizeof(u32))); } stm32_hash_set_nblw(hdev, DIV_ROUND_UP(ncp, sizeof(u32))); reg = stm32_hash_read(hdev, HASH_STR); reg |= HASH_STR_DCAL; stm32_hash_write(hdev, HASH_STR, reg); err = -EINPROGRESS; } if (hdev->flags & HASH_FLAGS_HMAC) { if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; err = stm32_hash_hmac_dma_send(hdev); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve48992.09%150.00%
Arnd Bergmann427.91%150.00%
Total531100.00%2100.00%


static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) { struct stm32_hash_dev *hdev = NULL, *tmp; spin_lock_bh(&stm32_hash.lock); if (!ctx->hdev) { list_for_each_entry(tmp, &stm32_hash.dev_list, list) { hdev = tmp; break; } ctx->hdev = hdev; } else { hdev = ctx->hdev; } spin_unlock_bh(&stm32_hash.lock); return hdev; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve81100.00%1100.00%
Total81100.00%1100.00%


static bool stm32_hash_dma_aligned_data(struct ahash_request *req) { struct scatterlist *sg; struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); int i; if (req->nbytes <= HASH_DMA_THRESHOLD) return false; if (sg_nents(req->src) > 1) { if (hdev->dma_mode == 1) return false; for_each_sg(req->src, sg, sg_nents(req->src), i) { if ((!IS_ALIGNED(sg->length, sizeof(u32))) && (!sg_is_last(sg))) return false; } } if (req->src->offset % 4) return false; return true; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve133100.00%1100.00%
Total133100.00%1100.00%


static int stm32_hash_init(struct ahash_request *req) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); rctx->hdev = hdev; rctx->flags = HASH_FLAGS_CPU; rctx->digcnt = crypto_ahash_digestsize(tfm); switch (rctx->digcnt) { case MD5_DIGEST_SIZE: rctx->flags |= HASH_FLAGS_MD5; break; case SHA1_DIGEST_SIZE: rctx->flags |= HASH_FLAGS_SHA1; break; case SHA224_DIGEST_SIZE: rctx->flags |= HASH_FLAGS_SHA224; break; case SHA256_DIGEST_SIZE: rctx->flags |= HASH_FLAGS_SHA256; break; default: return -EINVAL; } rctx->bufcnt = 0; rctx->buflen = HASH_BUFLEN; rctx->total = 0; rctx->offset = 0; rctx->data_type = HASH_DATA_8_BITS; memset(rctx->buffer, 0, HASH_BUFLEN); if (ctx->flags & HASH_FLAGS_HMAC) rctx->flags |= HASH_FLAGS_HMAC; dev_dbg(hdev->dev, "%s Flags %lx\n", __func__, rctx->flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve198100.00%1100.00%
Total198100.00%1100.00%


static int stm32_hash_update_req(struct stm32_hash_dev *hdev) { return stm32_hash_update_cpu(hdev); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve17100.00%1100.00%
Total17100.00%1100.00%


static int stm32_hash_final_req(struct stm32_hash_dev *hdev) { struct ahash_request *req = hdev->req; struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); int err; if (!(rctx->flags & HASH_FLAGS_CPU)) err = stm32_hash_dma_send(hdev); else err = stm32_hash_xmit_cpu(hdev, rctx->buffer, rctx->bufcnt, 1); rctx->bufcnt = 0; return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve78100.00%1100.00%
Total78100.00%1100.00%


static void stm32_hash_copy_hash(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); u32 *hash = (u32 *)rctx->digest; unsigned int i, hashsize; switch (rctx->flags & HASH_FLAGS_ALGO_MASK) { case HASH_FLAGS_MD5: hashsize = MD5_DIGEST_SIZE; break; case HASH_FLAGS_SHA1: hashsize = SHA1_DIGEST_SIZE; break; case HASH_FLAGS_SHA224: hashsize = SHA224_DIGEST_SIZE; break; case HASH_FLAGS_SHA256: hashsize = SHA256_DIGEST_SIZE; break; default: return; } for (i = 0; i < hashsize / sizeof(u32); i++) hash[i] = be32_to_cpu(stm32_hash_read(rctx->hdev, HASH_HREG(i))); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve121100.00%1100.00%
Total121100.00%1100.00%


static int stm32_hash_finish(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); if (!req->result) return -EINVAL; memcpy(req->result, rctx->digest, rctx->digcnt); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve50100.00%1100.00%
Total50100.00%1100.00%


static void stm32_hash_finish_req(struct ahash_request *req, int err) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_dev *hdev = rctx->hdev; if (!err && (HASH_FLAGS_FINAL & hdev->flags)) { stm32_hash_copy_hash(req); err = stm32_hash_finish(req); hdev->flags &= ~(HASH_FLAGS_FINAL | HASH_FLAGS_CPU | HASH_FLAGS_INIT | HASH_FLAGS_DMA_READY | HASH_FLAGS_OUTPUT_READY | HASH_FLAGS_HMAC | HASH_FLAGS_HMAC_INIT | HASH_FLAGS_HMAC_FINAL | HASH_FLAGS_HMAC_KEY); } else { rctx->flags |= HASH_FLAGS_ERRORS; } crypto_finalize_hash_request(hdev->engine, req, err); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve105100.00%1100.00%
Total105100.00%1100.00%


static int stm32_hash_hw_init(struct stm32_hash_dev *hdev, struct stm32_hash_request_ctx *rctx) { if (!(HASH_FLAGS_INIT & hdev->flags)) { stm32_hash_write(hdev, HASH_CR, HASH_CR_INIT); stm32_hash_write(hdev, HASH_STR, 0); stm32_hash_write(hdev, HASH_DIN, 0); stm32_hash_write(hdev, HASH_IMR, 0); hdev->err = 0; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve74100.00%1100.00%
Total74100.00%1100.00%


static int stm32_hash_handle_queue(struct stm32_hash_dev *hdev, struct ahash_request *req) { return crypto_transfer_hash_request_to_engine(hdev->engine, req); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve26100.00%1100.00%
Total26100.00%1100.00%


static int stm32_hash_prepare_req(struct crypto_engine *engine, struct ahash_request *req) { struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); struct stm32_hash_request_ctx *rctx; if (!hdev) return -ENODEV; hdev->req = req; rctx = ahash_request_ctx(req); dev_dbg(hdev->dev, "processing new req, op: %lu, nbytes %d\n", rctx->op, req->nbytes); return stm32_hash_hw_init(hdev, rctx); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve91100.00%1100.00%
Total91100.00%1100.00%


static int stm32_hash_one_request(struct crypto_engine *engine, struct ahash_request *req) { struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); struct stm32_hash_request_ctx *rctx; int err = 0; if (!hdev) return -ENODEV; hdev->req = req; rctx = ahash_request_ctx(req); if (rctx->op == HASH_OP_UPDATE) err = stm32_hash_update_req(hdev); else if (rctx->op == HASH_OP_FINAL) err = stm32_hash_final_req(hdev); if (err != -EINPROGRESS) /* done task will not finish it, so do it here */ stm32_hash_finish_req(req, err); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve120100.00%1100.00%
Total120100.00%1100.00%


static int stm32_hash_enqueue(struct ahash_request *req, unsigned int op) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_ctx *ctx = crypto_tfm_ctx(req->base.tfm); struct stm32_hash_dev *hdev = ctx->hdev; rctx->op = op; return stm32_hash_handle_queue(hdev, req); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve62100.00%1100.00%
Total62100.00%1100.00%


static int stm32_hash_update(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); if (!req->nbytes || !(rctx->flags & HASH_FLAGS_CPU)) return 0; rctx->total = req->nbytes; rctx->sg = req->src; rctx->offset = 0; if ((rctx->bufcnt + rctx->total < rctx->buflen)) { stm32_hash_append_sg(rctx); return 0; } return stm32_hash_enqueue(req, HASH_OP_UPDATE); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve96100.00%2100.00%
Total96100.00%2100.00%


static int stm32_hash_final(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); rctx->flags |= HASH_FLAGS_FINUP; return stm32_hash_enqueue(req, HASH_OP_FINAL); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve35100.00%1100.00%
Total35100.00%1100.00%


static int stm32_hash_finup(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); int err1, err2; rctx->flags |= HASH_FLAGS_FINUP; if (hdev->dma_lch && stm32_hash_dma_aligned_data(req)) rctx->flags &= ~HASH_FLAGS_CPU; err1 = stm32_hash_update(req); if (err1 == -EINPROGRESS || err1 == -EBUSY) return err1; /* * final() has to be always called to cleanup resources * even if update() failed, except EINPROGRESS */ err2 = stm32_hash_final(req); return err1 ?: err2; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve109100.00%1100.00%
Total109100.00%1100.00%


static int stm32_hash_digest(struct ahash_request *req) { return stm32_hash_init(req) ?: stm32_hash_finup(req); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve23100.00%1100.00%
Total23100.00%1100.00%


static int stm32_hash_export(struct ahash_request *req, void *out) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); u32 *preg; unsigned int i; while (!(stm32_hash_read(hdev, HASH_SR) & HASH_SR_DATA_INPUT_READY)) cpu_relax(); rctx->hw_context = kmalloc(sizeof(u32) * (3 + HASH_CSR_REGISTER_NUMBER), GFP_KERNEL); preg = rctx->hw_context; *preg++ = stm32_hash_read(hdev, HASH_IMR); *preg++ = stm32_hash_read(hdev, HASH_STR); *preg++ = stm32_hash_read(hdev, HASH_CR); for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); memcpy(out, rctx, sizeof(*rctx)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve175100.00%1100.00%
Total175100.00%1100.00%


static int stm32_hash_import(struct ahash_request *req, const void *in) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); const u32 *preg = in; u32 reg; unsigned int i; memcpy(rctx, in, sizeof(*rctx)); preg = rctx->hw_context; stm32_hash_write(hdev, HASH_IMR, *preg++); stm32_hash_write(hdev, HASH_STR, *preg++); stm32_hash_write(hdev, HASH_CR, *preg); reg = *preg++ | HASH_CR_INIT; stm32_hash_write(hdev, HASH_CR, reg); for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) stm32_hash_write(hdev, HASH_CSR(i), *preg++); kfree(rctx->hw_context); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve168100.00%1100.00%
Total168100.00%1100.00%


static int stm32_hash_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); if (keylen <= HASH_MAX_KEY_SIZE) { memcpy(ctx->key, key, keylen); ctx->keylen = keylen; } else { return -ENOMEM; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve65100.00%1100.00%
Total65100.00%1100.00%


static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, const char *algs_hmac_name) { struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct stm32_hash_request_ctx)); ctx->keylen = 0; if (algs_hmac_name) ctx->flags |= HASH_FLAGS_HMAC; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve59100.00%1100.00%
Total59100.00%1100.00%


static int stm32_hash_cra_init(struct crypto_tfm *tfm) { return stm32_hash_cra_init_algs(tfm, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve19100.00%1100.00%
Total19100.00%1100.00%


static int stm32_hash_cra_md5_init(struct crypto_tfm *tfm) { return stm32_hash_cra_init_algs(tfm, "md5"); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve19100.00%1100.00%
Total19100.00%1100.00%


static int stm32_hash_cra_sha1_init(struct crypto_tfm *tfm) { return stm32_hash_cra_init_algs(tfm, "sha1"); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve19100.00%1100.00%
Total19100.00%1100.00%


static int stm32_hash_cra_sha224_init(struct crypto_tfm *tfm) { return stm32_hash_cra_init_algs(tfm, "sha224"); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve19100.00%1100.00%
Total19100.00%1100.00%


static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm) { return stm32_hash_cra_init_algs(tfm, "sha256"); }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve19100.00%1100.00%
Total19100.00%1100.00%


static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) { struct stm32_hash_dev *hdev = dev_id; if (HASH_FLAGS_CPU & hdev->flags) { if (HASH_FLAGS_OUTPUT_READY & hdev->flags) { hdev->flags &= ~HASH_FLAGS_OUTPUT_READY; goto finish; } } else if (HASH_FLAGS_DMA_READY & hdev->flags) { if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) { hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE; goto finish; } } return IRQ_HANDLED; finish: /* Finish current request */ stm32_hash_finish_req(hdev->req, 0); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve99100.00%2100.00%
Total99100.00%2100.00%


static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) { struct stm32_hash_dev *hdev = dev_id; u32 reg; reg = stm32_hash_read(hdev, HASH_SR); if (reg & HASH_SR_OUTPUT_READY) { reg &= ~HASH_SR_OUTPUT_READY; stm32_hash_write(hdev, HASH_SR, reg); hdev->flags |= HASH_FLAGS_OUTPUT_READY; return IRQ_WAKE_THREAD; } return IRQ_NONE; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve66100.00%1100.00%
Total66100.00%1100.00%

static struct ahash_alg algs_md5_sha1[] = { { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "md5", .cra_driver_name = "stm32-md5", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .setkey = stm32_hash_setkey, .halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "hmac(md5)", .cra_driver_name = "stm32-hmac-md5", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_md5_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "sha1", .cra_driver_name = "stm32-sha1", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .setkey = stm32_hash_setkey, .halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "hmac(sha1)", .cra_driver_name = "stm32-hmac-sha1", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_sha1_init, .cra_module = THIS_MODULE, } } }, }; static struct ahash_alg algs_sha224_sha256[] = { { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "sha224", .cra_driver_name = "stm32-sha224", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .setkey = stm32_hash_setkey, .export = stm32_hash_export, .import = stm32_hash_import, .halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "hmac(sha224)", .cra_driver_name = "stm32-hmac-sha224", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_sha224_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "sha256", .cra_driver_name = "stm32-sha256", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_init, .cra_module = THIS_MODULE, } } }, { .init = stm32_hash_init, .update = stm32_hash_update, .final = stm32_hash_final, .finup = stm32_hash_finup, .digest = stm32_hash_digest, .export = stm32_hash_export, .import = stm32_hash_import, .setkey = stm32_hash_setkey, .halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_request_ctx), .base = { .cra_name = "hmac(sha256)", .cra_driver_name = "stm32-hmac-sha256", .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, .cra_init = stm32_hash_cra_sha256_init, .cra_module = THIS_MODULE, } } }, };
static int stm32_hash_register_algs(struct stm32_hash_dev *hdev) { unsigned int i, j; int err; for (i = 0; i < hdev->pdata->algs_info_size; i++) { for (j = 0; j < hdev->pdata->algs_info[i].size; j++) { err = crypto_register_ahash( &hdev->pdata->algs_info[i].algs_list[j]); if (err) goto err_algs; } } return 0; err_algs: dev_err(hdev->dev, "Algo %d : %d failed\n", i, j); for (; i--; ) { for (; j--;) crypto_unregister_ahash( &hdev->pdata->algs_info[i].algs_list[j]); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve145100.00%1100.00%
Total145100.00%1100.00%


static int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev) { unsigned int i, j; for (i = 0; i < hdev->pdata->algs_info_size; i++) { for (j = 0; j < hdev->pdata->algs_info[i].size; j++) crypto_unregister_ahash( &hdev->pdata->algs_info[i].algs_list[j]); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve79100.00%1100.00%
Total79100.00%1100.00%

static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = { { .algs_list = algs_md5_sha1, .size = ARRAY_SIZE(algs_md5_sha1), }, }; static const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = { .algs_info = stm32_hash_algs_info_stm32f4, .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4), }; static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { { .algs_list = algs_md5_sha1, .size = ARRAY_SIZE(algs_md5_sha1), }, { .algs_list = algs_sha224_sha256, .size = ARRAY_SIZE(algs_sha224_sha256), }, }; static const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = { .algs_info = stm32_hash_algs_info_stm32f7, .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7), }; static const struct of_device_id stm32_hash_of_match[] = { { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4, }, { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7, }, {}, }; MODULE_DEVICE_TABLE(of, stm32_hash_of_match);
static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, struct device *dev) { int err; hdev->pdata = of_device_get_match_data(dev); if (!hdev->pdata) { dev_err(dev, "no compatible OF match\n"); return -EINVAL; } err = of_property_read_u32(dev->of_node, "dma-maxburst", &hdev->dma_maxburst); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve6089.55%150.00%
Corentin Labbe710.45%150.00%
Total67100.00%2100.00%


static int stm32_hash_probe(struct platform_device *pdev) { struct stm32_hash_dev *hdev; struct device *dev = &pdev->dev; struct resource *res; int ret, irq; hdev = devm_kzalloc(dev, sizeof(*hdev), GFP_KERNEL); if (!hdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdev->io_base = devm_ioremap_resource(dev, res); if (IS_ERR(hdev->io_base)) return PTR_ERR(hdev->io_base); hdev->phys_base = res->start; ret = stm32_hash_get_of_match(hdev, dev); if (ret) return ret; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "Cannot get IRQ resource\n"); return irq; } ret = devm_request_threaded_irq(dev, irq, stm32_hash_irq_handler, stm32_hash_irq_thread, IRQF_ONESHOT, dev_name(dev), hdev); if (ret) { dev_err(dev, "Cannot grab IRQ\n"); return ret; } hdev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(hdev->clk)) { dev_err(dev, "failed to get clock for hash (%lu)\n", PTR_ERR(hdev->clk)); return PTR_ERR(hdev->clk); } ret = clk_prepare_enable(hdev->clk); if (ret) { dev_err(dev, "failed to enable hash clock (%d)\n", ret); return ret; } hdev->rst = devm_reset_control_get(&pdev->dev, NULL); if (!IS_ERR(hdev->rst)) { reset_control_assert(hdev->rst); udelay(2); reset_control_deassert(hdev->rst); } hdev->dev = dev; platform_set_drvdata(pdev, hdev); ret = stm32_hash_dma_init(hdev); if (ret) dev_dbg(dev, "DMA mode not available\n"); spin_lock(&stm32_hash.lock); list_add_tail(&hdev->list, &stm32_hash.dev_list); spin_unlock(&stm32_hash.lock); /* Initialize crypto engine */ hdev->engine = crypto_engine_alloc_init(dev, 1); if (!hdev->engine) { ret = -ENOMEM; goto err_engine; } hdev->engine->prepare_hash_request = stm32_hash_prepare_req; hdev->engine->hash_one_request = stm32_hash_one_request; ret = crypto_engine_start(hdev->engine); if (ret) goto err_engine_start; hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR); /* Register algos */ ret = stm32_hash_register_algs(hdev); if (ret) goto err_algs; dev_info(dev, "Init HASH done HW ver %x DMA mode %u\n", stm32_hash_read(hdev, HASH_VER), hdev->dma_mode); return 0; err_algs: err_engine_start: crypto_engine_exit(hdev->engine); err_engine: spin_lock(&stm32_hash.lock); list_del(&hdev->list); spin_unlock(&stm32_hash.lock); if (hdev->dma_lch) dma_release_channel(hdev->dma_lch); clk_disable_unprepare(hdev->clk); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve535100.00%1100.00%
Total535100.00%1100.00%


static int stm32_hash_remove(struct platform_device *pdev) { static struct stm32_hash_dev *hdev; hdev = platform_get_drvdata(pdev); if (!hdev) return -ENODEV; stm32_hash_unregister_algs(hdev); crypto_engine_exit(hdev->engine); spin_lock(&stm32_hash.lock); list_del(&hdev->list); spin_unlock(&stm32_hash.lock); if (hdev->dma_lch) dma_release_channel(hdev->dma_lch); clk_disable_unprepare(hdev->clk); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve92100.00%1100.00%
Total92100.00%1100.00%

static struct platform_driver stm32_hash_driver = { .probe = stm32_hash_probe, .remove = stm32_hash_remove, .driver = { .name = "stm32-hash", .of_match_table = stm32_hash_of_match, } }; module_platform_driver(stm32_hash_driver); MODULE_DESCRIPTION("STM32 SHA1/224/256 & MD5 (HMAC) hw accelerator driver"); MODULE_AUTHOR("Lionel Debieve <lionel.debieve@st.com>"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Lionel Debieve697399.30%360.00%
Arnd Bergmann420.60%120.00%
Corentin Labbe70.10%120.00%
Total7022100.00%5100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.