18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Cryptographic API. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Support for OMAP SHA1/MD5 HW acceleration. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2010 Nokia Corporation 88c2ecf20Sopenharmony_ci * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 98c2ecf20Sopenharmony_ci * Copyright (c) 2011 Texas Instruments Incorporated 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Some ideas are from old omap-sha1-md5.c driver. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "%s: " fmt, __func__ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/device.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/init.h> 208c2ecf20Sopenharmony_ci#include <linux/errno.h> 218c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 228c2ecf20Sopenharmony_ci#include <linux/kernel.h> 238c2ecf20Sopenharmony_ci#include <linux/irq.h> 248c2ecf20Sopenharmony_ci#include <linux/io.h> 258c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 268c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 278c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 288c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 298c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 308c2ecf20Sopenharmony_ci#include <linux/of.h> 318c2ecf20Sopenharmony_ci#include <linux/of_device.h> 328c2ecf20Sopenharmony_ci#include <linux/of_address.h> 338c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 348c2ecf20Sopenharmony_ci#include <linux/delay.h> 358c2ecf20Sopenharmony_ci#include <linux/crypto.h> 368c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 378c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 388c2ecf20Sopenharmony_ci#include <crypto/sha.h> 398c2ecf20Sopenharmony_ci#include <crypto/hash.h> 408c2ecf20Sopenharmony_ci#include <crypto/hmac.h> 418c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 428c2ecf20Sopenharmony_ci#include <crypto/engine.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define MD5_DIGEST_SIZE 16 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define SHA_REG_IDIGEST(dd, x) ((dd)->pdata->idigest_ofs + ((x)*0x04)) 478c2ecf20Sopenharmony_ci#define SHA_REG_DIN(dd, x) ((dd)->pdata->din_ofs + ((x) * 0x04)) 488c2ecf20Sopenharmony_ci#define SHA_REG_DIGCNT(dd) ((dd)->pdata->digcnt_ofs) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define SHA_REG_ODIGEST(dd, x) ((dd)->pdata->odigest_ofs + (x * 0x04)) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define SHA_REG_CTRL 0x18 538c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_LENGTH (0xFFFFFFFF << 5) 548c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_CLOSE_HASH (1 << 4) 558c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_ALGO_CONST (1 << 3) 568c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_ALGO (1 << 2) 578c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_INPUT_READY (1 << 1) 588c2ecf20Sopenharmony_ci#define SHA_REG_CTRL_OUTPUT_READY (1 << 0) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define SHA_REG_REV(dd) ((dd)->pdata->rev_ofs) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define SHA_REG_MASK(dd) ((dd)->pdata->mask_ofs) 638c2ecf20Sopenharmony_ci#define SHA_REG_MASK_DMA_EN (1 << 3) 648c2ecf20Sopenharmony_ci#define SHA_REG_MASK_IT_EN (1 << 2) 658c2ecf20Sopenharmony_ci#define SHA_REG_MASK_SOFTRESET (1 << 1) 668c2ecf20Sopenharmony_ci#define SHA_REG_AUTOIDLE (1 << 0) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define SHA_REG_SYSSTATUS(dd) ((dd)->pdata->sysstatus_ofs) 698c2ecf20Sopenharmony_ci#define SHA_REG_SYSSTATUS_RESETDONE (1 << 0) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define SHA_REG_MODE(dd) ((dd)->pdata->mode_ofs) 728c2ecf20Sopenharmony_ci#define SHA_REG_MODE_HMAC_OUTER_HASH (1 << 7) 738c2ecf20Sopenharmony_ci#define SHA_REG_MODE_HMAC_KEY_PROC (1 << 5) 748c2ecf20Sopenharmony_ci#define SHA_REG_MODE_CLOSE_HASH (1 << 4) 758c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_CONSTANT (1 << 3) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_MASK (7 << 0) 788c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_MD5_128 (0 << 1) 798c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1) 808c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_SHA2_224 (2 << 1) 818c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_SHA2_256 (3 << 1) 828c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_SHA2_384 (1 << 0) 838c2ecf20Sopenharmony_ci#define SHA_REG_MODE_ALGO_SHA2_512 (3 << 0) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define SHA_REG_LENGTH(dd) ((dd)->pdata->length_ofs) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define SHA_REG_IRQSTATUS 0x118 888c2ecf20Sopenharmony_ci#define SHA_REG_IRQSTATUS_CTX_RDY (1 << 3) 898c2ecf20Sopenharmony_ci#define SHA_REG_IRQSTATUS_PARTHASH_RDY (1 << 2) 908c2ecf20Sopenharmony_ci#define SHA_REG_IRQSTATUS_INPUT_RDY (1 << 1) 918c2ecf20Sopenharmony_ci#define SHA_REG_IRQSTATUS_OUTPUT_RDY (1 << 0) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define SHA_REG_IRQENA 0x11C 948c2ecf20Sopenharmony_ci#define SHA_REG_IRQENA_CTX_RDY (1 << 3) 958c2ecf20Sopenharmony_ci#define SHA_REG_IRQENA_PARTHASH_RDY (1 << 2) 968c2ecf20Sopenharmony_ci#define SHA_REG_IRQENA_INPUT_RDY (1 << 1) 978c2ecf20Sopenharmony_ci#define SHA_REG_IRQENA_OUTPUT_RDY (1 << 0) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#define DEFAULT_TIMEOUT_INTERVAL HZ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define DEFAULT_AUTOSUSPEND_DELAY 1000 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* mostly device flags */ 1048c2ecf20Sopenharmony_ci#define FLAGS_FINAL 1 1058c2ecf20Sopenharmony_ci#define FLAGS_DMA_ACTIVE 2 1068c2ecf20Sopenharmony_ci#define FLAGS_OUTPUT_READY 3 1078c2ecf20Sopenharmony_ci#define FLAGS_INIT 4 1088c2ecf20Sopenharmony_ci#define FLAGS_CPU 5 1098c2ecf20Sopenharmony_ci#define FLAGS_DMA_READY 6 1108c2ecf20Sopenharmony_ci#define FLAGS_AUTO_XOR 7 1118c2ecf20Sopenharmony_ci#define FLAGS_BE32_SHA1 8 1128c2ecf20Sopenharmony_ci#define FLAGS_SGS_COPIED 9 1138c2ecf20Sopenharmony_ci#define FLAGS_SGS_ALLOCED 10 1148c2ecf20Sopenharmony_ci#define FLAGS_HUGE 11 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* context flags */ 1178c2ecf20Sopenharmony_ci#define FLAGS_FINUP 16 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHIFT 18 1208c2ecf20Sopenharmony_ci#define FLAGS_MODE_MASK (SHA_REG_MODE_ALGO_MASK << FLAGS_MODE_SHIFT) 1218c2ecf20Sopenharmony_ci#define FLAGS_MODE_MD5 (SHA_REG_MODE_ALGO_MD5_128 << FLAGS_MODE_SHIFT) 1228c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 << FLAGS_MODE_SHIFT) 1238c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHA224 (SHA_REG_MODE_ALGO_SHA2_224 << FLAGS_MODE_SHIFT) 1248c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHA256 (SHA_REG_MODE_ALGO_SHA2_256 << FLAGS_MODE_SHIFT) 1258c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHA384 (SHA_REG_MODE_ALGO_SHA2_384 << FLAGS_MODE_SHIFT) 1268c2ecf20Sopenharmony_ci#define FLAGS_MODE_SHA512 (SHA_REG_MODE_ALGO_SHA2_512 << FLAGS_MODE_SHIFT) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define FLAGS_HMAC 21 1298c2ecf20Sopenharmony_ci#define FLAGS_ERROR 22 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define OP_UPDATE 1 1328c2ecf20Sopenharmony_ci#define OP_FINAL 2 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define OMAP_ALIGN_MASK (sizeof(u32)-1) 1358c2ecf20Sopenharmony_ci#define OMAP_ALIGNED __attribute__((aligned(sizeof(u32)))) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define BUFLEN SHA512_BLOCK_SIZE 1388c2ecf20Sopenharmony_ci#define OMAP_SHA_DMA_THRESHOLD 256 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#define OMAP_SHA_MAX_DMA_LEN (1024 * 2048) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistruct omap_sham_dev; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistruct omap_sham_reqctx { 1458c2ecf20Sopenharmony_ci struct omap_sham_dev *dd; 1468c2ecf20Sopenharmony_ci unsigned long flags; 1478c2ecf20Sopenharmony_ci u8 op; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci u8 digest[SHA512_DIGEST_SIZE] OMAP_ALIGNED; 1508c2ecf20Sopenharmony_ci size_t digcnt; 1518c2ecf20Sopenharmony_ci size_t bufcnt; 1528c2ecf20Sopenharmony_ci size_t buflen; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* walk state */ 1558c2ecf20Sopenharmony_ci struct scatterlist *sg; 1568c2ecf20Sopenharmony_ci struct scatterlist sgl[2]; 1578c2ecf20Sopenharmony_ci int offset; /* offset in current sg */ 1588c2ecf20Sopenharmony_ci int sg_len; 1598c2ecf20Sopenharmony_ci unsigned int total; /* total request */ 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci u8 buffer[] OMAP_ALIGNED; 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistruct omap_sham_hmac_ctx { 1658c2ecf20Sopenharmony_ci struct crypto_shash *shash; 1668c2ecf20Sopenharmony_ci u8 ipad[SHA512_BLOCK_SIZE] OMAP_ALIGNED; 1678c2ecf20Sopenharmony_ci u8 opad[SHA512_BLOCK_SIZE] OMAP_ALIGNED; 1688c2ecf20Sopenharmony_ci}; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistruct omap_sham_ctx { 1718c2ecf20Sopenharmony_ci struct crypto_engine_ctx enginectx; 1728c2ecf20Sopenharmony_ci unsigned long flags; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci /* fallback stuff */ 1758c2ecf20Sopenharmony_ci struct crypto_shash *fallback; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx base[]; 1788c2ecf20Sopenharmony_ci}; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci#define OMAP_SHAM_QUEUE_LENGTH 10 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistruct omap_sham_algs_info { 1838c2ecf20Sopenharmony_ci struct ahash_alg *algs_list; 1848c2ecf20Sopenharmony_ci unsigned int size; 1858c2ecf20Sopenharmony_ci unsigned int registered; 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistruct omap_sham_pdata { 1898c2ecf20Sopenharmony_ci struct omap_sham_algs_info *algs_info; 1908c2ecf20Sopenharmony_ci unsigned int algs_info_size; 1918c2ecf20Sopenharmony_ci unsigned long flags; 1928c2ecf20Sopenharmony_ci int digest_size; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci void (*copy_hash)(struct ahash_request *req, int out); 1958c2ecf20Sopenharmony_ci void (*write_ctrl)(struct omap_sham_dev *dd, size_t length, 1968c2ecf20Sopenharmony_ci int final, int dma); 1978c2ecf20Sopenharmony_ci void (*trigger)(struct omap_sham_dev *dd, size_t length); 1988c2ecf20Sopenharmony_ci int (*poll_irq)(struct omap_sham_dev *dd); 1998c2ecf20Sopenharmony_ci irqreturn_t (*intr_hdlr)(int irq, void *dev_id); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci u32 odigest_ofs; 2028c2ecf20Sopenharmony_ci u32 idigest_ofs; 2038c2ecf20Sopenharmony_ci u32 din_ofs; 2048c2ecf20Sopenharmony_ci u32 digcnt_ofs; 2058c2ecf20Sopenharmony_ci u32 rev_ofs; 2068c2ecf20Sopenharmony_ci u32 mask_ofs; 2078c2ecf20Sopenharmony_ci u32 sysstatus_ofs; 2088c2ecf20Sopenharmony_ci u32 mode_ofs; 2098c2ecf20Sopenharmony_ci u32 length_ofs; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci u32 major_mask; 2128c2ecf20Sopenharmony_ci u32 major_shift; 2138c2ecf20Sopenharmony_ci u32 minor_mask; 2148c2ecf20Sopenharmony_ci u32 minor_shift; 2158c2ecf20Sopenharmony_ci}; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistruct omap_sham_dev { 2188c2ecf20Sopenharmony_ci struct list_head list; 2198c2ecf20Sopenharmony_ci unsigned long phys_base; 2208c2ecf20Sopenharmony_ci struct device *dev; 2218c2ecf20Sopenharmony_ci void __iomem *io_base; 2228c2ecf20Sopenharmony_ci int irq; 2238c2ecf20Sopenharmony_ci int err; 2248c2ecf20Sopenharmony_ci struct dma_chan *dma_lch; 2258c2ecf20Sopenharmony_ci struct tasklet_struct done_task; 2268c2ecf20Sopenharmony_ci u8 polling_mode; 2278c2ecf20Sopenharmony_ci u8 xmit_buf[BUFLEN] OMAP_ALIGNED; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci unsigned long flags; 2308c2ecf20Sopenharmony_ci int fallback_sz; 2318c2ecf20Sopenharmony_ci struct crypto_queue queue; 2328c2ecf20Sopenharmony_ci struct ahash_request *req; 2338c2ecf20Sopenharmony_ci struct crypto_engine *engine; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci const struct omap_sham_pdata *pdata; 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistruct omap_sham_drv { 2398c2ecf20Sopenharmony_ci struct list_head dev_list; 2408c2ecf20Sopenharmony_ci spinlock_t lock; 2418c2ecf20Sopenharmony_ci unsigned long flags; 2428c2ecf20Sopenharmony_ci}; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic struct omap_sham_drv sham = { 2458c2ecf20Sopenharmony_ci .dev_list = LIST_HEAD_INIT(sham.dev_list), 2468c2ecf20Sopenharmony_ci .lock = __SPIN_LOCK_UNLOCKED(sham.lock), 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int omap_sham_enqueue(struct ahash_request *req, unsigned int op); 2508c2ecf20Sopenharmony_cistatic void omap_sham_finish_req(struct ahash_request *req, int err); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic inline u32 omap_sham_read(struct omap_sham_dev *dd, u32 offset) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci return __raw_readl(dd->io_base + offset); 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic inline void omap_sham_write(struct omap_sham_dev *dd, 2588c2ecf20Sopenharmony_ci u32 offset, u32 value) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci __raw_writel(value, dd->io_base + offset); 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic inline void omap_sham_write_mask(struct omap_sham_dev *dd, u32 address, 2648c2ecf20Sopenharmony_ci u32 value, u32 mask) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci u32 val; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci val = omap_sham_read(dd, address); 2698c2ecf20Sopenharmony_ci val &= ~mask; 2708c2ecf20Sopenharmony_ci val |= value; 2718c2ecf20Sopenharmony_ci omap_sham_write(dd, address, val); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci unsigned long timeout = jiffies + DEFAULT_TIMEOUT_INTERVAL; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci while (!(omap_sham_read(dd, offset) & bit)) { 2798c2ecf20Sopenharmony_ci if (time_is_before_jiffies(timeout)) 2808c2ecf20Sopenharmony_ci return -ETIMEDOUT; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci return 0; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic void omap_sham_copy_hash_omap2(struct ahash_request *req, int out) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 2898c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 2908c2ecf20Sopenharmony_ci u32 *hash = (u32 *)ctx->digest; 2918c2ecf20Sopenharmony_ci int i; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) { 2948c2ecf20Sopenharmony_ci if (out) 2958c2ecf20Sopenharmony_ci hash[i] = omap_sham_read(dd, SHA_REG_IDIGEST(dd, i)); 2968c2ecf20Sopenharmony_ci else 2978c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_IDIGEST(dd, i), hash[i]); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic void omap_sham_copy_hash_omap4(struct ahash_request *req, int out) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 3048c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 3058c2ecf20Sopenharmony_ci int i; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (ctx->flags & BIT(FLAGS_HMAC)) { 3088c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req); 3098c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm); 3108c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 3118c2ecf20Sopenharmony_ci u32 *opad = (u32 *)bctx->opad; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) { 3148c2ecf20Sopenharmony_ci if (out) 3158c2ecf20Sopenharmony_ci opad[i] = omap_sham_read(dd, 3168c2ecf20Sopenharmony_ci SHA_REG_ODIGEST(dd, i)); 3178c2ecf20Sopenharmony_ci else 3188c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_ODIGEST(dd, i), 3198c2ecf20Sopenharmony_ci opad[i]); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci omap_sham_copy_hash_omap2(req, out); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic void omap_sham_copy_ready_hash(struct ahash_request *req) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 3298c2ecf20Sopenharmony_ci u32 *in = (u32 *)ctx->digest; 3308c2ecf20Sopenharmony_ci u32 *hash = (u32 *)req->result; 3318c2ecf20Sopenharmony_ci int i, d, big_endian = 0; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (!hash) 3348c2ecf20Sopenharmony_ci return; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci switch (ctx->flags & FLAGS_MODE_MASK) { 3378c2ecf20Sopenharmony_ci case FLAGS_MODE_MD5: 3388c2ecf20Sopenharmony_ci d = MD5_DIGEST_SIZE / sizeof(u32); 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA1: 3418c2ecf20Sopenharmony_ci /* OMAP2 SHA1 is big endian */ 3428c2ecf20Sopenharmony_ci if (test_bit(FLAGS_BE32_SHA1, &ctx->dd->flags)) 3438c2ecf20Sopenharmony_ci big_endian = 1; 3448c2ecf20Sopenharmony_ci d = SHA1_DIGEST_SIZE / sizeof(u32); 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA224: 3478c2ecf20Sopenharmony_ci d = SHA224_DIGEST_SIZE / sizeof(u32); 3488c2ecf20Sopenharmony_ci break; 3498c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA256: 3508c2ecf20Sopenharmony_ci d = SHA256_DIGEST_SIZE / sizeof(u32); 3518c2ecf20Sopenharmony_ci break; 3528c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA384: 3538c2ecf20Sopenharmony_ci d = SHA384_DIGEST_SIZE / sizeof(u32); 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA512: 3568c2ecf20Sopenharmony_ci d = SHA512_DIGEST_SIZE / sizeof(u32); 3578c2ecf20Sopenharmony_ci break; 3588c2ecf20Sopenharmony_ci default: 3598c2ecf20Sopenharmony_ci d = 0; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (big_endian) 3638c2ecf20Sopenharmony_ci for (i = 0; i < d; i++) 3648c2ecf20Sopenharmony_ci hash[i] = be32_to_cpup((__be32 *)in + i); 3658c2ecf20Sopenharmony_ci else 3668c2ecf20Sopenharmony_ci for (i = 0; i < d; i++) 3678c2ecf20Sopenharmony_ci hash[i] = le32_to_cpup((__le32 *)in + i); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic int omap_sham_hw_init(struct omap_sham_dev *dd) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci int err; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci err = pm_runtime_resume_and_get(dd->dev); 3758c2ecf20Sopenharmony_ci if (err < 0) { 3768c2ecf20Sopenharmony_ci dev_err(dd->dev, "failed to get sync: %d\n", err); 3778c2ecf20Sopenharmony_ci return err; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (!test_bit(FLAGS_INIT, &dd->flags)) { 3818c2ecf20Sopenharmony_ci set_bit(FLAGS_INIT, &dd->flags); 3828c2ecf20Sopenharmony_ci dd->err = 0; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return 0; 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length, 3898c2ecf20Sopenharmony_ci int final, int dma) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 3928c2ecf20Sopenharmony_ci u32 val = length << 5, mask; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (likely(ctx->digcnt)) 3958c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_MASK(dd), 3988c2ecf20Sopenharmony_ci SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0), 3998c2ecf20Sopenharmony_ci SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN); 4008c2ecf20Sopenharmony_ci /* 4018c2ecf20Sopenharmony_ci * Setting ALGO_CONST only for the first iteration 4028c2ecf20Sopenharmony_ci * and CLOSE_HASH only for the last one. 4038c2ecf20Sopenharmony_ci */ 4048c2ecf20Sopenharmony_ci if ((ctx->flags & FLAGS_MODE_MASK) == FLAGS_MODE_SHA1) 4058c2ecf20Sopenharmony_ci val |= SHA_REG_CTRL_ALGO; 4068c2ecf20Sopenharmony_ci if (!ctx->digcnt) 4078c2ecf20Sopenharmony_ci val |= SHA_REG_CTRL_ALGO_CONST; 4088c2ecf20Sopenharmony_ci if (final) 4098c2ecf20Sopenharmony_ci val |= SHA_REG_CTRL_CLOSE_HASH; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci mask = SHA_REG_CTRL_ALGO_CONST | SHA_REG_CTRL_CLOSE_HASH | 4128c2ecf20Sopenharmony_ci SHA_REG_CTRL_ALGO | SHA_REG_CTRL_LENGTH; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY); 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int get_block_size(struct omap_sham_reqctx *ctx) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci int d; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci switch (ctx->flags & FLAGS_MODE_MASK) { 4318c2ecf20Sopenharmony_ci case FLAGS_MODE_MD5: 4328c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA1: 4338c2ecf20Sopenharmony_ci d = SHA1_BLOCK_SIZE; 4348c2ecf20Sopenharmony_ci break; 4358c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA224: 4368c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA256: 4378c2ecf20Sopenharmony_ci d = SHA256_BLOCK_SIZE; 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA384: 4408c2ecf20Sopenharmony_ci case FLAGS_MODE_SHA512: 4418c2ecf20Sopenharmony_ci d = SHA512_BLOCK_SIZE; 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci default: 4448c2ecf20Sopenharmony_ci d = 0; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci return d; 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset, 4518c2ecf20Sopenharmony_ci u32 *value, int count) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci for (; count--; value++, offset += 4) 4548c2ecf20Sopenharmony_ci omap_sham_write(dd, offset, *value); 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length, 4588c2ecf20Sopenharmony_ci int final, int dma) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 4618c2ecf20Sopenharmony_ci u32 val, mask; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (likely(ctx->digcnt)) 4648c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* 4678c2ecf20Sopenharmony_ci * Setting ALGO_CONST only for the first iteration and 4688c2ecf20Sopenharmony_ci * CLOSE_HASH only for the last one. Note that flags mode bits 4698c2ecf20Sopenharmony_ci * correspond to algorithm encoding in mode register. 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_ci val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT); 4728c2ecf20Sopenharmony_ci if (!ctx->digcnt) { 4738c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req); 4748c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm); 4758c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 4768c2ecf20Sopenharmony_ci int bs, nr_dr; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci val |= SHA_REG_MODE_ALGO_CONSTANT; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (ctx->flags & BIT(FLAGS_HMAC)) { 4818c2ecf20Sopenharmony_ci bs = get_block_size(ctx); 4828c2ecf20Sopenharmony_ci nr_dr = bs / (2 * sizeof(u32)); 4838c2ecf20Sopenharmony_ci val |= SHA_REG_MODE_HMAC_KEY_PROC; 4848c2ecf20Sopenharmony_ci omap_sham_write_n(dd, SHA_REG_ODIGEST(dd, 0), 4858c2ecf20Sopenharmony_ci (u32 *)bctx->ipad, nr_dr); 4868c2ecf20Sopenharmony_ci omap_sham_write_n(dd, SHA_REG_IDIGEST(dd, 0), 4878c2ecf20Sopenharmony_ci (u32 *)bctx->ipad + nr_dr, nr_dr); 4888c2ecf20Sopenharmony_ci ctx->digcnt += bs; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (final) { 4938c2ecf20Sopenharmony_ci val |= SHA_REG_MODE_CLOSE_HASH; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (ctx->flags & BIT(FLAGS_HMAC)) 4968c2ecf20Sopenharmony_ci val |= SHA_REG_MODE_HMAC_OUTER_HASH; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci mask = SHA_REG_MODE_ALGO_CONSTANT | SHA_REG_MODE_CLOSE_HASH | 5008c2ecf20Sopenharmony_ci SHA_REG_MODE_ALGO_MASK | SHA_REG_MODE_HMAC_OUTER_HASH | 5018c2ecf20Sopenharmony_ci SHA_REG_MODE_HMAC_KEY_PROC; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx\n", val, ctx->flags); 5048c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_MODE(dd), val, mask); 5058c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY); 5068c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_MASK(dd), 5078c2ecf20Sopenharmony_ci SHA_REG_MASK_IT_EN | 5088c2ecf20Sopenharmony_ci (dma ? SHA_REG_MASK_DMA_EN : 0), 5098c2ecf20Sopenharmony_ci SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN); 5108c2ecf20Sopenharmony_ci} 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_cistatic void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_LENGTH(dd), length); 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_cistatic int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci return omap_sham_wait(dd, SHA_REG_IRQSTATUS, 5208c2ecf20Sopenharmony_ci SHA_REG_IRQSTATUS_INPUT_RDY); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic int omap_sham_xmit_cpu(struct omap_sham_dev *dd, size_t length, 5248c2ecf20Sopenharmony_ci int final) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 5278c2ecf20Sopenharmony_ci int count, len32, bs32, offset = 0; 5288c2ecf20Sopenharmony_ci const u32 *buffer; 5298c2ecf20Sopenharmony_ci int mlen; 5308c2ecf20Sopenharmony_ci struct sg_mapping_iter mi; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "xmit_cpu: digcnt: %zd, length: %zd, final: %d\n", 5338c2ecf20Sopenharmony_ci ctx->digcnt, length, final); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci dd->pdata->write_ctrl(dd, length, final, 0); 5368c2ecf20Sopenharmony_ci dd->pdata->trigger(dd, length); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* should be non-zero before next lines to disable clocks later */ 5398c2ecf20Sopenharmony_ci ctx->digcnt += length; 5408c2ecf20Sopenharmony_ci ctx->total -= length; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci if (final) 5438c2ecf20Sopenharmony_ci set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */ 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci set_bit(FLAGS_CPU, &dd->flags); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci len32 = DIV_ROUND_UP(length, sizeof(u32)); 5488c2ecf20Sopenharmony_ci bs32 = get_block_size(ctx) / sizeof(u32); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci sg_miter_start(&mi, ctx->sg, ctx->sg_len, 5518c2ecf20Sopenharmony_ci SG_MITER_FROM_SG | SG_MITER_ATOMIC); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci mlen = 0; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci while (len32) { 5568c2ecf20Sopenharmony_ci if (dd->pdata->poll_irq(dd)) 5578c2ecf20Sopenharmony_ci return -ETIMEDOUT; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci for (count = 0; count < min(len32, bs32); count++, offset++) { 5608c2ecf20Sopenharmony_ci if (!mlen) { 5618c2ecf20Sopenharmony_ci sg_miter_next(&mi); 5628c2ecf20Sopenharmony_ci mlen = mi.length; 5638c2ecf20Sopenharmony_ci if (!mlen) { 5648c2ecf20Sopenharmony_ci pr_err("sg miter failure.\n"); 5658c2ecf20Sopenharmony_ci return -EINVAL; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci offset = 0; 5688c2ecf20Sopenharmony_ci buffer = mi.addr; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci omap_sham_write(dd, SHA_REG_DIN(dd, count), 5718c2ecf20Sopenharmony_ci buffer[offset]); 5728c2ecf20Sopenharmony_ci mlen -= 4; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci len32 -= min(len32, bs32); 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci sg_miter_stop(&mi); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci return -EINPROGRESS; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic void omap_sham_dma_callback(void *param) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = param; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci set_bit(FLAGS_DMA_READY, &dd->flags); 5878c2ecf20Sopenharmony_ci tasklet_schedule(&dd->done_task); 5888c2ecf20Sopenharmony_ci} 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_cistatic int omap_sham_xmit_dma(struct omap_sham_dev *dd, size_t length, 5918c2ecf20Sopenharmony_ci int final) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 5948c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *tx; 5958c2ecf20Sopenharmony_ci struct dma_slave_config cfg; 5968c2ecf20Sopenharmony_ci int ret; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "xmit_dma: digcnt: %zd, length: %zd, final: %d\n", 5998c2ecf20Sopenharmony_ci ctx->digcnt, length, final); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (!dma_map_sg(dd->dev, ctx->sg, ctx->sg_len, DMA_TO_DEVICE)) { 6028c2ecf20Sopenharmony_ci dev_err(dd->dev, "dma_map_sg error\n"); 6038c2ecf20Sopenharmony_ci return -EINVAL; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci cfg.dst_addr = dd->phys_base + SHA_REG_DIN(dd, 0); 6098c2ecf20Sopenharmony_ci cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 6108c2ecf20Sopenharmony_ci cfg.dst_maxburst = get_block_size(ctx) / DMA_SLAVE_BUSWIDTH_4_BYTES; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(dd->dma_lch, &cfg); 6138c2ecf20Sopenharmony_ci if (ret) { 6148c2ecf20Sopenharmony_ci pr_err("omap-sham: can't configure dmaengine slave: %d\n", ret); 6158c2ecf20Sopenharmony_ci return ret; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci tx = dmaengine_prep_slave_sg(dd->dma_lch, ctx->sg, ctx->sg_len, 6198c2ecf20Sopenharmony_ci DMA_MEM_TO_DEV, 6208c2ecf20Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (!tx) { 6238c2ecf20Sopenharmony_ci dev_err(dd->dev, "prep_slave_sg failed\n"); 6248c2ecf20Sopenharmony_ci return -EINVAL; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci tx->callback = omap_sham_dma_callback; 6288c2ecf20Sopenharmony_ci tx->callback_param = dd; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci dd->pdata->write_ctrl(dd, length, final, 1); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci ctx->digcnt += length; 6338c2ecf20Sopenharmony_ci ctx->total -= length; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci if (final) 6368c2ecf20Sopenharmony_ci set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */ 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci set_bit(FLAGS_DMA_ACTIVE, &dd->flags); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci dmaengine_submit(tx); 6418c2ecf20Sopenharmony_ci dma_async_issue_pending(dd->dma_lch); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci dd->pdata->trigger(dd, length); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci return -EINPROGRESS; 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic int omap_sham_copy_sg_lists(struct omap_sham_reqctx *ctx, 6498c2ecf20Sopenharmony_ci struct scatterlist *sg, int bs, int new_len) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci int n = sg_nents(sg); 6528c2ecf20Sopenharmony_ci struct scatterlist *tmp; 6538c2ecf20Sopenharmony_ci int offset = ctx->offset; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci ctx->total = new_len; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (ctx->bufcnt) 6588c2ecf20Sopenharmony_ci n++; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci ctx->sg = kmalloc_array(n, sizeof(*sg), GFP_KERNEL); 6618c2ecf20Sopenharmony_ci if (!ctx->sg) 6628c2ecf20Sopenharmony_ci return -ENOMEM; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci sg_init_table(ctx->sg, n); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci tmp = ctx->sg; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci ctx->sg_len = 0; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (ctx->bufcnt) { 6718c2ecf20Sopenharmony_ci sg_set_buf(tmp, ctx->dd->xmit_buf, ctx->bufcnt); 6728c2ecf20Sopenharmony_ci tmp = sg_next(tmp); 6738c2ecf20Sopenharmony_ci ctx->sg_len++; 6748c2ecf20Sopenharmony_ci new_len -= ctx->bufcnt; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci while (sg && new_len) { 6788c2ecf20Sopenharmony_ci int len = sg->length - offset; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci if (len <= 0) { 6818c2ecf20Sopenharmony_ci offset -= sg->length; 6828c2ecf20Sopenharmony_ci sg = sg_next(sg); 6838c2ecf20Sopenharmony_ci continue; 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci if (new_len < len) 6878c2ecf20Sopenharmony_ci len = new_len; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (len > 0) { 6908c2ecf20Sopenharmony_ci new_len -= len; 6918c2ecf20Sopenharmony_ci sg_set_page(tmp, sg_page(sg), len, sg->offset + offset); 6928c2ecf20Sopenharmony_ci offset = 0; 6938c2ecf20Sopenharmony_ci ctx->offset = 0; 6948c2ecf20Sopenharmony_ci ctx->sg_len++; 6958c2ecf20Sopenharmony_ci if (new_len <= 0) 6968c2ecf20Sopenharmony_ci break; 6978c2ecf20Sopenharmony_ci tmp = sg_next(tmp); 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci sg = sg_next(sg); 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (tmp) 7048c2ecf20Sopenharmony_ci sg_mark_end(tmp); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci set_bit(FLAGS_SGS_ALLOCED, &ctx->dd->flags); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci ctx->offset += new_len - ctx->bufcnt; 7098c2ecf20Sopenharmony_ci ctx->bufcnt = 0; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci return 0; 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic int omap_sham_copy_sgs(struct omap_sham_reqctx *ctx, 7158c2ecf20Sopenharmony_ci struct scatterlist *sg, int bs, 7168c2ecf20Sopenharmony_ci unsigned int new_len) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci int pages; 7198c2ecf20Sopenharmony_ci void *buf; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci pages = get_order(new_len); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci buf = (void *)__get_free_pages(GFP_ATOMIC, pages); 7248c2ecf20Sopenharmony_ci if (!buf) { 7258c2ecf20Sopenharmony_ci pr_err("Couldn't allocate pages for unaligned cases.\n"); 7268c2ecf20Sopenharmony_ci return -ENOMEM; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci if (ctx->bufcnt) 7308c2ecf20Sopenharmony_ci memcpy(buf, ctx->dd->xmit_buf, ctx->bufcnt); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(buf + ctx->bufcnt, sg, ctx->offset, 7338c2ecf20Sopenharmony_ci min(new_len, ctx->total) - ctx->bufcnt, 0); 7348c2ecf20Sopenharmony_ci sg_init_table(ctx->sgl, 1); 7358c2ecf20Sopenharmony_ci sg_set_buf(ctx->sgl, buf, new_len); 7368c2ecf20Sopenharmony_ci ctx->sg = ctx->sgl; 7378c2ecf20Sopenharmony_ci set_bit(FLAGS_SGS_COPIED, &ctx->dd->flags); 7388c2ecf20Sopenharmony_ci ctx->sg_len = 1; 7398c2ecf20Sopenharmony_ci ctx->offset += new_len - ctx->bufcnt; 7408c2ecf20Sopenharmony_ci ctx->bufcnt = 0; 7418c2ecf20Sopenharmony_ci ctx->total = new_len; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci return 0; 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic int omap_sham_align_sgs(struct scatterlist *sg, 7478c2ecf20Sopenharmony_ci int nbytes, int bs, bool final, 7488c2ecf20Sopenharmony_ci struct omap_sham_reqctx *rctx) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci int n = 0; 7518c2ecf20Sopenharmony_ci bool aligned = true; 7528c2ecf20Sopenharmony_ci bool list_ok = true; 7538c2ecf20Sopenharmony_ci struct scatterlist *sg_tmp = sg; 7548c2ecf20Sopenharmony_ci int new_len; 7558c2ecf20Sopenharmony_ci int offset = rctx->offset; 7568c2ecf20Sopenharmony_ci int bufcnt = rctx->bufcnt; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci if (!sg || !sg->length || !nbytes) { 7598c2ecf20Sopenharmony_ci if (bufcnt) { 7608c2ecf20Sopenharmony_ci bufcnt = DIV_ROUND_UP(bufcnt, bs) * bs; 7618c2ecf20Sopenharmony_ci sg_init_table(rctx->sgl, 1); 7628c2ecf20Sopenharmony_ci sg_set_buf(rctx->sgl, rctx->dd->xmit_buf, bufcnt); 7638c2ecf20Sopenharmony_ci rctx->sg = rctx->sgl; 7648c2ecf20Sopenharmony_ci rctx->sg_len = 1; 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci return 0; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci new_len = nbytes; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (offset) 7738c2ecf20Sopenharmony_ci list_ok = false; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci if (final) 7768c2ecf20Sopenharmony_ci new_len = DIV_ROUND_UP(new_len, bs) * bs; 7778c2ecf20Sopenharmony_ci else 7788c2ecf20Sopenharmony_ci new_len = (new_len - 1) / bs * bs; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci if (!new_len) 7818c2ecf20Sopenharmony_ci return 0; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci if (nbytes != new_len) 7848c2ecf20Sopenharmony_ci list_ok = false; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci while (nbytes > 0 && sg_tmp) { 7878c2ecf20Sopenharmony_ci n++; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci if (bufcnt) { 7908c2ecf20Sopenharmony_ci if (!IS_ALIGNED(bufcnt, bs)) { 7918c2ecf20Sopenharmony_ci aligned = false; 7928c2ecf20Sopenharmony_ci break; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci nbytes -= bufcnt; 7958c2ecf20Sopenharmony_ci bufcnt = 0; 7968c2ecf20Sopenharmony_ci if (!nbytes) 7978c2ecf20Sopenharmony_ci list_ok = false; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci continue; 8008c2ecf20Sopenharmony_ci } 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci#ifdef CONFIG_ZONE_DMA 8038c2ecf20Sopenharmony_ci if (page_zonenum(sg_page(sg_tmp)) != ZONE_DMA) { 8048c2ecf20Sopenharmony_ci aligned = false; 8058c2ecf20Sopenharmony_ci break; 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci#endif 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci if (offset < sg_tmp->length) { 8108c2ecf20Sopenharmony_ci if (!IS_ALIGNED(offset + sg_tmp->offset, 4)) { 8118c2ecf20Sopenharmony_ci aligned = false; 8128c2ecf20Sopenharmony_ci break; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci if (!IS_ALIGNED(sg_tmp->length - offset, bs)) { 8168c2ecf20Sopenharmony_ci aligned = false; 8178c2ecf20Sopenharmony_ci break; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci if (offset) { 8228c2ecf20Sopenharmony_ci offset -= sg_tmp->length; 8238c2ecf20Sopenharmony_ci if (offset < 0) { 8248c2ecf20Sopenharmony_ci nbytes += offset; 8258c2ecf20Sopenharmony_ci offset = 0; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci } else { 8288c2ecf20Sopenharmony_ci nbytes -= sg_tmp->length; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci sg_tmp = sg_next(sg_tmp); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci if (nbytes < 0) { 8348c2ecf20Sopenharmony_ci list_ok = false; 8358c2ecf20Sopenharmony_ci break; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci if (new_len > OMAP_SHA_MAX_DMA_LEN) { 8408c2ecf20Sopenharmony_ci new_len = OMAP_SHA_MAX_DMA_LEN; 8418c2ecf20Sopenharmony_ci aligned = false; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (!aligned) 8458c2ecf20Sopenharmony_ci return omap_sham_copy_sgs(rctx, sg, bs, new_len); 8468c2ecf20Sopenharmony_ci else if (!list_ok) 8478c2ecf20Sopenharmony_ci return omap_sham_copy_sg_lists(rctx, sg, bs, new_len); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci rctx->total = new_len; 8508c2ecf20Sopenharmony_ci rctx->offset += new_len; 8518c2ecf20Sopenharmony_ci rctx->sg_len = n; 8528c2ecf20Sopenharmony_ci if (rctx->bufcnt) { 8538c2ecf20Sopenharmony_ci sg_init_table(rctx->sgl, 2); 8548c2ecf20Sopenharmony_ci sg_set_buf(rctx->sgl, rctx->dd->xmit_buf, rctx->bufcnt); 8558c2ecf20Sopenharmony_ci sg_chain(rctx->sgl, 2, sg); 8568c2ecf20Sopenharmony_ci rctx->sg = rctx->sgl; 8578c2ecf20Sopenharmony_ci } else { 8588c2ecf20Sopenharmony_ci rctx->sg = sg; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci return 0; 8628c2ecf20Sopenharmony_ci} 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_cistatic int omap_sham_prepare_request(struct crypto_engine *engine, void *areq) 8658c2ecf20Sopenharmony_ci{ 8668c2ecf20Sopenharmony_ci struct ahash_request *req = container_of(areq, struct ahash_request, 8678c2ecf20Sopenharmony_ci base); 8688c2ecf20Sopenharmony_ci struct omap_sham_reqctx *rctx = ahash_request_ctx(req); 8698c2ecf20Sopenharmony_ci int bs; 8708c2ecf20Sopenharmony_ci int ret; 8718c2ecf20Sopenharmony_ci unsigned int nbytes; 8728c2ecf20Sopenharmony_ci bool final = rctx->flags & BIT(FLAGS_FINUP); 8738c2ecf20Sopenharmony_ci bool update = rctx->op == OP_UPDATE; 8748c2ecf20Sopenharmony_ci int hash_later; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci bs = get_block_size(rctx); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci nbytes = rctx->bufcnt; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci if (update) 8818c2ecf20Sopenharmony_ci nbytes += req->nbytes - rctx->offset; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci dev_dbg(rctx->dd->dev, 8848c2ecf20Sopenharmony_ci "%s: nbytes=%d, bs=%d, total=%d, offset=%d, bufcnt=%zd\n", 8858c2ecf20Sopenharmony_ci __func__, nbytes, bs, rctx->total, rctx->offset, 8868c2ecf20Sopenharmony_ci rctx->bufcnt); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (!nbytes) 8898c2ecf20Sopenharmony_ci return 0; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci rctx->total = nbytes; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci if (update && req->nbytes && (!IS_ALIGNED(rctx->bufcnt, bs))) { 8948c2ecf20Sopenharmony_ci int len = bs - rctx->bufcnt % bs; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (len > req->nbytes) 8978c2ecf20Sopenharmony_ci len = req->nbytes; 8988c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->buffer + rctx->bufcnt, req->src, 8998c2ecf20Sopenharmony_ci 0, len, 0); 9008c2ecf20Sopenharmony_ci rctx->bufcnt += len; 9018c2ecf20Sopenharmony_ci rctx->offset = len; 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci if (rctx->bufcnt) 9058c2ecf20Sopenharmony_ci memcpy(rctx->dd->xmit_buf, rctx->buffer, rctx->bufcnt); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci ret = omap_sham_align_sgs(req->src, nbytes, bs, final, rctx); 9088c2ecf20Sopenharmony_ci if (ret) 9098c2ecf20Sopenharmony_ci return ret; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci hash_later = nbytes - rctx->total; 9128c2ecf20Sopenharmony_ci if (hash_later < 0) 9138c2ecf20Sopenharmony_ci hash_later = 0; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci if (hash_later && hash_later <= rctx->buflen) { 9168c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->buffer, 9178c2ecf20Sopenharmony_ci req->src, 9188c2ecf20Sopenharmony_ci req->nbytes - hash_later, 9198c2ecf20Sopenharmony_ci hash_later, 0); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci rctx->bufcnt = hash_later; 9228c2ecf20Sopenharmony_ci } else { 9238c2ecf20Sopenharmony_ci rctx->bufcnt = 0; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci if (hash_later > rctx->buflen) 9278c2ecf20Sopenharmony_ci set_bit(FLAGS_HUGE, &rctx->dd->flags); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci rctx->total = min(nbytes, rctx->total); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci return 0; 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic int omap_sham_update_dma_stop(struct omap_sham_dev *dd) 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci dma_unmap_sg(dd->dev, ctx->sg, ctx->sg_len, DMA_TO_DEVICE); 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci clear_bit(FLAGS_DMA_ACTIVE, &dd->flags); 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci return 0; 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic struct omap_sham_dev *omap_sham_find_dev(struct omap_sham_reqctx *ctx) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci struct omap_sham_dev *dd; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci if (ctx->dd) 9508c2ecf20Sopenharmony_ci return ctx->dd; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci spin_lock_bh(&sham.lock); 9538c2ecf20Sopenharmony_ci dd = list_first_entry(&sham.dev_list, struct omap_sham_dev, list); 9548c2ecf20Sopenharmony_ci list_move_tail(&dd->list, &sham.dev_list); 9558c2ecf20Sopenharmony_ci ctx->dd = dd; 9568c2ecf20Sopenharmony_ci spin_unlock_bh(&sham.lock); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci return dd; 9598c2ecf20Sopenharmony_ci} 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_cistatic int omap_sham_init(struct ahash_request *req) 9628c2ecf20Sopenharmony_ci{ 9638c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 9648c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm); 9658c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 9668c2ecf20Sopenharmony_ci struct omap_sham_dev *dd; 9678c2ecf20Sopenharmony_ci int bs = 0; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci ctx->dd = NULL; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci dd = omap_sham_find_dev(ctx); 9728c2ecf20Sopenharmony_ci if (!dd) 9738c2ecf20Sopenharmony_ci return -ENODEV; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci ctx->flags = 0; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "init: digest size: %d\n", 9788c2ecf20Sopenharmony_ci crypto_ahash_digestsize(tfm)); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci switch (crypto_ahash_digestsize(tfm)) { 9818c2ecf20Sopenharmony_ci case MD5_DIGEST_SIZE: 9828c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_MD5; 9838c2ecf20Sopenharmony_ci bs = SHA1_BLOCK_SIZE; 9848c2ecf20Sopenharmony_ci break; 9858c2ecf20Sopenharmony_ci case SHA1_DIGEST_SIZE: 9868c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_SHA1; 9878c2ecf20Sopenharmony_ci bs = SHA1_BLOCK_SIZE; 9888c2ecf20Sopenharmony_ci break; 9898c2ecf20Sopenharmony_ci case SHA224_DIGEST_SIZE: 9908c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_SHA224; 9918c2ecf20Sopenharmony_ci bs = SHA224_BLOCK_SIZE; 9928c2ecf20Sopenharmony_ci break; 9938c2ecf20Sopenharmony_ci case SHA256_DIGEST_SIZE: 9948c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_SHA256; 9958c2ecf20Sopenharmony_ci bs = SHA256_BLOCK_SIZE; 9968c2ecf20Sopenharmony_ci break; 9978c2ecf20Sopenharmony_ci case SHA384_DIGEST_SIZE: 9988c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_SHA384; 9998c2ecf20Sopenharmony_ci bs = SHA384_BLOCK_SIZE; 10008c2ecf20Sopenharmony_ci break; 10018c2ecf20Sopenharmony_ci case SHA512_DIGEST_SIZE: 10028c2ecf20Sopenharmony_ci ctx->flags |= FLAGS_MODE_SHA512; 10038c2ecf20Sopenharmony_ci bs = SHA512_BLOCK_SIZE; 10048c2ecf20Sopenharmony_ci break; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci ctx->bufcnt = 0; 10088c2ecf20Sopenharmony_ci ctx->digcnt = 0; 10098c2ecf20Sopenharmony_ci ctx->total = 0; 10108c2ecf20Sopenharmony_ci ctx->offset = 0; 10118c2ecf20Sopenharmony_ci ctx->buflen = BUFLEN; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (tctx->flags & BIT(FLAGS_HMAC)) { 10148c2ecf20Sopenharmony_ci if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) { 10158c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci memcpy(ctx->buffer, bctx->ipad, bs); 10188c2ecf20Sopenharmony_ci ctx->bufcnt = bs; 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_HMAC); 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci return 0; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic int omap_sham_update_req(struct omap_sham_dev *dd) 10298c2ecf20Sopenharmony_ci{ 10308c2ecf20Sopenharmony_ci struct ahash_request *req = dd->req; 10318c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 10328c2ecf20Sopenharmony_ci int err; 10338c2ecf20Sopenharmony_ci bool final = (ctx->flags & BIT(FLAGS_FINUP)) && 10348c2ecf20Sopenharmony_ci !(dd->flags & BIT(FLAGS_HUGE)); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "update_req: total: %u, digcnt: %zd, final: %d", 10378c2ecf20Sopenharmony_ci ctx->total, ctx->digcnt, final); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci if (ctx->total < get_block_size(ctx) || 10408c2ecf20Sopenharmony_ci ctx->total < dd->fallback_sz) 10418c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_CPU); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (ctx->flags & BIT(FLAGS_CPU)) 10448c2ecf20Sopenharmony_ci err = omap_sham_xmit_cpu(dd, ctx->total, final); 10458c2ecf20Sopenharmony_ci else 10468c2ecf20Sopenharmony_ci err = omap_sham_xmit_dma(dd, ctx->total, final); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci /* wait for dma completion before can take more data */ 10498c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "update: err: %d, digcnt: %zd\n", err, ctx->digcnt); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci return err; 10528c2ecf20Sopenharmony_ci} 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_cistatic int omap_sham_final_req(struct omap_sham_dev *dd) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci struct ahash_request *req = dd->req; 10578c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 10588c2ecf20Sopenharmony_ci int err = 0, use_dma = 1; 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci if (dd->flags & BIT(FLAGS_HUGE)) 10618c2ecf20Sopenharmony_ci return 0; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if ((ctx->total <= get_block_size(ctx)) || dd->polling_mode) 10648c2ecf20Sopenharmony_ci /* 10658c2ecf20Sopenharmony_ci * faster to handle last block with cpu or 10668c2ecf20Sopenharmony_ci * use cpu when dma is not present. 10678c2ecf20Sopenharmony_ci */ 10688c2ecf20Sopenharmony_ci use_dma = 0; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (use_dma) 10718c2ecf20Sopenharmony_ci err = omap_sham_xmit_dma(dd, ctx->total, 1); 10728c2ecf20Sopenharmony_ci else 10738c2ecf20Sopenharmony_ci err = omap_sham_xmit_cpu(dd, ctx->total, 1); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci ctx->bufcnt = 0; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "final_req: err: %d\n", err); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci return err; 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_cistatic int omap_sham_hash_one_req(struct crypto_engine *engine, void *areq) 10838c2ecf20Sopenharmony_ci{ 10848c2ecf20Sopenharmony_ci struct ahash_request *req = container_of(areq, struct ahash_request, 10858c2ecf20Sopenharmony_ci base); 10868c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 10878c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 10888c2ecf20Sopenharmony_ci int err; 10898c2ecf20Sopenharmony_ci bool final = (ctx->flags & BIT(FLAGS_FINUP)) && 10908c2ecf20Sopenharmony_ci !(dd->flags & BIT(FLAGS_HUGE)); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "hash-one: op: %u, total: %u, digcnt: %zd, final: %d", 10938c2ecf20Sopenharmony_ci ctx->op, ctx->total, ctx->digcnt, final); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci dd->req = req; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci err = omap_sham_hw_init(dd); 10988c2ecf20Sopenharmony_ci if (err) 10998c2ecf20Sopenharmony_ci return err; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (ctx->digcnt) 11028c2ecf20Sopenharmony_ci dd->pdata->copy_hash(req, 0); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (ctx->op == OP_UPDATE) 11058c2ecf20Sopenharmony_ci err = omap_sham_update_req(dd); 11068c2ecf20Sopenharmony_ci else if (ctx->op == OP_FINAL) 11078c2ecf20Sopenharmony_ci err = omap_sham_final_req(dd); 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) 11108c2ecf20Sopenharmony_ci omap_sham_finish_req(req, err); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci return 0; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cistatic int omap_sham_finish_hmac(struct ahash_request *req) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); 11188c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 11198c2ecf20Sopenharmony_ci int bs = crypto_shash_blocksize(bctx->shash); 11208c2ecf20Sopenharmony_ci int ds = crypto_shash_digestsize(bctx->shash); 11218c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, bctx->shash); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci shash->tfm = bctx->shash; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci return crypto_shash_init(shash) ?: 11268c2ecf20Sopenharmony_ci crypto_shash_update(shash, bctx->opad, bs) ?: 11278c2ecf20Sopenharmony_ci crypto_shash_finup(shash, req->result, ds, req->result); 11288c2ecf20Sopenharmony_ci} 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_cistatic int omap_sham_finish(struct ahash_request *req) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 11338c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 11348c2ecf20Sopenharmony_ci int err = 0; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (ctx->digcnt) { 11378c2ecf20Sopenharmony_ci omap_sham_copy_ready_hash(req); 11388c2ecf20Sopenharmony_ci if ((ctx->flags & BIT(FLAGS_HMAC)) && 11398c2ecf20Sopenharmony_ci !test_bit(FLAGS_AUTO_XOR, &dd->flags)) 11408c2ecf20Sopenharmony_ci err = omap_sham_finish_hmac(req); 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "digcnt: %zd, bufcnt: %zd\n", ctx->digcnt, ctx->bufcnt); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci return err; 11468c2ecf20Sopenharmony_ci} 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_cistatic void omap_sham_finish_req(struct ahash_request *req, int err) 11498c2ecf20Sopenharmony_ci{ 11508c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 11518c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (test_bit(FLAGS_SGS_COPIED, &dd->flags)) 11548c2ecf20Sopenharmony_ci free_pages((unsigned long)sg_virt(ctx->sg), 11558c2ecf20Sopenharmony_ci get_order(ctx->sg->length)); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci if (test_bit(FLAGS_SGS_ALLOCED, &dd->flags)) 11588c2ecf20Sopenharmony_ci kfree(ctx->sg); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci ctx->sg = NULL; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci dd->flags &= ~(BIT(FLAGS_SGS_ALLOCED) | BIT(FLAGS_SGS_COPIED) | 11638c2ecf20Sopenharmony_ci BIT(FLAGS_CPU) | BIT(FLAGS_DMA_READY) | 11648c2ecf20Sopenharmony_ci BIT(FLAGS_OUTPUT_READY)); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (!err) 11678c2ecf20Sopenharmony_ci dd->pdata->copy_hash(req, 1); 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (dd->flags & BIT(FLAGS_HUGE)) { 11708c2ecf20Sopenharmony_ci /* Re-enqueue the request */ 11718c2ecf20Sopenharmony_ci omap_sham_enqueue(req, ctx->op); 11728c2ecf20Sopenharmony_ci return; 11738c2ecf20Sopenharmony_ci } 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci if (!err) { 11768c2ecf20Sopenharmony_ci if (test_bit(FLAGS_FINAL, &dd->flags)) 11778c2ecf20Sopenharmony_ci err = omap_sham_finish(req); 11788c2ecf20Sopenharmony_ci } else { 11798c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_ERROR); 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* atomic operation is not needed here */ 11838c2ecf20Sopenharmony_ci dd->flags &= ~(BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) | 11848c2ecf20Sopenharmony_ci BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY)); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dd->dev); 11878c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dd->dev); 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci ctx->offset = 0; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci crypto_finalize_hash_request(dd->engine, req, err); 11928c2ecf20Sopenharmony_ci} 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_cistatic int omap_sham_handle_queue(struct omap_sham_dev *dd, 11958c2ecf20Sopenharmony_ci struct ahash_request *req) 11968c2ecf20Sopenharmony_ci{ 11978c2ecf20Sopenharmony_ci return crypto_transfer_hash_request_to_engine(dd->engine, req); 11988c2ecf20Sopenharmony_ci} 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_cistatic int omap_sham_enqueue(struct ahash_request *req, unsigned int op) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 12038c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = ctx->dd; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci ctx->op = op; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci return omap_sham_handle_queue(dd, req); 12088c2ecf20Sopenharmony_ci} 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_cistatic int omap_sham_update(struct ahash_request *req) 12118c2ecf20Sopenharmony_ci{ 12128c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 12138c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = omap_sham_find_dev(ctx); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci if (!req->nbytes) 12168c2ecf20Sopenharmony_ci return 0; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci if (ctx->bufcnt + req->nbytes <= ctx->buflen) { 12198c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, req->src, 12208c2ecf20Sopenharmony_ci 0, req->nbytes, 0); 12218c2ecf20Sopenharmony_ci ctx->bufcnt += req->nbytes; 12228c2ecf20Sopenharmony_ci return 0; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci if (dd->polling_mode) 12268c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_CPU); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci return omap_sham_enqueue(req, OP_UPDATE); 12298c2ecf20Sopenharmony_ci} 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_cistatic int omap_sham_final_shash(struct ahash_request *req) 12328c2ecf20Sopenharmony_ci{ 12338c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); 12348c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 12358c2ecf20Sopenharmony_ci int offset = 0; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* 12388c2ecf20Sopenharmony_ci * If we are running HMAC on limited hardware support, skip 12398c2ecf20Sopenharmony_ci * the ipad in the beginning of the buffer if we are going for 12408c2ecf20Sopenharmony_ci * software fallback algorithm. 12418c2ecf20Sopenharmony_ci */ 12428c2ecf20Sopenharmony_ci if (test_bit(FLAGS_HMAC, &ctx->flags) && 12438c2ecf20Sopenharmony_ci !test_bit(FLAGS_AUTO_XOR, &ctx->dd->flags)) 12448c2ecf20Sopenharmony_ci offset = get_block_size(ctx); 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci return crypto_shash_tfm_digest(tctx->fallback, ctx->buffer + offset, 12478c2ecf20Sopenharmony_ci ctx->bufcnt - offset, req->result); 12488c2ecf20Sopenharmony_ci} 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_cistatic int omap_sham_final(struct ahash_request *req) 12518c2ecf20Sopenharmony_ci{ 12528c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_FINUP); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (ctx->flags & BIT(FLAGS_ERROR)) 12578c2ecf20Sopenharmony_ci return 0; /* uncompleted hash is not needed */ 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci /* 12608c2ecf20Sopenharmony_ci * OMAP HW accel works only with buffers >= 9. 12618c2ecf20Sopenharmony_ci * HMAC is always >= 9 because ipad == block size. 12628c2ecf20Sopenharmony_ci * If buffersize is less than fallback_sz, we use fallback 12638c2ecf20Sopenharmony_ci * SW encoding, as using DMA + HW in this case doesn't provide 12648c2ecf20Sopenharmony_ci * any benefit. 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci if (!ctx->digcnt && ctx->bufcnt < ctx->dd->fallback_sz) 12678c2ecf20Sopenharmony_ci return omap_sham_final_shash(req); 12688c2ecf20Sopenharmony_ci else if (ctx->bufcnt) 12698c2ecf20Sopenharmony_ci return omap_sham_enqueue(req, OP_FINAL); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci /* copy ready hash (+ finalize hmac) */ 12728c2ecf20Sopenharmony_ci return omap_sham_finish(req); 12738c2ecf20Sopenharmony_ci} 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_cistatic int omap_sham_finup(struct ahash_request *req) 12768c2ecf20Sopenharmony_ci{ 12778c2ecf20Sopenharmony_ci struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 12788c2ecf20Sopenharmony_ci int err1, err2; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci ctx->flags |= BIT(FLAGS_FINUP); 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci err1 = omap_sham_update(req); 12838c2ecf20Sopenharmony_ci if (err1 == -EINPROGRESS || err1 == -EBUSY) 12848c2ecf20Sopenharmony_ci return err1; 12858c2ecf20Sopenharmony_ci /* 12868c2ecf20Sopenharmony_ci * final() has to be always called to cleanup resources 12878c2ecf20Sopenharmony_ci * even if udpate() failed, except EINPROGRESS 12888c2ecf20Sopenharmony_ci */ 12898c2ecf20Sopenharmony_ci err2 = omap_sham_final(req); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci return err1 ?: err2; 12928c2ecf20Sopenharmony_ci} 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cistatic int omap_sham_digest(struct ahash_request *req) 12958c2ecf20Sopenharmony_ci{ 12968c2ecf20Sopenharmony_ci return omap_sham_init(req) ?: omap_sham_finup(req); 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_cistatic int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key, 13008c2ecf20Sopenharmony_ci unsigned int keylen) 13018c2ecf20Sopenharmony_ci{ 13028c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm); 13038c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 13048c2ecf20Sopenharmony_ci int bs = crypto_shash_blocksize(bctx->shash); 13058c2ecf20Sopenharmony_ci int ds = crypto_shash_digestsize(bctx->shash); 13068c2ecf20Sopenharmony_ci int err, i; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci err = crypto_shash_setkey(tctx->fallback, key, keylen); 13098c2ecf20Sopenharmony_ci if (err) 13108c2ecf20Sopenharmony_ci return err; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (keylen > bs) { 13138c2ecf20Sopenharmony_ci err = crypto_shash_tfm_digest(bctx->shash, key, keylen, 13148c2ecf20Sopenharmony_ci bctx->ipad); 13158c2ecf20Sopenharmony_ci if (err) 13168c2ecf20Sopenharmony_ci return err; 13178c2ecf20Sopenharmony_ci keylen = ds; 13188c2ecf20Sopenharmony_ci } else { 13198c2ecf20Sopenharmony_ci memcpy(bctx->ipad, key, keylen); 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci memset(bctx->ipad + keylen, 0, bs - keylen); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci if (!test_bit(FLAGS_AUTO_XOR, &sham.flags)) { 13258c2ecf20Sopenharmony_ci memcpy(bctx->opad, bctx->ipad, bs); 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci for (i = 0; i < bs; i++) { 13288c2ecf20Sopenharmony_ci bctx->ipad[i] ^= HMAC_IPAD_VALUE; 13298c2ecf20Sopenharmony_ci bctx->opad[i] ^= HMAC_OPAD_VALUE; 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci return err; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_cistatic int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) 13378c2ecf20Sopenharmony_ci{ 13388c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm); 13398c2ecf20Sopenharmony_ci const char *alg_name = crypto_tfm_alg_name(tfm); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci /* Allocate a fallback and abort if it failed. */ 13428c2ecf20Sopenharmony_ci tctx->fallback = crypto_alloc_shash(alg_name, 0, 13438c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 13448c2ecf20Sopenharmony_ci if (IS_ERR(tctx->fallback)) { 13458c2ecf20Sopenharmony_ci pr_err("omap-sham: fallback driver '%s' " 13468c2ecf20Sopenharmony_ci "could not be loaded.\n", alg_name); 13478c2ecf20Sopenharmony_ci return PTR_ERR(tctx->fallback); 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 13518c2ecf20Sopenharmony_ci sizeof(struct omap_sham_reqctx) + BUFLEN); 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci if (alg_base) { 13548c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 13558c2ecf20Sopenharmony_ci tctx->flags |= BIT(FLAGS_HMAC); 13568c2ecf20Sopenharmony_ci bctx->shash = crypto_alloc_shash(alg_base, 0, 13578c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 13588c2ecf20Sopenharmony_ci if (IS_ERR(bctx->shash)) { 13598c2ecf20Sopenharmony_ci pr_err("omap-sham: base driver '%s' " 13608c2ecf20Sopenharmony_ci "could not be loaded.\n", alg_base); 13618c2ecf20Sopenharmony_ci crypto_free_shash(tctx->fallback); 13628c2ecf20Sopenharmony_ci return PTR_ERR(bctx->shash); 13638c2ecf20Sopenharmony_ci } 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci tctx->enginectx.op.do_one_request = omap_sham_hash_one_req; 13688c2ecf20Sopenharmony_ci tctx->enginectx.op.prepare_request = omap_sham_prepare_request; 13698c2ecf20Sopenharmony_ci tctx->enginectx.op.unprepare_request = NULL; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci return 0; 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic int omap_sham_cra_init(struct crypto_tfm *tfm) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, NULL); 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_cistatic int omap_sham_cra_sha1_init(struct crypto_tfm *tfm) 13808c2ecf20Sopenharmony_ci{ 13818c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "sha1"); 13828c2ecf20Sopenharmony_ci} 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_cistatic int omap_sham_cra_sha224_init(struct crypto_tfm *tfm) 13858c2ecf20Sopenharmony_ci{ 13868c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "sha224"); 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic int omap_sham_cra_sha256_init(struct crypto_tfm *tfm) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "sha256"); 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_cistatic int omap_sham_cra_md5_init(struct crypto_tfm *tfm) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "md5"); 13978c2ecf20Sopenharmony_ci} 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_cistatic int omap_sham_cra_sha384_init(struct crypto_tfm *tfm) 14008c2ecf20Sopenharmony_ci{ 14018c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "sha384"); 14028c2ecf20Sopenharmony_ci} 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_cistatic int omap_sham_cra_sha512_init(struct crypto_tfm *tfm) 14058c2ecf20Sopenharmony_ci{ 14068c2ecf20Sopenharmony_ci return omap_sham_cra_init_alg(tfm, "sha512"); 14078c2ecf20Sopenharmony_ci} 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_cistatic void omap_sham_cra_exit(struct crypto_tfm *tfm) 14108c2ecf20Sopenharmony_ci{ 14118c2ecf20Sopenharmony_ci struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci crypto_free_shash(tctx->fallback); 14148c2ecf20Sopenharmony_ci tctx->fallback = NULL; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci if (tctx->flags & BIT(FLAGS_HMAC)) { 14178c2ecf20Sopenharmony_ci struct omap_sham_hmac_ctx *bctx = tctx->base; 14188c2ecf20Sopenharmony_ci crypto_free_shash(bctx->shash); 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci} 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_cistatic int omap_sham_export(struct ahash_request *req, void *out) 14238c2ecf20Sopenharmony_ci{ 14248c2ecf20Sopenharmony_ci struct omap_sham_reqctx *rctx = ahash_request_ctx(req); 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci memcpy(out, rctx, sizeof(*rctx) + rctx->bufcnt); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci return 0; 14298c2ecf20Sopenharmony_ci} 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_cistatic int omap_sham_import(struct ahash_request *req, const void *in) 14328c2ecf20Sopenharmony_ci{ 14338c2ecf20Sopenharmony_ci struct omap_sham_reqctx *rctx = ahash_request_ctx(req); 14348c2ecf20Sopenharmony_ci const struct omap_sham_reqctx *ctx_in = in; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci memcpy(rctx, in, sizeof(*rctx) + ctx_in->bufcnt); 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci return 0; 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_cistatic struct ahash_alg algs_sha1_md5[] = { 14428c2ecf20Sopenharmony_ci{ 14438c2ecf20Sopenharmony_ci .init = omap_sham_init, 14448c2ecf20Sopenharmony_ci .update = omap_sham_update, 14458c2ecf20Sopenharmony_ci .final = omap_sham_final, 14468c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 14478c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 14488c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 14498c2ecf20Sopenharmony_ci .halg.base = { 14508c2ecf20Sopenharmony_ci .cra_name = "sha1", 14518c2ecf20Sopenharmony_ci .cra_driver_name = "omap-sha1", 14528c2ecf20Sopenharmony_ci .cra_priority = 400, 14538c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 14548c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 14558c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 14568c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 14578c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 14588c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 14598c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 14608c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 14618c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 14628c2ecf20Sopenharmony_ci } 14638c2ecf20Sopenharmony_ci}, 14648c2ecf20Sopenharmony_ci{ 14658c2ecf20Sopenharmony_ci .init = omap_sham_init, 14668c2ecf20Sopenharmony_ci .update = omap_sham_update, 14678c2ecf20Sopenharmony_ci .final = omap_sham_final, 14688c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 14698c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 14708c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 14718c2ecf20Sopenharmony_ci .halg.base = { 14728c2ecf20Sopenharmony_ci .cra_name = "md5", 14738c2ecf20Sopenharmony_ci .cra_driver_name = "omap-md5", 14748c2ecf20Sopenharmony_ci .cra_priority = 400, 14758c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 14768c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 14778c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 14788c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 14798c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 14808c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 14818c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 14828c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 14838c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci}, 14868c2ecf20Sopenharmony_ci{ 14878c2ecf20Sopenharmony_ci .init = omap_sham_init, 14888c2ecf20Sopenharmony_ci .update = omap_sham_update, 14898c2ecf20Sopenharmony_ci .final = omap_sham_final, 14908c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 14918c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 14928c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 14938c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 14948c2ecf20Sopenharmony_ci .halg.base = { 14958c2ecf20Sopenharmony_ci .cra_name = "hmac(sha1)", 14968c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-sha1", 14978c2ecf20Sopenharmony_ci .cra_priority = 400, 14988c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 14998c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 15008c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 15018c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 15028c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 15038c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 15048c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 15058c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15068c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_sha1_init, 15078c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci}, 15108c2ecf20Sopenharmony_ci{ 15118c2ecf20Sopenharmony_ci .init = omap_sham_init, 15128c2ecf20Sopenharmony_ci .update = omap_sham_update, 15138c2ecf20Sopenharmony_ci .final = omap_sham_final, 15148c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 15158c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 15168c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 15178c2ecf20Sopenharmony_ci .halg.digestsize = MD5_DIGEST_SIZE, 15188c2ecf20Sopenharmony_ci .halg.base = { 15198c2ecf20Sopenharmony_ci .cra_name = "hmac(md5)", 15208c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-md5", 15218c2ecf20Sopenharmony_ci .cra_priority = 400, 15228c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 15238c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 15248c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 15258c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 15268c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 15278c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 15288c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 15298c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15308c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_md5_init, 15318c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci} 15348c2ecf20Sopenharmony_ci}; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci/* OMAP4 has some algs in addition to what OMAP2 has */ 15378c2ecf20Sopenharmony_cistatic struct ahash_alg algs_sha224_sha256[] = { 15388c2ecf20Sopenharmony_ci{ 15398c2ecf20Sopenharmony_ci .init = omap_sham_init, 15408c2ecf20Sopenharmony_ci .update = omap_sham_update, 15418c2ecf20Sopenharmony_ci .final = omap_sham_final, 15428c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 15438c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 15448c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 15458c2ecf20Sopenharmony_ci .halg.base = { 15468c2ecf20Sopenharmony_ci .cra_name = "sha224", 15478c2ecf20Sopenharmony_ci .cra_driver_name = "omap-sha224", 15488c2ecf20Sopenharmony_ci .cra_priority = 400, 15498c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 15508c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 15518c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 15528c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 15538c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 15548c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 15558c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15568c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 15578c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci}, 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci .init = omap_sham_init, 15628c2ecf20Sopenharmony_ci .update = omap_sham_update, 15638c2ecf20Sopenharmony_ci .final = omap_sham_final, 15648c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 15658c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 15668c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 15678c2ecf20Sopenharmony_ci .halg.base = { 15688c2ecf20Sopenharmony_ci .cra_name = "sha256", 15698c2ecf20Sopenharmony_ci .cra_driver_name = "omap-sha256", 15708c2ecf20Sopenharmony_ci .cra_priority = 400, 15718c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 15728c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 15738c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 15748c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 15758c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 15768c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 15778c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 15788c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 15798c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci}, 15828c2ecf20Sopenharmony_ci{ 15838c2ecf20Sopenharmony_ci .init = omap_sham_init, 15848c2ecf20Sopenharmony_ci .update = omap_sham_update, 15858c2ecf20Sopenharmony_ci .final = omap_sham_final, 15868c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 15878c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 15888c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 15898c2ecf20Sopenharmony_ci .halg.digestsize = SHA224_DIGEST_SIZE, 15908c2ecf20Sopenharmony_ci .halg.base = { 15918c2ecf20Sopenharmony_ci .cra_name = "hmac(sha224)", 15928c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-sha224", 15938c2ecf20Sopenharmony_ci .cra_priority = 400, 15948c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 15958c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 15968c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 15978c2ecf20Sopenharmony_ci .cra_blocksize = SHA224_BLOCK_SIZE, 15988c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 15998c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 16008c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 16018c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16028c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_sha224_init, 16038c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci}, 16068c2ecf20Sopenharmony_ci{ 16078c2ecf20Sopenharmony_ci .init = omap_sham_init, 16088c2ecf20Sopenharmony_ci .update = omap_sham_update, 16098c2ecf20Sopenharmony_ci .final = omap_sham_final, 16108c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 16118c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 16128c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 16138c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 16148c2ecf20Sopenharmony_ci .halg.base = { 16158c2ecf20Sopenharmony_ci .cra_name = "hmac(sha256)", 16168c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-sha256", 16178c2ecf20Sopenharmony_ci .cra_priority = 400, 16188c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 16198c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 16208c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 16218c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 16228c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 16238c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 16248c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 16258c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16268c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_sha256_init, 16278c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 16288c2ecf20Sopenharmony_ci } 16298c2ecf20Sopenharmony_ci}, 16308c2ecf20Sopenharmony_ci}; 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_cistatic struct ahash_alg algs_sha384_sha512[] = { 16338c2ecf20Sopenharmony_ci{ 16348c2ecf20Sopenharmony_ci .init = omap_sham_init, 16358c2ecf20Sopenharmony_ci .update = omap_sham_update, 16368c2ecf20Sopenharmony_ci .final = omap_sham_final, 16378c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 16388c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 16398c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 16408c2ecf20Sopenharmony_ci .halg.base = { 16418c2ecf20Sopenharmony_ci .cra_name = "sha384", 16428c2ecf20Sopenharmony_ci .cra_driver_name = "omap-sha384", 16438c2ecf20Sopenharmony_ci .cra_priority = 400, 16448c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 16458c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 16468c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 16478c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 16488c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 16498c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 16508c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16518c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 16528c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci}, 16558c2ecf20Sopenharmony_ci{ 16568c2ecf20Sopenharmony_ci .init = omap_sham_init, 16578c2ecf20Sopenharmony_ci .update = omap_sham_update, 16588c2ecf20Sopenharmony_ci .final = omap_sham_final, 16598c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 16608c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 16618c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 16628c2ecf20Sopenharmony_ci .halg.base = { 16638c2ecf20Sopenharmony_ci .cra_name = "sha512", 16648c2ecf20Sopenharmony_ci .cra_driver_name = "omap-sha512", 16658c2ecf20Sopenharmony_ci .cra_priority = 400, 16668c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 16678c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 16688c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 16698c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 16708c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx), 16718c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 16728c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16738c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_init, 16748c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci}, 16778c2ecf20Sopenharmony_ci{ 16788c2ecf20Sopenharmony_ci .init = omap_sham_init, 16798c2ecf20Sopenharmony_ci .update = omap_sham_update, 16808c2ecf20Sopenharmony_ci .final = omap_sham_final, 16818c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 16828c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 16838c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 16848c2ecf20Sopenharmony_ci .halg.digestsize = SHA384_DIGEST_SIZE, 16858c2ecf20Sopenharmony_ci .halg.base = { 16868c2ecf20Sopenharmony_ci .cra_name = "hmac(sha384)", 16878c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-sha384", 16888c2ecf20Sopenharmony_ci .cra_priority = 400, 16898c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 16908c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 16918c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 16928c2ecf20Sopenharmony_ci .cra_blocksize = SHA384_BLOCK_SIZE, 16938c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 16948c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 16958c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 16968c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 16978c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_sha384_init, 16988c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci}, 17018c2ecf20Sopenharmony_ci{ 17028c2ecf20Sopenharmony_ci .init = omap_sham_init, 17038c2ecf20Sopenharmony_ci .update = omap_sham_update, 17048c2ecf20Sopenharmony_ci .final = omap_sham_final, 17058c2ecf20Sopenharmony_ci .finup = omap_sham_finup, 17068c2ecf20Sopenharmony_ci .digest = omap_sham_digest, 17078c2ecf20Sopenharmony_ci .setkey = omap_sham_setkey, 17088c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 17098c2ecf20Sopenharmony_ci .halg.base = { 17108c2ecf20Sopenharmony_ci .cra_name = "hmac(sha512)", 17118c2ecf20Sopenharmony_ci .cra_driver_name = "omap-hmac-sha512", 17128c2ecf20Sopenharmony_ci .cra_priority = 400, 17138c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | 17148c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 17158c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 17168c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 17178c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct omap_sham_ctx) + 17188c2ecf20Sopenharmony_ci sizeof(struct omap_sham_hmac_ctx), 17198c2ecf20Sopenharmony_ci .cra_alignmask = OMAP_ALIGN_MASK, 17208c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 17218c2ecf20Sopenharmony_ci .cra_init = omap_sham_cra_sha512_init, 17228c2ecf20Sopenharmony_ci .cra_exit = omap_sham_cra_exit, 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci}, 17258c2ecf20Sopenharmony_ci}; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic void omap_sham_done_task(unsigned long data) 17288c2ecf20Sopenharmony_ci{ 17298c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = (struct omap_sham_dev *)data; 17308c2ecf20Sopenharmony_ci int err = 0; 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "%s: flags=%lx\n", __func__, dd->flags); 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci if (test_bit(FLAGS_CPU, &dd->flags)) { 17358c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags)) 17368c2ecf20Sopenharmony_ci goto finish; 17378c2ecf20Sopenharmony_ci } else if (test_bit(FLAGS_DMA_READY, &dd->flags)) { 17388c2ecf20Sopenharmony_ci if (test_bit(FLAGS_DMA_ACTIVE, &dd->flags)) { 17398c2ecf20Sopenharmony_ci omap_sham_update_dma_stop(dd); 17408c2ecf20Sopenharmony_ci if (dd->err) { 17418c2ecf20Sopenharmony_ci err = dd->err; 17428c2ecf20Sopenharmony_ci goto finish; 17438c2ecf20Sopenharmony_ci } 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags)) { 17468c2ecf20Sopenharmony_ci /* hash or semi-hash ready */ 17478c2ecf20Sopenharmony_ci clear_bit(FLAGS_DMA_READY, &dd->flags); 17488c2ecf20Sopenharmony_ci goto finish; 17498c2ecf20Sopenharmony_ci } 17508c2ecf20Sopenharmony_ci } 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci return; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_cifinish: 17558c2ecf20Sopenharmony_ci dev_dbg(dd->dev, "update done: err: %d\n", err); 17568c2ecf20Sopenharmony_ci /* finish curent request */ 17578c2ecf20Sopenharmony_ci omap_sham_finish_req(dd->req, err); 17588c2ecf20Sopenharmony_ci} 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_cistatic irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd) 17618c2ecf20Sopenharmony_ci{ 17628c2ecf20Sopenharmony_ci set_bit(FLAGS_OUTPUT_READY, &dd->flags); 17638c2ecf20Sopenharmony_ci tasklet_schedule(&dd->done_task); 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci return IRQ_HANDLED; 17668c2ecf20Sopenharmony_ci} 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_cistatic irqreturn_t omap_sham_irq_omap2(int irq, void *dev_id) 17698c2ecf20Sopenharmony_ci{ 17708c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_id; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci if (unlikely(test_bit(FLAGS_FINAL, &dd->flags))) 17738c2ecf20Sopenharmony_ci /* final -> allow device to go to power-saving mode */ 17748c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH); 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_CTRL, SHA_REG_CTRL_OUTPUT_READY, 17778c2ecf20Sopenharmony_ci SHA_REG_CTRL_OUTPUT_READY); 17788c2ecf20Sopenharmony_ci omap_sham_read(dd, SHA_REG_CTRL); 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci return omap_sham_irq_common(dd); 17818c2ecf20Sopenharmony_ci} 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_cistatic irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id) 17848c2ecf20Sopenharmony_ci{ 17858c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_id; 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci omap_sham_write_mask(dd, SHA_REG_MASK(dd), 0, SHA_REG_MASK_IT_EN); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci return omap_sham_irq_common(dd); 17908c2ecf20Sopenharmony_ci} 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_cistatic struct omap_sham_algs_info omap_sham_algs_info_omap2[] = { 17938c2ecf20Sopenharmony_ci { 17948c2ecf20Sopenharmony_ci .algs_list = algs_sha1_md5, 17958c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1_md5), 17968c2ecf20Sopenharmony_ci }, 17978c2ecf20Sopenharmony_ci}; 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_cistatic const struct omap_sham_pdata omap_sham_pdata_omap2 = { 18008c2ecf20Sopenharmony_ci .algs_info = omap_sham_algs_info_omap2, 18018c2ecf20Sopenharmony_ci .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap2), 18028c2ecf20Sopenharmony_ci .flags = BIT(FLAGS_BE32_SHA1), 18038c2ecf20Sopenharmony_ci .digest_size = SHA1_DIGEST_SIZE, 18048c2ecf20Sopenharmony_ci .copy_hash = omap_sham_copy_hash_omap2, 18058c2ecf20Sopenharmony_ci .write_ctrl = omap_sham_write_ctrl_omap2, 18068c2ecf20Sopenharmony_ci .trigger = omap_sham_trigger_omap2, 18078c2ecf20Sopenharmony_ci .poll_irq = omap_sham_poll_irq_omap2, 18088c2ecf20Sopenharmony_ci .intr_hdlr = omap_sham_irq_omap2, 18098c2ecf20Sopenharmony_ci .idigest_ofs = 0x00, 18108c2ecf20Sopenharmony_ci .din_ofs = 0x1c, 18118c2ecf20Sopenharmony_ci .digcnt_ofs = 0x14, 18128c2ecf20Sopenharmony_ci .rev_ofs = 0x5c, 18138c2ecf20Sopenharmony_ci .mask_ofs = 0x60, 18148c2ecf20Sopenharmony_ci .sysstatus_ofs = 0x64, 18158c2ecf20Sopenharmony_ci .major_mask = 0xf0, 18168c2ecf20Sopenharmony_ci .major_shift = 4, 18178c2ecf20Sopenharmony_ci .minor_mask = 0x0f, 18188c2ecf20Sopenharmony_ci .minor_shift = 0, 18198c2ecf20Sopenharmony_ci}; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 18228c2ecf20Sopenharmony_cistatic struct omap_sham_algs_info omap_sham_algs_info_omap4[] = { 18238c2ecf20Sopenharmony_ci { 18248c2ecf20Sopenharmony_ci .algs_list = algs_sha1_md5, 18258c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1_md5), 18268c2ecf20Sopenharmony_ci }, 18278c2ecf20Sopenharmony_ci { 18288c2ecf20Sopenharmony_ci .algs_list = algs_sha224_sha256, 18298c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha224_sha256), 18308c2ecf20Sopenharmony_ci }, 18318c2ecf20Sopenharmony_ci}; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_cistatic const struct omap_sham_pdata omap_sham_pdata_omap4 = { 18348c2ecf20Sopenharmony_ci .algs_info = omap_sham_algs_info_omap4, 18358c2ecf20Sopenharmony_ci .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap4), 18368c2ecf20Sopenharmony_ci .flags = BIT(FLAGS_AUTO_XOR), 18378c2ecf20Sopenharmony_ci .digest_size = SHA256_DIGEST_SIZE, 18388c2ecf20Sopenharmony_ci .copy_hash = omap_sham_copy_hash_omap4, 18398c2ecf20Sopenharmony_ci .write_ctrl = omap_sham_write_ctrl_omap4, 18408c2ecf20Sopenharmony_ci .trigger = omap_sham_trigger_omap4, 18418c2ecf20Sopenharmony_ci .poll_irq = omap_sham_poll_irq_omap4, 18428c2ecf20Sopenharmony_ci .intr_hdlr = omap_sham_irq_omap4, 18438c2ecf20Sopenharmony_ci .idigest_ofs = 0x020, 18448c2ecf20Sopenharmony_ci .odigest_ofs = 0x0, 18458c2ecf20Sopenharmony_ci .din_ofs = 0x080, 18468c2ecf20Sopenharmony_ci .digcnt_ofs = 0x040, 18478c2ecf20Sopenharmony_ci .rev_ofs = 0x100, 18488c2ecf20Sopenharmony_ci .mask_ofs = 0x110, 18498c2ecf20Sopenharmony_ci .sysstatus_ofs = 0x114, 18508c2ecf20Sopenharmony_ci .mode_ofs = 0x44, 18518c2ecf20Sopenharmony_ci .length_ofs = 0x48, 18528c2ecf20Sopenharmony_ci .major_mask = 0x0700, 18538c2ecf20Sopenharmony_ci .major_shift = 8, 18548c2ecf20Sopenharmony_ci .minor_mask = 0x003f, 18558c2ecf20Sopenharmony_ci .minor_shift = 0, 18568c2ecf20Sopenharmony_ci}; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_cistatic struct omap_sham_algs_info omap_sham_algs_info_omap5[] = { 18598c2ecf20Sopenharmony_ci { 18608c2ecf20Sopenharmony_ci .algs_list = algs_sha1_md5, 18618c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha1_md5), 18628c2ecf20Sopenharmony_ci }, 18638c2ecf20Sopenharmony_ci { 18648c2ecf20Sopenharmony_ci .algs_list = algs_sha224_sha256, 18658c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha224_sha256), 18668c2ecf20Sopenharmony_ci }, 18678c2ecf20Sopenharmony_ci { 18688c2ecf20Sopenharmony_ci .algs_list = algs_sha384_sha512, 18698c2ecf20Sopenharmony_ci .size = ARRAY_SIZE(algs_sha384_sha512), 18708c2ecf20Sopenharmony_ci }, 18718c2ecf20Sopenharmony_ci}; 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_cistatic const struct omap_sham_pdata omap_sham_pdata_omap5 = { 18748c2ecf20Sopenharmony_ci .algs_info = omap_sham_algs_info_omap5, 18758c2ecf20Sopenharmony_ci .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap5), 18768c2ecf20Sopenharmony_ci .flags = BIT(FLAGS_AUTO_XOR), 18778c2ecf20Sopenharmony_ci .digest_size = SHA512_DIGEST_SIZE, 18788c2ecf20Sopenharmony_ci .copy_hash = omap_sham_copy_hash_omap4, 18798c2ecf20Sopenharmony_ci .write_ctrl = omap_sham_write_ctrl_omap4, 18808c2ecf20Sopenharmony_ci .trigger = omap_sham_trigger_omap4, 18818c2ecf20Sopenharmony_ci .poll_irq = omap_sham_poll_irq_omap4, 18828c2ecf20Sopenharmony_ci .intr_hdlr = omap_sham_irq_omap4, 18838c2ecf20Sopenharmony_ci .idigest_ofs = 0x240, 18848c2ecf20Sopenharmony_ci .odigest_ofs = 0x200, 18858c2ecf20Sopenharmony_ci .din_ofs = 0x080, 18868c2ecf20Sopenharmony_ci .digcnt_ofs = 0x280, 18878c2ecf20Sopenharmony_ci .rev_ofs = 0x100, 18888c2ecf20Sopenharmony_ci .mask_ofs = 0x110, 18898c2ecf20Sopenharmony_ci .sysstatus_ofs = 0x114, 18908c2ecf20Sopenharmony_ci .mode_ofs = 0x284, 18918c2ecf20Sopenharmony_ci .length_ofs = 0x288, 18928c2ecf20Sopenharmony_ci .major_mask = 0x0700, 18938c2ecf20Sopenharmony_ci .major_shift = 8, 18948c2ecf20Sopenharmony_ci .minor_mask = 0x003f, 18958c2ecf20Sopenharmony_ci .minor_shift = 0, 18968c2ecf20Sopenharmony_ci}; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic const struct of_device_id omap_sham_of_match[] = { 18998c2ecf20Sopenharmony_ci { 19008c2ecf20Sopenharmony_ci .compatible = "ti,omap2-sham", 19018c2ecf20Sopenharmony_ci .data = &omap_sham_pdata_omap2, 19028c2ecf20Sopenharmony_ci }, 19038c2ecf20Sopenharmony_ci { 19048c2ecf20Sopenharmony_ci .compatible = "ti,omap3-sham", 19058c2ecf20Sopenharmony_ci .data = &omap_sham_pdata_omap2, 19068c2ecf20Sopenharmony_ci }, 19078c2ecf20Sopenharmony_ci { 19088c2ecf20Sopenharmony_ci .compatible = "ti,omap4-sham", 19098c2ecf20Sopenharmony_ci .data = &omap_sham_pdata_omap4, 19108c2ecf20Sopenharmony_ci }, 19118c2ecf20Sopenharmony_ci { 19128c2ecf20Sopenharmony_ci .compatible = "ti,omap5-sham", 19138c2ecf20Sopenharmony_ci .data = &omap_sham_pdata_omap5, 19148c2ecf20Sopenharmony_ci }, 19158c2ecf20Sopenharmony_ci {}, 19168c2ecf20Sopenharmony_ci}; 19178c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, omap_sham_of_match); 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_cistatic int omap_sham_get_res_of(struct omap_sham_dev *dd, 19208c2ecf20Sopenharmony_ci struct device *dev, struct resource *res) 19218c2ecf20Sopenharmony_ci{ 19228c2ecf20Sopenharmony_ci struct device_node *node = dev->of_node; 19238c2ecf20Sopenharmony_ci int err = 0; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci dd->pdata = of_device_get_match_data(dev); 19268c2ecf20Sopenharmony_ci if (!dd->pdata) { 19278c2ecf20Sopenharmony_ci dev_err(dev, "no compatible OF match\n"); 19288c2ecf20Sopenharmony_ci err = -EINVAL; 19298c2ecf20Sopenharmony_ci goto err; 19308c2ecf20Sopenharmony_ci } 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci err = of_address_to_resource(node, 0, res); 19338c2ecf20Sopenharmony_ci if (err < 0) { 19348c2ecf20Sopenharmony_ci dev_err(dev, "can't translate OF node address\n"); 19358c2ecf20Sopenharmony_ci err = -EINVAL; 19368c2ecf20Sopenharmony_ci goto err; 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci dd->irq = irq_of_parse_and_map(node, 0); 19408c2ecf20Sopenharmony_ci if (!dd->irq) { 19418c2ecf20Sopenharmony_ci dev_err(dev, "can't translate OF irq value\n"); 19428c2ecf20Sopenharmony_ci err = -EINVAL; 19438c2ecf20Sopenharmony_ci goto err; 19448c2ecf20Sopenharmony_ci } 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_cierr: 19478c2ecf20Sopenharmony_ci return err; 19488c2ecf20Sopenharmony_ci} 19498c2ecf20Sopenharmony_ci#else 19508c2ecf20Sopenharmony_cistatic const struct of_device_id omap_sham_of_match[] = { 19518c2ecf20Sopenharmony_ci {}, 19528c2ecf20Sopenharmony_ci}; 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_cistatic int omap_sham_get_res_of(struct omap_sham_dev *dd, 19558c2ecf20Sopenharmony_ci struct device *dev, struct resource *res) 19568c2ecf20Sopenharmony_ci{ 19578c2ecf20Sopenharmony_ci return -EINVAL; 19588c2ecf20Sopenharmony_ci} 19598c2ecf20Sopenharmony_ci#endif 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_cistatic int omap_sham_get_res_pdev(struct omap_sham_dev *dd, 19628c2ecf20Sopenharmony_ci struct platform_device *pdev, struct resource *res) 19638c2ecf20Sopenharmony_ci{ 19648c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 19658c2ecf20Sopenharmony_ci struct resource *r; 19668c2ecf20Sopenharmony_ci int err = 0; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci /* Get the base address */ 19698c2ecf20Sopenharmony_ci r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 19708c2ecf20Sopenharmony_ci if (!r) { 19718c2ecf20Sopenharmony_ci dev_err(dev, "no MEM resource info\n"); 19728c2ecf20Sopenharmony_ci err = -ENODEV; 19738c2ecf20Sopenharmony_ci goto err; 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci memcpy(res, r, sizeof(*res)); 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci /* Get the IRQ */ 19788c2ecf20Sopenharmony_ci dd->irq = platform_get_irq(pdev, 0); 19798c2ecf20Sopenharmony_ci if (dd->irq < 0) { 19808c2ecf20Sopenharmony_ci err = dd->irq; 19818c2ecf20Sopenharmony_ci goto err; 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci /* Only OMAP2/3 can be non-DT */ 19858c2ecf20Sopenharmony_ci dd->pdata = &omap_sham_pdata_omap2; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_cierr: 19888c2ecf20Sopenharmony_ci return err; 19898c2ecf20Sopenharmony_ci} 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_cistatic ssize_t fallback_show(struct device *dev, struct device_attribute *attr, 19928c2ecf20Sopenharmony_ci char *buf) 19938c2ecf20Sopenharmony_ci{ 19948c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_get_drvdata(dev); 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", dd->fallback_sz); 19978c2ecf20Sopenharmony_ci} 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_cistatic ssize_t fallback_store(struct device *dev, struct device_attribute *attr, 20008c2ecf20Sopenharmony_ci const char *buf, size_t size) 20018c2ecf20Sopenharmony_ci{ 20028c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_get_drvdata(dev); 20038c2ecf20Sopenharmony_ci ssize_t status; 20048c2ecf20Sopenharmony_ci long value; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci status = kstrtol(buf, 0, &value); 20078c2ecf20Sopenharmony_ci if (status) 20088c2ecf20Sopenharmony_ci return status; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci /* HW accelerator only works with buffers > 9 */ 20118c2ecf20Sopenharmony_ci if (value < 9) { 20128c2ecf20Sopenharmony_ci dev_err(dev, "minimum fallback size 9\n"); 20138c2ecf20Sopenharmony_ci return -EINVAL; 20148c2ecf20Sopenharmony_ci } 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci dd->fallback_sz = value; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci return size; 20198c2ecf20Sopenharmony_ci} 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_cistatic ssize_t queue_len_show(struct device *dev, struct device_attribute *attr, 20228c2ecf20Sopenharmony_ci char *buf) 20238c2ecf20Sopenharmony_ci{ 20248c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_get_drvdata(dev); 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", dd->queue.max_qlen); 20278c2ecf20Sopenharmony_ci} 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_cistatic ssize_t queue_len_store(struct device *dev, 20308c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 20318c2ecf20Sopenharmony_ci size_t size) 20328c2ecf20Sopenharmony_ci{ 20338c2ecf20Sopenharmony_ci struct omap_sham_dev *dd = dev_get_drvdata(dev); 20348c2ecf20Sopenharmony_ci ssize_t status; 20358c2ecf20Sopenharmony_ci long value; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci status = kstrtol(buf, 0, &value); 20388c2ecf20Sopenharmony_ci if (status) 20398c2ecf20Sopenharmony_ci return status; 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci if (value < 1) 20428c2ecf20Sopenharmony_ci return -EINVAL; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci /* 20458c2ecf20Sopenharmony_ci * Changing the queue size in fly is safe, if size becomes smaller 20468c2ecf20Sopenharmony_ci * than current size, it will just not accept new entries until 20478c2ecf20Sopenharmony_ci * it has shrank enough. 20488c2ecf20Sopenharmony_ci */ 20498c2ecf20Sopenharmony_ci dd->queue.max_qlen = value; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci return size; 20528c2ecf20Sopenharmony_ci} 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(queue_len); 20558c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(fallback); 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_cistatic struct attribute *omap_sham_attrs[] = { 20588c2ecf20Sopenharmony_ci &dev_attr_queue_len.attr, 20598c2ecf20Sopenharmony_ci &dev_attr_fallback.attr, 20608c2ecf20Sopenharmony_ci NULL, 20618c2ecf20Sopenharmony_ci}; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_cistatic struct attribute_group omap_sham_attr_group = { 20648c2ecf20Sopenharmony_ci .attrs = omap_sham_attrs, 20658c2ecf20Sopenharmony_ci}; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_cistatic int omap_sham_probe(struct platform_device *pdev) 20688c2ecf20Sopenharmony_ci{ 20698c2ecf20Sopenharmony_ci struct omap_sham_dev *dd; 20708c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 20718c2ecf20Sopenharmony_ci struct resource res; 20728c2ecf20Sopenharmony_ci dma_cap_mask_t mask; 20738c2ecf20Sopenharmony_ci int err, i, j; 20748c2ecf20Sopenharmony_ci u32 rev; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci dd = devm_kzalloc(dev, sizeof(struct omap_sham_dev), GFP_KERNEL); 20778c2ecf20Sopenharmony_ci if (dd == NULL) { 20788c2ecf20Sopenharmony_ci dev_err(dev, "unable to alloc data struct.\n"); 20798c2ecf20Sopenharmony_ci err = -ENOMEM; 20808c2ecf20Sopenharmony_ci goto data_err; 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci dd->dev = dev; 20838c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dd); 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dd->list); 20868c2ecf20Sopenharmony_ci tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd); 20878c2ecf20Sopenharmony_ci crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH); 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) : 20908c2ecf20Sopenharmony_ci omap_sham_get_res_pdev(dd, pdev, &res); 20918c2ecf20Sopenharmony_ci if (err) 20928c2ecf20Sopenharmony_ci goto data_err; 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci dd->io_base = devm_ioremap_resource(dev, &res); 20958c2ecf20Sopenharmony_ci if (IS_ERR(dd->io_base)) { 20968c2ecf20Sopenharmony_ci err = PTR_ERR(dd->io_base); 20978c2ecf20Sopenharmony_ci goto data_err; 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci dd->phys_base = res.start; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr, 21028c2ecf20Sopenharmony_ci IRQF_TRIGGER_NONE, dev_name(dev), dd); 21038c2ecf20Sopenharmony_ci if (err) { 21048c2ecf20Sopenharmony_ci dev_err(dev, "unable to request irq %d, err = %d\n", 21058c2ecf20Sopenharmony_ci dd->irq, err); 21068c2ecf20Sopenharmony_ci goto data_err; 21078c2ecf20Sopenharmony_ci } 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci dma_cap_zero(mask); 21108c2ecf20Sopenharmony_ci dma_cap_set(DMA_SLAVE, mask); 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci dd->dma_lch = dma_request_chan(dev, "rx"); 21138c2ecf20Sopenharmony_ci if (IS_ERR(dd->dma_lch)) { 21148c2ecf20Sopenharmony_ci err = PTR_ERR(dd->dma_lch); 21158c2ecf20Sopenharmony_ci if (err == -EPROBE_DEFER) 21168c2ecf20Sopenharmony_ci goto data_err; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci dd->polling_mode = 1; 21198c2ecf20Sopenharmony_ci dev_dbg(dev, "using polling mode instead of dma\n"); 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci dd->flags |= dd->pdata->flags; 21238c2ecf20Sopenharmony_ci sham.flags |= dd->pdata->flags; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci pm_runtime_use_autosuspend(dev); 21268c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY); 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci dd->fallback_sz = OMAP_SHA_DMA_THRESHOLD; 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 21318c2ecf20Sopenharmony_ci pm_runtime_irq_safe(dev); 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci err = pm_runtime_resume_and_get(dev); 21348c2ecf20Sopenharmony_ci if (err < 0) { 21358c2ecf20Sopenharmony_ci dev_err(dev, "failed to get sync: %d\n", err); 21368c2ecf20Sopenharmony_ci goto err_pm; 21378c2ecf20Sopenharmony_ci } 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci rev = omap_sham_read(dd, SHA_REG_REV(dd)); 21408c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci dev_info(dev, "hw accel on OMAP rev %u.%u\n", 21438c2ecf20Sopenharmony_ci (rev & dd->pdata->major_mask) >> dd->pdata->major_shift, 21448c2ecf20Sopenharmony_ci (rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci spin_lock_bh(&sham.lock); 21478c2ecf20Sopenharmony_ci list_add_tail(&dd->list, &sham.dev_list); 21488c2ecf20Sopenharmony_ci spin_unlock_bh(&sham.lock); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci dd->engine = crypto_engine_alloc_init(dev, 1); 21518c2ecf20Sopenharmony_ci if (!dd->engine) { 21528c2ecf20Sopenharmony_ci err = -ENOMEM; 21538c2ecf20Sopenharmony_ci goto err_engine; 21548c2ecf20Sopenharmony_ci } 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci err = crypto_engine_start(dd->engine); 21578c2ecf20Sopenharmony_ci if (err) 21588c2ecf20Sopenharmony_ci goto err_engine_start; 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci for (i = 0; i < dd->pdata->algs_info_size; i++) { 21618c2ecf20Sopenharmony_ci if (dd->pdata->algs_info[i].registered) 21628c2ecf20Sopenharmony_ci break; 21638c2ecf20Sopenharmony_ci 21648c2ecf20Sopenharmony_ci for (j = 0; j < dd->pdata->algs_info[i].size; j++) { 21658c2ecf20Sopenharmony_ci struct ahash_alg *alg; 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci alg = &dd->pdata->algs_info[i].algs_list[j]; 21688c2ecf20Sopenharmony_ci alg->export = omap_sham_export; 21698c2ecf20Sopenharmony_ci alg->import = omap_sham_import; 21708c2ecf20Sopenharmony_ci alg->halg.statesize = sizeof(struct omap_sham_reqctx) + 21718c2ecf20Sopenharmony_ci BUFLEN; 21728c2ecf20Sopenharmony_ci err = crypto_register_ahash(alg); 21738c2ecf20Sopenharmony_ci if (err) 21748c2ecf20Sopenharmony_ci goto err_algs; 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci dd->pdata->algs_info[i].registered++; 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci } 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci err = sysfs_create_group(&dev->kobj, &omap_sham_attr_group); 21818c2ecf20Sopenharmony_ci if (err) { 21828c2ecf20Sopenharmony_ci dev_err(dev, "could not create sysfs device attrs\n"); 21838c2ecf20Sopenharmony_ci goto err_algs; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci return 0; 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_cierr_algs: 21898c2ecf20Sopenharmony_ci for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) 21908c2ecf20Sopenharmony_ci for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) 21918c2ecf20Sopenharmony_ci crypto_unregister_ahash( 21928c2ecf20Sopenharmony_ci &dd->pdata->algs_info[i].algs_list[j]); 21938c2ecf20Sopenharmony_cierr_engine_start: 21948c2ecf20Sopenharmony_ci crypto_engine_exit(dd->engine); 21958c2ecf20Sopenharmony_cierr_engine: 21968c2ecf20Sopenharmony_ci spin_lock_bh(&sham.lock); 21978c2ecf20Sopenharmony_ci list_del(&dd->list); 21988c2ecf20Sopenharmony_ci spin_unlock_bh(&sham.lock); 21998c2ecf20Sopenharmony_cierr_pm: 22008c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 22018c2ecf20Sopenharmony_ci if (!dd->polling_mode) 22028c2ecf20Sopenharmony_ci dma_release_channel(dd->dma_lch); 22038c2ecf20Sopenharmony_cidata_err: 22048c2ecf20Sopenharmony_ci dev_err(dev, "initialization failed.\n"); 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci return err; 22078c2ecf20Sopenharmony_ci} 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_cistatic int omap_sham_remove(struct platform_device *pdev) 22108c2ecf20Sopenharmony_ci{ 22118c2ecf20Sopenharmony_ci struct omap_sham_dev *dd; 22128c2ecf20Sopenharmony_ci int i, j; 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci dd = platform_get_drvdata(pdev); 22158c2ecf20Sopenharmony_ci if (!dd) 22168c2ecf20Sopenharmony_ci return -ENODEV; 22178c2ecf20Sopenharmony_ci spin_lock_bh(&sham.lock); 22188c2ecf20Sopenharmony_ci list_del(&dd->list); 22198c2ecf20Sopenharmony_ci spin_unlock_bh(&sham.lock); 22208c2ecf20Sopenharmony_ci for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) 22218c2ecf20Sopenharmony_ci for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { 22228c2ecf20Sopenharmony_ci crypto_unregister_ahash( 22238c2ecf20Sopenharmony_ci &dd->pdata->algs_info[i].algs_list[j]); 22248c2ecf20Sopenharmony_ci dd->pdata->algs_info[i].registered--; 22258c2ecf20Sopenharmony_ci } 22268c2ecf20Sopenharmony_ci tasklet_kill(&dd->done_task); 22278c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci if (!dd->polling_mode) 22308c2ecf20Sopenharmony_ci dma_release_channel(dd->dma_lch); 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci sysfs_remove_group(&dd->dev->kobj, &omap_sham_attr_group); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci return 0; 22358c2ecf20Sopenharmony_ci} 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 22388c2ecf20Sopenharmony_cistatic int omap_sham_suspend(struct device *dev) 22398c2ecf20Sopenharmony_ci{ 22408c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 22418c2ecf20Sopenharmony_ci return 0; 22428c2ecf20Sopenharmony_ci} 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_cistatic int omap_sham_resume(struct device *dev) 22458c2ecf20Sopenharmony_ci{ 22468c2ecf20Sopenharmony_ci int err = pm_runtime_resume_and_get(dev); 22478c2ecf20Sopenharmony_ci if (err < 0) { 22488c2ecf20Sopenharmony_ci dev_err(dev, "failed to get sync: %d\n", err); 22498c2ecf20Sopenharmony_ci return err; 22508c2ecf20Sopenharmony_ci } 22518c2ecf20Sopenharmony_ci return 0; 22528c2ecf20Sopenharmony_ci} 22538c2ecf20Sopenharmony_ci#endif 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(omap_sham_pm_ops, omap_sham_suspend, omap_sham_resume); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_cistatic struct platform_driver omap_sham_driver = { 22588c2ecf20Sopenharmony_ci .probe = omap_sham_probe, 22598c2ecf20Sopenharmony_ci .remove = omap_sham_remove, 22608c2ecf20Sopenharmony_ci .driver = { 22618c2ecf20Sopenharmony_ci .name = "omap-sham", 22628c2ecf20Sopenharmony_ci .pm = &omap_sham_pm_ops, 22638c2ecf20Sopenharmony_ci .of_match_table = omap_sham_of_match, 22648c2ecf20Sopenharmony_ci }, 22658c2ecf20Sopenharmony_ci}; 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_cimodule_platform_driver(omap_sham_driver); 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("OMAP SHA1/MD5 hw acceleration support."); 22708c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 22718c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dmitry Kasatkin"); 22728c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:omap-sham"); 2273