xref: /linux/drivers/crypto/stm32/stm32-cryp.c (revision bbb2832620ac4e136416aa97af7310636422dea9)
1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e054ec2SFabien DESSENNE /*
39e054ec2SFabien DESSENNE  * Copyright (C) STMicroelectronics SA 2017
49e054ec2SFabien DESSENNE  * Author: Fabien Dessenne <fabien.dessenne@st.com>
59e054ec2SFabien DESSENNE  */
69e054ec2SFabien DESSENNE 
79e054ec2SFabien DESSENNE #include <linux/clk.h>
89e054ec2SFabien DESSENNE #include <linux/delay.h>
99e054ec2SFabien DESSENNE #include <linux/interrupt.h>
109e054ec2SFabien DESSENNE #include <linux/iopoll.h>
119e054ec2SFabien DESSENNE #include <linux/module.h>
129e054ec2SFabien DESSENNE #include <linux/of_device.h>
139e054ec2SFabien DESSENNE #include <linux/platform_device.h>
1465f9aa36Slionel.debieve@st.com #include <linux/pm_runtime.h>
159e054ec2SFabien DESSENNE #include <linux/reset.h>
169e054ec2SFabien DESSENNE 
179e054ec2SFabien DESSENNE #include <crypto/aes.h>
18b5d0ba83SArd Biesheuvel #include <crypto/internal/des.h>
199e054ec2SFabien DESSENNE #include <crypto/engine.h>
209e054ec2SFabien DESSENNE #include <crypto/scatterwalk.h>
219d3b5030SFabien DESSENNE #include <crypto/internal/aead.h>
2247ece481SArd Biesheuvel #include <crypto/internal/skcipher.h>
239e054ec2SFabien DESSENNE 
249e054ec2SFabien DESSENNE #define DRIVER_NAME             "stm32-cryp"
259e054ec2SFabien DESSENNE 
269e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */
279e054ec2SFabien DESSENNE #define FLG_ENCRYPT             BIT(0)
289e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */
299e054ec2SFabien DESSENNE #define FLG_AES                 BIT(1)
309e054ec2SFabien DESSENNE #define FLG_DES                 BIT(2)
319e054ec2SFabien DESSENNE #define FLG_TDES                BIT(3)
329e054ec2SFabien DESSENNE #define FLG_ECB                 BIT(4)
339e054ec2SFabien DESSENNE #define FLG_CBC                 BIT(5)
349e054ec2SFabien DESSENNE #define FLG_CTR                 BIT(6)
359d3b5030SFabien DESSENNE #define FLG_GCM                 BIT(7)
369d3b5030SFabien DESSENNE #define FLG_CCM                 BIT(8)
379e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */
389e054ec2SFabien DESSENNE #define FLG_MODE_MASK           GENMASK(15, 0)
399d3b5030SFabien DESSENNE /* Bit [31..16] status  */
409d3b5030SFabien DESSENNE #define FLG_CCM_PADDED_WA       BIT(16)
419e054ec2SFabien DESSENNE 
429e054ec2SFabien DESSENNE /* Registers */
439e054ec2SFabien DESSENNE #define CRYP_CR                 0x00000000
449e054ec2SFabien DESSENNE #define CRYP_SR                 0x00000004
459e054ec2SFabien DESSENNE #define CRYP_DIN                0x00000008
469e054ec2SFabien DESSENNE #define CRYP_DOUT               0x0000000C
479e054ec2SFabien DESSENNE #define CRYP_DMACR              0x00000010
489e054ec2SFabien DESSENNE #define CRYP_IMSCR              0x00000014
499e054ec2SFabien DESSENNE #define CRYP_RISR               0x00000018
509e054ec2SFabien DESSENNE #define CRYP_MISR               0x0000001C
519e054ec2SFabien DESSENNE #define CRYP_K0LR               0x00000020
529e054ec2SFabien DESSENNE #define CRYP_K0RR               0x00000024
539e054ec2SFabien DESSENNE #define CRYP_K1LR               0x00000028
549e054ec2SFabien DESSENNE #define CRYP_K1RR               0x0000002C
559e054ec2SFabien DESSENNE #define CRYP_K2LR               0x00000030
569e054ec2SFabien DESSENNE #define CRYP_K2RR               0x00000034
579e054ec2SFabien DESSENNE #define CRYP_K3LR               0x00000038
589e054ec2SFabien DESSENNE #define CRYP_K3RR               0x0000003C
599e054ec2SFabien DESSENNE #define CRYP_IV0LR              0x00000040
609e054ec2SFabien DESSENNE #define CRYP_IV0RR              0x00000044
619e054ec2SFabien DESSENNE #define CRYP_IV1LR              0x00000048
629e054ec2SFabien DESSENNE #define CRYP_IV1RR              0x0000004C
639d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R         0x00000050
649d3b5030SFabien DESSENNE #define CRYP_CSGCM0R            0x00000070
659e054ec2SFabien DESSENNE 
669e054ec2SFabien DESSENNE /* Registers values */
679e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC          0x00000004
689e054ec2SFabien DESSENNE #define CR_TDES_ECB             0x00000000
699e054ec2SFabien DESSENNE #define CR_TDES_CBC             0x00000008
709e054ec2SFabien DESSENNE #define CR_DES_ECB              0x00000010
719e054ec2SFabien DESSENNE #define CR_DES_CBC              0x00000018
729e054ec2SFabien DESSENNE #define CR_AES_ECB              0x00000020
739e054ec2SFabien DESSENNE #define CR_AES_CBC              0x00000028
749e054ec2SFabien DESSENNE #define CR_AES_CTR              0x00000030
759e054ec2SFabien DESSENNE #define CR_AES_KP               0x00000038
769d3b5030SFabien DESSENNE #define CR_AES_GCM              0x00080000
779d3b5030SFabien DESSENNE #define CR_AES_CCM              0x00080008
789e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN          0xFFFFFFFF
799e054ec2SFabien DESSENNE #define CR_ALGO_MASK            0x00080038
809e054ec2SFabien DESSENNE #define CR_DATA32               0x00000000
819e054ec2SFabien DESSENNE #define CR_DATA16               0x00000040
829e054ec2SFabien DESSENNE #define CR_DATA8                0x00000080
839e054ec2SFabien DESSENNE #define CR_DATA1                0x000000C0
849e054ec2SFabien DESSENNE #define CR_KEY128               0x00000000
859e054ec2SFabien DESSENNE #define CR_KEY192               0x00000100
869e054ec2SFabien DESSENNE #define CR_KEY256               0x00000200
879e054ec2SFabien DESSENNE #define CR_FFLUSH               0x00004000
889e054ec2SFabien DESSENNE #define CR_CRYPEN               0x00008000
899d3b5030SFabien DESSENNE #define CR_PH_INIT              0x00000000
909d3b5030SFabien DESSENNE #define CR_PH_HEADER            0x00010000
919d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD           0x00020000
929d3b5030SFabien DESSENNE #define CR_PH_FINAL             0x00030000
939d3b5030SFabien DESSENNE #define CR_PH_MASK              0x00030000
949d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT          20
959e054ec2SFabien DESSENNE 
969e054ec2SFabien DESSENNE #define SR_BUSY                 0x00000010
979e054ec2SFabien DESSENNE #define SR_OFNE                 0x00000004
989e054ec2SFabien DESSENNE 
999e054ec2SFabien DESSENNE #define IMSCR_IN                BIT(0)
1009e054ec2SFabien DESSENNE #define IMSCR_OUT               BIT(1)
1019e054ec2SFabien DESSENNE 
1029e054ec2SFabien DESSENNE #define MISR_IN                 BIT(0)
1039e054ec2SFabien DESSENNE #define MISR_OUT                BIT(1)
1049e054ec2SFabien DESSENNE 
1059e054ec2SFabien DESSENNE /* Misc */
1069e054ec2SFabien DESSENNE #define AES_BLOCK_32            (AES_BLOCK_SIZE / sizeof(u32))
1079d3b5030SFabien DESSENNE #define GCM_CTR_INIT            2
1089e054ec2SFabien DESSENNE #define _walked_in              (cryp->in_walk.offset - cryp->in_sg->offset)
1099e054ec2SFabien DESSENNE #define _walked_out             (cryp->out_walk.offset - cryp->out_sg->offset)
11065f9aa36Slionel.debieve@st.com #define CRYP_AUTOSUSPEND_DELAY	50
1119e054ec2SFabien DESSENNE 
1129d3b5030SFabien DESSENNE struct stm32_cryp_caps {
1139d3b5030SFabien DESSENNE 	bool                    swap_final;
1149d3b5030SFabien DESSENNE 	bool                    padding_wa;
1159d3b5030SFabien DESSENNE };
1169d3b5030SFabien DESSENNE 
1179e054ec2SFabien DESSENNE struct stm32_cryp_ctx {
118dc7bcef5SCorentin LABBE 	struct crypto_engine_ctx enginectx;
1199e054ec2SFabien DESSENNE 	struct stm32_cryp       *cryp;
1209e054ec2SFabien DESSENNE 	int                     keylen;
121*bbb28326SHerbert Xu 	__be32                  key[AES_KEYSIZE_256 / sizeof(u32)];
1229e054ec2SFabien DESSENNE 	unsigned long           flags;
1239e054ec2SFabien DESSENNE };
1249e054ec2SFabien DESSENNE 
1259e054ec2SFabien DESSENNE struct stm32_cryp_reqctx {
1269e054ec2SFabien DESSENNE 	unsigned long mode;
1279e054ec2SFabien DESSENNE };
1289e054ec2SFabien DESSENNE 
1299e054ec2SFabien DESSENNE struct stm32_cryp {
1309e054ec2SFabien DESSENNE 	struct list_head        list;
1319e054ec2SFabien DESSENNE 	struct device           *dev;
1329e054ec2SFabien DESSENNE 	void __iomem            *regs;
1339e054ec2SFabien DESSENNE 	struct clk              *clk;
1349e054ec2SFabien DESSENNE 	unsigned long           flags;
1359e054ec2SFabien DESSENNE 	u32                     irq_status;
1369d3b5030SFabien DESSENNE 	const struct stm32_cryp_caps *caps;
1379e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx   *ctx;
1389e054ec2SFabien DESSENNE 
1399e054ec2SFabien DESSENNE 	struct crypto_engine    *engine;
1409e054ec2SFabien DESSENNE 
14147ece481SArd Biesheuvel 	struct skcipher_request *req;
1429d3b5030SFabien DESSENNE 	struct aead_request     *areq;
1439e054ec2SFabien DESSENNE 
1449d3b5030SFabien DESSENNE 	size_t                  authsize;
1459e054ec2SFabien DESSENNE 	size_t                  hw_blocksize;
1469e054ec2SFabien DESSENNE 
1479e054ec2SFabien DESSENNE 	size_t                  total_in;
1489e054ec2SFabien DESSENNE 	size_t                  total_in_save;
1499e054ec2SFabien DESSENNE 	size_t                  total_out;
1509e054ec2SFabien DESSENNE 	size_t                  total_out_save;
1519e054ec2SFabien DESSENNE 
1529e054ec2SFabien DESSENNE 	struct scatterlist      *in_sg;
1539e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg;
1549e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg_save;
1559e054ec2SFabien DESSENNE 
1569e054ec2SFabien DESSENNE 	struct scatterlist      in_sgl;
1579e054ec2SFabien DESSENNE 	struct scatterlist      out_sgl;
1589e054ec2SFabien DESSENNE 	bool                    sgs_copied;
1599e054ec2SFabien DESSENNE 
1609e054ec2SFabien DESSENNE 	int                     in_sg_len;
1619e054ec2SFabien DESSENNE 	int                     out_sg_len;
1629e054ec2SFabien DESSENNE 
1639e054ec2SFabien DESSENNE 	struct scatter_walk     in_walk;
1649e054ec2SFabien DESSENNE 	struct scatter_walk     out_walk;
1659e054ec2SFabien DESSENNE 
1669e054ec2SFabien DESSENNE 	u32                     last_ctr[4];
1679d3b5030SFabien DESSENNE 	u32                     gcm_ctr;
1689e054ec2SFabien DESSENNE };
1699e054ec2SFabien DESSENNE 
1709e054ec2SFabien DESSENNE struct stm32_cryp_list {
1719e054ec2SFabien DESSENNE 	struct list_head        dev_list;
1729e054ec2SFabien DESSENNE 	spinlock_t              lock; /* protect dev_list */
1739e054ec2SFabien DESSENNE };
1749e054ec2SFabien DESSENNE 
1759e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = {
1769e054ec2SFabien DESSENNE 	.dev_list = LIST_HEAD_INIT(cryp_list.dev_list),
1779e054ec2SFabien DESSENNE 	.lock     = __SPIN_LOCK_UNLOCKED(cryp_list.lock),
1789e054ec2SFabien DESSENNE };
1799e054ec2SFabien DESSENNE 
1809e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp)
1819e054ec2SFabien DESSENNE {
1829e054ec2SFabien DESSENNE 	return cryp->flags & FLG_AES;
1839e054ec2SFabien DESSENNE }
1849e054ec2SFabien DESSENNE 
1859e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp)
1869e054ec2SFabien DESSENNE {
1879e054ec2SFabien DESSENNE 	return cryp->flags & FLG_DES;
1889e054ec2SFabien DESSENNE }
1899e054ec2SFabien DESSENNE 
1909e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp)
1919e054ec2SFabien DESSENNE {
1929e054ec2SFabien DESSENNE 	return cryp->flags & FLG_TDES;
1939e054ec2SFabien DESSENNE }
1949e054ec2SFabien DESSENNE 
1959e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp)
1969e054ec2SFabien DESSENNE {
1979e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ECB;
1989e054ec2SFabien DESSENNE }
1999e054ec2SFabien DESSENNE 
2009e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp)
2019e054ec2SFabien DESSENNE {
2029e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CBC;
2039e054ec2SFabien DESSENNE }
2049e054ec2SFabien DESSENNE 
2059e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp)
2069e054ec2SFabien DESSENNE {
2079e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CTR;
2089e054ec2SFabien DESSENNE }
2099e054ec2SFabien DESSENNE 
2109d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp)
2119d3b5030SFabien DESSENNE {
2129d3b5030SFabien DESSENNE 	return cryp->flags & FLG_GCM;
2139d3b5030SFabien DESSENNE }
2149d3b5030SFabien DESSENNE 
2159d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp)
2169d3b5030SFabien DESSENNE {
2179d3b5030SFabien DESSENNE 	return cryp->flags & FLG_CCM;
2189d3b5030SFabien DESSENNE }
2199d3b5030SFabien DESSENNE 
2209e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp)
2219e054ec2SFabien DESSENNE {
2229e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ENCRYPT;
2239e054ec2SFabien DESSENNE }
2249e054ec2SFabien DESSENNE 
2259e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp)
2269e054ec2SFabien DESSENNE {
2279e054ec2SFabien DESSENNE 	return !is_encrypt(cryp);
2289e054ec2SFabien DESSENNE }
2299e054ec2SFabien DESSENNE 
2309e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst)
2319e054ec2SFabien DESSENNE {
2329e054ec2SFabien DESSENNE 	return readl_relaxed(cryp->regs + ofst);
2339e054ec2SFabien DESSENNE }
2349e054ec2SFabien DESSENNE 
2359e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val)
2369e054ec2SFabien DESSENNE {
2379e054ec2SFabien DESSENNE 	writel_relaxed(val, cryp->regs + ofst);
2389e054ec2SFabien DESSENNE }
2399e054ec2SFabien DESSENNE 
2409e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
2419e054ec2SFabien DESSENNE {
2429e054ec2SFabien DESSENNE 	u32 status;
2439e054ec2SFabien DESSENNE 
2449e054ec2SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status,
2459e054ec2SFabien DESSENNE 			!(status & SR_BUSY), 10, 100000);
2469e054ec2SFabien DESSENNE }
2479e054ec2SFabien DESSENNE 
2489d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
2499d3b5030SFabien DESSENNE {
2509d3b5030SFabien DESSENNE 	u32 status;
2519d3b5030SFabien DESSENNE 
2529d3b5030SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_CR, status,
2539d3b5030SFabien DESSENNE 			!(status & CR_CRYPEN), 10, 100000);
2549d3b5030SFabien DESSENNE }
2559d3b5030SFabien DESSENNE 
2569d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp)
2579d3b5030SFabien DESSENNE {
2589d3b5030SFabien DESSENNE 	u32 status;
2599d3b5030SFabien DESSENNE 
2609d3b5030SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status,
2619d3b5030SFabien DESSENNE 			status & SR_OFNE, 10, 100000);
2629d3b5030SFabien DESSENNE }
2639d3b5030SFabien DESSENNE 
2649d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp);
2659d3b5030SFabien DESSENNE 
2669e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx)
2679e054ec2SFabien DESSENNE {
2689e054ec2SFabien DESSENNE 	struct stm32_cryp *tmp, *cryp = NULL;
2699e054ec2SFabien DESSENNE 
2709e054ec2SFabien DESSENNE 	spin_lock_bh(&cryp_list.lock);
2719e054ec2SFabien DESSENNE 	if (!ctx->cryp) {
2729e054ec2SFabien DESSENNE 		list_for_each_entry(tmp, &cryp_list.dev_list, list) {
2739e054ec2SFabien DESSENNE 			cryp = tmp;
2749e054ec2SFabien DESSENNE 			break;
2759e054ec2SFabien DESSENNE 		}
2769e054ec2SFabien DESSENNE 		ctx->cryp = cryp;
2779e054ec2SFabien DESSENNE 	} else {
2789e054ec2SFabien DESSENNE 		cryp = ctx->cryp;
2799e054ec2SFabien DESSENNE 	}
2809e054ec2SFabien DESSENNE 
2819e054ec2SFabien DESSENNE 	spin_unlock_bh(&cryp_list.lock);
2829e054ec2SFabien DESSENNE 
2839e054ec2SFabien DESSENNE 	return cryp;
2849e054ec2SFabien DESSENNE }
2859e054ec2SFabien DESSENNE 
2869e054ec2SFabien DESSENNE static int stm32_cryp_check_aligned(struct scatterlist *sg, size_t total,
2879e054ec2SFabien DESSENNE 				    size_t align)
2889e054ec2SFabien DESSENNE {
2899e054ec2SFabien DESSENNE 	int len = 0;
2909e054ec2SFabien DESSENNE 
2919e054ec2SFabien DESSENNE 	if (!total)
2929e054ec2SFabien DESSENNE 		return 0;
2939e054ec2SFabien DESSENNE 
2949e054ec2SFabien DESSENNE 	if (!IS_ALIGNED(total, align))
2959e054ec2SFabien DESSENNE 		return -EINVAL;
2969e054ec2SFabien DESSENNE 
2979e054ec2SFabien DESSENNE 	while (sg) {
2989e054ec2SFabien DESSENNE 		if (!IS_ALIGNED(sg->offset, sizeof(u32)))
2999e054ec2SFabien DESSENNE 			return -EINVAL;
3009e054ec2SFabien DESSENNE 
3019e054ec2SFabien DESSENNE 		if (!IS_ALIGNED(sg->length, align))
3029e054ec2SFabien DESSENNE 			return -EINVAL;
3039e054ec2SFabien DESSENNE 
3049e054ec2SFabien DESSENNE 		len += sg->length;
3059e054ec2SFabien DESSENNE 		sg = sg_next(sg);
3069e054ec2SFabien DESSENNE 	}
3079e054ec2SFabien DESSENNE 
3089e054ec2SFabien DESSENNE 	if (len != total)
3099e054ec2SFabien DESSENNE 		return -EINVAL;
3109e054ec2SFabien DESSENNE 
3119e054ec2SFabien DESSENNE 	return 0;
3129e054ec2SFabien DESSENNE }
3139e054ec2SFabien DESSENNE 
3149e054ec2SFabien DESSENNE static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp)
3159e054ec2SFabien DESSENNE {
3169e054ec2SFabien DESSENNE 	int ret;
3179e054ec2SFabien DESSENNE 
3189e054ec2SFabien DESSENNE 	ret = stm32_cryp_check_aligned(cryp->in_sg, cryp->total_in,
3199e054ec2SFabien DESSENNE 				       cryp->hw_blocksize);
3209e054ec2SFabien DESSENNE 	if (ret)
3219e054ec2SFabien DESSENNE 		return ret;
3229e054ec2SFabien DESSENNE 
3239e054ec2SFabien DESSENNE 	ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out,
3249e054ec2SFabien DESSENNE 				       cryp->hw_blocksize);
3259e054ec2SFabien DESSENNE 
3269e054ec2SFabien DESSENNE 	return ret;
3279e054ec2SFabien DESSENNE }
3289e054ec2SFabien DESSENNE 
3299e054ec2SFabien DESSENNE static void sg_copy_buf(void *buf, struct scatterlist *sg,
3309e054ec2SFabien DESSENNE 			unsigned int start, unsigned int nbytes, int out)
3319e054ec2SFabien DESSENNE {
3329e054ec2SFabien DESSENNE 	struct scatter_walk walk;
3339e054ec2SFabien DESSENNE 
3349e054ec2SFabien DESSENNE 	if (!nbytes)
3359e054ec2SFabien DESSENNE 		return;
3369e054ec2SFabien DESSENNE 
3379e054ec2SFabien DESSENNE 	scatterwalk_start(&walk, sg);
3389e054ec2SFabien DESSENNE 	scatterwalk_advance(&walk, start);
3399e054ec2SFabien DESSENNE 	scatterwalk_copychunks(buf, &walk, nbytes, out);
3409e054ec2SFabien DESSENNE 	scatterwalk_done(&walk, out, 0);
3419e054ec2SFabien DESSENNE }
3429e054ec2SFabien DESSENNE 
3439e054ec2SFabien DESSENNE static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp)
3449e054ec2SFabien DESSENNE {
3459e054ec2SFabien DESSENNE 	void *buf_in, *buf_out;
3469e054ec2SFabien DESSENNE 	int pages, total_in, total_out;
3479e054ec2SFabien DESSENNE 
3489e054ec2SFabien DESSENNE 	if (!stm32_cryp_check_io_aligned(cryp)) {
3499e054ec2SFabien DESSENNE 		cryp->sgs_copied = 0;
3509e054ec2SFabien DESSENNE 		return 0;
3519e054ec2SFabien DESSENNE 	}
3529e054ec2SFabien DESSENNE 
3539e054ec2SFabien DESSENNE 	total_in = ALIGN(cryp->total_in, cryp->hw_blocksize);
3549e054ec2SFabien DESSENNE 	pages = total_in ? get_order(total_in) : 1;
3559e054ec2SFabien DESSENNE 	buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
3569e054ec2SFabien DESSENNE 
3579e054ec2SFabien DESSENNE 	total_out = ALIGN(cryp->total_out, cryp->hw_blocksize);
3589e054ec2SFabien DESSENNE 	pages = total_out ? get_order(total_out) : 1;
3599e054ec2SFabien DESSENNE 	buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
3609e054ec2SFabien DESSENNE 
3619e054ec2SFabien DESSENNE 	if (!buf_in || !buf_out) {
3629e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Can't allocate pages when unaligned\n");
3639e054ec2SFabien DESSENNE 		cryp->sgs_copied = 0;
3649e054ec2SFabien DESSENNE 		return -EFAULT;
3659e054ec2SFabien DESSENNE 	}
3669e054ec2SFabien DESSENNE 
3679e054ec2SFabien DESSENNE 	sg_copy_buf(buf_in, cryp->in_sg, 0, cryp->total_in, 0);
3689e054ec2SFabien DESSENNE 
3699e054ec2SFabien DESSENNE 	sg_init_one(&cryp->in_sgl, buf_in, total_in);
3709e054ec2SFabien DESSENNE 	cryp->in_sg = &cryp->in_sgl;
3719e054ec2SFabien DESSENNE 	cryp->in_sg_len = 1;
3729e054ec2SFabien DESSENNE 
3739e054ec2SFabien DESSENNE 	sg_init_one(&cryp->out_sgl, buf_out, total_out);
3749e054ec2SFabien DESSENNE 	cryp->out_sg_save = cryp->out_sg;
3759e054ec2SFabien DESSENNE 	cryp->out_sg = &cryp->out_sgl;
3769e054ec2SFabien DESSENNE 	cryp->out_sg_len = 1;
3779e054ec2SFabien DESSENNE 
3789e054ec2SFabien DESSENNE 	cryp->sgs_copied = 1;
3799e054ec2SFabien DESSENNE 
3809e054ec2SFabien DESSENNE 	return 0;
3819e054ec2SFabien DESSENNE }
3829e054ec2SFabien DESSENNE 
383*bbb28326SHerbert Xu static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv)
3849e054ec2SFabien DESSENNE {
3859e054ec2SFabien DESSENNE 	if (!iv)
3869e054ec2SFabien DESSENNE 		return;
3879e054ec2SFabien DESSENNE 
388*bbb28326SHerbert Xu 	stm32_cryp_write(cryp, CRYP_IV0LR, be32_to_cpu(*iv++));
389*bbb28326SHerbert Xu 	stm32_cryp_write(cryp, CRYP_IV0RR, be32_to_cpu(*iv++));
3909e054ec2SFabien DESSENNE 
3919e054ec2SFabien DESSENNE 	if (is_aes(cryp)) {
392*bbb28326SHerbert Xu 		stm32_cryp_write(cryp, CRYP_IV1LR, be32_to_cpu(*iv++));
393*bbb28326SHerbert Xu 		stm32_cryp_write(cryp, CRYP_IV1RR, be32_to_cpu(*iv++));
3949e054ec2SFabien DESSENNE 	}
3959e054ec2SFabien DESSENNE }
3969e054ec2SFabien DESSENNE 
3975f49f18dSLionel Debieve static void stm32_cryp_get_iv(struct stm32_cryp *cryp)
3985f49f18dSLionel Debieve {
39947ece481SArd Biesheuvel 	struct skcipher_request *req = cryp->req;
400*bbb28326SHerbert Xu 	__be32 *tmp = (void *)req->iv;
4015f49f18dSLionel Debieve 
4025f49f18dSLionel Debieve 	if (!tmp)
4035f49f18dSLionel Debieve 		return;
4045f49f18dSLionel Debieve 
4055f49f18dSLionel Debieve 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0LR));
4065f49f18dSLionel Debieve 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0RR));
4075f49f18dSLionel Debieve 
4085f49f18dSLionel Debieve 	if (is_aes(cryp)) {
4095f49f18dSLionel Debieve 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1LR));
4105f49f18dSLionel Debieve 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1RR));
4115f49f18dSLionel Debieve 	}
4125f49f18dSLionel Debieve }
4135f49f18dSLionel Debieve 
4149e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c)
4159e054ec2SFabien DESSENNE {
4169e054ec2SFabien DESSENNE 	unsigned int i;
4179e054ec2SFabien DESSENNE 	int r_id;
4189e054ec2SFabien DESSENNE 
4199e054ec2SFabien DESSENNE 	if (is_des(c)) {
420*bbb28326SHerbert Xu 		stm32_cryp_write(c, CRYP_K1LR, be32_to_cpu(c->ctx->key[0]));
421*bbb28326SHerbert Xu 		stm32_cryp_write(c, CRYP_K1RR, be32_to_cpu(c->ctx->key[1]));
4229e054ec2SFabien DESSENNE 	} else {
4239e054ec2SFabien DESSENNE 		r_id = CRYP_K3RR;
4249e054ec2SFabien DESSENNE 		for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4)
4259e054ec2SFabien DESSENNE 			stm32_cryp_write(c, r_id,
426*bbb28326SHerbert Xu 					 be32_to_cpu(c->ctx->key[i - 1]));
4279e054ec2SFabien DESSENNE 	}
4289e054ec2SFabien DESSENNE }
4299e054ec2SFabien DESSENNE 
4309e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp)
4319e054ec2SFabien DESSENNE {
4329e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ecb(cryp))
4339e054ec2SFabien DESSENNE 		return CR_AES_ECB;
4349e054ec2SFabien DESSENNE 
4359e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_cbc(cryp))
4369e054ec2SFabien DESSENNE 		return CR_AES_CBC;
4379e054ec2SFabien DESSENNE 
4389e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
4399e054ec2SFabien DESSENNE 		return CR_AES_CTR;
4409e054ec2SFabien DESSENNE 
4419d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_gcm(cryp))
4429d3b5030SFabien DESSENNE 		return CR_AES_GCM;
4439d3b5030SFabien DESSENNE 
4449d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_ccm(cryp))
4459d3b5030SFabien DESSENNE 		return CR_AES_CCM;
4469d3b5030SFabien DESSENNE 
4479e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_ecb(cryp))
4489e054ec2SFabien DESSENNE 		return CR_DES_ECB;
4499e054ec2SFabien DESSENNE 
4509e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_cbc(cryp))
4519e054ec2SFabien DESSENNE 		return CR_DES_CBC;
4529e054ec2SFabien DESSENNE 
4539e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_ecb(cryp))
4549e054ec2SFabien DESSENNE 		return CR_TDES_ECB;
4559e054ec2SFabien DESSENNE 
4569e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_cbc(cryp))
4579e054ec2SFabien DESSENNE 		return CR_TDES_CBC;
4589e054ec2SFabien DESSENNE 
4599e054ec2SFabien DESSENNE 	dev_err(cryp->dev, "Unknown mode\n");
4609e054ec2SFabien DESSENNE 	return CR_AES_UNKNOWN;
4619e054ec2SFabien DESSENNE }
4629e054ec2SFabien DESSENNE 
4639d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp)
4649d3b5030SFabien DESSENNE {
4659d3b5030SFabien DESSENNE 	return is_encrypt(cryp) ? cryp->areq->cryptlen :
4669d3b5030SFabien DESSENNE 				  cryp->areq->cryptlen - cryp->authsize;
4679d3b5030SFabien DESSENNE }
4689d3b5030SFabien DESSENNE 
4699d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg)
4709d3b5030SFabien DESSENNE {
4719d3b5030SFabien DESSENNE 	int ret;
472*bbb28326SHerbert Xu 	__be32 iv[4];
4739d3b5030SFabien DESSENNE 
4749d3b5030SFabien DESSENNE 	/* Phase 1 : init */
4759d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, 12);
4769d3b5030SFabien DESSENNE 	iv[3] = cpu_to_be32(GCM_CTR_INIT);
4779d3b5030SFabien DESSENNE 	cryp->gcm_ctr = GCM_CTR_INIT;
4789d3b5030SFabien DESSENNE 	stm32_cryp_hw_write_iv(cryp, iv);
4799d3b5030SFabien DESSENNE 
4809d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN);
4819d3b5030SFabien DESSENNE 
4829d3b5030SFabien DESSENNE 	/* Wait for end of processing */
4839d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
4849d3b5030SFabien DESSENNE 	if (ret)
4859d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (gcm init)\n");
4869d3b5030SFabien DESSENNE 
4879d3b5030SFabien DESSENNE 	return ret;
4889d3b5030SFabien DESSENNE }
4899d3b5030SFabien DESSENNE 
4909d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg)
4919d3b5030SFabien DESSENNE {
4929d3b5030SFabien DESSENNE 	int ret;
4939d3b5030SFabien DESSENNE 	u8 iv[AES_BLOCK_SIZE], b0[AES_BLOCK_SIZE];
494*bbb28326SHerbert Xu 	__be32 *bd;
4959d3b5030SFabien DESSENNE 	u32 *d;
4969d3b5030SFabien DESSENNE 	unsigned int i, textlen;
4979d3b5030SFabien DESSENNE 
4989d3b5030SFabien DESSENNE 	/* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */
4999d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
5009d3b5030SFabien DESSENNE 	memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
5019d3b5030SFabien DESSENNE 	iv[AES_BLOCK_SIZE - 1] = 1;
502*bbb28326SHerbert Xu 	stm32_cryp_hw_write_iv(cryp, (__be32 *)iv);
5039d3b5030SFabien DESSENNE 
5049d3b5030SFabien DESSENNE 	/* Build B0 */
5059d3b5030SFabien DESSENNE 	memcpy(b0, iv, AES_BLOCK_SIZE);
5069d3b5030SFabien DESSENNE 
5079d3b5030SFabien DESSENNE 	b0[0] |= (8 * ((cryp->authsize - 2) / 2));
5089d3b5030SFabien DESSENNE 
5099d3b5030SFabien DESSENNE 	if (cryp->areq->assoclen)
5109d3b5030SFabien DESSENNE 		b0[0] |= 0x40;
5119d3b5030SFabien DESSENNE 
5129d3b5030SFabien DESSENNE 	textlen = stm32_cryp_get_input_text_len(cryp);
5139d3b5030SFabien DESSENNE 
5149d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 2] = textlen >> 8;
5159d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF;
5169d3b5030SFabien DESSENNE 
5179d3b5030SFabien DESSENNE 	/* Enable HW */
5189d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN);
5199d3b5030SFabien DESSENNE 
5209d3b5030SFabien DESSENNE 	/* Write B0 */
5219d3b5030SFabien DESSENNE 	d = (u32 *)b0;
522*bbb28326SHerbert Xu 	bd = (__be32 *)b0;
5239d3b5030SFabien DESSENNE 
5249d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
525*bbb28326SHerbert Xu 		u32 xd = d[i];
526*bbb28326SHerbert Xu 
5279d3b5030SFabien DESSENNE 		if (!cryp->caps->padding_wa)
528*bbb28326SHerbert Xu 			xd = be32_to_cpu(bd[i]);
529*bbb28326SHerbert Xu 		stm32_cryp_write(cryp, CRYP_DIN, xd);
5309d3b5030SFabien DESSENNE 	}
5319d3b5030SFabien DESSENNE 
5329d3b5030SFabien DESSENNE 	/* Wait for end of processing */
5339d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
5349d3b5030SFabien DESSENNE 	if (ret)
5359d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (ccm init)\n");
5369d3b5030SFabien DESSENNE 
5379d3b5030SFabien DESSENNE 	return ret;
5389d3b5030SFabien DESSENNE }
5399d3b5030SFabien DESSENNE 
5409e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
5419e054ec2SFabien DESSENNE {
5429e054ec2SFabien DESSENNE 	int ret;
5439e054ec2SFabien DESSENNE 	u32 cfg, hw_mode;
5449e054ec2SFabien DESSENNE 
54565f9aa36Slionel.debieve@st.com 	pm_runtime_get_sync(cryp->dev);
54665f9aa36Slionel.debieve@st.com 
5479e054ec2SFabien DESSENNE 	/* Disable interrupt */
5489e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
5499e054ec2SFabien DESSENNE 
5509e054ec2SFabien DESSENNE 	/* Set key */
5519e054ec2SFabien DESSENNE 	stm32_cryp_hw_write_key(cryp);
5529e054ec2SFabien DESSENNE 
5539e054ec2SFabien DESSENNE 	/* Set configuration */
5549e054ec2SFabien DESSENNE 	cfg = CR_DATA8 | CR_FFLUSH;
5559e054ec2SFabien DESSENNE 
5569e054ec2SFabien DESSENNE 	switch (cryp->ctx->keylen) {
5579e054ec2SFabien DESSENNE 	case AES_KEYSIZE_128:
5589e054ec2SFabien DESSENNE 		cfg |= CR_KEY128;
5599e054ec2SFabien DESSENNE 		break;
5609e054ec2SFabien DESSENNE 
5619e054ec2SFabien DESSENNE 	case AES_KEYSIZE_192:
5629e054ec2SFabien DESSENNE 		cfg |= CR_KEY192;
5639e054ec2SFabien DESSENNE 		break;
5649e054ec2SFabien DESSENNE 
5659e054ec2SFabien DESSENNE 	default:
5669e054ec2SFabien DESSENNE 	case AES_KEYSIZE_256:
5679e054ec2SFabien DESSENNE 		cfg |= CR_KEY256;
5689e054ec2SFabien DESSENNE 		break;
5699e054ec2SFabien DESSENNE 	}
5709e054ec2SFabien DESSENNE 
5719e054ec2SFabien DESSENNE 	hw_mode = stm32_cryp_get_hw_mode(cryp);
5729e054ec2SFabien DESSENNE 	if (hw_mode == CR_AES_UNKNOWN)
5739e054ec2SFabien DESSENNE 		return -EINVAL;
5749e054ec2SFabien DESSENNE 
5759e054ec2SFabien DESSENNE 	/* AES ECB/CBC decrypt: run key preparation first */
5769e054ec2SFabien DESSENNE 	if (is_decrypt(cryp) &&
5779e054ec2SFabien DESSENNE 	    ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
5789e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN);
5799e054ec2SFabien DESSENNE 
5809e054ec2SFabien DESSENNE 		/* Wait for end of processing */
5819e054ec2SFabien DESSENNE 		ret = stm32_cryp_wait_busy(cryp);
5829e054ec2SFabien DESSENNE 		if (ret) {
5839e054ec2SFabien DESSENNE 			dev_err(cryp->dev, "Timeout (key preparation)\n");
5849e054ec2SFabien DESSENNE 			return ret;
5859e054ec2SFabien DESSENNE 		}
5869e054ec2SFabien DESSENNE 	}
5879e054ec2SFabien DESSENNE 
5889e054ec2SFabien DESSENNE 	cfg |= hw_mode;
5899e054ec2SFabien DESSENNE 
5909e054ec2SFabien DESSENNE 	if (is_decrypt(cryp))
5919e054ec2SFabien DESSENNE 		cfg |= CR_DEC_NOT_ENC;
5929e054ec2SFabien DESSENNE 
5939e054ec2SFabien DESSENNE 	/* Apply config and flush (valid when CRYPEN = 0) */
5949e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
5959e054ec2SFabien DESSENNE 
5969e054ec2SFabien DESSENNE 	switch (hw_mode) {
5979d3b5030SFabien DESSENNE 	case CR_AES_GCM:
5989d3b5030SFabien DESSENNE 	case CR_AES_CCM:
5999d3b5030SFabien DESSENNE 		/* Phase 1 : init */
6009d3b5030SFabien DESSENNE 		if (hw_mode == CR_AES_CCM)
6019d3b5030SFabien DESSENNE 			ret = stm32_cryp_ccm_init(cryp, cfg);
6029d3b5030SFabien DESSENNE 		else
6039d3b5030SFabien DESSENNE 			ret = stm32_cryp_gcm_init(cryp, cfg);
6049d3b5030SFabien DESSENNE 
6059d3b5030SFabien DESSENNE 		if (ret)
6069d3b5030SFabien DESSENNE 			return ret;
6079d3b5030SFabien DESSENNE 
6089d3b5030SFabien DESSENNE 		/* Phase 2 : header (authenticated data) */
6099d3b5030SFabien DESSENNE 		if (cryp->areq->assoclen) {
6109d3b5030SFabien DESSENNE 			cfg |= CR_PH_HEADER;
6119d3b5030SFabien DESSENNE 		} else if (stm32_cryp_get_input_text_len(cryp)) {
6129d3b5030SFabien DESSENNE 			cfg |= CR_PH_PAYLOAD;
6139d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_CR, cfg);
6149d3b5030SFabien DESSENNE 		} else {
6159d3b5030SFabien DESSENNE 			cfg |= CR_PH_INIT;
6169d3b5030SFabien DESSENNE 		}
6179d3b5030SFabien DESSENNE 
6189d3b5030SFabien DESSENNE 		break;
6199d3b5030SFabien DESSENNE 
6209e054ec2SFabien DESSENNE 	case CR_DES_CBC:
6219e054ec2SFabien DESSENNE 	case CR_TDES_CBC:
6229e054ec2SFabien DESSENNE 	case CR_AES_CBC:
6239e054ec2SFabien DESSENNE 	case CR_AES_CTR:
624*bbb28326SHerbert Xu 		stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->req->iv);
6259e054ec2SFabien DESSENNE 		break;
6269e054ec2SFabien DESSENNE 
6279e054ec2SFabien DESSENNE 	default:
6289e054ec2SFabien DESSENNE 		break;
6299e054ec2SFabien DESSENNE 	}
6309e054ec2SFabien DESSENNE 
6319e054ec2SFabien DESSENNE 	/* Enable now */
6329e054ec2SFabien DESSENNE 	cfg |= CR_CRYPEN;
6339e054ec2SFabien DESSENNE 
6349e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
6359e054ec2SFabien DESSENNE 
6369d3b5030SFabien DESSENNE 	cryp->flags &= ~FLG_CCM_PADDED_WA;
6379d3b5030SFabien DESSENNE 
6389e054ec2SFabien DESSENNE 	return 0;
6399e054ec2SFabien DESSENNE }
6409e054ec2SFabien DESSENNE 
6419d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
6429e054ec2SFabien DESSENNE {
6439d3b5030SFabien DESSENNE 	if (!err && (is_gcm(cryp) || is_ccm(cryp)))
6449d3b5030SFabien DESSENNE 		/* Phase 4 : output tag */
6459d3b5030SFabien DESSENNE 		err = stm32_cryp_read_auth_tag(cryp);
6469e054ec2SFabien DESSENNE 
6475f49f18dSLionel Debieve 	if (!err && (!(is_gcm(cryp) || is_ccm(cryp))))
6485f49f18dSLionel Debieve 		stm32_cryp_get_iv(cryp);
6495f49f18dSLionel Debieve 
6509e054ec2SFabien DESSENNE 	if (cryp->sgs_copied) {
6519e054ec2SFabien DESSENNE 		void *buf_in, *buf_out;
6529e054ec2SFabien DESSENNE 		int pages, len;
6539e054ec2SFabien DESSENNE 
6549e054ec2SFabien DESSENNE 		buf_in = sg_virt(&cryp->in_sgl);
6559e054ec2SFabien DESSENNE 		buf_out = sg_virt(&cryp->out_sgl);
6569e054ec2SFabien DESSENNE 
6579e054ec2SFabien DESSENNE 		sg_copy_buf(buf_out, cryp->out_sg_save, 0,
6589e054ec2SFabien DESSENNE 			    cryp->total_out_save, 1);
6599e054ec2SFabien DESSENNE 
6609e054ec2SFabien DESSENNE 		len = ALIGN(cryp->total_in_save, cryp->hw_blocksize);
6619e054ec2SFabien DESSENNE 		pages = len ? get_order(len) : 1;
6629e054ec2SFabien DESSENNE 		free_pages((unsigned long)buf_in, pages);
6639e054ec2SFabien DESSENNE 
6649e054ec2SFabien DESSENNE 		len = ALIGN(cryp->total_out_save, cryp->hw_blocksize);
6659e054ec2SFabien DESSENNE 		pages = len ? get_order(len) : 1;
6669e054ec2SFabien DESSENNE 		free_pages((unsigned long)buf_out, pages);
6679e054ec2SFabien DESSENNE 	}
6689e054ec2SFabien DESSENNE 
66965f9aa36Slionel.debieve@st.com 	pm_runtime_mark_last_busy(cryp->dev);
67065f9aa36Slionel.debieve@st.com 	pm_runtime_put_autosuspend(cryp->dev);
67165f9aa36Slionel.debieve@st.com 
67229aed438SLionel Debieve 	if (is_gcm(cryp) || is_ccm(cryp))
6739d3b5030SFabien DESSENNE 		crypto_finalize_aead_request(cryp->engine, cryp->areq, err);
67429aed438SLionel Debieve 	else
67547ece481SArd Biesheuvel 		crypto_finalize_skcipher_request(cryp->engine, cryp->req,
6769d3b5030SFabien DESSENNE 						   err);
6779e054ec2SFabien DESSENNE 
6789e054ec2SFabien DESSENNE 	memset(cryp->ctx->key, 0, cryp->ctx->keylen);
6799e054ec2SFabien DESSENNE }
6809e054ec2SFabien DESSENNE 
6819e054ec2SFabien DESSENNE static int stm32_cryp_cpu_start(struct stm32_cryp *cryp)
6829e054ec2SFabien DESSENNE {
6839e054ec2SFabien DESSENNE 	/* Enable interrupt and let the IRQ handler do everything */
6849e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, IMSCR_IN | IMSCR_OUT);
6859e054ec2SFabien DESSENNE 
6869e054ec2SFabien DESSENNE 	return 0;
6879e054ec2SFabien DESSENNE }
6889e054ec2SFabien DESSENNE 
689dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq);
690dc7bcef5SCorentin LABBE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
691dc7bcef5SCorentin LABBE 					 void *areq);
692dc7bcef5SCorentin LABBE 
69347ece481SArd Biesheuvel static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm)
6949e054ec2SFabien DESSENNE {
69547ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
696dc7bcef5SCorentin LABBE 
69747ece481SArd Biesheuvel 	crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx));
6989e054ec2SFabien DESSENNE 
699dc7bcef5SCorentin LABBE 	ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req;
700dc7bcef5SCorentin LABBE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req;
701dc7bcef5SCorentin LABBE 	ctx->enginectx.op.unprepare_request = NULL;
7029e054ec2SFabien DESSENNE 	return 0;
7039e054ec2SFabien DESSENNE }
7049e054ec2SFabien DESSENNE 
7059d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq);
7069d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine,
7079d3b5030SFabien DESSENNE 				       void *areq);
7089d3b5030SFabien DESSENNE 
7099d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm)
7109d3b5030SFabien DESSENNE {
7119d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
7129d3b5030SFabien DESSENNE 
7139d3b5030SFabien DESSENNE 	tfm->reqsize = sizeof(struct stm32_cryp_reqctx);
7149d3b5030SFabien DESSENNE 
7159d3b5030SFabien DESSENNE 	ctx->enginectx.op.do_one_request = stm32_cryp_aead_one_req;
7169d3b5030SFabien DESSENNE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_aead_req;
7179d3b5030SFabien DESSENNE 	ctx->enginectx.op.unprepare_request = NULL;
7189d3b5030SFabien DESSENNE 
7199d3b5030SFabien DESSENNE 	return 0;
7209d3b5030SFabien DESSENNE }
7219d3b5030SFabien DESSENNE 
72247ece481SArd Biesheuvel static int stm32_cryp_crypt(struct skcipher_request *req, unsigned long mode)
7239e054ec2SFabien DESSENNE {
72447ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
72547ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
72647ece481SArd Biesheuvel 	struct stm32_cryp_reqctx *rctx = skcipher_request_ctx(req);
7279e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
7289e054ec2SFabien DESSENNE 
7299e054ec2SFabien DESSENNE 	if (!cryp)
7309e054ec2SFabien DESSENNE 		return -ENODEV;
7319e054ec2SFabien DESSENNE 
7329e054ec2SFabien DESSENNE 	rctx->mode = mode;
7339e054ec2SFabien DESSENNE 
73447ece481SArd Biesheuvel 	return crypto_transfer_skcipher_request_to_engine(cryp->engine, req);
7359e054ec2SFabien DESSENNE }
7369e054ec2SFabien DESSENNE 
7379d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode)
7389d3b5030SFabien DESSENNE {
7399d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
7409d3b5030SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx = aead_request_ctx(req);
7419d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
7429d3b5030SFabien DESSENNE 
7439d3b5030SFabien DESSENNE 	if (!cryp)
7449d3b5030SFabien DESSENNE 		return -ENODEV;
7459d3b5030SFabien DESSENNE 
7469d3b5030SFabien DESSENNE 	rctx->mode = mode;
7479d3b5030SFabien DESSENNE 
7489d3b5030SFabien DESSENNE 	return crypto_transfer_aead_request_to_engine(cryp->engine, req);
7499d3b5030SFabien DESSENNE }
7509d3b5030SFabien DESSENNE 
75147ece481SArd Biesheuvel static int stm32_cryp_setkey(struct crypto_skcipher *tfm, const u8 *key,
7529e054ec2SFabien DESSENNE 			     unsigned int keylen)
7539e054ec2SFabien DESSENNE {
75447ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
7559e054ec2SFabien DESSENNE 
7569e054ec2SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
7579e054ec2SFabien DESSENNE 	ctx->keylen = keylen;
7589e054ec2SFabien DESSENNE 
7599e054ec2SFabien DESSENNE 	return 0;
7609e054ec2SFabien DESSENNE }
7619e054ec2SFabien DESSENNE 
76247ece481SArd Biesheuvel static int stm32_cryp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
7639e054ec2SFabien DESSENNE 				 unsigned int keylen)
7649e054ec2SFabien DESSENNE {
7659e054ec2SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
7669e054ec2SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
7679e054ec2SFabien DESSENNE 		return -EINVAL;
7689e054ec2SFabien DESSENNE 	else
7699e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
7709e054ec2SFabien DESSENNE }
7719e054ec2SFabien DESSENNE 
77247ece481SArd Biesheuvel static int stm32_cryp_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
7739e054ec2SFabien DESSENNE 				 unsigned int keylen)
7749e054ec2SFabien DESSENNE {
77547ece481SArd Biesheuvel 	return verify_skcipher_des_key(tfm, key) ?:
776b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
7779e054ec2SFabien DESSENNE }
7789e054ec2SFabien DESSENNE 
77947ece481SArd Biesheuvel static int stm32_cryp_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key,
7809e054ec2SFabien DESSENNE 				  unsigned int keylen)
7819e054ec2SFabien DESSENNE {
78247ece481SArd Biesheuvel 	return verify_skcipher_des3_key(tfm, key) ?:
783b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
7849e054ec2SFabien DESSENNE }
7859e054ec2SFabien DESSENNE 
7869d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
7879d3b5030SFabien DESSENNE 				      unsigned int keylen)
7889d3b5030SFabien DESSENNE {
7899d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
7909d3b5030SFabien DESSENNE 
7919d3b5030SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
7929d3b5030SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
7939d3b5030SFabien DESSENNE 		return -EINVAL;
7949d3b5030SFabien DESSENNE 
7959d3b5030SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
7969d3b5030SFabien DESSENNE 	ctx->keylen = keylen;
7979d3b5030SFabien DESSENNE 
7989d3b5030SFabien DESSENNE 	return 0;
7999d3b5030SFabien DESSENNE }
8009d3b5030SFabien DESSENNE 
8019d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
8029d3b5030SFabien DESSENNE 					  unsigned int authsize)
8039d3b5030SFabien DESSENNE {
8049d3b5030SFabien DESSENNE 	return authsize == AES_BLOCK_SIZE ? 0 : -EINVAL;
8059d3b5030SFabien DESSENNE }
8069d3b5030SFabien DESSENNE 
8079d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
8089d3b5030SFabien DESSENNE 					  unsigned int authsize)
8099d3b5030SFabien DESSENNE {
8109d3b5030SFabien DESSENNE 	switch (authsize) {
8119d3b5030SFabien DESSENNE 	case 4:
8129d3b5030SFabien DESSENNE 	case 6:
8139d3b5030SFabien DESSENNE 	case 8:
8149d3b5030SFabien DESSENNE 	case 10:
8159d3b5030SFabien DESSENNE 	case 12:
8169d3b5030SFabien DESSENNE 	case 14:
8179d3b5030SFabien DESSENNE 	case 16:
8189d3b5030SFabien DESSENNE 		break;
8199d3b5030SFabien DESSENNE 	default:
8209d3b5030SFabien DESSENNE 		return -EINVAL;
8219d3b5030SFabien DESSENNE 	}
8229d3b5030SFabien DESSENNE 
8239d3b5030SFabien DESSENNE 	return 0;
8249d3b5030SFabien DESSENNE }
8259d3b5030SFabien DESSENNE 
82647ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req)
8279e054ec2SFabien DESSENNE {
8289e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
8299e054ec2SFabien DESSENNE }
8309e054ec2SFabien DESSENNE 
83147ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req)
8329e054ec2SFabien DESSENNE {
8339e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
8349e054ec2SFabien DESSENNE }
8359e054ec2SFabien DESSENNE 
83647ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req)
8379e054ec2SFabien DESSENNE {
8389e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
8399e054ec2SFabien DESSENNE }
8409e054ec2SFabien DESSENNE 
84147ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req)
8429e054ec2SFabien DESSENNE {
8439e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
8449e054ec2SFabien DESSENNE }
8459e054ec2SFabien DESSENNE 
84647ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req)
8479e054ec2SFabien DESSENNE {
8489e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
8499e054ec2SFabien DESSENNE }
8509e054ec2SFabien DESSENNE 
85147ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req)
8529e054ec2SFabien DESSENNE {
8539e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
8549e054ec2SFabien DESSENNE }
8559e054ec2SFabien DESSENNE 
8569d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req)
8579d3b5030SFabien DESSENNE {
8589d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT);
8599d3b5030SFabien DESSENNE }
8609d3b5030SFabien DESSENNE 
8619d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
8629d3b5030SFabien DESSENNE {
8639d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
8649d3b5030SFabien DESSENNE }
8659d3b5030SFabien DESSENNE 
8669d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req)
8679d3b5030SFabien DESSENNE {
8689d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT);
8699d3b5030SFabien DESSENNE }
8709d3b5030SFabien DESSENNE 
8719d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req)
8729d3b5030SFabien DESSENNE {
8739d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
8749d3b5030SFabien DESSENNE }
8759d3b5030SFabien DESSENNE 
87647ece481SArd Biesheuvel static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req)
8779e054ec2SFabien DESSENNE {
8789e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
8799e054ec2SFabien DESSENNE }
8809e054ec2SFabien DESSENNE 
88147ece481SArd Biesheuvel static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req)
8829e054ec2SFabien DESSENNE {
8839e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
8849e054ec2SFabien DESSENNE }
8859e054ec2SFabien DESSENNE 
88647ece481SArd Biesheuvel static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req)
8879e054ec2SFabien DESSENNE {
8889e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
8899e054ec2SFabien DESSENNE }
8909e054ec2SFabien DESSENNE 
89147ece481SArd Biesheuvel static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req)
8929e054ec2SFabien DESSENNE {
8939e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
8949e054ec2SFabien DESSENNE }
8959e054ec2SFabien DESSENNE 
89647ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req)
8979e054ec2SFabien DESSENNE {
8989e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
8999e054ec2SFabien DESSENNE }
9009e054ec2SFabien DESSENNE 
90147ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req)
9029e054ec2SFabien DESSENNE {
9039e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
9049e054ec2SFabien DESSENNE }
9059e054ec2SFabien DESSENNE 
90647ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req)
9079e054ec2SFabien DESSENNE {
9089e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
9099e054ec2SFabien DESSENNE }
9109e054ec2SFabien DESSENNE 
91147ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req)
9129e054ec2SFabien DESSENNE {
9139e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
9149e054ec2SFabien DESSENNE }
9159e054ec2SFabien DESSENNE 
91647ece481SArd Biesheuvel static int stm32_cryp_prepare_req(struct skcipher_request *req,
9179d3b5030SFabien DESSENNE 				  struct aead_request *areq)
9189e054ec2SFabien DESSENNE {
9199e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx;
9209e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
9219e054ec2SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx;
9229e054ec2SFabien DESSENNE 	int ret;
9239e054ec2SFabien DESSENNE 
9249d3b5030SFabien DESSENNE 	if (!req && !areq)
9259e054ec2SFabien DESSENNE 		return -EINVAL;
9269e054ec2SFabien DESSENNE 
92747ece481SArd Biesheuvel 	ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) :
9289d3b5030SFabien DESSENNE 		    crypto_aead_ctx(crypto_aead_reqtfm(areq));
9299e054ec2SFabien DESSENNE 
9309e054ec2SFabien DESSENNE 	cryp = ctx->cryp;
9319e054ec2SFabien DESSENNE 
9329e054ec2SFabien DESSENNE 	if (!cryp)
9339e054ec2SFabien DESSENNE 		return -ENODEV;
9349e054ec2SFabien DESSENNE 
93547ece481SArd Biesheuvel 	rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq);
9369e054ec2SFabien DESSENNE 	rctx->mode &= FLG_MODE_MASK;
9379e054ec2SFabien DESSENNE 
9389e054ec2SFabien DESSENNE 	ctx->cryp = cryp;
9399e054ec2SFabien DESSENNE 
9409e054ec2SFabien DESSENNE 	cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode;
9419e054ec2SFabien DESSENNE 	cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE;
9429e054ec2SFabien DESSENNE 	cryp->ctx = ctx;
9439e054ec2SFabien DESSENNE 
9449d3b5030SFabien DESSENNE 	if (req) {
9459e054ec2SFabien DESSENNE 		cryp->req = req;
94629aed438SLionel Debieve 		cryp->areq = NULL;
94747ece481SArd Biesheuvel 		cryp->total_in = req->cryptlen;
9489e054ec2SFabien DESSENNE 		cryp->total_out = cryp->total_in;
9499d3b5030SFabien DESSENNE 	} else {
9509d3b5030SFabien DESSENNE 		/*
9519d3b5030SFabien DESSENNE 		 * Length of input and output data:
9529d3b5030SFabien DESSENNE 		 * Encryption case:
9539d3b5030SFabien DESSENNE 		 *  INPUT  =   AssocData  ||   PlainText
9549d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->
9559d3b5030SFabien DESSENNE 		 *          <------- total_in ----------->
9569d3b5030SFabien DESSENNE 		 *
9579d3b5030SFabien DESSENNE 		 *  OUTPUT =   AssocData  ||  CipherText  ||   AuthTag
9589d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->  <- authsize ->
9599d3b5030SFabien DESSENNE 		 *          <---------------- total_out ----------------->
9609d3b5030SFabien DESSENNE 		 *
9619d3b5030SFabien DESSENNE 		 * Decryption case:
9629d3b5030SFabien DESSENNE 		 *  INPUT  =   AssocData  ||  CipherText  ||  AuthTag
9639d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <--------- cryptlen --------->
9649d3b5030SFabien DESSENNE 		 *                                          <- authsize ->
9659d3b5030SFabien DESSENNE 		 *          <---------------- total_in ------------------>
9669d3b5030SFabien DESSENNE 		 *
9679d3b5030SFabien DESSENNE 		 *  OUTPUT =   AssocData  ||   PlainText
9689d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- crypten - authsize ->
9699d3b5030SFabien DESSENNE 		 *          <---------- total_out ----------------->
9709d3b5030SFabien DESSENNE 		 */
9719d3b5030SFabien DESSENNE 		cryp->areq = areq;
97229aed438SLionel Debieve 		cryp->req = NULL;
9739d3b5030SFabien DESSENNE 		cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
9749d3b5030SFabien DESSENNE 		cryp->total_in = areq->assoclen + areq->cryptlen;
9759d3b5030SFabien DESSENNE 		if (is_encrypt(cryp))
9769d3b5030SFabien DESSENNE 			/* Append auth tag to output */
9779d3b5030SFabien DESSENNE 			cryp->total_out = cryp->total_in + cryp->authsize;
9789d3b5030SFabien DESSENNE 		else
9799d3b5030SFabien DESSENNE 			/* No auth tag in output */
9809d3b5030SFabien DESSENNE 			cryp->total_out = cryp->total_in - cryp->authsize;
9819d3b5030SFabien DESSENNE 	}
9829e054ec2SFabien DESSENNE 
9839e054ec2SFabien DESSENNE 	cryp->total_in_save = cryp->total_in;
9849e054ec2SFabien DESSENNE 	cryp->total_out_save = cryp->total_out;
9859e054ec2SFabien DESSENNE 
9869d3b5030SFabien DESSENNE 	cryp->in_sg = req ? req->src : areq->src;
9879d3b5030SFabien DESSENNE 	cryp->out_sg = req ? req->dst : areq->dst;
9889e054ec2SFabien DESSENNE 	cryp->out_sg_save = cryp->out_sg;
9899e054ec2SFabien DESSENNE 
9909e054ec2SFabien DESSENNE 	cryp->in_sg_len = sg_nents_for_len(cryp->in_sg, cryp->total_in);
9919e054ec2SFabien DESSENNE 	if (cryp->in_sg_len < 0) {
9929e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Cannot get in_sg_len\n");
9939e054ec2SFabien DESSENNE 		ret = cryp->in_sg_len;
99429aed438SLionel Debieve 		return ret;
9959e054ec2SFabien DESSENNE 	}
9969e054ec2SFabien DESSENNE 
9979e054ec2SFabien DESSENNE 	cryp->out_sg_len = sg_nents_for_len(cryp->out_sg, cryp->total_out);
9989e054ec2SFabien DESSENNE 	if (cryp->out_sg_len < 0) {
9999e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Cannot get out_sg_len\n");
10009e054ec2SFabien DESSENNE 		ret = cryp->out_sg_len;
100129aed438SLionel Debieve 		return ret;
10029e054ec2SFabien DESSENNE 	}
10039e054ec2SFabien DESSENNE 
10049e054ec2SFabien DESSENNE 	ret = stm32_cryp_copy_sgs(cryp);
10059e054ec2SFabien DESSENNE 	if (ret)
100629aed438SLionel Debieve 		return ret;
10079e054ec2SFabien DESSENNE 
10089e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->in_walk, cryp->in_sg);
10099e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->out_walk, cryp->out_sg);
10109e054ec2SFabien DESSENNE 
10119d3b5030SFabien DESSENNE 	if (is_gcm(cryp) || is_ccm(cryp)) {
10129d3b5030SFabien DESSENNE 		/* In output, jump after assoc data */
10139d3b5030SFabien DESSENNE 		scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen);
10149d3b5030SFabien DESSENNE 		cryp->total_out -= cryp->areq->assoclen;
10159d3b5030SFabien DESSENNE 	}
10169d3b5030SFabien DESSENNE 
10179e054ec2SFabien DESSENNE 	ret = stm32_cryp_hw_init(cryp);
10189e054ec2SFabien DESSENNE 	return ret;
10199e054ec2SFabien DESSENNE }
10209e054ec2SFabien DESSENNE 
10219e054ec2SFabien DESSENNE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
1022dc7bcef5SCorentin LABBE 					 void *areq)
10239e054ec2SFabien DESSENNE {
102447ece481SArd Biesheuvel 	struct skcipher_request *req = container_of(areq,
102547ece481SArd Biesheuvel 						      struct skcipher_request,
1026dc7bcef5SCorentin LABBE 						      base);
1027dc7bcef5SCorentin LABBE 
10289d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(req, NULL);
10299e054ec2SFabien DESSENNE }
10309e054ec2SFabien DESSENNE 
1031dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq)
10329e054ec2SFabien DESSENNE {
103347ece481SArd Biesheuvel 	struct skcipher_request *req = container_of(areq,
103447ece481SArd Biesheuvel 						      struct skcipher_request,
1035dc7bcef5SCorentin LABBE 						      base);
103647ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
103747ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
10389e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
10399e054ec2SFabien DESSENNE 
10409e054ec2SFabien DESSENNE 	if (!cryp)
10419e054ec2SFabien DESSENNE 		return -ENODEV;
10429e054ec2SFabien DESSENNE 
10439e054ec2SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
10449e054ec2SFabien DESSENNE }
10459e054ec2SFabien DESSENNE 
10469d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq)
10479d3b5030SFabien DESSENNE {
10489d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
10499d3b5030SFabien DESSENNE 						base);
10509d3b5030SFabien DESSENNE 
10519d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(NULL, req);
10529d3b5030SFabien DESSENNE }
10539d3b5030SFabien DESSENNE 
10549d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq)
10559d3b5030SFabien DESSENNE {
10569d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
10579d3b5030SFabien DESSENNE 						base);
10589d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
10599d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
10609d3b5030SFabien DESSENNE 
10619d3b5030SFabien DESSENNE 	if (!cryp)
10629d3b5030SFabien DESSENNE 		return -ENODEV;
10639d3b5030SFabien DESSENNE 
10649d3b5030SFabien DESSENNE 	if (unlikely(!cryp->areq->assoclen &&
10659d3b5030SFabien DESSENNE 		     !stm32_cryp_get_input_text_len(cryp))) {
10669d3b5030SFabien DESSENNE 		/* No input data to process: get tag and finish */
10679d3b5030SFabien DESSENNE 		stm32_cryp_finish_req(cryp, 0);
10689d3b5030SFabien DESSENNE 		return 0;
10699d3b5030SFabien DESSENNE 	}
10709d3b5030SFabien DESSENNE 
10719d3b5030SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
10729d3b5030SFabien DESSENNE }
10739d3b5030SFabien DESSENNE 
10749e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_out(struct stm32_cryp *cryp, u32 *dst,
10759e054ec2SFabien DESSENNE 				unsigned int n)
10769e054ec2SFabien DESSENNE {
10779e054ec2SFabien DESSENNE 	scatterwalk_advance(&cryp->out_walk, n);
10789e054ec2SFabien DESSENNE 
10799e054ec2SFabien DESSENNE 	if (unlikely(cryp->out_sg->length == _walked_out)) {
10809e054ec2SFabien DESSENNE 		cryp->out_sg = sg_next(cryp->out_sg);
10819e054ec2SFabien DESSENNE 		if (cryp->out_sg) {
10829e054ec2SFabien DESSENNE 			scatterwalk_start(&cryp->out_walk, cryp->out_sg);
10839e054ec2SFabien DESSENNE 			return (sg_virt(cryp->out_sg) + _walked_out);
10849e054ec2SFabien DESSENNE 		}
10859e054ec2SFabien DESSENNE 	}
10869e054ec2SFabien DESSENNE 
10879e054ec2SFabien DESSENNE 	return (u32 *)((u8 *)dst + n);
10889e054ec2SFabien DESSENNE }
10899e054ec2SFabien DESSENNE 
10909e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_in(struct stm32_cryp *cryp, u32 *src,
10919e054ec2SFabien DESSENNE 			       unsigned int n)
10929e054ec2SFabien DESSENNE {
10939e054ec2SFabien DESSENNE 	scatterwalk_advance(&cryp->in_walk, n);
10949e054ec2SFabien DESSENNE 
10959e054ec2SFabien DESSENNE 	if (unlikely(cryp->in_sg->length == _walked_in)) {
10969e054ec2SFabien DESSENNE 		cryp->in_sg = sg_next(cryp->in_sg);
10979e054ec2SFabien DESSENNE 		if (cryp->in_sg) {
10989e054ec2SFabien DESSENNE 			scatterwalk_start(&cryp->in_walk, cryp->in_sg);
10999e054ec2SFabien DESSENNE 			return (sg_virt(cryp->in_sg) + _walked_in);
11009e054ec2SFabien DESSENNE 		}
11019e054ec2SFabien DESSENNE 	}
11029e054ec2SFabien DESSENNE 
11039e054ec2SFabien DESSENNE 	return (u32 *)((u8 *)src + n);
11049e054ec2SFabien DESSENNE }
11059e054ec2SFabien DESSENNE 
11069d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
11079d3b5030SFabien DESSENNE {
11089d3b5030SFabien DESSENNE 	u32 cfg, size_bit, *dst, d32;
11099d3b5030SFabien DESSENNE 	u8 *d8;
11109d3b5030SFabien DESSENNE 	unsigned int i, j;
11119d3b5030SFabien DESSENNE 	int ret = 0;
11129d3b5030SFabien DESSENNE 
11139d3b5030SFabien DESSENNE 	/* Update Config */
11149d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
11159d3b5030SFabien DESSENNE 
11169d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
11179d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
11189d3b5030SFabien DESSENNE 	cfg &= ~CR_DEC_NOT_ENC;
11199d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
11209d3b5030SFabien DESSENNE 
11219d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
11229d3b5030SFabien DESSENNE 
11239d3b5030SFabien DESSENNE 	if (is_gcm(cryp)) {
11249d3b5030SFabien DESSENNE 		/* GCM: write aad and payload size (in bits) */
11259d3b5030SFabien DESSENNE 		size_bit = cryp->areq->assoclen * 8;
11269d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1127*bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
11289d3b5030SFabien DESSENNE 
11299d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, 0);
11309d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, size_bit);
11319d3b5030SFabien DESSENNE 
11329d3b5030SFabien DESSENNE 		size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
11339d3b5030SFabien DESSENNE 				cryp->areq->cryptlen - AES_BLOCK_SIZE;
11349d3b5030SFabien DESSENNE 		size_bit *= 8;
11359d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1136*bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
11379d3b5030SFabien DESSENNE 
11389d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, 0);
11399d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, size_bit);
11409d3b5030SFabien DESSENNE 	} else {
11419d3b5030SFabien DESSENNE 		/* CCM: write CTR0 */
11429d3b5030SFabien DESSENNE 		u8 iv[AES_BLOCK_SIZE];
11439d3b5030SFabien DESSENNE 		u32 *iv32 = (u32 *)iv;
1144*bbb28326SHerbert Xu 		__be32 *biv;
1145*bbb28326SHerbert Xu 
1146*bbb28326SHerbert Xu 		biv = (void *)iv;
11479d3b5030SFabien DESSENNE 
11489d3b5030SFabien DESSENNE 		memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
11499d3b5030SFabien DESSENNE 		memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
11509d3b5030SFabien DESSENNE 
11519d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
1152*bbb28326SHerbert Xu 			u32 xiv = iv32[i];
1153*bbb28326SHerbert Xu 
11549d3b5030SFabien DESSENNE 			if (!cryp->caps->padding_wa)
1155*bbb28326SHerbert Xu 				xiv = be32_to_cpu(biv[i]);
1156*bbb28326SHerbert Xu 			stm32_cryp_write(cryp, CRYP_DIN, xiv);
11579d3b5030SFabien DESSENNE 		}
11589d3b5030SFabien DESSENNE 	}
11599d3b5030SFabien DESSENNE 
11609d3b5030SFabien DESSENNE 	/* Wait for output data */
11619d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_output(cryp);
11629d3b5030SFabien DESSENNE 	if (ret) {
11639d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (read tag)\n");
11649d3b5030SFabien DESSENNE 		return ret;
11659d3b5030SFabien DESSENNE 	}
11669d3b5030SFabien DESSENNE 
11679d3b5030SFabien DESSENNE 	if (is_encrypt(cryp)) {
11689d3b5030SFabien DESSENNE 		/* Get and write tag */
11699d3b5030SFabien DESSENNE 		dst = sg_virt(cryp->out_sg) + _walked_out;
11709d3b5030SFabien DESSENNE 
11719d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
11729d3b5030SFabien DESSENNE 			if (cryp->total_out >= sizeof(u32)) {
11739d3b5030SFabien DESSENNE 				/* Read a full u32 */
11749d3b5030SFabien DESSENNE 				*dst = stm32_cryp_read(cryp, CRYP_DOUT);
11759d3b5030SFabien DESSENNE 
11769d3b5030SFabien DESSENNE 				dst = stm32_cryp_next_out(cryp, dst,
11779d3b5030SFabien DESSENNE 							  sizeof(u32));
11789d3b5030SFabien DESSENNE 				cryp->total_out -= sizeof(u32);
11799d3b5030SFabien DESSENNE 			} else if (!cryp->total_out) {
11809d3b5030SFabien DESSENNE 				/* Empty fifo out (data from input padding) */
11819d3b5030SFabien DESSENNE 				stm32_cryp_read(cryp, CRYP_DOUT);
11829d3b5030SFabien DESSENNE 			} else {
11839d3b5030SFabien DESSENNE 				/* Read less than an u32 */
11849d3b5030SFabien DESSENNE 				d32 = stm32_cryp_read(cryp, CRYP_DOUT);
11859d3b5030SFabien DESSENNE 				d8 = (u8 *)&d32;
11869d3b5030SFabien DESSENNE 
11879d3b5030SFabien DESSENNE 				for (j = 0; j < cryp->total_out; j++) {
11889d3b5030SFabien DESSENNE 					*((u8 *)dst) = *(d8++);
11899d3b5030SFabien DESSENNE 					dst = stm32_cryp_next_out(cryp, dst, 1);
11909d3b5030SFabien DESSENNE 				}
11919d3b5030SFabien DESSENNE 				cryp->total_out = 0;
11929d3b5030SFabien DESSENNE 			}
11939d3b5030SFabien DESSENNE 		}
11949d3b5030SFabien DESSENNE 	} else {
11959d3b5030SFabien DESSENNE 		/* Get and check tag */
11969d3b5030SFabien DESSENNE 		u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
11979d3b5030SFabien DESSENNE 
11989d3b5030SFabien DESSENNE 		scatterwalk_map_and_copy(in_tag, cryp->in_sg,
11999d3b5030SFabien DESSENNE 					 cryp->total_in_save - cryp->authsize,
12009d3b5030SFabien DESSENNE 					 cryp->authsize, 0);
12019d3b5030SFabien DESSENNE 
12029d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++)
12039d3b5030SFabien DESSENNE 			out_tag[i] = stm32_cryp_read(cryp, CRYP_DOUT);
12049d3b5030SFabien DESSENNE 
12059d3b5030SFabien DESSENNE 		if (crypto_memneq(in_tag, out_tag, cryp->authsize))
12069d3b5030SFabien DESSENNE 			ret = -EBADMSG;
12079d3b5030SFabien DESSENNE 	}
12089d3b5030SFabien DESSENNE 
12099d3b5030SFabien DESSENNE 	/* Disable cryp */
12109d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
12119d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
12129d3b5030SFabien DESSENNE 
12139d3b5030SFabien DESSENNE 	return ret;
12149d3b5030SFabien DESSENNE }
12159d3b5030SFabien DESSENNE 
12169e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp)
12179e054ec2SFabien DESSENNE {
12189e054ec2SFabien DESSENNE 	u32 cr;
12199e054ec2SFabien DESSENNE 
12209e054ec2SFabien DESSENNE 	if (unlikely(cryp->last_ctr[3] == 0xFFFFFFFF)) {
12219e054ec2SFabien DESSENNE 		cryp->last_ctr[3] = 0;
12229e054ec2SFabien DESSENNE 		cryp->last_ctr[2]++;
12239e054ec2SFabien DESSENNE 		if (!cryp->last_ctr[2]) {
12249e054ec2SFabien DESSENNE 			cryp->last_ctr[1]++;
12259e054ec2SFabien DESSENNE 			if (!cryp->last_ctr[1])
12269e054ec2SFabien DESSENNE 				cryp->last_ctr[0]++;
12279e054ec2SFabien DESSENNE 		}
12289e054ec2SFabien DESSENNE 
12299e054ec2SFabien DESSENNE 		cr = stm32_cryp_read(cryp, CRYP_CR);
12309e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cr & ~CR_CRYPEN);
12319e054ec2SFabien DESSENNE 
12329e054ec2SFabien DESSENNE 		stm32_cryp_hw_write_iv(cryp, (u32 *)cryp->last_ctr);
12339e054ec2SFabien DESSENNE 
12349e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cr);
12359e054ec2SFabien DESSENNE 	}
12369e054ec2SFabien DESSENNE 
12379e054ec2SFabien DESSENNE 	cryp->last_ctr[0] = stm32_cryp_read(cryp, CRYP_IV0LR);
12389e054ec2SFabien DESSENNE 	cryp->last_ctr[1] = stm32_cryp_read(cryp, CRYP_IV0RR);
12399e054ec2SFabien DESSENNE 	cryp->last_ctr[2] = stm32_cryp_read(cryp, CRYP_IV1LR);
12409e054ec2SFabien DESSENNE 	cryp->last_ctr[3] = stm32_cryp_read(cryp, CRYP_IV1RR);
12419e054ec2SFabien DESSENNE }
12429e054ec2SFabien DESSENNE 
12439e054ec2SFabien DESSENNE static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
12449e054ec2SFabien DESSENNE {
12459e054ec2SFabien DESSENNE 	unsigned int i, j;
12469e054ec2SFabien DESSENNE 	u32 d32, *dst;
12479e054ec2SFabien DESSENNE 	u8 *d8;
12489d3b5030SFabien DESSENNE 	size_t tag_size;
12499d3b5030SFabien DESSENNE 
12509d3b5030SFabien DESSENNE 	/* Do no read tag now (if any) */
12519d3b5030SFabien DESSENNE 	if (is_encrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp)))
12529d3b5030SFabien DESSENNE 		tag_size = cryp->authsize;
12539d3b5030SFabien DESSENNE 	else
12549d3b5030SFabien DESSENNE 		tag_size = 0;
12559e054ec2SFabien DESSENNE 
12569e054ec2SFabien DESSENNE 	dst = sg_virt(cryp->out_sg) + _walked_out;
12579e054ec2SFabien DESSENNE 
12589e054ec2SFabien DESSENNE 	for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
12599d3b5030SFabien DESSENNE 		if (likely(cryp->total_out - tag_size >= sizeof(u32))) {
12609e054ec2SFabien DESSENNE 			/* Read a full u32 */
12619e054ec2SFabien DESSENNE 			*dst = stm32_cryp_read(cryp, CRYP_DOUT);
12629e054ec2SFabien DESSENNE 
12639e054ec2SFabien DESSENNE 			dst = stm32_cryp_next_out(cryp, dst, sizeof(u32));
12649e054ec2SFabien DESSENNE 			cryp->total_out -= sizeof(u32);
12659d3b5030SFabien DESSENNE 		} else if (cryp->total_out == tag_size) {
12669e054ec2SFabien DESSENNE 			/* Empty fifo out (data from input padding) */
12679e054ec2SFabien DESSENNE 			d32 = stm32_cryp_read(cryp, CRYP_DOUT);
12689e054ec2SFabien DESSENNE 		} else {
12699e054ec2SFabien DESSENNE 			/* Read less than an u32 */
12709e054ec2SFabien DESSENNE 			d32 = stm32_cryp_read(cryp, CRYP_DOUT);
12719e054ec2SFabien DESSENNE 			d8 = (u8 *)&d32;
12729e054ec2SFabien DESSENNE 
12739d3b5030SFabien DESSENNE 			for (j = 0; j < cryp->total_out - tag_size; j++) {
12749e054ec2SFabien DESSENNE 				*((u8 *)dst) = *(d8++);
12759e054ec2SFabien DESSENNE 				dst = stm32_cryp_next_out(cryp, dst, 1);
12769e054ec2SFabien DESSENNE 			}
12779d3b5030SFabien DESSENNE 			cryp->total_out = tag_size;
12789e054ec2SFabien DESSENNE 		}
12799e054ec2SFabien DESSENNE 	}
12809e054ec2SFabien DESSENNE 
12819d3b5030SFabien DESSENNE 	return !(cryp->total_out - tag_size) || !cryp->total_in;
12829e054ec2SFabien DESSENNE }
12839e054ec2SFabien DESSENNE 
12849e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
12859e054ec2SFabien DESSENNE {
12869e054ec2SFabien DESSENNE 	unsigned int i, j;
12879e054ec2SFabien DESSENNE 	u32 *src;
12889e054ec2SFabien DESSENNE 	u8 d8[4];
12899d3b5030SFabien DESSENNE 	size_t tag_size;
12909d3b5030SFabien DESSENNE 
12919d3b5030SFabien DESSENNE 	/* Do no write tag (if any) */
12929d3b5030SFabien DESSENNE 	if (is_decrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp)))
12939d3b5030SFabien DESSENNE 		tag_size = cryp->authsize;
12949d3b5030SFabien DESSENNE 	else
12959d3b5030SFabien DESSENNE 		tag_size = 0;
12969e054ec2SFabien DESSENNE 
12979e054ec2SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
12989e054ec2SFabien DESSENNE 
12999e054ec2SFabien DESSENNE 	for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
13009d3b5030SFabien DESSENNE 		if (likely(cryp->total_in - tag_size >= sizeof(u32))) {
13019e054ec2SFabien DESSENNE 			/* Write a full u32 */
13029e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *src);
13039e054ec2SFabien DESSENNE 
13049e054ec2SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, sizeof(u32));
13059e054ec2SFabien DESSENNE 			cryp->total_in -= sizeof(u32);
13069d3b5030SFabien DESSENNE 		} else if (cryp->total_in == tag_size) {
13079e054ec2SFabien DESSENNE 			/* Write padding data */
13089e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, 0);
13099e054ec2SFabien DESSENNE 		} else {
13109e054ec2SFabien DESSENNE 			/* Write less than an u32 */
13119e054ec2SFabien DESSENNE 			memset(d8, 0, sizeof(u32));
13129d3b5030SFabien DESSENNE 			for (j = 0; j < cryp->total_in - tag_size; j++) {
13139e054ec2SFabien DESSENNE 				d8[j] = *((u8 *)src);
13149e054ec2SFabien DESSENNE 				src = stm32_cryp_next_in(cryp, src, 1);
13159e054ec2SFabien DESSENNE 			}
13169e054ec2SFabien DESSENNE 
13179e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
13189d3b5030SFabien DESSENNE 			cryp->total_in = tag_size;
13199e054ec2SFabien DESSENNE 		}
13209e054ec2SFabien DESSENNE 	}
13219e054ec2SFabien DESSENNE }
13229e054ec2SFabien DESSENNE 
13239d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
13249d3b5030SFabien DESSENNE {
13259d3b5030SFabien DESSENNE 	int err;
13269d3b5030SFabien DESSENNE 	u32 cfg, tmp[AES_BLOCK_32];
13279d3b5030SFabien DESSENNE 	size_t total_in_ori = cryp->total_in;
13289d3b5030SFabien DESSENNE 	struct scatterlist *out_sg_ori = cryp->out_sg;
13299d3b5030SFabien DESSENNE 	unsigned int i;
13309d3b5030SFabien DESSENNE 
13319d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
13329d3b5030SFabien DESSENNE 
13339d3b5030SFabien DESSENNE 	/* a) disable ip */
13349d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
13359d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
13369d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
13379d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13389d3b5030SFabien DESSENNE 
13399d3b5030SFabien DESSENNE 	/* b) Update IV1R */
13409d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV1RR, cryp->gcm_ctr - 2);
13419d3b5030SFabien DESSENNE 
13429d3b5030SFabien DESSENNE 	/* c) change mode to CTR */
13439d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
13449d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
13459d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13469d3b5030SFabien DESSENNE 
13479d3b5030SFabien DESSENNE 	/* a) enable IP */
13489d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
13499d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13509d3b5030SFabien DESSENNE 
13519d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
13529d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
13539d3b5030SFabien DESSENNE 	cryp->total_in = total_in_ori;
13549d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
13559d3b5030SFabien DESSENNE 	if (err) {
13569d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (write gcm header)\n");
13579d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
13589d3b5030SFabien DESSENNE 	}
13599d3b5030SFabien DESSENNE 
13609d3b5030SFabien DESSENNE 	/* c) get and store encrypted data */
13619d3b5030SFabien DESSENNE 	stm32_cryp_irq_read_data(cryp);
13629d3b5030SFabien DESSENNE 	scatterwalk_map_and_copy(tmp, out_sg_ori,
13639d3b5030SFabien DESSENNE 				 cryp->total_in_save - total_in_ori,
13649d3b5030SFabien DESSENNE 				 total_in_ori, 0);
13659d3b5030SFabien DESSENNE 
13669d3b5030SFabien DESSENNE 	/* d) change mode back to AES GCM */
13679d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
13689d3b5030SFabien DESSENNE 	cfg |= CR_AES_GCM;
13699d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13709d3b5030SFabien DESSENNE 
13719d3b5030SFabien DESSENNE 	/* e) change phase to Final */
13729d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
13739d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
13749d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13759d3b5030SFabien DESSENNE 
13769d3b5030SFabien DESSENNE 	/* f) write padded data */
13779d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
13789d3b5030SFabien DESSENNE 		if (cryp->total_in)
13799d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, tmp[i]);
13809d3b5030SFabien DESSENNE 		else
13819d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, 0);
13829d3b5030SFabien DESSENNE 
13839d3b5030SFabien DESSENNE 		cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in);
13849d3b5030SFabien DESSENNE 	}
13859d3b5030SFabien DESSENNE 
13869d3b5030SFabien DESSENNE 	/* g) Empty fifo out */
13879d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
13889d3b5030SFabien DESSENNE 	if (err) {
13899d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (write gcm header)\n");
13909d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
13919d3b5030SFabien DESSENNE 	}
13929d3b5030SFabien DESSENNE 
13939d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++)
13949d3b5030SFabien DESSENNE 		stm32_cryp_read(cryp, CRYP_DOUT);
13959d3b5030SFabien DESSENNE 
13969d3b5030SFabien DESSENNE 	/* h) run the he normal Final phase */
13979d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, 0);
13989d3b5030SFabien DESSENNE }
13999d3b5030SFabien DESSENNE 
14009d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
14019d3b5030SFabien DESSENNE {
14029d3b5030SFabien DESSENNE 	u32 cfg, payload_bytes;
14039d3b5030SFabien DESSENNE 
14049d3b5030SFabien DESSENNE 	/* disable ip, set NPBLB and reneable ip */
14059d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
14069d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14079d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14089d3b5030SFabien DESSENNE 
14099d3b5030SFabien DESSENNE 	payload_bytes = is_decrypt(cryp) ? cryp->total_in - cryp->authsize :
14109d3b5030SFabien DESSENNE 					   cryp->total_in;
14119d3b5030SFabien DESSENNE 	cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT;
14129d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14139d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14149d3b5030SFabien DESSENNE }
14159d3b5030SFabien DESSENNE 
14169d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
14179d3b5030SFabien DESSENNE {
14189d3b5030SFabien DESSENNE 	int err = 0;
14199d3b5030SFabien DESSENNE 	u32 cfg, iv1tmp;
14209d3b5030SFabien DESSENNE 	u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32];
14219d3b5030SFabien DESSENNE 	size_t last_total_out, total_in_ori = cryp->total_in;
14229d3b5030SFabien DESSENNE 	struct scatterlist *out_sg_ori = cryp->out_sg;
14239d3b5030SFabien DESSENNE 	unsigned int i;
14249d3b5030SFabien DESSENNE 
14259d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
14269d3b5030SFabien DESSENNE 	cryp->flags |= FLG_CCM_PADDED_WA;
14279d3b5030SFabien DESSENNE 
14289d3b5030SFabien DESSENNE 	/* a) disable ip */
14299d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
14309d3b5030SFabien DESSENNE 
14319d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
14329d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14339d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14349d3b5030SFabien DESSENNE 
14359d3b5030SFabien DESSENNE 	/* b) get IV1 from CRYP_CSGCMCCM7 */
14369d3b5030SFabien DESSENNE 	iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4);
14379d3b5030SFabien DESSENNE 
14389d3b5030SFabien DESSENNE 	/* c) Load CRYP_CSGCMCCMxR */
14399d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp1); i++)
14409d3b5030SFabien DESSENNE 		cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
14419d3b5030SFabien DESSENNE 
14429d3b5030SFabien DESSENNE 	/* d) Write IV1R */
14439d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV1RR, iv1tmp);
14449d3b5030SFabien DESSENNE 
14459d3b5030SFabien DESSENNE 	/* e) change mode to CTR */
14469d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14479d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
14489d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14499d3b5030SFabien DESSENNE 
14509d3b5030SFabien DESSENNE 	/* a) enable IP */
14519d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14529d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14539d3b5030SFabien DESSENNE 
14549d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
14559d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
14569d3b5030SFabien DESSENNE 	cryp->total_in = total_in_ori;
14579d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14589d3b5030SFabien DESSENNE 	if (err) {
14599d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (wite ccm padded data)\n");
14609d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14619d3b5030SFabien DESSENNE 	}
14629d3b5030SFabien DESSENNE 
14639d3b5030SFabien DESSENNE 	/* c) get and store decrypted data */
14649d3b5030SFabien DESSENNE 	last_total_out = cryp->total_out;
14659d3b5030SFabien DESSENNE 	stm32_cryp_irq_read_data(cryp);
14669d3b5030SFabien DESSENNE 
14679d3b5030SFabien DESSENNE 	memset(tmp, 0, sizeof(tmp));
14689d3b5030SFabien DESSENNE 	scatterwalk_map_and_copy(tmp, out_sg_ori,
14699d3b5030SFabien DESSENNE 				 cryp->total_out_save - last_total_out,
14709d3b5030SFabien DESSENNE 				 last_total_out, 0);
14719d3b5030SFabien DESSENNE 
14729d3b5030SFabien DESSENNE 	/* d) Load again CRYP_CSGCMCCMxR */
14739d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
14749d3b5030SFabien DESSENNE 		cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
14759d3b5030SFabien DESSENNE 
14769d3b5030SFabien DESSENNE 	/* e) change mode back to AES CCM */
14779d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14789d3b5030SFabien DESSENNE 	cfg |= CR_AES_CCM;
14799d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14809d3b5030SFabien DESSENNE 
14819d3b5030SFabien DESSENNE 	/* f) change phase to header */
14829d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
14839d3b5030SFabien DESSENNE 	cfg |= CR_PH_HEADER;
14849d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14859d3b5030SFabien DESSENNE 
14869d3b5030SFabien DESSENNE 	/* g) XOR and write padded data */
14879d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(tmp); i++) {
14889d3b5030SFabien DESSENNE 		tmp[i] ^= cstmp1[i];
14899d3b5030SFabien DESSENNE 		tmp[i] ^= cstmp2[i];
14909d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, tmp[i]);
14919d3b5030SFabien DESSENNE 	}
14929d3b5030SFabien DESSENNE 
14939d3b5030SFabien DESSENNE 	/* h) wait for completion */
14949d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_busy(cryp);
14959d3b5030SFabien DESSENNE 	if (err)
14969d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (wite ccm padded data)\n");
14979d3b5030SFabien DESSENNE 
14989d3b5030SFabien DESSENNE 	/* i) run the he normal Final phase */
14999d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, err);
15009d3b5030SFabien DESSENNE }
15019d3b5030SFabien DESSENNE 
15029e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
15039e054ec2SFabien DESSENNE {
15049e054ec2SFabien DESSENNE 	if (unlikely(!cryp->total_in)) {
15059e054ec2SFabien DESSENNE 		dev_warn(cryp->dev, "No more data to process\n");
15069e054ec2SFabien DESSENNE 		return;
15079e054ec2SFabien DESSENNE 	}
15089e054ec2SFabien DESSENNE 
15099d3b5030SFabien DESSENNE 	if (unlikely(cryp->total_in < AES_BLOCK_SIZE &&
15109d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
15119d3b5030SFabien DESSENNE 		     is_encrypt(cryp))) {
15129d3b5030SFabien DESSENNE 		/* Padding for AES GCM encryption */
15139d3b5030SFabien DESSENNE 		if (cryp->caps->padding_wa)
15149d3b5030SFabien DESSENNE 			/* Special case 1 */
15159d3b5030SFabien DESSENNE 			return stm32_cryp_irq_write_gcm_padded_data(cryp);
15169d3b5030SFabien DESSENNE 
15179d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
15189d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
15199d3b5030SFabien DESSENNE 	}
15209d3b5030SFabien DESSENNE 
15219d3b5030SFabien DESSENNE 	if (unlikely((cryp->total_in - cryp->authsize < AES_BLOCK_SIZE) &&
15229d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
15239d3b5030SFabien DESSENNE 		     is_decrypt(cryp))) {
15249d3b5030SFabien DESSENNE 		/* Padding for AES CCM decryption */
15259d3b5030SFabien DESSENNE 		if (cryp->caps->padding_wa)
15269d3b5030SFabien DESSENNE 			/* Special case 2 */
15279d3b5030SFabien DESSENNE 			return stm32_cryp_irq_write_ccm_padded_data(cryp);
15289d3b5030SFabien DESSENNE 
15299d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
15309d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
15319d3b5030SFabien DESSENNE 	}
15329d3b5030SFabien DESSENNE 
15339e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
15349e054ec2SFabien DESSENNE 		stm32_cryp_check_ctr_counter(cryp);
15359e054ec2SFabien DESSENNE 
15369e054ec2SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
15379e054ec2SFabien DESSENNE }
15389e054ec2SFabien DESSENNE 
15399d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
15409d3b5030SFabien DESSENNE {
15419d3b5030SFabien DESSENNE 	int err;
15429d3b5030SFabien DESSENNE 	unsigned int i, j;
15439d3b5030SFabien DESSENNE 	u32 cfg, *src;
15449d3b5030SFabien DESSENNE 
15459d3b5030SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
15469d3b5030SFabien DESSENNE 
15479d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
15489d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, *src);
15499d3b5030SFabien DESSENNE 
15509d3b5030SFabien DESSENNE 		src = stm32_cryp_next_in(cryp, src, sizeof(u32));
15519d3b5030SFabien DESSENNE 		cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in);
15529d3b5030SFabien DESSENNE 
15539d3b5030SFabien DESSENNE 		/* Check if whole header written */
15549d3b5030SFabien DESSENNE 		if ((cryp->total_in_save - cryp->total_in) ==
15559d3b5030SFabien DESSENNE 				cryp->areq->assoclen) {
15569d3b5030SFabien DESSENNE 			/* Write padding if needed */
15579d3b5030SFabien DESSENNE 			for (j = i + 1; j < AES_BLOCK_32; j++)
15589d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_DIN, 0);
15599d3b5030SFabien DESSENNE 
15609d3b5030SFabien DESSENNE 			/* Wait for completion */
15619d3b5030SFabien DESSENNE 			err = stm32_cryp_wait_busy(cryp);
15629d3b5030SFabien DESSENNE 			if (err) {
15639d3b5030SFabien DESSENNE 				dev_err(cryp->dev, "Timeout (gcm header)\n");
15649d3b5030SFabien DESSENNE 				return stm32_cryp_finish_req(cryp, err);
15659d3b5030SFabien DESSENNE 			}
15669d3b5030SFabien DESSENNE 
15679d3b5030SFabien DESSENNE 			if (stm32_cryp_get_input_text_len(cryp)) {
15689d3b5030SFabien DESSENNE 				/* Phase 3 : payload */
15699d3b5030SFabien DESSENNE 				cfg = stm32_cryp_read(cryp, CRYP_CR);
15709d3b5030SFabien DESSENNE 				cfg &= ~CR_CRYPEN;
15719d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
15729d3b5030SFabien DESSENNE 
15739d3b5030SFabien DESSENNE 				cfg &= ~CR_PH_MASK;
15749d3b5030SFabien DESSENNE 				cfg |= CR_PH_PAYLOAD;
15759d3b5030SFabien DESSENNE 				cfg |= CR_CRYPEN;
15769d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
15779d3b5030SFabien DESSENNE 			} else {
15789d3b5030SFabien DESSENNE 				/* Phase 4 : tag */
15799d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_IMSCR, 0);
15809d3b5030SFabien DESSENNE 				stm32_cryp_finish_req(cryp, 0);
15819d3b5030SFabien DESSENNE 			}
15829d3b5030SFabien DESSENNE 
15839d3b5030SFabien DESSENNE 			break;
15849d3b5030SFabien DESSENNE 		}
15859d3b5030SFabien DESSENNE 
15869d3b5030SFabien DESSENNE 		if (!cryp->total_in)
15879d3b5030SFabien DESSENNE 			break;
15889d3b5030SFabien DESSENNE 	}
15899d3b5030SFabien DESSENNE }
15909d3b5030SFabien DESSENNE 
15919d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
15929d3b5030SFabien DESSENNE {
15939d3b5030SFabien DESSENNE 	int err;
15949d3b5030SFabien DESSENNE 	unsigned int i = 0, j, k;
15959d3b5030SFabien DESSENNE 	u32 alen, cfg, *src;
15969d3b5030SFabien DESSENNE 	u8 d8[4];
15979d3b5030SFabien DESSENNE 
15989d3b5030SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
15999d3b5030SFabien DESSENNE 	alen = cryp->areq->assoclen;
16009d3b5030SFabien DESSENNE 
16019d3b5030SFabien DESSENNE 	if (!_walked_in) {
16029d3b5030SFabien DESSENNE 		if (cryp->areq->assoclen <= 65280) {
16039d3b5030SFabien DESSENNE 			/* Write first u32 of B1 */
16049d3b5030SFabien DESSENNE 			d8[0] = (alen >> 8) & 0xFF;
16059d3b5030SFabien DESSENNE 			d8[1] = alen & 0xFF;
16069d3b5030SFabien DESSENNE 			d8[2] = *((u8 *)src);
16079d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16089d3b5030SFabien DESSENNE 			d8[3] = *((u8 *)src);
16099d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16109d3b5030SFabien DESSENNE 
16119d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16129d3b5030SFabien DESSENNE 			i++;
16139d3b5030SFabien DESSENNE 
16149d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 2, cryp->total_in);
16159d3b5030SFabien DESSENNE 		} else {
16169d3b5030SFabien DESSENNE 			/* Build the two first u32 of B1 */
16179d3b5030SFabien DESSENNE 			d8[0] = 0xFF;
16189d3b5030SFabien DESSENNE 			d8[1] = 0xFE;
16199d3b5030SFabien DESSENNE 			d8[2] = alen & 0xFF000000;
16209d3b5030SFabien DESSENNE 			d8[3] = alen & 0x00FF0000;
16219d3b5030SFabien DESSENNE 
16229d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16239d3b5030SFabien DESSENNE 			i++;
16249d3b5030SFabien DESSENNE 
16259d3b5030SFabien DESSENNE 			d8[0] = alen & 0x0000FF00;
16269d3b5030SFabien DESSENNE 			d8[1] = alen & 0x000000FF;
16279d3b5030SFabien DESSENNE 			d8[2] = *((u8 *)src);
16289d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16299d3b5030SFabien DESSENNE 			d8[3] = *((u8 *)src);
16309d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16319d3b5030SFabien DESSENNE 
16329d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16339d3b5030SFabien DESSENNE 			i++;
16349d3b5030SFabien DESSENNE 
16359d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 2, cryp->total_in);
16369d3b5030SFabien DESSENNE 		}
16379d3b5030SFabien DESSENNE 	}
16389d3b5030SFabien DESSENNE 
16399d3b5030SFabien DESSENNE 	/* Write next u32 */
16409d3b5030SFabien DESSENNE 	for (; i < AES_BLOCK_32; i++) {
16419d3b5030SFabien DESSENNE 		/* Build an u32 */
16429d3b5030SFabien DESSENNE 		memset(d8, 0, sizeof(u32));
16439d3b5030SFabien DESSENNE 		for (k = 0; k < sizeof(u32); k++) {
16449d3b5030SFabien DESSENNE 			d8[k] = *((u8 *)src);
16459d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16469d3b5030SFabien DESSENNE 
16479d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 1, cryp->total_in);
16489d3b5030SFabien DESSENNE 			if ((cryp->total_in_save - cryp->total_in) == alen)
16499d3b5030SFabien DESSENNE 				break;
16509d3b5030SFabien DESSENNE 		}
16519d3b5030SFabien DESSENNE 
16529d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16539d3b5030SFabien DESSENNE 
16549d3b5030SFabien DESSENNE 		if ((cryp->total_in_save - cryp->total_in) == alen) {
16559d3b5030SFabien DESSENNE 			/* Write padding if needed */
16569d3b5030SFabien DESSENNE 			for (j = i + 1; j < AES_BLOCK_32; j++)
16579d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_DIN, 0);
16589d3b5030SFabien DESSENNE 
16599d3b5030SFabien DESSENNE 			/* Wait for completion */
16609d3b5030SFabien DESSENNE 			err = stm32_cryp_wait_busy(cryp);
16619d3b5030SFabien DESSENNE 			if (err) {
16629d3b5030SFabien DESSENNE 				dev_err(cryp->dev, "Timeout (ccm header)\n");
16639d3b5030SFabien DESSENNE 				return stm32_cryp_finish_req(cryp, err);
16649d3b5030SFabien DESSENNE 			}
16659d3b5030SFabien DESSENNE 
16669d3b5030SFabien DESSENNE 			if (stm32_cryp_get_input_text_len(cryp)) {
16679d3b5030SFabien DESSENNE 				/* Phase 3 : payload */
16689d3b5030SFabien DESSENNE 				cfg = stm32_cryp_read(cryp, CRYP_CR);
16699d3b5030SFabien DESSENNE 				cfg &= ~CR_CRYPEN;
16709d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
16719d3b5030SFabien DESSENNE 
16729d3b5030SFabien DESSENNE 				cfg &= ~CR_PH_MASK;
16739d3b5030SFabien DESSENNE 				cfg |= CR_PH_PAYLOAD;
16749d3b5030SFabien DESSENNE 				cfg |= CR_CRYPEN;
16759d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
16769d3b5030SFabien DESSENNE 			} else {
16779d3b5030SFabien DESSENNE 				/* Phase 4 : tag */
16789d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_IMSCR, 0);
16799d3b5030SFabien DESSENNE 				stm32_cryp_finish_req(cryp, 0);
16809d3b5030SFabien DESSENNE 			}
16819d3b5030SFabien DESSENNE 
16829d3b5030SFabien DESSENNE 			break;
16839d3b5030SFabien DESSENNE 		}
16849d3b5030SFabien DESSENNE 	}
16859d3b5030SFabien DESSENNE }
16869d3b5030SFabien DESSENNE 
16879e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg)
16889e054ec2SFabien DESSENNE {
16899e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
16909d3b5030SFabien DESSENNE 	u32 ph;
16919e054ec2SFabien DESSENNE 
16929e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_OUT)
16939e054ec2SFabien DESSENNE 		/* Output FIFO IRQ: read data */
16949e054ec2SFabien DESSENNE 		if (unlikely(stm32_cryp_irq_read_data(cryp))) {
16959e054ec2SFabien DESSENNE 			/* All bytes processed, finish */
16969e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_IMSCR, 0);
16979d3b5030SFabien DESSENNE 			stm32_cryp_finish_req(cryp, 0);
16989e054ec2SFabien DESSENNE 			return IRQ_HANDLED;
16999e054ec2SFabien DESSENNE 		}
17009e054ec2SFabien DESSENNE 
17019e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_IN) {
17029d3b5030SFabien DESSENNE 		if (is_gcm(cryp)) {
17039d3b5030SFabien DESSENNE 			ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK;
17049d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
17059d3b5030SFabien DESSENNE 				/* Write Header */
17069d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_gcm_header(cryp);
17079d3b5030SFabien DESSENNE 			else
17089e054ec2SFabien DESSENNE 				/* Input FIFO IRQ: write data */
17099e054ec2SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
17109d3b5030SFabien DESSENNE 			cryp->gcm_ctr++;
17119d3b5030SFabien DESSENNE 		} else if (is_ccm(cryp)) {
17129d3b5030SFabien DESSENNE 			ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK;
17139d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
17149d3b5030SFabien DESSENNE 				/* Write Header */
17159d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_ccm_header(cryp);
17169d3b5030SFabien DESSENNE 			else
17179d3b5030SFabien DESSENNE 				/* Input FIFO IRQ: write data */
17189d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
17199d3b5030SFabien DESSENNE 		} else {
17209d3b5030SFabien DESSENNE 			/* Input FIFO IRQ: write data */
17219d3b5030SFabien DESSENNE 			stm32_cryp_irq_write_data(cryp);
17229d3b5030SFabien DESSENNE 		}
17239e054ec2SFabien DESSENNE 	}
17249e054ec2SFabien DESSENNE 
17259e054ec2SFabien DESSENNE 	return IRQ_HANDLED;
17269e054ec2SFabien DESSENNE }
17279e054ec2SFabien DESSENNE 
17289e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg)
17299e054ec2SFabien DESSENNE {
17309e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
17319e054ec2SFabien DESSENNE 
17329e054ec2SFabien DESSENNE 	cryp->irq_status = stm32_cryp_read(cryp, CRYP_MISR);
17339e054ec2SFabien DESSENNE 
17349e054ec2SFabien DESSENNE 	return IRQ_WAKE_THREAD;
17359e054ec2SFabien DESSENNE }
17369e054ec2SFabien DESSENNE 
173747ece481SArd Biesheuvel static struct skcipher_alg crypto_algs[] = {
17389e054ec2SFabien DESSENNE {
173947ece481SArd Biesheuvel 	.base.cra_name		= "ecb(aes)",
174047ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-aes",
174147ece481SArd Biesheuvel 	.base.cra_priority	= 200,
174247ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
174347ece481SArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
174447ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
174547ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
174647ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
174747ece481SArd Biesheuvel 
174847ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17499e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17509e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17519e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17529e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_ecb_encrypt,
17539e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_ecb_decrypt,
17549e054ec2SFabien DESSENNE },
17559e054ec2SFabien DESSENNE {
175647ece481SArd Biesheuvel 	.base.cra_name		= "cbc(aes)",
175747ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-aes",
175847ece481SArd Biesheuvel 	.base.cra_priority	= 200,
175947ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
176047ece481SArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
176147ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
176247ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
176347ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
176447ece481SArd Biesheuvel 
176547ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17669e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17679e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17689e054ec2SFabien DESSENNE 	.ivsize			= AES_BLOCK_SIZE,
17699e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17709e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_cbc_encrypt,
17719e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_cbc_decrypt,
17729e054ec2SFabien DESSENNE },
17739e054ec2SFabien DESSENNE {
177447ece481SArd Biesheuvel 	.base.cra_name		= "ctr(aes)",
177547ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ctr-aes",
177647ece481SArd Biesheuvel 	.base.cra_priority	= 200,
177747ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
177847ece481SArd Biesheuvel 	.base.cra_blocksize	= 1,
177947ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
178047ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
178147ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
178247ece481SArd Biesheuvel 
178347ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17849e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17859e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17869e054ec2SFabien DESSENNE 	.ivsize			= AES_BLOCK_SIZE,
17879e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17889e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_ctr_encrypt,
17899e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_ctr_decrypt,
17909e054ec2SFabien DESSENNE },
17919e054ec2SFabien DESSENNE {
179247ece481SArd Biesheuvel 	.base.cra_name		= "ecb(des)",
179347ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-des",
179447ece481SArd Biesheuvel 	.base.cra_priority	= 200,
179547ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
179647ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
179747ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
179847ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
179947ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
180047ece481SArd Biesheuvel 
180147ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18029e054ec2SFabien DESSENNE 	.min_keysize		= DES_BLOCK_SIZE,
18039e054ec2SFabien DESSENNE 	.max_keysize		= DES_BLOCK_SIZE,
18049e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_des_setkey,
18059e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_des_ecb_encrypt,
18069e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_des_ecb_decrypt,
18079e054ec2SFabien DESSENNE },
18089e054ec2SFabien DESSENNE {
180947ece481SArd Biesheuvel 	.base.cra_name		= "cbc(des)",
181047ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-des",
181147ece481SArd Biesheuvel 	.base.cra_priority	= 200,
181247ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
181347ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
181447ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
181547ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
181647ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
181747ece481SArd Biesheuvel 
181847ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18199e054ec2SFabien DESSENNE 	.min_keysize		= DES_BLOCK_SIZE,
18209e054ec2SFabien DESSENNE 	.max_keysize		= DES_BLOCK_SIZE,
18219e054ec2SFabien DESSENNE 	.ivsize			= DES_BLOCK_SIZE,
18229e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_des_setkey,
18239e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_des_cbc_encrypt,
18249e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_des_cbc_decrypt,
18259e054ec2SFabien DESSENNE },
18269e054ec2SFabien DESSENNE {
182747ece481SArd Biesheuvel 	.base.cra_name		= "ecb(des3_ede)",
182847ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-des3",
182947ece481SArd Biesheuvel 	.base.cra_priority	= 200,
183047ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
183147ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
183247ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
183347ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
183447ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
183547ece481SArd Biesheuvel 
183647ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18379e054ec2SFabien DESSENNE 	.min_keysize		= 3 * DES_BLOCK_SIZE,
18389e054ec2SFabien DESSENNE 	.max_keysize		= 3 * DES_BLOCK_SIZE,
18399e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_tdes_setkey,
18409e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_tdes_ecb_encrypt,
18419e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_tdes_ecb_decrypt,
18429e054ec2SFabien DESSENNE },
18439e054ec2SFabien DESSENNE {
184447ece481SArd Biesheuvel 	.base.cra_name		= "cbc(des3_ede)",
184547ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-des3",
184647ece481SArd Biesheuvel 	.base.cra_priority	= 200,
184747ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
184847ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
184947ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
185047ece481SArd Biesheuvel 	.base.cra_alignmask	= 0xf,
185147ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
185247ece481SArd Biesheuvel 
185347ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18549e054ec2SFabien DESSENNE 	.min_keysize		= 3 * DES_BLOCK_SIZE,
18559e054ec2SFabien DESSENNE 	.max_keysize		= 3 * DES_BLOCK_SIZE,
18569e054ec2SFabien DESSENNE 	.ivsize			= DES_BLOCK_SIZE,
18579e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_tdes_setkey,
18589e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_tdes_cbc_encrypt,
18599e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_tdes_cbc_decrypt,
18609e054ec2SFabien DESSENNE },
18619e054ec2SFabien DESSENNE };
18629e054ec2SFabien DESSENNE 
18639d3b5030SFabien DESSENNE static struct aead_alg aead_algs[] = {
18649d3b5030SFabien DESSENNE {
18659d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18669d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_gcm_setauthsize,
18679d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_gcm_encrypt,
18689d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_gcm_decrypt,
18699d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18709d3b5030SFabien DESSENNE 	.ivsize		= 12,
18719d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18729d3b5030SFabien DESSENNE 
18739d3b5030SFabien DESSENNE 	.base = {
18749d3b5030SFabien DESSENNE 		.cra_name		= "gcm(aes)",
18759d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-gcm-aes",
18769d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18779d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18789d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18799d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18809d3b5030SFabien DESSENNE 		.cra_alignmask		= 0xf,
18819d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18829d3b5030SFabien DESSENNE 	},
18839d3b5030SFabien DESSENNE },
18849d3b5030SFabien DESSENNE {
18859d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18869d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_ccm_setauthsize,
18879d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_ccm_encrypt,
18889d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_ccm_decrypt,
18899d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18909d3b5030SFabien DESSENNE 	.ivsize		= AES_BLOCK_SIZE,
18919d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18929d3b5030SFabien DESSENNE 
18939d3b5030SFabien DESSENNE 	.base = {
18949d3b5030SFabien DESSENNE 		.cra_name		= "ccm(aes)",
18959d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-ccm-aes",
18969d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18979d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18989d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18999d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
19009d3b5030SFabien DESSENNE 		.cra_alignmask		= 0xf,
19019d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
19029d3b5030SFabien DESSENNE 	},
19039d3b5030SFabien DESSENNE },
19049d3b5030SFabien DESSENNE };
19059d3b5030SFabien DESSENNE 
19069d3b5030SFabien DESSENNE static const struct stm32_cryp_caps f7_data = {
19079d3b5030SFabien DESSENNE 	.swap_final = true,
19089d3b5030SFabien DESSENNE 	.padding_wa = true,
19099d3b5030SFabien DESSENNE };
19109d3b5030SFabien DESSENNE 
1911a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = {
1912a43a3484SFabien DESSENNE 	.swap_final = false,
1913a43a3484SFabien DESSENNE 	.padding_wa = false,
1914a43a3484SFabien DESSENNE };
1915a43a3484SFabien DESSENNE 
19169e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = {
19179d3b5030SFabien DESSENNE 	{ .compatible = "st,stm32f756-cryp", .data = &f7_data},
1918a43a3484SFabien DESSENNE 	{ .compatible = "st,stm32mp1-cryp", .data = &mp1_data},
19199e054ec2SFabien DESSENNE 	{},
19209e054ec2SFabien DESSENNE };
1921761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids);
19229e054ec2SFabien DESSENNE 
19239e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev)
19249e054ec2SFabien DESSENNE {
19259e054ec2SFabien DESSENNE 	struct device *dev = &pdev->dev;
19269e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
19279e054ec2SFabien DESSENNE 	struct reset_control *rst;
19289e054ec2SFabien DESSENNE 	int irq, ret;
19299e054ec2SFabien DESSENNE 
19309e054ec2SFabien DESSENNE 	cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL);
19319e054ec2SFabien DESSENNE 	if (!cryp)
19329e054ec2SFabien DESSENNE 		return -ENOMEM;
19339e054ec2SFabien DESSENNE 
19349d3b5030SFabien DESSENNE 	cryp->caps = of_device_get_match_data(dev);
19359d3b5030SFabien DESSENNE 	if (!cryp->caps)
19369d3b5030SFabien DESSENNE 		return -ENODEV;
19379d3b5030SFabien DESSENNE 
19389e054ec2SFabien DESSENNE 	cryp->dev = dev;
19399e054ec2SFabien DESSENNE 
1940473b4d99SYueHaibing 	cryp->regs = devm_platform_ioremap_resource(pdev, 0);
194160bcf265Sweiyongjun \(A\) 	if (IS_ERR(cryp->regs))
19429e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->regs);
19439e054ec2SFabien DESSENNE 
19449e054ec2SFabien DESSENNE 	irq = platform_get_irq(pdev, 0);
1945514838e9SStephen Boyd 	if (irq < 0)
19469e054ec2SFabien DESSENNE 		return irq;
19479e054ec2SFabien DESSENNE 
19489e054ec2SFabien DESSENNE 	ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq,
19499e054ec2SFabien DESSENNE 					stm32_cryp_irq_thread, IRQF_ONESHOT,
19509e054ec2SFabien DESSENNE 					dev_name(dev), cryp);
19519e054ec2SFabien DESSENNE 	if (ret) {
19529e054ec2SFabien DESSENNE 		dev_err(dev, "Cannot grab IRQ\n");
19539e054ec2SFabien DESSENNE 		return ret;
19549e054ec2SFabien DESSENNE 	}
19559e054ec2SFabien DESSENNE 
19569e054ec2SFabien DESSENNE 	cryp->clk = devm_clk_get(dev, NULL);
19579e054ec2SFabien DESSENNE 	if (IS_ERR(cryp->clk)) {
19589e054ec2SFabien DESSENNE 		dev_err(dev, "Could not get clock\n");
19599e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->clk);
19609e054ec2SFabien DESSENNE 	}
19619e054ec2SFabien DESSENNE 
19629e054ec2SFabien DESSENNE 	ret = clk_prepare_enable(cryp->clk);
19639e054ec2SFabien DESSENNE 	if (ret) {
19649e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Failed to enable clock\n");
19659e054ec2SFabien DESSENNE 		return ret;
19669e054ec2SFabien DESSENNE 	}
19679e054ec2SFabien DESSENNE 
196865f9aa36Slionel.debieve@st.com 	pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY);
196965f9aa36Slionel.debieve@st.com 	pm_runtime_use_autosuspend(dev);
197065f9aa36Slionel.debieve@st.com 
197165f9aa36Slionel.debieve@st.com 	pm_runtime_get_noresume(dev);
197265f9aa36Slionel.debieve@st.com 	pm_runtime_set_active(dev);
197365f9aa36Slionel.debieve@st.com 	pm_runtime_enable(dev);
197465f9aa36Slionel.debieve@st.com 
19759e054ec2SFabien DESSENNE 	rst = devm_reset_control_get(dev, NULL);
19769e054ec2SFabien DESSENNE 	if (!IS_ERR(rst)) {
19779e054ec2SFabien DESSENNE 		reset_control_assert(rst);
19789e054ec2SFabien DESSENNE 		udelay(2);
19799e054ec2SFabien DESSENNE 		reset_control_deassert(rst);
19809e054ec2SFabien DESSENNE 	}
19819e054ec2SFabien DESSENNE 
19829e054ec2SFabien DESSENNE 	platform_set_drvdata(pdev, cryp);
19839e054ec2SFabien DESSENNE 
19849e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
19859e054ec2SFabien DESSENNE 	list_add(&cryp->list, &cryp_list.dev_list);
19869e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
19879e054ec2SFabien DESSENNE 
19889e054ec2SFabien DESSENNE 	/* Initialize crypto engine */
19899e054ec2SFabien DESSENNE 	cryp->engine = crypto_engine_alloc_init(dev, 1);
19909e054ec2SFabien DESSENNE 	if (!cryp->engine) {
19919e054ec2SFabien DESSENNE 		dev_err(dev, "Could not init crypto engine\n");
19929e054ec2SFabien DESSENNE 		ret = -ENOMEM;
19939e054ec2SFabien DESSENNE 		goto err_engine1;
19949e054ec2SFabien DESSENNE 	}
19959e054ec2SFabien DESSENNE 
19969e054ec2SFabien DESSENNE 	ret = crypto_engine_start(cryp->engine);
19979e054ec2SFabien DESSENNE 	if (ret) {
19989e054ec2SFabien DESSENNE 		dev_err(dev, "Could not start crypto engine\n");
19999e054ec2SFabien DESSENNE 		goto err_engine2;
20009e054ec2SFabien DESSENNE 	}
20019e054ec2SFabien DESSENNE 
200247ece481SArd Biesheuvel 	ret = crypto_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20039e054ec2SFabien DESSENNE 	if (ret) {
20049e054ec2SFabien DESSENNE 		dev_err(dev, "Could not register algs\n");
20059e054ec2SFabien DESSENNE 		goto err_algs;
20069e054ec2SFabien DESSENNE 	}
20079e054ec2SFabien DESSENNE 
20089d3b5030SFabien DESSENNE 	ret = crypto_register_aeads(aead_algs, ARRAY_SIZE(aead_algs));
20099d3b5030SFabien DESSENNE 	if (ret)
20109d3b5030SFabien DESSENNE 		goto err_aead_algs;
20119d3b5030SFabien DESSENNE 
20129e054ec2SFabien DESSENNE 	dev_info(dev, "Initialized\n");
20139e054ec2SFabien DESSENNE 
201465f9aa36Slionel.debieve@st.com 	pm_runtime_put_sync(dev);
201565f9aa36Slionel.debieve@st.com 
20169e054ec2SFabien DESSENNE 	return 0;
20179e054ec2SFabien DESSENNE 
20189d3b5030SFabien DESSENNE err_aead_algs:
201947ece481SArd Biesheuvel 	crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20209e054ec2SFabien DESSENNE err_algs:
20219e054ec2SFabien DESSENNE err_engine2:
20229e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20239e054ec2SFabien DESSENNE err_engine1:
20249e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20259e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20269e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20279e054ec2SFabien DESSENNE 
202865f9aa36Slionel.debieve@st.com 	pm_runtime_disable(dev);
202965f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(dev);
203065f9aa36Slionel.debieve@st.com 	pm_runtime_disable(dev);
203165f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(dev);
203265f9aa36Slionel.debieve@st.com 
20339e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20349e054ec2SFabien DESSENNE 
20359e054ec2SFabien DESSENNE 	return ret;
20369e054ec2SFabien DESSENNE }
20379e054ec2SFabien DESSENNE 
20389e054ec2SFabien DESSENNE static int stm32_cryp_remove(struct platform_device *pdev)
20399e054ec2SFabien DESSENNE {
20409e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = platform_get_drvdata(pdev);
204165f9aa36Slionel.debieve@st.com 	int ret;
20429e054ec2SFabien DESSENNE 
20439e054ec2SFabien DESSENNE 	if (!cryp)
20449e054ec2SFabien DESSENNE 		return -ENODEV;
20459e054ec2SFabien DESSENNE 
204665f9aa36Slionel.debieve@st.com 	ret = pm_runtime_get_sync(cryp->dev);
204765f9aa36Slionel.debieve@st.com 	if (ret < 0)
204865f9aa36Slionel.debieve@st.com 		return ret;
204965f9aa36Slionel.debieve@st.com 
20509d3b5030SFabien DESSENNE 	crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
205147ece481SArd Biesheuvel 	crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20529e054ec2SFabien DESSENNE 
20539e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20549e054ec2SFabien DESSENNE 
20559e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20569e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20579e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20589e054ec2SFabien DESSENNE 
205965f9aa36Slionel.debieve@st.com 	pm_runtime_disable(cryp->dev);
206065f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(cryp->dev);
206165f9aa36Slionel.debieve@st.com 
20629e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20639e054ec2SFabien DESSENNE 
20649e054ec2SFabien DESSENNE 	return 0;
20659e054ec2SFabien DESSENNE }
20669e054ec2SFabien DESSENNE 
206765f9aa36Slionel.debieve@st.com #ifdef CONFIG_PM
206865f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_suspend(struct device *dev)
206965f9aa36Slionel.debieve@st.com {
207065f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
207165f9aa36Slionel.debieve@st.com 
207265f9aa36Slionel.debieve@st.com 	clk_disable_unprepare(cryp->clk);
207365f9aa36Slionel.debieve@st.com 
207465f9aa36Slionel.debieve@st.com 	return 0;
207565f9aa36Slionel.debieve@st.com }
207665f9aa36Slionel.debieve@st.com 
207765f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_resume(struct device *dev)
207865f9aa36Slionel.debieve@st.com {
207965f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
208065f9aa36Slionel.debieve@st.com 	int ret;
208165f9aa36Slionel.debieve@st.com 
208265f9aa36Slionel.debieve@st.com 	ret = clk_prepare_enable(cryp->clk);
208365f9aa36Slionel.debieve@st.com 	if (ret) {
208465f9aa36Slionel.debieve@st.com 		dev_err(cryp->dev, "Failed to prepare_enable clock\n");
208565f9aa36Slionel.debieve@st.com 		return ret;
208665f9aa36Slionel.debieve@st.com 	}
208765f9aa36Slionel.debieve@st.com 
208865f9aa36Slionel.debieve@st.com 	return 0;
208965f9aa36Slionel.debieve@st.com }
209065f9aa36Slionel.debieve@st.com #endif
209165f9aa36Slionel.debieve@st.com 
209265f9aa36Slionel.debieve@st.com static const struct dev_pm_ops stm32_cryp_pm_ops = {
209365f9aa36Slionel.debieve@st.com 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
209465f9aa36Slionel.debieve@st.com 				pm_runtime_force_resume)
209565f9aa36Slionel.debieve@st.com 	SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend,
209665f9aa36Slionel.debieve@st.com 			   stm32_cryp_runtime_resume, NULL)
209765f9aa36Slionel.debieve@st.com };
209865f9aa36Slionel.debieve@st.com 
20999e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = {
21009e054ec2SFabien DESSENNE 	.probe  = stm32_cryp_probe,
21019e054ec2SFabien DESSENNE 	.remove = stm32_cryp_remove,
21029e054ec2SFabien DESSENNE 	.driver = {
21039e054ec2SFabien DESSENNE 		.name           = DRIVER_NAME,
210465f9aa36Slionel.debieve@st.com 		.pm		= &stm32_cryp_pm_ops,
21059e054ec2SFabien DESSENNE 		.of_match_table = stm32_dt_ids,
21069e054ec2SFabien DESSENNE 	},
21079e054ec2SFabien DESSENNE };
21089e054ec2SFabien DESSENNE 
21099e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver);
21109e054ec2SFabien DESSENNE 
21119e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
21129e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver");
21139e054ec2SFabien DESSENNE MODULE_LICENSE("GPL");
2114