xref: /linux/drivers/crypto/stm32/stm32-cryp.c (revision a43a34845a156c9e1dae00e33595a508d53e0365)
19e054ec2SFabien DESSENNE /*
29e054ec2SFabien DESSENNE  * Copyright (C) STMicroelectronics SA 2017
39e054ec2SFabien DESSENNE  * Author: Fabien Dessenne <fabien.dessenne@st.com>
49e054ec2SFabien DESSENNE  * License terms:  GNU General Public License (GPL), version 2
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>
149e054ec2SFabien DESSENNE #include <linux/reset.h>
159e054ec2SFabien DESSENNE 
169e054ec2SFabien DESSENNE #include <crypto/aes.h>
179e054ec2SFabien DESSENNE #include <crypto/des.h>
189e054ec2SFabien DESSENNE #include <crypto/engine.h>
199e054ec2SFabien DESSENNE #include <crypto/scatterwalk.h>
209d3b5030SFabien DESSENNE #include <crypto/internal/aead.h>
219e054ec2SFabien DESSENNE 
229e054ec2SFabien DESSENNE #define DRIVER_NAME             "stm32-cryp"
239e054ec2SFabien DESSENNE 
249e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */
259e054ec2SFabien DESSENNE #define FLG_ENCRYPT             BIT(0)
269e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */
279e054ec2SFabien DESSENNE #define FLG_AES                 BIT(1)
289e054ec2SFabien DESSENNE #define FLG_DES                 BIT(2)
299e054ec2SFabien DESSENNE #define FLG_TDES                BIT(3)
309e054ec2SFabien DESSENNE #define FLG_ECB                 BIT(4)
319e054ec2SFabien DESSENNE #define FLG_CBC                 BIT(5)
329e054ec2SFabien DESSENNE #define FLG_CTR                 BIT(6)
339d3b5030SFabien DESSENNE #define FLG_GCM                 BIT(7)
349d3b5030SFabien DESSENNE #define FLG_CCM                 BIT(8)
359e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */
369e054ec2SFabien DESSENNE #define FLG_MODE_MASK           GENMASK(15, 0)
379d3b5030SFabien DESSENNE /* Bit [31..16] status  */
389d3b5030SFabien DESSENNE #define FLG_CCM_PADDED_WA       BIT(16)
399e054ec2SFabien DESSENNE 
409e054ec2SFabien DESSENNE /* Registers */
419e054ec2SFabien DESSENNE #define CRYP_CR                 0x00000000
429e054ec2SFabien DESSENNE #define CRYP_SR                 0x00000004
439e054ec2SFabien DESSENNE #define CRYP_DIN                0x00000008
449e054ec2SFabien DESSENNE #define CRYP_DOUT               0x0000000C
459e054ec2SFabien DESSENNE #define CRYP_DMACR              0x00000010
469e054ec2SFabien DESSENNE #define CRYP_IMSCR              0x00000014
479e054ec2SFabien DESSENNE #define CRYP_RISR               0x00000018
489e054ec2SFabien DESSENNE #define CRYP_MISR               0x0000001C
499e054ec2SFabien DESSENNE #define CRYP_K0LR               0x00000020
509e054ec2SFabien DESSENNE #define CRYP_K0RR               0x00000024
519e054ec2SFabien DESSENNE #define CRYP_K1LR               0x00000028
529e054ec2SFabien DESSENNE #define CRYP_K1RR               0x0000002C
539e054ec2SFabien DESSENNE #define CRYP_K2LR               0x00000030
549e054ec2SFabien DESSENNE #define CRYP_K2RR               0x00000034
559e054ec2SFabien DESSENNE #define CRYP_K3LR               0x00000038
569e054ec2SFabien DESSENNE #define CRYP_K3RR               0x0000003C
579e054ec2SFabien DESSENNE #define CRYP_IV0LR              0x00000040
589e054ec2SFabien DESSENNE #define CRYP_IV0RR              0x00000044
599e054ec2SFabien DESSENNE #define CRYP_IV1LR              0x00000048
609e054ec2SFabien DESSENNE #define CRYP_IV1RR              0x0000004C
619d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R         0x00000050
629d3b5030SFabien DESSENNE #define CRYP_CSGCM0R            0x00000070
639e054ec2SFabien DESSENNE 
649e054ec2SFabien DESSENNE /* Registers values */
659e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC          0x00000004
669e054ec2SFabien DESSENNE #define CR_TDES_ECB             0x00000000
679e054ec2SFabien DESSENNE #define CR_TDES_CBC             0x00000008
689e054ec2SFabien DESSENNE #define CR_DES_ECB              0x00000010
699e054ec2SFabien DESSENNE #define CR_DES_CBC              0x00000018
709e054ec2SFabien DESSENNE #define CR_AES_ECB              0x00000020
719e054ec2SFabien DESSENNE #define CR_AES_CBC              0x00000028
729e054ec2SFabien DESSENNE #define CR_AES_CTR              0x00000030
739e054ec2SFabien DESSENNE #define CR_AES_KP               0x00000038
749d3b5030SFabien DESSENNE #define CR_AES_GCM              0x00080000
759d3b5030SFabien DESSENNE #define CR_AES_CCM              0x00080008
769e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN          0xFFFFFFFF
779e054ec2SFabien DESSENNE #define CR_ALGO_MASK            0x00080038
789e054ec2SFabien DESSENNE #define CR_DATA32               0x00000000
799e054ec2SFabien DESSENNE #define CR_DATA16               0x00000040
809e054ec2SFabien DESSENNE #define CR_DATA8                0x00000080
819e054ec2SFabien DESSENNE #define CR_DATA1                0x000000C0
829e054ec2SFabien DESSENNE #define CR_KEY128               0x00000000
839e054ec2SFabien DESSENNE #define CR_KEY192               0x00000100
849e054ec2SFabien DESSENNE #define CR_KEY256               0x00000200
859e054ec2SFabien DESSENNE #define CR_FFLUSH               0x00004000
869e054ec2SFabien DESSENNE #define CR_CRYPEN               0x00008000
879d3b5030SFabien DESSENNE #define CR_PH_INIT              0x00000000
889d3b5030SFabien DESSENNE #define CR_PH_HEADER            0x00010000
899d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD           0x00020000
909d3b5030SFabien DESSENNE #define CR_PH_FINAL             0x00030000
919d3b5030SFabien DESSENNE #define CR_PH_MASK              0x00030000
929d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT          20
939e054ec2SFabien DESSENNE 
949e054ec2SFabien DESSENNE #define SR_BUSY                 0x00000010
959e054ec2SFabien DESSENNE #define SR_OFNE                 0x00000004
969e054ec2SFabien DESSENNE 
979e054ec2SFabien DESSENNE #define IMSCR_IN                BIT(0)
989e054ec2SFabien DESSENNE #define IMSCR_OUT               BIT(1)
999e054ec2SFabien DESSENNE 
1009e054ec2SFabien DESSENNE #define MISR_IN                 BIT(0)
1019e054ec2SFabien DESSENNE #define MISR_OUT                BIT(1)
1029e054ec2SFabien DESSENNE 
1039e054ec2SFabien DESSENNE /* Misc */
1049e054ec2SFabien DESSENNE #define AES_BLOCK_32            (AES_BLOCK_SIZE / sizeof(u32))
1059d3b5030SFabien DESSENNE #define GCM_CTR_INIT            2
1069e054ec2SFabien DESSENNE #define _walked_in              (cryp->in_walk.offset - cryp->in_sg->offset)
1079e054ec2SFabien DESSENNE #define _walked_out             (cryp->out_walk.offset - cryp->out_sg->offset)
1089e054ec2SFabien DESSENNE 
1099d3b5030SFabien DESSENNE struct stm32_cryp_caps {
1109d3b5030SFabien DESSENNE 	bool                    swap_final;
1119d3b5030SFabien DESSENNE 	bool                    padding_wa;
1129d3b5030SFabien DESSENNE };
1139d3b5030SFabien DESSENNE 
1149e054ec2SFabien DESSENNE struct stm32_cryp_ctx {
115dc7bcef5SCorentin LABBE 	struct crypto_engine_ctx enginectx;
1169e054ec2SFabien DESSENNE 	struct stm32_cryp       *cryp;
1179e054ec2SFabien DESSENNE 	int                     keylen;
1189e054ec2SFabien DESSENNE 	u32                     key[AES_KEYSIZE_256 / sizeof(u32)];
1199e054ec2SFabien DESSENNE 	unsigned long           flags;
1209e054ec2SFabien DESSENNE };
1219e054ec2SFabien DESSENNE 
1229e054ec2SFabien DESSENNE struct stm32_cryp_reqctx {
1239e054ec2SFabien DESSENNE 	unsigned long mode;
1249e054ec2SFabien DESSENNE };
1259e054ec2SFabien DESSENNE 
1269e054ec2SFabien DESSENNE struct stm32_cryp {
1279e054ec2SFabien DESSENNE 	struct list_head        list;
1289e054ec2SFabien DESSENNE 	struct device           *dev;
1299e054ec2SFabien DESSENNE 	void __iomem            *regs;
1309e054ec2SFabien DESSENNE 	struct clk              *clk;
1319e054ec2SFabien DESSENNE 	unsigned long           flags;
1329e054ec2SFabien DESSENNE 	u32                     irq_status;
1339d3b5030SFabien DESSENNE 	const struct stm32_cryp_caps *caps;
1349e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx   *ctx;
1359e054ec2SFabien DESSENNE 
1369e054ec2SFabien DESSENNE 	struct crypto_engine    *engine;
1379e054ec2SFabien DESSENNE 
1389d3b5030SFabien DESSENNE 	struct mutex            lock; /* protects req / areq */
1399e054ec2SFabien DESSENNE 	struct ablkcipher_request *req;
1409d3b5030SFabien DESSENNE 	struct aead_request     *areq;
1419e054ec2SFabien DESSENNE 
1429d3b5030SFabien DESSENNE 	size_t                  authsize;
1439e054ec2SFabien DESSENNE 	size_t                  hw_blocksize;
1449e054ec2SFabien DESSENNE 
1459e054ec2SFabien DESSENNE 	size_t                  total_in;
1469e054ec2SFabien DESSENNE 	size_t                  total_in_save;
1479e054ec2SFabien DESSENNE 	size_t                  total_out;
1489e054ec2SFabien DESSENNE 	size_t                  total_out_save;
1499e054ec2SFabien DESSENNE 
1509e054ec2SFabien DESSENNE 	struct scatterlist      *in_sg;
1519e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg;
1529e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg_save;
1539e054ec2SFabien DESSENNE 
1549e054ec2SFabien DESSENNE 	struct scatterlist      in_sgl;
1559e054ec2SFabien DESSENNE 	struct scatterlist      out_sgl;
1569e054ec2SFabien DESSENNE 	bool                    sgs_copied;
1579e054ec2SFabien DESSENNE 
1589e054ec2SFabien DESSENNE 	int                     in_sg_len;
1599e054ec2SFabien DESSENNE 	int                     out_sg_len;
1609e054ec2SFabien DESSENNE 
1619e054ec2SFabien DESSENNE 	struct scatter_walk     in_walk;
1629e054ec2SFabien DESSENNE 	struct scatter_walk     out_walk;
1639e054ec2SFabien DESSENNE 
1649e054ec2SFabien DESSENNE 	u32                     last_ctr[4];
1659d3b5030SFabien DESSENNE 	u32                     gcm_ctr;
1669e054ec2SFabien DESSENNE };
1679e054ec2SFabien DESSENNE 
1689e054ec2SFabien DESSENNE struct stm32_cryp_list {
1699e054ec2SFabien DESSENNE 	struct list_head        dev_list;
1709e054ec2SFabien DESSENNE 	spinlock_t              lock; /* protect dev_list */
1719e054ec2SFabien DESSENNE };
1729e054ec2SFabien DESSENNE 
1739e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = {
1749e054ec2SFabien DESSENNE 	.dev_list = LIST_HEAD_INIT(cryp_list.dev_list),
1759e054ec2SFabien DESSENNE 	.lock     = __SPIN_LOCK_UNLOCKED(cryp_list.lock),
1769e054ec2SFabien DESSENNE };
1779e054ec2SFabien DESSENNE 
1789e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp)
1799e054ec2SFabien DESSENNE {
1809e054ec2SFabien DESSENNE 	return cryp->flags & FLG_AES;
1819e054ec2SFabien DESSENNE }
1829e054ec2SFabien DESSENNE 
1839e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp)
1849e054ec2SFabien DESSENNE {
1859e054ec2SFabien DESSENNE 	return cryp->flags & FLG_DES;
1869e054ec2SFabien DESSENNE }
1879e054ec2SFabien DESSENNE 
1889e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp)
1899e054ec2SFabien DESSENNE {
1909e054ec2SFabien DESSENNE 	return cryp->flags & FLG_TDES;
1919e054ec2SFabien DESSENNE }
1929e054ec2SFabien DESSENNE 
1939e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp)
1949e054ec2SFabien DESSENNE {
1959e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ECB;
1969e054ec2SFabien DESSENNE }
1979e054ec2SFabien DESSENNE 
1989e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp)
1999e054ec2SFabien DESSENNE {
2009e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CBC;
2019e054ec2SFabien DESSENNE }
2029e054ec2SFabien DESSENNE 
2039e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp)
2049e054ec2SFabien DESSENNE {
2059e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CTR;
2069e054ec2SFabien DESSENNE }
2079e054ec2SFabien DESSENNE 
2089d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp)
2099d3b5030SFabien DESSENNE {
2109d3b5030SFabien DESSENNE 	return cryp->flags & FLG_GCM;
2119d3b5030SFabien DESSENNE }
2129d3b5030SFabien DESSENNE 
2139d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp)
2149d3b5030SFabien DESSENNE {
2159d3b5030SFabien DESSENNE 	return cryp->flags & FLG_CCM;
2169d3b5030SFabien DESSENNE }
2179d3b5030SFabien DESSENNE 
2189e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp)
2199e054ec2SFabien DESSENNE {
2209e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ENCRYPT;
2219e054ec2SFabien DESSENNE }
2229e054ec2SFabien DESSENNE 
2239e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp)
2249e054ec2SFabien DESSENNE {
2259e054ec2SFabien DESSENNE 	return !is_encrypt(cryp);
2269e054ec2SFabien DESSENNE }
2279e054ec2SFabien DESSENNE 
2289e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst)
2299e054ec2SFabien DESSENNE {
2309e054ec2SFabien DESSENNE 	return readl_relaxed(cryp->regs + ofst);
2319e054ec2SFabien DESSENNE }
2329e054ec2SFabien DESSENNE 
2339e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val)
2349e054ec2SFabien DESSENNE {
2359e054ec2SFabien DESSENNE 	writel_relaxed(val, cryp->regs + ofst);
2369e054ec2SFabien DESSENNE }
2379e054ec2SFabien DESSENNE 
2389e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
2399e054ec2SFabien DESSENNE {
2409e054ec2SFabien DESSENNE 	u32 status;
2419e054ec2SFabien DESSENNE 
2429e054ec2SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status,
2439e054ec2SFabien DESSENNE 			!(status & SR_BUSY), 10, 100000);
2449e054ec2SFabien DESSENNE }
2459e054ec2SFabien DESSENNE 
2469d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
2479d3b5030SFabien DESSENNE {
2489d3b5030SFabien DESSENNE 	u32 status;
2499d3b5030SFabien DESSENNE 
2509d3b5030SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_CR, status,
2519d3b5030SFabien DESSENNE 			!(status & CR_CRYPEN), 10, 100000);
2529d3b5030SFabien DESSENNE }
2539d3b5030SFabien DESSENNE 
2549d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp)
2559d3b5030SFabien DESSENNE {
2569d3b5030SFabien DESSENNE 	u32 status;
2579d3b5030SFabien DESSENNE 
2589d3b5030SFabien DESSENNE 	return readl_relaxed_poll_timeout(cryp->regs + CRYP_SR, status,
2599d3b5030SFabien DESSENNE 			status & SR_OFNE, 10, 100000);
2609d3b5030SFabien DESSENNE }
2619d3b5030SFabien DESSENNE 
2629d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp);
2639d3b5030SFabien DESSENNE 
2649e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx)
2659e054ec2SFabien DESSENNE {
2669e054ec2SFabien DESSENNE 	struct stm32_cryp *tmp, *cryp = NULL;
2679e054ec2SFabien DESSENNE 
2689e054ec2SFabien DESSENNE 	spin_lock_bh(&cryp_list.lock);
2699e054ec2SFabien DESSENNE 	if (!ctx->cryp) {
2709e054ec2SFabien DESSENNE 		list_for_each_entry(tmp, &cryp_list.dev_list, list) {
2719e054ec2SFabien DESSENNE 			cryp = tmp;
2729e054ec2SFabien DESSENNE 			break;
2739e054ec2SFabien DESSENNE 		}
2749e054ec2SFabien DESSENNE 		ctx->cryp = cryp;
2759e054ec2SFabien DESSENNE 	} else {
2769e054ec2SFabien DESSENNE 		cryp = ctx->cryp;
2779e054ec2SFabien DESSENNE 	}
2789e054ec2SFabien DESSENNE 
2799e054ec2SFabien DESSENNE 	spin_unlock_bh(&cryp_list.lock);
2809e054ec2SFabien DESSENNE 
2819e054ec2SFabien DESSENNE 	return cryp;
2829e054ec2SFabien DESSENNE }
2839e054ec2SFabien DESSENNE 
2849e054ec2SFabien DESSENNE static int stm32_cryp_check_aligned(struct scatterlist *sg, size_t total,
2859e054ec2SFabien DESSENNE 				    size_t align)
2869e054ec2SFabien DESSENNE {
2879e054ec2SFabien DESSENNE 	int len = 0;
2889e054ec2SFabien DESSENNE 
2899e054ec2SFabien DESSENNE 	if (!total)
2909e054ec2SFabien DESSENNE 		return 0;
2919e054ec2SFabien DESSENNE 
2929e054ec2SFabien DESSENNE 	if (!IS_ALIGNED(total, align))
2939e054ec2SFabien DESSENNE 		return -EINVAL;
2949e054ec2SFabien DESSENNE 
2959e054ec2SFabien DESSENNE 	while (sg) {
2969e054ec2SFabien DESSENNE 		if (!IS_ALIGNED(sg->offset, sizeof(u32)))
2979e054ec2SFabien DESSENNE 			return -EINVAL;
2989e054ec2SFabien DESSENNE 
2999e054ec2SFabien DESSENNE 		if (!IS_ALIGNED(sg->length, align))
3009e054ec2SFabien DESSENNE 			return -EINVAL;
3019e054ec2SFabien DESSENNE 
3029e054ec2SFabien DESSENNE 		len += sg->length;
3039e054ec2SFabien DESSENNE 		sg = sg_next(sg);
3049e054ec2SFabien DESSENNE 	}
3059e054ec2SFabien DESSENNE 
3069e054ec2SFabien DESSENNE 	if (len != total)
3079e054ec2SFabien DESSENNE 		return -EINVAL;
3089e054ec2SFabien DESSENNE 
3099e054ec2SFabien DESSENNE 	return 0;
3109e054ec2SFabien DESSENNE }
3119e054ec2SFabien DESSENNE 
3129e054ec2SFabien DESSENNE static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp)
3139e054ec2SFabien DESSENNE {
3149e054ec2SFabien DESSENNE 	int ret;
3159e054ec2SFabien DESSENNE 
3169e054ec2SFabien DESSENNE 	ret = stm32_cryp_check_aligned(cryp->in_sg, cryp->total_in,
3179e054ec2SFabien DESSENNE 				       cryp->hw_blocksize);
3189e054ec2SFabien DESSENNE 	if (ret)
3199e054ec2SFabien DESSENNE 		return ret;
3209e054ec2SFabien DESSENNE 
3219e054ec2SFabien DESSENNE 	ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out,
3229e054ec2SFabien DESSENNE 				       cryp->hw_blocksize);
3239e054ec2SFabien DESSENNE 
3249e054ec2SFabien DESSENNE 	return ret;
3259e054ec2SFabien DESSENNE }
3269e054ec2SFabien DESSENNE 
3279e054ec2SFabien DESSENNE static void sg_copy_buf(void *buf, struct scatterlist *sg,
3289e054ec2SFabien DESSENNE 			unsigned int start, unsigned int nbytes, int out)
3299e054ec2SFabien DESSENNE {
3309e054ec2SFabien DESSENNE 	struct scatter_walk walk;
3319e054ec2SFabien DESSENNE 
3329e054ec2SFabien DESSENNE 	if (!nbytes)
3339e054ec2SFabien DESSENNE 		return;
3349e054ec2SFabien DESSENNE 
3359e054ec2SFabien DESSENNE 	scatterwalk_start(&walk, sg);
3369e054ec2SFabien DESSENNE 	scatterwalk_advance(&walk, start);
3379e054ec2SFabien DESSENNE 	scatterwalk_copychunks(buf, &walk, nbytes, out);
3389e054ec2SFabien DESSENNE 	scatterwalk_done(&walk, out, 0);
3399e054ec2SFabien DESSENNE }
3409e054ec2SFabien DESSENNE 
3419e054ec2SFabien DESSENNE static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp)
3429e054ec2SFabien DESSENNE {
3439e054ec2SFabien DESSENNE 	void *buf_in, *buf_out;
3449e054ec2SFabien DESSENNE 	int pages, total_in, total_out;
3459e054ec2SFabien DESSENNE 
3469e054ec2SFabien DESSENNE 	if (!stm32_cryp_check_io_aligned(cryp)) {
3479e054ec2SFabien DESSENNE 		cryp->sgs_copied = 0;
3489e054ec2SFabien DESSENNE 		return 0;
3499e054ec2SFabien DESSENNE 	}
3509e054ec2SFabien DESSENNE 
3519e054ec2SFabien DESSENNE 	total_in = ALIGN(cryp->total_in, cryp->hw_blocksize);
3529e054ec2SFabien DESSENNE 	pages = total_in ? get_order(total_in) : 1;
3539e054ec2SFabien DESSENNE 	buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
3549e054ec2SFabien DESSENNE 
3559e054ec2SFabien DESSENNE 	total_out = ALIGN(cryp->total_out, cryp->hw_blocksize);
3569e054ec2SFabien DESSENNE 	pages = total_out ? get_order(total_out) : 1;
3579e054ec2SFabien DESSENNE 	buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
3589e054ec2SFabien DESSENNE 
3599e054ec2SFabien DESSENNE 	if (!buf_in || !buf_out) {
3609e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Can't allocate pages when unaligned\n");
3619e054ec2SFabien DESSENNE 		cryp->sgs_copied = 0;
3629e054ec2SFabien DESSENNE 		return -EFAULT;
3639e054ec2SFabien DESSENNE 	}
3649e054ec2SFabien DESSENNE 
3659e054ec2SFabien DESSENNE 	sg_copy_buf(buf_in, cryp->in_sg, 0, cryp->total_in, 0);
3669e054ec2SFabien DESSENNE 
3679e054ec2SFabien DESSENNE 	sg_init_one(&cryp->in_sgl, buf_in, total_in);
3689e054ec2SFabien DESSENNE 	cryp->in_sg = &cryp->in_sgl;
3699e054ec2SFabien DESSENNE 	cryp->in_sg_len = 1;
3709e054ec2SFabien DESSENNE 
3719e054ec2SFabien DESSENNE 	sg_init_one(&cryp->out_sgl, buf_out, total_out);
3729e054ec2SFabien DESSENNE 	cryp->out_sg_save = cryp->out_sg;
3739e054ec2SFabien DESSENNE 	cryp->out_sg = &cryp->out_sgl;
3749e054ec2SFabien DESSENNE 	cryp->out_sg_len = 1;
3759e054ec2SFabien DESSENNE 
3769e054ec2SFabien DESSENNE 	cryp->sgs_copied = 1;
3779e054ec2SFabien DESSENNE 
3789e054ec2SFabien DESSENNE 	return 0;
3799e054ec2SFabien DESSENNE }
3809e054ec2SFabien DESSENNE 
3819e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, u32 *iv)
3829e054ec2SFabien DESSENNE {
3839e054ec2SFabien DESSENNE 	if (!iv)
3849e054ec2SFabien DESSENNE 		return;
3859e054ec2SFabien DESSENNE 
3869e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV0LR, cpu_to_be32(*iv++));
3879e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV0RR, cpu_to_be32(*iv++));
3889e054ec2SFabien DESSENNE 
3899e054ec2SFabien DESSENNE 	if (is_aes(cryp)) {
3909e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_IV1LR, cpu_to_be32(*iv++));
3919e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_IV1RR, cpu_to_be32(*iv++));
3929e054ec2SFabien DESSENNE 	}
3939e054ec2SFabien DESSENNE }
3949e054ec2SFabien DESSENNE 
3959e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c)
3969e054ec2SFabien DESSENNE {
3979e054ec2SFabien DESSENNE 	unsigned int i;
3989e054ec2SFabien DESSENNE 	int r_id;
3999e054ec2SFabien DESSENNE 
4009e054ec2SFabien DESSENNE 	if (is_des(c)) {
4019e054ec2SFabien DESSENNE 		stm32_cryp_write(c, CRYP_K1LR, cpu_to_be32(c->ctx->key[0]));
4029e054ec2SFabien DESSENNE 		stm32_cryp_write(c, CRYP_K1RR, cpu_to_be32(c->ctx->key[1]));
4039e054ec2SFabien DESSENNE 	} else {
4049e054ec2SFabien DESSENNE 		r_id = CRYP_K3RR;
4059e054ec2SFabien DESSENNE 		for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4)
4069e054ec2SFabien DESSENNE 			stm32_cryp_write(c, r_id,
4079e054ec2SFabien DESSENNE 					 cpu_to_be32(c->ctx->key[i - 1]));
4089e054ec2SFabien DESSENNE 	}
4099e054ec2SFabien DESSENNE }
4109e054ec2SFabien DESSENNE 
4119e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp)
4129e054ec2SFabien DESSENNE {
4139e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ecb(cryp))
4149e054ec2SFabien DESSENNE 		return CR_AES_ECB;
4159e054ec2SFabien DESSENNE 
4169e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_cbc(cryp))
4179e054ec2SFabien DESSENNE 		return CR_AES_CBC;
4189e054ec2SFabien DESSENNE 
4199e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
4209e054ec2SFabien DESSENNE 		return CR_AES_CTR;
4219e054ec2SFabien DESSENNE 
4229d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_gcm(cryp))
4239d3b5030SFabien DESSENNE 		return CR_AES_GCM;
4249d3b5030SFabien DESSENNE 
4259d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_ccm(cryp))
4269d3b5030SFabien DESSENNE 		return CR_AES_CCM;
4279d3b5030SFabien DESSENNE 
4289e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_ecb(cryp))
4299e054ec2SFabien DESSENNE 		return CR_DES_ECB;
4309e054ec2SFabien DESSENNE 
4319e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_cbc(cryp))
4329e054ec2SFabien DESSENNE 		return CR_DES_CBC;
4339e054ec2SFabien DESSENNE 
4349e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_ecb(cryp))
4359e054ec2SFabien DESSENNE 		return CR_TDES_ECB;
4369e054ec2SFabien DESSENNE 
4379e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_cbc(cryp))
4389e054ec2SFabien DESSENNE 		return CR_TDES_CBC;
4399e054ec2SFabien DESSENNE 
4409e054ec2SFabien DESSENNE 	dev_err(cryp->dev, "Unknown mode\n");
4419e054ec2SFabien DESSENNE 	return CR_AES_UNKNOWN;
4429e054ec2SFabien DESSENNE }
4439e054ec2SFabien DESSENNE 
4449d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp)
4459d3b5030SFabien DESSENNE {
4469d3b5030SFabien DESSENNE 	return is_encrypt(cryp) ? cryp->areq->cryptlen :
4479d3b5030SFabien DESSENNE 				  cryp->areq->cryptlen - cryp->authsize;
4489d3b5030SFabien DESSENNE }
4499d3b5030SFabien DESSENNE 
4509d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg)
4519d3b5030SFabien DESSENNE {
4529d3b5030SFabien DESSENNE 	int ret;
4539d3b5030SFabien DESSENNE 	u32 iv[4];
4549d3b5030SFabien DESSENNE 
4559d3b5030SFabien DESSENNE 	/* Phase 1 : init */
4569d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, 12);
4579d3b5030SFabien DESSENNE 	iv[3] = cpu_to_be32(GCM_CTR_INIT);
4589d3b5030SFabien DESSENNE 	cryp->gcm_ctr = GCM_CTR_INIT;
4599d3b5030SFabien DESSENNE 	stm32_cryp_hw_write_iv(cryp, iv);
4609d3b5030SFabien DESSENNE 
4619d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN);
4629d3b5030SFabien DESSENNE 
4639d3b5030SFabien DESSENNE 	/* Wait for end of processing */
4649d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
4659d3b5030SFabien DESSENNE 	if (ret)
4669d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (gcm init)\n");
4679d3b5030SFabien DESSENNE 
4689d3b5030SFabien DESSENNE 	return ret;
4699d3b5030SFabien DESSENNE }
4709d3b5030SFabien DESSENNE 
4719d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg)
4729d3b5030SFabien DESSENNE {
4739d3b5030SFabien DESSENNE 	int ret;
4749d3b5030SFabien DESSENNE 	u8 iv[AES_BLOCK_SIZE], b0[AES_BLOCK_SIZE];
4759d3b5030SFabien DESSENNE 	u32 *d;
4769d3b5030SFabien DESSENNE 	unsigned int i, textlen;
4779d3b5030SFabien DESSENNE 
4789d3b5030SFabien DESSENNE 	/* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */
4799d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
4809d3b5030SFabien DESSENNE 	memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
4819d3b5030SFabien DESSENNE 	iv[AES_BLOCK_SIZE - 1] = 1;
4829d3b5030SFabien DESSENNE 	stm32_cryp_hw_write_iv(cryp, (u32 *)iv);
4839d3b5030SFabien DESSENNE 
4849d3b5030SFabien DESSENNE 	/* Build B0 */
4859d3b5030SFabien DESSENNE 	memcpy(b0, iv, AES_BLOCK_SIZE);
4869d3b5030SFabien DESSENNE 
4879d3b5030SFabien DESSENNE 	b0[0] |= (8 * ((cryp->authsize - 2) / 2));
4889d3b5030SFabien DESSENNE 
4899d3b5030SFabien DESSENNE 	if (cryp->areq->assoclen)
4909d3b5030SFabien DESSENNE 		b0[0] |= 0x40;
4919d3b5030SFabien DESSENNE 
4929d3b5030SFabien DESSENNE 	textlen = stm32_cryp_get_input_text_len(cryp);
4939d3b5030SFabien DESSENNE 
4949d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 2] = textlen >> 8;
4959d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF;
4969d3b5030SFabien DESSENNE 
4979d3b5030SFabien DESSENNE 	/* Enable HW */
4989d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg | CR_PH_INIT | CR_CRYPEN);
4999d3b5030SFabien DESSENNE 
5009d3b5030SFabien DESSENNE 	/* Write B0 */
5019d3b5030SFabien DESSENNE 	d = (u32 *)b0;
5029d3b5030SFabien DESSENNE 
5039d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
5049d3b5030SFabien DESSENNE 		if (!cryp->caps->padding_wa)
5059d3b5030SFabien DESSENNE 			*d = cpu_to_be32(*d);
5069d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, *d++);
5079d3b5030SFabien DESSENNE 	}
5089d3b5030SFabien DESSENNE 
5099d3b5030SFabien DESSENNE 	/* Wait for end of processing */
5109d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
5119d3b5030SFabien DESSENNE 	if (ret)
5129d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (ccm init)\n");
5139d3b5030SFabien DESSENNE 
5149d3b5030SFabien DESSENNE 	return ret;
5159d3b5030SFabien DESSENNE }
5169d3b5030SFabien DESSENNE 
5179e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
5189e054ec2SFabien DESSENNE {
5199e054ec2SFabien DESSENNE 	int ret;
5209e054ec2SFabien DESSENNE 	u32 cfg, hw_mode;
5219e054ec2SFabien DESSENNE 
5229e054ec2SFabien DESSENNE 	/* Disable interrupt */
5239e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
5249e054ec2SFabien DESSENNE 
5259e054ec2SFabien DESSENNE 	/* Set key */
5269e054ec2SFabien DESSENNE 	stm32_cryp_hw_write_key(cryp);
5279e054ec2SFabien DESSENNE 
5289e054ec2SFabien DESSENNE 	/* Set configuration */
5299e054ec2SFabien DESSENNE 	cfg = CR_DATA8 | CR_FFLUSH;
5309e054ec2SFabien DESSENNE 
5319e054ec2SFabien DESSENNE 	switch (cryp->ctx->keylen) {
5329e054ec2SFabien DESSENNE 	case AES_KEYSIZE_128:
5339e054ec2SFabien DESSENNE 		cfg |= CR_KEY128;
5349e054ec2SFabien DESSENNE 		break;
5359e054ec2SFabien DESSENNE 
5369e054ec2SFabien DESSENNE 	case AES_KEYSIZE_192:
5379e054ec2SFabien DESSENNE 		cfg |= CR_KEY192;
5389e054ec2SFabien DESSENNE 		break;
5399e054ec2SFabien DESSENNE 
5409e054ec2SFabien DESSENNE 	default:
5419e054ec2SFabien DESSENNE 	case AES_KEYSIZE_256:
5429e054ec2SFabien DESSENNE 		cfg |= CR_KEY256;
5439e054ec2SFabien DESSENNE 		break;
5449e054ec2SFabien DESSENNE 	}
5459e054ec2SFabien DESSENNE 
5469e054ec2SFabien DESSENNE 	hw_mode = stm32_cryp_get_hw_mode(cryp);
5479e054ec2SFabien DESSENNE 	if (hw_mode == CR_AES_UNKNOWN)
5489e054ec2SFabien DESSENNE 		return -EINVAL;
5499e054ec2SFabien DESSENNE 
5509e054ec2SFabien DESSENNE 	/* AES ECB/CBC decrypt: run key preparation first */
5519e054ec2SFabien DESSENNE 	if (is_decrypt(cryp) &&
5529e054ec2SFabien DESSENNE 	    ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
5539e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN);
5549e054ec2SFabien DESSENNE 
5559e054ec2SFabien DESSENNE 		/* Wait for end of processing */
5569e054ec2SFabien DESSENNE 		ret = stm32_cryp_wait_busy(cryp);
5579e054ec2SFabien DESSENNE 		if (ret) {
5589e054ec2SFabien DESSENNE 			dev_err(cryp->dev, "Timeout (key preparation)\n");
5599e054ec2SFabien DESSENNE 			return ret;
5609e054ec2SFabien DESSENNE 		}
5619e054ec2SFabien DESSENNE 	}
5629e054ec2SFabien DESSENNE 
5639e054ec2SFabien DESSENNE 	cfg |= hw_mode;
5649e054ec2SFabien DESSENNE 
5659e054ec2SFabien DESSENNE 	if (is_decrypt(cryp))
5669e054ec2SFabien DESSENNE 		cfg |= CR_DEC_NOT_ENC;
5679e054ec2SFabien DESSENNE 
5689e054ec2SFabien DESSENNE 	/* Apply config and flush (valid when CRYPEN = 0) */
5699e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
5709e054ec2SFabien DESSENNE 
5719e054ec2SFabien DESSENNE 	switch (hw_mode) {
5729d3b5030SFabien DESSENNE 	case CR_AES_GCM:
5739d3b5030SFabien DESSENNE 	case CR_AES_CCM:
5749d3b5030SFabien DESSENNE 		/* Phase 1 : init */
5759d3b5030SFabien DESSENNE 		if (hw_mode == CR_AES_CCM)
5769d3b5030SFabien DESSENNE 			ret = stm32_cryp_ccm_init(cryp, cfg);
5779d3b5030SFabien DESSENNE 		else
5789d3b5030SFabien DESSENNE 			ret = stm32_cryp_gcm_init(cryp, cfg);
5799d3b5030SFabien DESSENNE 
5809d3b5030SFabien DESSENNE 		if (ret)
5819d3b5030SFabien DESSENNE 			return ret;
5829d3b5030SFabien DESSENNE 
5839d3b5030SFabien DESSENNE 		/* Phase 2 : header (authenticated data) */
5849d3b5030SFabien DESSENNE 		if (cryp->areq->assoclen) {
5859d3b5030SFabien DESSENNE 			cfg |= CR_PH_HEADER;
5869d3b5030SFabien DESSENNE 		} else if (stm32_cryp_get_input_text_len(cryp)) {
5879d3b5030SFabien DESSENNE 			cfg |= CR_PH_PAYLOAD;
5889d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_CR, cfg);
5899d3b5030SFabien DESSENNE 		} else {
5909d3b5030SFabien DESSENNE 			cfg |= CR_PH_INIT;
5919d3b5030SFabien DESSENNE 		}
5929d3b5030SFabien DESSENNE 
5939d3b5030SFabien DESSENNE 		break;
5949d3b5030SFabien DESSENNE 
5959e054ec2SFabien DESSENNE 	case CR_DES_CBC:
5969e054ec2SFabien DESSENNE 	case CR_TDES_CBC:
5979e054ec2SFabien DESSENNE 	case CR_AES_CBC:
5989e054ec2SFabien DESSENNE 	case CR_AES_CTR:
5999e054ec2SFabien DESSENNE 		stm32_cryp_hw_write_iv(cryp, (u32 *)cryp->req->info);
6009e054ec2SFabien DESSENNE 		break;
6019e054ec2SFabien DESSENNE 
6029e054ec2SFabien DESSENNE 	default:
6039e054ec2SFabien DESSENNE 		break;
6049e054ec2SFabien DESSENNE 	}
6059e054ec2SFabien DESSENNE 
6069e054ec2SFabien DESSENNE 	/* Enable now */
6079e054ec2SFabien DESSENNE 	cfg |= CR_CRYPEN;
6089e054ec2SFabien DESSENNE 
6099e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
6109e054ec2SFabien DESSENNE 
6119d3b5030SFabien DESSENNE 	cryp->flags &= ~FLG_CCM_PADDED_WA;
6129d3b5030SFabien DESSENNE 
6139e054ec2SFabien DESSENNE 	return 0;
6149e054ec2SFabien DESSENNE }
6159e054ec2SFabien DESSENNE 
6169d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
6179e054ec2SFabien DESSENNE {
6189d3b5030SFabien DESSENNE 	if (!err && (is_gcm(cryp) || is_ccm(cryp)))
6199d3b5030SFabien DESSENNE 		/* Phase 4 : output tag */
6209d3b5030SFabien DESSENNE 		err = stm32_cryp_read_auth_tag(cryp);
6219e054ec2SFabien DESSENNE 
6229e054ec2SFabien DESSENNE 	if (cryp->sgs_copied) {
6239e054ec2SFabien DESSENNE 		void *buf_in, *buf_out;
6249e054ec2SFabien DESSENNE 		int pages, len;
6259e054ec2SFabien DESSENNE 
6269e054ec2SFabien DESSENNE 		buf_in = sg_virt(&cryp->in_sgl);
6279e054ec2SFabien DESSENNE 		buf_out = sg_virt(&cryp->out_sgl);
6289e054ec2SFabien DESSENNE 
6299e054ec2SFabien DESSENNE 		sg_copy_buf(buf_out, cryp->out_sg_save, 0,
6309e054ec2SFabien DESSENNE 			    cryp->total_out_save, 1);
6319e054ec2SFabien DESSENNE 
6329e054ec2SFabien DESSENNE 		len = ALIGN(cryp->total_in_save, cryp->hw_blocksize);
6339e054ec2SFabien DESSENNE 		pages = len ? get_order(len) : 1;
6349e054ec2SFabien DESSENNE 		free_pages((unsigned long)buf_in, pages);
6359e054ec2SFabien DESSENNE 
6369e054ec2SFabien DESSENNE 		len = ALIGN(cryp->total_out_save, cryp->hw_blocksize);
6379e054ec2SFabien DESSENNE 		pages = len ? get_order(len) : 1;
6389e054ec2SFabien DESSENNE 		free_pages((unsigned long)buf_out, pages);
6399e054ec2SFabien DESSENNE 	}
6409e054ec2SFabien DESSENNE 
6419d3b5030SFabien DESSENNE 	if (is_gcm(cryp) || is_ccm(cryp)) {
6429d3b5030SFabien DESSENNE 		crypto_finalize_aead_request(cryp->engine, cryp->areq, err);
6439d3b5030SFabien DESSENNE 		cryp->areq = NULL;
6449d3b5030SFabien DESSENNE 	} else {
6459d3b5030SFabien DESSENNE 		crypto_finalize_ablkcipher_request(cryp->engine, cryp->req,
6469d3b5030SFabien DESSENNE 						   err);
6479e054ec2SFabien DESSENNE 		cryp->req = NULL;
6489d3b5030SFabien DESSENNE 	}
6499e054ec2SFabien DESSENNE 
6509e054ec2SFabien DESSENNE 	memset(cryp->ctx->key, 0, cryp->ctx->keylen);
6519e054ec2SFabien DESSENNE 
6529e054ec2SFabien DESSENNE 	mutex_unlock(&cryp->lock);
6539e054ec2SFabien DESSENNE }
6549e054ec2SFabien DESSENNE 
6559e054ec2SFabien DESSENNE static int stm32_cryp_cpu_start(struct stm32_cryp *cryp)
6569e054ec2SFabien DESSENNE {
6579e054ec2SFabien DESSENNE 	/* Enable interrupt and let the IRQ handler do everything */
6589e054ec2SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, IMSCR_IN | IMSCR_OUT);
6599e054ec2SFabien DESSENNE 
6609e054ec2SFabien DESSENNE 	return 0;
6619e054ec2SFabien DESSENNE }
6629e054ec2SFabien DESSENNE 
663dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq);
664dc7bcef5SCorentin LABBE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
665dc7bcef5SCorentin LABBE 					 void *areq);
666dc7bcef5SCorentin LABBE 
6679e054ec2SFabien DESSENNE static int stm32_cryp_cra_init(struct crypto_tfm *tfm)
6689e054ec2SFabien DESSENNE {
669dc7bcef5SCorentin LABBE 	struct stm32_cryp_ctx *ctx = crypto_tfm_ctx(tfm);
670dc7bcef5SCorentin LABBE 
6719e054ec2SFabien DESSENNE 	tfm->crt_ablkcipher.reqsize = sizeof(struct stm32_cryp_reqctx);
6729e054ec2SFabien DESSENNE 
673dc7bcef5SCorentin LABBE 	ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req;
674dc7bcef5SCorentin LABBE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req;
675dc7bcef5SCorentin LABBE 	ctx->enginectx.op.unprepare_request = NULL;
6769e054ec2SFabien DESSENNE 	return 0;
6779e054ec2SFabien DESSENNE }
6789e054ec2SFabien DESSENNE 
6799d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq);
6809d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine,
6819d3b5030SFabien DESSENNE 				       void *areq);
6829d3b5030SFabien DESSENNE 
6839d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm)
6849d3b5030SFabien DESSENNE {
6859d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
6869d3b5030SFabien DESSENNE 
6879d3b5030SFabien DESSENNE 	tfm->reqsize = sizeof(struct stm32_cryp_reqctx);
6889d3b5030SFabien DESSENNE 
6899d3b5030SFabien DESSENNE 	ctx->enginectx.op.do_one_request = stm32_cryp_aead_one_req;
6909d3b5030SFabien DESSENNE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_aead_req;
6919d3b5030SFabien DESSENNE 	ctx->enginectx.op.unprepare_request = NULL;
6929d3b5030SFabien DESSENNE 
6939d3b5030SFabien DESSENNE 	return 0;
6949d3b5030SFabien DESSENNE }
6959d3b5030SFabien DESSENNE 
6969e054ec2SFabien DESSENNE static int stm32_cryp_crypt(struct ablkcipher_request *req, unsigned long mode)
6979e054ec2SFabien DESSENNE {
6989e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_ablkcipher_ctx(
6999e054ec2SFabien DESSENNE 			crypto_ablkcipher_reqtfm(req));
7009e054ec2SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx = ablkcipher_request_ctx(req);
7019e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
7029e054ec2SFabien DESSENNE 
7039e054ec2SFabien DESSENNE 	if (!cryp)
7049e054ec2SFabien DESSENNE 		return -ENODEV;
7059e054ec2SFabien DESSENNE 
7069e054ec2SFabien DESSENNE 	rctx->mode = mode;
7079e054ec2SFabien DESSENNE 
708dc7bcef5SCorentin LABBE 	return crypto_transfer_ablkcipher_request_to_engine(cryp->engine, req);
7099e054ec2SFabien DESSENNE }
7109e054ec2SFabien DESSENNE 
7119d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode)
7129d3b5030SFabien DESSENNE {
7139d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
7149d3b5030SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx = aead_request_ctx(req);
7159d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
7169d3b5030SFabien DESSENNE 
7179d3b5030SFabien DESSENNE 	if (!cryp)
7189d3b5030SFabien DESSENNE 		return -ENODEV;
7199d3b5030SFabien DESSENNE 
7209d3b5030SFabien DESSENNE 	rctx->mode = mode;
7219d3b5030SFabien DESSENNE 
7229d3b5030SFabien DESSENNE 	return crypto_transfer_aead_request_to_engine(cryp->engine, req);
7239d3b5030SFabien DESSENNE }
7249d3b5030SFabien DESSENNE 
7259e054ec2SFabien DESSENNE static int stm32_cryp_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
7269e054ec2SFabien DESSENNE 			     unsigned int keylen)
7279e054ec2SFabien DESSENNE {
7289e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_ablkcipher_ctx(tfm);
7299e054ec2SFabien DESSENNE 
7309e054ec2SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
7319e054ec2SFabien DESSENNE 	ctx->keylen = keylen;
7329e054ec2SFabien DESSENNE 
7339e054ec2SFabien DESSENNE 	return 0;
7349e054ec2SFabien DESSENNE }
7359e054ec2SFabien DESSENNE 
7369e054ec2SFabien DESSENNE static int stm32_cryp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
7379e054ec2SFabien DESSENNE 				 unsigned int keylen)
7389e054ec2SFabien DESSENNE {
7399e054ec2SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
7409e054ec2SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
7419e054ec2SFabien DESSENNE 		return -EINVAL;
7429e054ec2SFabien DESSENNE 	else
7439e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
7449e054ec2SFabien DESSENNE }
7459e054ec2SFabien DESSENNE 
7469e054ec2SFabien DESSENNE static int stm32_cryp_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
7479e054ec2SFabien DESSENNE 				 unsigned int keylen)
7489e054ec2SFabien DESSENNE {
7499e054ec2SFabien DESSENNE 	if (keylen != DES_KEY_SIZE)
7509e054ec2SFabien DESSENNE 		return -EINVAL;
7519e054ec2SFabien DESSENNE 	else
7529e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
7539e054ec2SFabien DESSENNE }
7549e054ec2SFabien DESSENNE 
7559e054ec2SFabien DESSENNE static int stm32_cryp_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
7569e054ec2SFabien DESSENNE 				  unsigned int keylen)
7579e054ec2SFabien DESSENNE {
7589e054ec2SFabien DESSENNE 	if (keylen != (3 * DES_KEY_SIZE))
7599e054ec2SFabien DESSENNE 		return -EINVAL;
7609e054ec2SFabien DESSENNE 	else
7619e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
7629e054ec2SFabien DESSENNE }
7639e054ec2SFabien DESSENNE 
7649d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
7659d3b5030SFabien DESSENNE 				      unsigned int keylen)
7669d3b5030SFabien DESSENNE {
7679d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
7689d3b5030SFabien DESSENNE 
7699d3b5030SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
7709d3b5030SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
7719d3b5030SFabien DESSENNE 		return -EINVAL;
7729d3b5030SFabien DESSENNE 
7739d3b5030SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
7749d3b5030SFabien DESSENNE 	ctx->keylen = keylen;
7759d3b5030SFabien DESSENNE 
7769d3b5030SFabien DESSENNE 	return 0;
7779d3b5030SFabien DESSENNE }
7789d3b5030SFabien DESSENNE 
7799d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
7809d3b5030SFabien DESSENNE 					  unsigned int authsize)
7819d3b5030SFabien DESSENNE {
7829d3b5030SFabien DESSENNE 	return authsize == AES_BLOCK_SIZE ? 0 : -EINVAL;
7839d3b5030SFabien DESSENNE }
7849d3b5030SFabien DESSENNE 
7859d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
7869d3b5030SFabien DESSENNE 					  unsigned int authsize)
7879d3b5030SFabien DESSENNE {
7889d3b5030SFabien DESSENNE 	switch (authsize) {
7899d3b5030SFabien DESSENNE 	case 4:
7909d3b5030SFabien DESSENNE 	case 6:
7919d3b5030SFabien DESSENNE 	case 8:
7929d3b5030SFabien DESSENNE 	case 10:
7939d3b5030SFabien DESSENNE 	case 12:
7949d3b5030SFabien DESSENNE 	case 14:
7959d3b5030SFabien DESSENNE 	case 16:
7969d3b5030SFabien DESSENNE 		break;
7979d3b5030SFabien DESSENNE 	default:
7989d3b5030SFabien DESSENNE 		return -EINVAL;
7999d3b5030SFabien DESSENNE 	}
8009d3b5030SFabien DESSENNE 
8019d3b5030SFabien DESSENNE 	return 0;
8029d3b5030SFabien DESSENNE }
8039d3b5030SFabien DESSENNE 
8049e054ec2SFabien DESSENNE static int stm32_cryp_aes_ecb_encrypt(struct ablkcipher_request *req)
8059e054ec2SFabien DESSENNE {
8069e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
8079e054ec2SFabien DESSENNE }
8089e054ec2SFabien DESSENNE 
8099e054ec2SFabien DESSENNE static int stm32_cryp_aes_ecb_decrypt(struct ablkcipher_request *req)
8109e054ec2SFabien DESSENNE {
8119e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
8129e054ec2SFabien DESSENNE }
8139e054ec2SFabien DESSENNE 
8149e054ec2SFabien DESSENNE static int stm32_cryp_aes_cbc_encrypt(struct ablkcipher_request *req)
8159e054ec2SFabien DESSENNE {
8169e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
8179e054ec2SFabien DESSENNE }
8189e054ec2SFabien DESSENNE 
8199e054ec2SFabien DESSENNE static int stm32_cryp_aes_cbc_decrypt(struct ablkcipher_request *req)
8209e054ec2SFabien DESSENNE {
8219e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
8229e054ec2SFabien DESSENNE }
8239e054ec2SFabien DESSENNE 
8249e054ec2SFabien DESSENNE static int stm32_cryp_aes_ctr_encrypt(struct ablkcipher_request *req)
8259e054ec2SFabien DESSENNE {
8269e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
8279e054ec2SFabien DESSENNE }
8289e054ec2SFabien DESSENNE 
8299e054ec2SFabien DESSENNE static int stm32_cryp_aes_ctr_decrypt(struct ablkcipher_request *req)
8309e054ec2SFabien DESSENNE {
8319e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
8329e054ec2SFabien DESSENNE }
8339e054ec2SFabien DESSENNE 
8349d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req)
8359d3b5030SFabien DESSENNE {
8369d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT);
8379d3b5030SFabien DESSENNE }
8389d3b5030SFabien DESSENNE 
8399d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
8409d3b5030SFabien DESSENNE {
8419d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
8429d3b5030SFabien DESSENNE }
8439d3b5030SFabien DESSENNE 
8449d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req)
8459d3b5030SFabien DESSENNE {
8469d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT);
8479d3b5030SFabien DESSENNE }
8489d3b5030SFabien DESSENNE 
8499d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req)
8509d3b5030SFabien DESSENNE {
8519d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
8529d3b5030SFabien DESSENNE }
8539d3b5030SFabien DESSENNE 
8549e054ec2SFabien DESSENNE static int stm32_cryp_des_ecb_encrypt(struct ablkcipher_request *req)
8559e054ec2SFabien DESSENNE {
8569e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
8579e054ec2SFabien DESSENNE }
8589e054ec2SFabien DESSENNE 
8599e054ec2SFabien DESSENNE static int stm32_cryp_des_ecb_decrypt(struct ablkcipher_request *req)
8609e054ec2SFabien DESSENNE {
8619e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
8629e054ec2SFabien DESSENNE }
8639e054ec2SFabien DESSENNE 
8649e054ec2SFabien DESSENNE static int stm32_cryp_des_cbc_encrypt(struct ablkcipher_request *req)
8659e054ec2SFabien DESSENNE {
8669e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
8679e054ec2SFabien DESSENNE }
8689e054ec2SFabien DESSENNE 
8699e054ec2SFabien DESSENNE static int stm32_cryp_des_cbc_decrypt(struct ablkcipher_request *req)
8709e054ec2SFabien DESSENNE {
8719e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
8729e054ec2SFabien DESSENNE }
8739e054ec2SFabien DESSENNE 
8749e054ec2SFabien DESSENNE static int stm32_cryp_tdes_ecb_encrypt(struct ablkcipher_request *req)
8759e054ec2SFabien DESSENNE {
8769e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
8779e054ec2SFabien DESSENNE }
8789e054ec2SFabien DESSENNE 
8799e054ec2SFabien DESSENNE static int stm32_cryp_tdes_ecb_decrypt(struct ablkcipher_request *req)
8809e054ec2SFabien DESSENNE {
8819e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
8829e054ec2SFabien DESSENNE }
8839e054ec2SFabien DESSENNE 
8849e054ec2SFabien DESSENNE static int stm32_cryp_tdes_cbc_encrypt(struct ablkcipher_request *req)
8859e054ec2SFabien DESSENNE {
8869e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
8879e054ec2SFabien DESSENNE }
8889e054ec2SFabien DESSENNE 
8899e054ec2SFabien DESSENNE static int stm32_cryp_tdes_cbc_decrypt(struct ablkcipher_request *req)
8909e054ec2SFabien DESSENNE {
8919e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
8929e054ec2SFabien DESSENNE }
8939e054ec2SFabien DESSENNE 
8949d3b5030SFabien DESSENNE static int stm32_cryp_prepare_req(struct ablkcipher_request *req,
8959d3b5030SFabien DESSENNE 				  struct aead_request *areq)
8969e054ec2SFabien DESSENNE {
8979e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx;
8989e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
8999e054ec2SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx;
9009e054ec2SFabien DESSENNE 	int ret;
9019e054ec2SFabien DESSENNE 
9029d3b5030SFabien DESSENNE 	if (!req && !areq)
9039e054ec2SFabien DESSENNE 		return -EINVAL;
9049e054ec2SFabien DESSENNE 
9059d3b5030SFabien DESSENNE 	ctx = req ? crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)) :
9069d3b5030SFabien DESSENNE 		    crypto_aead_ctx(crypto_aead_reqtfm(areq));
9079e054ec2SFabien DESSENNE 
9089e054ec2SFabien DESSENNE 	cryp = ctx->cryp;
9099e054ec2SFabien DESSENNE 
9109e054ec2SFabien DESSENNE 	if (!cryp)
9119e054ec2SFabien DESSENNE 		return -ENODEV;
9129e054ec2SFabien DESSENNE 
9139e054ec2SFabien DESSENNE 	mutex_lock(&cryp->lock);
9149e054ec2SFabien DESSENNE 
9159d3b5030SFabien DESSENNE 	rctx = req ? ablkcipher_request_ctx(req) : aead_request_ctx(areq);
9169e054ec2SFabien DESSENNE 	rctx->mode &= FLG_MODE_MASK;
9179e054ec2SFabien DESSENNE 
9189e054ec2SFabien DESSENNE 	ctx->cryp = cryp;
9199e054ec2SFabien DESSENNE 
9209e054ec2SFabien DESSENNE 	cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode;
9219e054ec2SFabien DESSENNE 	cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE;
9229e054ec2SFabien DESSENNE 	cryp->ctx = ctx;
9239e054ec2SFabien DESSENNE 
9249d3b5030SFabien DESSENNE 	if (req) {
9259e054ec2SFabien DESSENNE 		cryp->req = req;
9269e054ec2SFabien DESSENNE 		cryp->total_in = req->nbytes;
9279e054ec2SFabien DESSENNE 		cryp->total_out = cryp->total_in;
9289d3b5030SFabien DESSENNE 	} else {
9299d3b5030SFabien DESSENNE 		/*
9309d3b5030SFabien DESSENNE 		 * Length of input and output data:
9319d3b5030SFabien DESSENNE 		 * Encryption case:
9329d3b5030SFabien DESSENNE 		 *  INPUT  =   AssocData  ||   PlainText
9339d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->
9349d3b5030SFabien DESSENNE 		 *          <------- total_in ----------->
9359d3b5030SFabien DESSENNE 		 *
9369d3b5030SFabien DESSENNE 		 *  OUTPUT =   AssocData  ||  CipherText  ||   AuthTag
9379d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->  <- authsize ->
9389d3b5030SFabien DESSENNE 		 *          <---------------- total_out ----------------->
9399d3b5030SFabien DESSENNE 		 *
9409d3b5030SFabien DESSENNE 		 * Decryption case:
9419d3b5030SFabien DESSENNE 		 *  INPUT  =   AssocData  ||  CipherText  ||  AuthTag
9429d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <--------- cryptlen --------->
9439d3b5030SFabien DESSENNE 		 *                                          <- authsize ->
9449d3b5030SFabien DESSENNE 		 *          <---------------- total_in ------------------>
9459d3b5030SFabien DESSENNE 		 *
9469d3b5030SFabien DESSENNE 		 *  OUTPUT =   AssocData  ||   PlainText
9479d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- crypten - authsize ->
9489d3b5030SFabien DESSENNE 		 *          <---------- total_out ----------------->
9499d3b5030SFabien DESSENNE 		 */
9509d3b5030SFabien DESSENNE 		cryp->areq = areq;
9519d3b5030SFabien DESSENNE 		cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
9529d3b5030SFabien DESSENNE 		cryp->total_in = areq->assoclen + areq->cryptlen;
9539d3b5030SFabien DESSENNE 		if (is_encrypt(cryp))
9549d3b5030SFabien DESSENNE 			/* Append auth tag to output */
9559d3b5030SFabien DESSENNE 			cryp->total_out = cryp->total_in + cryp->authsize;
9569d3b5030SFabien DESSENNE 		else
9579d3b5030SFabien DESSENNE 			/* No auth tag in output */
9589d3b5030SFabien DESSENNE 			cryp->total_out = cryp->total_in - cryp->authsize;
9599d3b5030SFabien DESSENNE 	}
9609e054ec2SFabien DESSENNE 
9619e054ec2SFabien DESSENNE 	cryp->total_in_save = cryp->total_in;
9629e054ec2SFabien DESSENNE 	cryp->total_out_save = cryp->total_out;
9639e054ec2SFabien DESSENNE 
9649d3b5030SFabien DESSENNE 	cryp->in_sg = req ? req->src : areq->src;
9659d3b5030SFabien DESSENNE 	cryp->out_sg = req ? req->dst : areq->dst;
9669e054ec2SFabien DESSENNE 	cryp->out_sg_save = cryp->out_sg;
9679e054ec2SFabien DESSENNE 
9689e054ec2SFabien DESSENNE 	cryp->in_sg_len = sg_nents_for_len(cryp->in_sg, cryp->total_in);
9699e054ec2SFabien DESSENNE 	if (cryp->in_sg_len < 0) {
9709e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Cannot get in_sg_len\n");
9719e054ec2SFabien DESSENNE 		ret = cryp->in_sg_len;
9729e054ec2SFabien DESSENNE 		goto out;
9739e054ec2SFabien DESSENNE 	}
9749e054ec2SFabien DESSENNE 
9759e054ec2SFabien DESSENNE 	cryp->out_sg_len = sg_nents_for_len(cryp->out_sg, cryp->total_out);
9769e054ec2SFabien DESSENNE 	if (cryp->out_sg_len < 0) {
9779e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Cannot get out_sg_len\n");
9789e054ec2SFabien DESSENNE 		ret = cryp->out_sg_len;
9799e054ec2SFabien DESSENNE 		goto out;
9809e054ec2SFabien DESSENNE 	}
9819e054ec2SFabien DESSENNE 
9829e054ec2SFabien DESSENNE 	ret = stm32_cryp_copy_sgs(cryp);
9839e054ec2SFabien DESSENNE 	if (ret)
9849e054ec2SFabien DESSENNE 		goto out;
9859e054ec2SFabien DESSENNE 
9869e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->in_walk, cryp->in_sg);
9879e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->out_walk, cryp->out_sg);
9889e054ec2SFabien DESSENNE 
9899d3b5030SFabien DESSENNE 	if (is_gcm(cryp) || is_ccm(cryp)) {
9909d3b5030SFabien DESSENNE 		/* In output, jump after assoc data */
9919d3b5030SFabien DESSENNE 		scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen);
9929d3b5030SFabien DESSENNE 		cryp->total_out -= cryp->areq->assoclen;
9939d3b5030SFabien DESSENNE 	}
9949d3b5030SFabien DESSENNE 
9959e054ec2SFabien DESSENNE 	ret = stm32_cryp_hw_init(cryp);
9969e054ec2SFabien DESSENNE out:
9979e054ec2SFabien DESSENNE 	if (ret)
9989e054ec2SFabien DESSENNE 		mutex_unlock(&cryp->lock);
9999e054ec2SFabien DESSENNE 
10009e054ec2SFabien DESSENNE 	return ret;
10019e054ec2SFabien DESSENNE }
10029e054ec2SFabien DESSENNE 
10039e054ec2SFabien DESSENNE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
1004dc7bcef5SCorentin LABBE 					 void *areq)
10059e054ec2SFabien DESSENNE {
1006dc7bcef5SCorentin LABBE 	struct ablkcipher_request *req = container_of(areq,
1007dc7bcef5SCorentin LABBE 						      struct ablkcipher_request,
1008dc7bcef5SCorentin LABBE 						      base);
1009dc7bcef5SCorentin LABBE 
10109d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(req, NULL);
10119e054ec2SFabien DESSENNE }
10129e054ec2SFabien DESSENNE 
1013dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq)
10149e054ec2SFabien DESSENNE {
1015dc7bcef5SCorentin LABBE 	struct ablkcipher_request *req = container_of(areq,
1016dc7bcef5SCorentin LABBE 						      struct ablkcipher_request,
1017dc7bcef5SCorentin LABBE 						      base);
10189e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_ablkcipher_ctx(
10199e054ec2SFabien DESSENNE 			crypto_ablkcipher_reqtfm(req));
10209e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
10219e054ec2SFabien DESSENNE 
10229e054ec2SFabien DESSENNE 	if (!cryp)
10239e054ec2SFabien DESSENNE 		return -ENODEV;
10249e054ec2SFabien DESSENNE 
10259e054ec2SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
10269e054ec2SFabien DESSENNE }
10279e054ec2SFabien DESSENNE 
10289d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq)
10299d3b5030SFabien DESSENNE {
10309d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
10319d3b5030SFabien DESSENNE 						base);
10329d3b5030SFabien DESSENNE 
10339d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(NULL, req);
10349d3b5030SFabien DESSENNE }
10359d3b5030SFabien DESSENNE 
10369d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq)
10379d3b5030SFabien DESSENNE {
10389d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
10399d3b5030SFabien DESSENNE 						base);
10409d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
10419d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
10429d3b5030SFabien DESSENNE 
10439d3b5030SFabien DESSENNE 	if (!cryp)
10449d3b5030SFabien DESSENNE 		return -ENODEV;
10459d3b5030SFabien DESSENNE 
10469d3b5030SFabien DESSENNE 	if (unlikely(!cryp->areq->assoclen &&
10479d3b5030SFabien DESSENNE 		     !stm32_cryp_get_input_text_len(cryp))) {
10489d3b5030SFabien DESSENNE 		/* No input data to process: get tag and finish */
10499d3b5030SFabien DESSENNE 		stm32_cryp_finish_req(cryp, 0);
10509d3b5030SFabien DESSENNE 		return 0;
10519d3b5030SFabien DESSENNE 	}
10529d3b5030SFabien DESSENNE 
10539d3b5030SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
10549d3b5030SFabien DESSENNE }
10559d3b5030SFabien DESSENNE 
10569e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_out(struct stm32_cryp *cryp, u32 *dst,
10579e054ec2SFabien DESSENNE 				unsigned int n)
10589e054ec2SFabien DESSENNE {
10599e054ec2SFabien DESSENNE 	scatterwalk_advance(&cryp->out_walk, n);
10609e054ec2SFabien DESSENNE 
10619e054ec2SFabien DESSENNE 	if (unlikely(cryp->out_sg->length == _walked_out)) {
10629e054ec2SFabien DESSENNE 		cryp->out_sg = sg_next(cryp->out_sg);
10639e054ec2SFabien DESSENNE 		if (cryp->out_sg) {
10649e054ec2SFabien DESSENNE 			scatterwalk_start(&cryp->out_walk, cryp->out_sg);
10659e054ec2SFabien DESSENNE 			return (sg_virt(cryp->out_sg) + _walked_out);
10669e054ec2SFabien DESSENNE 		}
10679e054ec2SFabien DESSENNE 	}
10689e054ec2SFabien DESSENNE 
10699e054ec2SFabien DESSENNE 	return (u32 *)((u8 *)dst + n);
10709e054ec2SFabien DESSENNE }
10719e054ec2SFabien DESSENNE 
10729e054ec2SFabien DESSENNE static u32 *stm32_cryp_next_in(struct stm32_cryp *cryp, u32 *src,
10739e054ec2SFabien DESSENNE 			       unsigned int n)
10749e054ec2SFabien DESSENNE {
10759e054ec2SFabien DESSENNE 	scatterwalk_advance(&cryp->in_walk, n);
10769e054ec2SFabien DESSENNE 
10779e054ec2SFabien DESSENNE 	if (unlikely(cryp->in_sg->length == _walked_in)) {
10789e054ec2SFabien DESSENNE 		cryp->in_sg = sg_next(cryp->in_sg);
10799e054ec2SFabien DESSENNE 		if (cryp->in_sg) {
10809e054ec2SFabien DESSENNE 			scatterwalk_start(&cryp->in_walk, cryp->in_sg);
10819e054ec2SFabien DESSENNE 			return (sg_virt(cryp->in_sg) + _walked_in);
10829e054ec2SFabien DESSENNE 		}
10839e054ec2SFabien DESSENNE 	}
10849e054ec2SFabien DESSENNE 
10859e054ec2SFabien DESSENNE 	return (u32 *)((u8 *)src + n);
10869e054ec2SFabien DESSENNE }
10879e054ec2SFabien DESSENNE 
10889d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
10899d3b5030SFabien DESSENNE {
10909d3b5030SFabien DESSENNE 	u32 cfg, size_bit, *dst, d32;
10919d3b5030SFabien DESSENNE 	u8 *d8;
10929d3b5030SFabien DESSENNE 	unsigned int i, j;
10939d3b5030SFabien DESSENNE 	int ret = 0;
10949d3b5030SFabien DESSENNE 
10959d3b5030SFabien DESSENNE 	/* Update Config */
10969d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
10979d3b5030SFabien DESSENNE 
10989d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
10999d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
11009d3b5030SFabien DESSENNE 	cfg &= ~CR_DEC_NOT_ENC;
11019d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
11029d3b5030SFabien DESSENNE 
11039d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
11049d3b5030SFabien DESSENNE 
11059d3b5030SFabien DESSENNE 	if (is_gcm(cryp)) {
11069d3b5030SFabien DESSENNE 		/* GCM: write aad and payload size (in bits) */
11079d3b5030SFabien DESSENNE 		size_bit = cryp->areq->assoclen * 8;
11089d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
11099d3b5030SFabien DESSENNE 			size_bit = cpu_to_be32(size_bit);
11109d3b5030SFabien DESSENNE 
11119d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, 0);
11129d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, size_bit);
11139d3b5030SFabien DESSENNE 
11149d3b5030SFabien DESSENNE 		size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
11159d3b5030SFabien DESSENNE 				cryp->areq->cryptlen - AES_BLOCK_SIZE;
11169d3b5030SFabien DESSENNE 		size_bit *= 8;
11179d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
11189d3b5030SFabien DESSENNE 			size_bit = cpu_to_be32(size_bit);
11199d3b5030SFabien DESSENNE 
11209d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, 0);
11219d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, size_bit);
11229d3b5030SFabien DESSENNE 	} else {
11239d3b5030SFabien DESSENNE 		/* CCM: write CTR0 */
11249d3b5030SFabien DESSENNE 		u8 iv[AES_BLOCK_SIZE];
11259d3b5030SFabien DESSENNE 		u32 *iv32 = (u32 *)iv;
11269d3b5030SFabien DESSENNE 
11279d3b5030SFabien DESSENNE 		memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
11289d3b5030SFabien DESSENNE 		memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
11299d3b5030SFabien DESSENNE 
11309d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
11319d3b5030SFabien DESSENNE 			if (!cryp->caps->padding_wa)
11329d3b5030SFabien DESSENNE 				*iv32 = cpu_to_be32(*iv32);
11339d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *iv32++);
11349d3b5030SFabien DESSENNE 		}
11359d3b5030SFabien DESSENNE 	}
11369d3b5030SFabien DESSENNE 
11379d3b5030SFabien DESSENNE 	/* Wait for output data */
11389d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_output(cryp);
11399d3b5030SFabien DESSENNE 	if (ret) {
11409d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (read tag)\n");
11419d3b5030SFabien DESSENNE 		return ret;
11429d3b5030SFabien DESSENNE 	}
11439d3b5030SFabien DESSENNE 
11449d3b5030SFabien DESSENNE 	if (is_encrypt(cryp)) {
11459d3b5030SFabien DESSENNE 		/* Get and write tag */
11469d3b5030SFabien DESSENNE 		dst = sg_virt(cryp->out_sg) + _walked_out;
11479d3b5030SFabien DESSENNE 
11489d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
11499d3b5030SFabien DESSENNE 			if (cryp->total_out >= sizeof(u32)) {
11509d3b5030SFabien DESSENNE 				/* Read a full u32 */
11519d3b5030SFabien DESSENNE 				*dst = stm32_cryp_read(cryp, CRYP_DOUT);
11529d3b5030SFabien DESSENNE 
11539d3b5030SFabien DESSENNE 				dst = stm32_cryp_next_out(cryp, dst,
11549d3b5030SFabien DESSENNE 							  sizeof(u32));
11559d3b5030SFabien DESSENNE 				cryp->total_out -= sizeof(u32);
11569d3b5030SFabien DESSENNE 			} else if (!cryp->total_out) {
11579d3b5030SFabien DESSENNE 				/* Empty fifo out (data from input padding) */
11589d3b5030SFabien DESSENNE 				stm32_cryp_read(cryp, CRYP_DOUT);
11599d3b5030SFabien DESSENNE 			} else {
11609d3b5030SFabien DESSENNE 				/* Read less than an u32 */
11619d3b5030SFabien DESSENNE 				d32 = stm32_cryp_read(cryp, CRYP_DOUT);
11629d3b5030SFabien DESSENNE 				d8 = (u8 *)&d32;
11639d3b5030SFabien DESSENNE 
11649d3b5030SFabien DESSENNE 				for (j = 0; j < cryp->total_out; j++) {
11659d3b5030SFabien DESSENNE 					*((u8 *)dst) = *(d8++);
11669d3b5030SFabien DESSENNE 					dst = stm32_cryp_next_out(cryp, dst, 1);
11679d3b5030SFabien DESSENNE 				}
11689d3b5030SFabien DESSENNE 				cryp->total_out = 0;
11699d3b5030SFabien DESSENNE 			}
11709d3b5030SFabien DESSENNE 		}
11719d3b5030SFabien DESSENNE 	} else {
11729d3b5030SFabien DESSENNE 		/* Get and check tag */
11739d3b5030SFabien DESSENNE 		u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
11749d3b5030SFabien DESSENNE 
11759d3b5030SFabien DESSENNE 		scatterwalk_map_and_copy(in_tag, cryp->in_sg,
11769d3b5030SFabien DESSENNE 					 cryp->total_in_save - cryp->authsize,
11779d3b5030SFabien DESSENNE 					 cryp->authsize, 0);
11789d3b5030SFabien DESSENNE 
11799d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++)
11809d3b5030SFabien DESSENNE 			out_tag[i] = stm32_cryp_read(cryp, CRYP_DOUT);
11819d3b5030SFabien DESSENNE 
11829d3b5030SFabien DESSENNE 		if (crypto_memneq(in_tag, out_tag, cryp->authsize))
11839d3b5030SFabien DESSENNE 			ret = -EBADMSG;
11849d3b5030SFabien DESSENNE 	}
11859d3b5030SFabien DESSENNE 
11869d3b5030SFabien DESSENNE 	/* Disable cryp */
11879d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
11889d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
11899d3b5030SFabien DESSENNE 
11909d3b5030SFabien DESSENNE 	return ret;
11919d3b5030SFabien DESSENNE }
11929d3b5030SFabien DESSENNE 
11939e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp)
11949e054ec2SFabien DESSENNE {
11959e054ec2SFabien DESSENNE 	u32 cr;
11969e054ec2SFabien DESSENNE 
11979e054ec2SFabien DESSENNE 	if (unlikely(cryp->last_ctr[3] == 0xFFFFFFFF)) {
11989e054ec2SFabien DESSENNE 		cryp->last_ctr[3] = 0;
11999e054ec2SFabien DESSENNE 		cryp->last_ctr[2]++;
12009e054ec2SFabien DESSENNE 		if (!cryp->last_ctr[2]) {
12019e054ec2SFabien DESSENNE 			cryp->last_ctr[1]++;
12029e054ec2SFabien DESSENNE 			if (!cryp->last_ctr[1])
12039e054ec2SFabien DESSENNE 				cryp->last_ctr[0]++;
12049e054ec2SFabien DESSENNE 		}
12059e054ec2SFabien DESSENNE 
12069e054ec2SFabien DESSENNE 		cr = stm32_cryp_read(cryp, CRYP_CR);
12079e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cr & ~CR_CRYPEN);
12089e054ec2SFabien DESSENNE 
12099e054ec2SFabien DESSENNE 		stm32_cryp_hw_write_iv(cryp, (u32 *)cryp->last_ctr);
12109e054ec2SFabien DESSENNE 
12119e054ec2SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_CR, cr);
12129e054ec2SFabien DESSENNE 	}
12139e054ec2SFabien DESSENNE 
12149e054ec2SFabien DESSENNE 	cryp->last_ctr[0] = stm32_cryp_read(cryp, CRYP_IV0LR);
12159e054ec2SFabien DESSENNE 	cryp->last_ctr[1] = stm32_cryp_read(cryp, CRYP_IV0RR);
12169e054ec2SFabien DESSENNE 	cryp->last_ctr[2] = stm32_cryp_read(cryp, CRYP_IV1LR);
12179e054ec2SFabien DESSENNE 	cryp->last_ctr[3] = stm32_cryp_read(cryp, CRYP_IV1RR);
12189e054ec2SFabien DESSENNE }
12199e054ec2SFabien DESSENNE 
12209e054ec2SFabien DESSENNE static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
12219e054ec2SFabien DESSENNE {
12229e054ec2SFabien DESSENNE 	unsigned int i, j;
12239e054ec2SFabien DESSENNE 	u32 d32, *dst;
12249e054ec2SFabien DESSENNE 	u8 *d8;
12259d3b5030SFabien DESSENNE 	size_t tag_size;
12269d3b5030SFabien DESSENNE 
12279d3b5030SFabien DESSENNE 	/* Do no read tag now (if any) */
12289d3b5030SFabien DESSENNE 	if (is_encrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp)))
12299d3b5030SFabien DESSENNE 		tag_size = cryp->authsize;
12309d3b5030SFabien DESSENNE 	else
12319d3b5030SFabien DESSENNE 		tag_size = 0;
12329e054ec2SFabien DESSENNE 
12339e054ec2SFabien DESSENNE 	dst = sg_virt(cryp->out_sg) + _walked_out;
12349e054ec2SFabien DESSENNE 
12359e054ec2SFabien DESSENNE 	for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
12369d3b5030SFabien DESSENNE 		if (likely(cryp->total_out - tag_size >= sizeof(u32))) {
12379e054ec2SFabien DESSENNE 			/* Read a full u32 */
12389e054ec2SFabien DESSENNE 			*dst = stm32_cryp_read(cryp, CRYP_DOUT);
12399e054ec2SFabien DESSENNE 
12409e054ec2SFabien DESSENNE 			dst = stm32_cryp_next_out(cryp, dst, sizeof(u32));
12419e054ec2SFabien DESSENNE 			cryp->total_out -= sizeof(u32);
12429d3b5030SFabien DESSENNE 		} else if (cryp->total_out == tag_size) {
12439e054ec2SFabien DESSENNE 			/* Empty fifo out (data from input padding) */
12449e054ec2SFabien DESSENNE 			d32 = stm32_cryp_read(cryp, CRYP_DOUT);
12459e054ec2SFabien DESSENNE 		} else {
12469e054ec2SFabien DESSENNE 			/* Read less than an u32 */
12479e054ec2SFabien DESSENNE 			d32 = stm32_cryp_read(cryp, CRYP_DOUT);
12489e054ec2SFabien DESSENNE 			d8 = (u8 *)&d32;
12499e054ec2SFabien DESSENNE 
12509d3b5030SFabien DESSENNE 			for (j = 0; j < cryp->total_out - tag_size; j++) {
12519e054ec2SFabien DESSENNE 				*((u8 *)dst) = *(d8++);
12529e054ec2SFabien DESSENNE 				dst = stm32_cryp_next_out(cryp, dst, 1);
12539e054ec2SFabien DESSENNE 			}
12549d3b5030SFabien DESSENNE 			cryp->total_out = tag_size;
12559e054ec2SFabien DESSENNE 		}
12569e054ec2SFabien DESSENNE 	}
12579e054ec2SFabien DESSENNE 
12589d3b5030SFabien DESSENNE 	return !(cryp->total_out - tag_size) || !cryp->total_in;
12599e054ec2SFabien DESSENNE }
12609e054ec2SFabien DESSENNE 
12619e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
12629e054ec2SFabien DESSENNE {
12639e054ec2SFabien DESSENNE 	unsigned int i, j;
12649e054ec2SFabien DESSENNE 	u32 *src;
12659e054ec2SFabien DESSENNE 	u8 d8[4];
12669d3b5030SFabien DESSENNE 	size_t tag_size;
12679d3b5030SFabien DESSENNE 
12689d3b5030SFabien DESSENNE 	/* Do no write tag (if any) */
12699d3b5030SFabien DESSENNE 	if (is_decrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp)))
12709d3b5030SFabien DESSENNE 		tag_size = cryp->authsize;
12719d3b5030SFabien DESSENNE 	else
12729d3b5030SFabien DESSENNE 		tag_size = 0;
12739e054ec2SFabien DESSENNE 
12749e054ec2SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
12759e054ec2SFabien DESSENNE 
12769e054ec2SFabien DESSENNE 	for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
12779d3b5030SFabien DESSENNE 		if (likely(cryp->total_in - tag_size >= sizeof(u32))) {
12789e054ec2SFabien DESSENNE 			/* Write a full u32 */
12799e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *src);
12809e054ec2SFabien DESSENNE 
12819e054ec2SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, sizeof(u32));
12829e054ec2SFabien DESSENNE 			cryp->total_in -= sizeof(u32);
12839d3b5030SFabien DESSENNE 		} else if (cryp->total_in == tag_size) {
12849e054ec2SFabien DESSENNE 			/* Write padding data */
12859e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, 0);
12869e054ec2SFabien DESSENNE 		} else {
12879e054ec2SFabien DESSENNE 			/* Write less than an u32 */
12889e054ec2SFabien DESSENNE 			memset(d8, 0, sizeof(u32));
12899d3b5030SFabien DESSENNE 			for (j = 0; j < cryp->total_in - tag_size; j++) {
12909e054ec2SFabien DESSENNE 				d8[j] = *((u8 *)src);
12919e054ec2SFabien DESSENNE 				src = stm32_cryp_next_in(cryp, src, 1);
12929e054ec2SFabien DESSENNE 			}
12939e054ec2SFabien DESSENNE 
12949e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
12959d3b5030SFabien DESSENNE 			cryp->total_in = tag_size;
12969e054ec2SFabien DESSENNE 		}
12979e054ec2SFabien DESSENNE 	}
12989e054ec2SFabien DESSENNE }
12999e054ec2SFabien DESSENNE 
13009d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
13019d3b5030SFabien DESSENNE {
13029d3b5030SFabien DESSENNE 	int err;
13039d3b5030SFabien DESSENNE 	u32 cfg, tmp[AES_BLOCK_32];
13049d3b5030SFabien DESSENNE 	size_t total_in_ori = cryp->total_in;
13059d3b5030SFabien DESSENNE 	struct scatterlist *out_sg_ori = cryp->out_sg;
13069d3b5030SFabien DESSENNE 	unsigned int i;
13079d3b5030SFabien DESSENNE 
13089d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
13099d3b5030SFabien DESSENNE 
13109d3b5030SFabien DESSENNE 	/* a) disable ip */
13119d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
13129d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
13139d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
13149d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13159d3b5030SFabien DESSENNE 
13169d3b5030SFabien DESSENNE 	/* b) Update IV1R */
13179d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV1RR, cryp->gcm_ctr - 2);
13189d3b5030SFabien DESSENNE 
13199d3b5030SFabien DESSENNE 	/* c) change mode to CTR */
13209d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
13219d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
13229d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13239d3b5030SFabien DESSENNE 
13249d3b5030SFabien DESSENNE 	/* a) enable IP */
13259d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
13269d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13279d3b5030SFabien DESSENNE 
13289d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
13299d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
13309d3b5030SFabien DESSENNE 	cryp->total_in = total_in_ori;
13319d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
13329d3b5030SFabien DESSENNE 	if (err) {
13339d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (write gcm header)\n");
13349d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
13359d3b5030SFabien DESSENNE 	}
13369d3b5030SFabien DESSENNE 
13379d3b5030SFabien DESSENNE 	/* c) get and store encrypted data */
13389d3b5030SFabien DESSENNE 	stm32_cryp_irq_read_data(cryp);
13399d3b5030SFabien DESSENNE 	scatterwalk_map_and_copy(tmp, out_sg_ori,
13409d3b5030SFabien DESSENNE 				 cryp->total_in_save - total_in_ori,
13419d3b5030SFabien DESSENNE 				 total_in_ori, 0);
13429d3b5030SFabien DESSENNE 
13439d3b5030SFabien DESSENNE 	/* d) change mode back to AES GCM */
13449d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
13459d3b5030SFabien DESSENNE 	cfg |= CR_AES_GCM;
13469d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13479d3b5030SFabien DESSENNE 
13489d3b5030SFabien DESSENNE 	/* e) change phase to Final */
13499d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
13509d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
13519d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13529d3b5030SFabien DESSENNE 
13539d3b5030SFabien DESSENNE 	/* f) write padded data */
13549d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
13559d3b5030SFabien DESSENNE 		if (cryp->total_in)
13569d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, tmp[i]);
13579d3b5030SFabien DESSENNE 		else
13589d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, 0);
13599d3b5030SFabien DESSENNE 
13609d3b5030SFabien DESSENNE 		cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in);
13619d3b5030SFabien DESSENNE 	}
13629d3b5030SFabien DESSENNE 
13639d3b5030SFabien DESSENNE 	/* g) Empty fifo out */
13649d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
13659d3b5030SFabien DESSENNE 	if (err) {
13669d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (write gcm header)\n");
13679d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
13689d3b5030SFabien DESSENNE 	}
13699d3b5030SFabien DESSENNE 
13709d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++)
13719d3b5030SFabien DESSENNE 		stm32_cryp_read(cryp, CRYP_DOUT);
13729d3b5030SFabien DESSENNE 
13739d3b5030SFabien DESSENNE 	/* h) run the he normal Final phase */
13749d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, 0);
13759d3b5030SFabien DESSENNE }
13769d3b5030SFabien DESSENNE 
13779d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
13789d3b5030SFabien DESSENNE {
13799d3b5030SFabien DESSENNE 	u32 cfg, payload_bytes;
13809d3b5030SFabien DESSENNE 
13819d3b5030SFabien DESSENNE 	/* disable ip, set NPBLB and reneable ip */
13829d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
13839d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
13849d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13859d3b5030SFabien DESSENNE 
13869d3b5030SFabien DESSENNE 	payload_bytes = is_decrypt(cryp) ? cryp->total_in - cryp->authsize :
13879d3b5030SFabien DESSENNE 					   cryp->total_in;
13889d3b5030SFabien DESSENNE 	cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT;
13899d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
13909d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
13919d3b5030SFabien DESSENNE }
13929d3b5030SFabien DESSENNE 
13939d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
13949d3b5030SFabien DESSENNE {
13959d3b5030SFabien DESSENNE 	int err = 0;
13969d3b5030SFabien DESSENNE 	u32 cfg, iv1tmp;
13979d3b5030SFabien DESSENNE 	u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32];
13989d3b5030SFabien DESSENNE 	size_t last_total_out, total_in_ori = cryp->total_in;
13999d3b5030SFabien DESSENNE 	struct scatterlist *out_sg_ori = cryp->out_sg;
14009d3b5030SFabien DESSENNE 	unsigned int i;
14019d3b5030SFabien DESSENNE 
14029d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
14039d3b5030SFabien DESSENNE 	cryp->flags |= FLG_CCM_PADDED_WA;
14049d3b5030SFabien DESSENNE 
14059d3b5030SFabien DESSENNE 	/* a) disable ip */
14069d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
14079d3b5030SFabien DESSENNE 
14089d3b5030SFabien DESSENNE 	cfg = stm32_cryp_read(cryp, CRYP_CR);
14099d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14109d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14119d3b5030SFabien DESSENNE 
14129d3b5030SFabien DESSENNE 	/* b) get IV1 from CRYP_CSGCMCCM7 */
14139d3b5030SFabien DESSENNE 	iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4);
14149d3b5030SFabien DESSENNE 
14159d3b5030SFabien DESSENNE 	/* c) Load CRYP_CSGCMCCMxR */
14169d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp1); i++)
14179d3b5030SFabien DESSENNE 		cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
14189d3b5030SFabien DESSENNE 
14199d3b5030SFabien DESSENNE 	/* d) Write IV1R */
14209d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_IV1RR, iv1tmp);
14219d3b5030SFabien DESSENNE 
14229d3b5030SFabien DESSENNE 	/* e) change mode to CTR */
14239d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14249d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
14259d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14269d3b5030SFabien DESSENNE 
14279d3b5030SFabien DESSENNE 	/* a) enable IP */
14289d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14299d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14309d3b5030SFabien DESSENNE 
14319d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
14329d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
14339d3b5030SFabien DESSENNE 	cryp->total_in = total_in_ori;
14349d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14359d3b5030SFabien DESSENNE 	if (err) {
14369d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (wite ccm padded data)\n");
14379d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14389d3b5030SFabien DESSENNE 	}
14399d3b5030SFabien DESSENNE 
14409d3b5030SFabien DESSENNE 	/* c) get and store decrypted data */
14419d3b5030SFabien DESSENNE 	last_total_out = cryp->total_out;
14429d3b5030SFabien DESSENNE 	stm32_cryp_irq_read_data(cryp);
14439d3b5030SFabien DESSENNE 
14449d3b5030SFabien DESSENNE 	memset(tmp, 0, sizeof(tmp));
14459d3b5030SFabien DESSENNE 	scatterwalk_map_and_copy(tmp, out_sg_ori,
14469d3b5030SFabien DESSENNE 				 cryp->total_out_save - last_total_out,
14479d3b5030SFabien DESSENNE 				 last_total_out, 0);
14489d3b5030SFabien DESSENNE 
14499d3b5030SFabien DESSENNE 	/* d) Load again CRYP_CSGCMCCMxR */
14509d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
14519d3b5030SFabien DESSENNE 		cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
14529d3b5030SFabien DESSENNE 
14539d3b5030SFabien DESSENNE 	/* e) change mode back to AES CCM */
14549d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14559d3b5030SFabien DESSENNE 	cfg |= CR_AES_CCM;
14569d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14579d3b5030SFabien DESSENNE 
14589d3b5030SFabien DESSENNE 	/* f) change phase to header */
14599d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
14609d3b5030SFabien DESSENNE 	cfg |= CR_PH_HEADER;
14619d3b5030SFabien DESSENNE 	stm32_cryp_write(cryp, CRYP_CR, cfg);
14629d3b5030SFabien DESSENNE 
14639d3b5030SFabien DESSENNE 	/* g) XOR and write padded data */
14649d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(tmp); i++) {
14659d3b5030SFabien DESSENNE 		tmp[i] ^= cstmp1[i];
14669d3b5030SFabien DESSENNE 		tmp[i] ^= cstmp2[i];
14679d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, tmp[i]);
14689d3b5030SFabien DESSENNE 	}
14699d3b5030SFabien DESSENNE 
14709d3b5030SFabien DESSENNE 	/* h) wait for completion */
14719d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_busy(cryp);
14729d3b5030SFabien DESSENNE 	if (err)
14739d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (wite ccm padded data)\n");
14749d3b5030SFabien DESSENNE 
14759d3b5030SFabien DESSENNE 	/* i) run the he normal Final phase */
14769d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, err);
14779d3b5030SFabien DESSENNE }
14789d3b5030SFabien DESSENNE 
14799e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
14809e054ec2SFabien DESSENNE {
14819e054ec2SFabien DESSENNE 	if (unlikely(!cryp->total_in)) {
14829e054ec2SFabien DESSENNE 		dev_warn(cryp->dev, "No more data to process\n");
14839e054ec2SFabien DESSENNE 		return;
14849e054ec2SFabien DESSENNE 	}
14859e054ec2SFabien DESSENNE 
14869d3b5030SFabien DESSENNE 	if (unlikely(cryp->total_in < AES_BLOCK_SIZE &&
14879d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
14889d3b5030SFabien DESSENNE 		     is_encrypt(cryp))) {
14899d3b5030SFabien DESSENNE 		/* Padding for AES GCM encryption */
14909d3b5030SFabien DESSENNE 		if (cryp->caps->padding_wa)
14919d3b5030SFabien DESSENNE 			/* Special case 1 */
14929d3b5030SFabien DESSENNE 			return stm32_cryp_irq_write_gcm_padded_data(cryp);
14939d3b5030SFabien DESSENNE 
14949d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
14959d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
14969d3b5030SFabien DESSENNE 	}
14979d3b5030SFabien DESSENNE 
14989d3b5030SFabien DESSENNE 	if (unlikely((cryp->total_in - cryp->authsize < AES_BLOCK_SIZE) &&
14999d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
15009d3b5030SFabien DESSENNE 		     is_decrypt(cryp))) {
15019d3b5030SFabien DESSENNE 		/* Padding for AES CCM decryption */
15029d3b5030SFabien DESSENNE 		if (cryp->caps->padding_wa)
15039d3b5030SFabien DESSENNE 			/* Special case 2 */
15049d3b5030SFabien DESSENNE 			return stm32_cryp_irq_write_ccm_padded_data(cryp);
15059d3b5030SFabien DESSENNE 
15069d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
15079d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
15089d3b5030SFabien DESSENNE 	}
15099d3b5030SFabien DESSENNE 
15109e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
15119e054ec2SFabien DESSENNE 		stm32_cryp_check_ctr_counter(cryp);
15129e054ec2SFabien DESSENNE 
15139e054ec2SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
15149e054ec2SFabien DESSENNE }
15159e054ec2SFabien DESSENNE 
15169d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp)
15179d3b5030SFabien DESSENNE {
15189d3b5030SFabien DESSENNE 	int err;
15199d3b5030SFabien DESSENNE 	unsigned int i, j;
15209d3b5030SFabien DESSENNE 	u32 cfg, *src;
15219d3b5030SFabien DESSENNE 
15229d3b5030SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
15239d3b5030SFabien DESSENNE 
15249d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
15259d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, *src);
15269d3b5030SFabien DESSENNE 
15279d3b5030SFabien DESSENNE 		src = stm32_cryp_next_in(cryp, src, sizeof(u32));
15289d3b5030SFabien DESSENNE 		cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in);
15299d3b5030SFabien DESSENNE 
15309d3b5030SFabien DESSENNE 		/* Check if whole header written */
15319d3b5030SFabien DESSENNE 		if ((cryp->total_in_save - cryp->total_in) ==
15329d3b5030SFabien DESSENNE 				cryp->areq->assoclen) {
15339d3b5030SFabien DESSENNE 			/* Write padding if needed */
15349d3b5030SFabien DESSENNE 			for (j = i + 1; j < AES_BLOCK_32; j++)
15359d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_DIN, 0);
15369d3b5030SFabien DESSENNE 
15379d3b5030SFabien DESSENNE 			/* Wait for completion */
15389d3b5030SFabien DESSENNE 			err = stm32_cryp_wait_busy(cryp);
15399d3b5030SFabien DESSENNE 			if (err) {
15409d3b5030SFabien DESSENNE 				dev_err(cryp->dev, "Timeout (gcm header)\n");
15419d3b5030SFabien DESSENNE 				return stm32_cryp_finish_req(cryp, err);
15429d3b5030SFabien DESSENNE 			}
15439d3b5030SFabien DESSENNE 
15449d3b5030SFabien DESSENNE 			if (stm32_cryp_get_input_text_len(cryp)) {
15459d3b5030SFabien DESSENNE 				/* Phase 3 : payload */
15469d3b5030SFabien DESSENNE 				cfg = stm32_cryp_read(cryp, CRYP_CR);
15479d3b5030SFabien DESSENNE 				cfg &= ~CR_CRYPEN;
15489d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
15499d3b5030SFabien DESSENNE 
15509d3b5030SFabien DESSENNE 				cfg &= ~CR_PH_MASK;
15519d3b5030SFabien DESSENNE 				cfg |= CR_PH_PAYLOAD;
15529d3b5030SFabien DESSENNE 				cfg |= CR_CRYPEN;
15539d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
15549d3b5030SFabien DESSENNE 			} else {
15559d3b5030SFabien DESSENNE 				/* Phase 4 : tag */
15569d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_IMSCR, 0);
15579d3b5030SFabien DESSENNE 				stm32_cryp_finish_req(cryp, 0);
15589d3b5030SFabien DESSENNE 			}
15599d3b5030SFabien DESSENNE 
15609d3b5030SFabien DESSENNE 			break;
15619d3b5030SFabien DESSENNE 		}
15629d3b5030SFabien DESSENNE 
15639d3b5030SFabien DESSENNE 		if (!cryp->total_in)
15649d3b5030SFabien DESSENNE 			break;
15659d3b5030SFabien DESSENNE 	}
15669d3b5030SFabien DESSENNE }
15679d3b5030SFabien DESSENNE 
15689d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp)
15699d3b5030SFabien DESSENNE {
15709d3b5030SFabien DESSENNE 	int err;
15719d3b5030SFabien DESSENNE 	unsigned int i = 0, j, k;
15729d3b5030SFabien DESSENNE 	u32 alen, cfg, *src;
15739d3b5030SFabien DESSENNE 	u8 d8[4];
15749d3b5030SFabien DESSENNE 
15759d3b5030SFabien DESSENNE 	src = sg_virt(cryp->in_sg) + _walked_in;
15769d3b5030SFabien DESSENNE 	alen = cryp->areq->assoclen;
15779d3b5030SFabien DESSENNE 
15789d3b5030SFabien DESSENNE 	if (!_walked_in) {
15799d3b5030SFabien DESSENNE 		if (cryp->areq->assoclen <= 65280) {
15809d3b5030SFabien DESSENNE 			/* Write first u32 of B1 */
15819d3b5030SFabien DESSENNE 			d8[0] = (alen >> 8) & 0xFF;
15829d3b5030SFabien DESSENNE 			d8[1] = alen & 0xFF;
15839d3b5030SFabien DESSENNE 			d8[2] = *((u8 *)src);
15849d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
15859d3b5030SFabien DESSENNE 			d8[3] = *((u8 *)src);
15869d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
15879d3b5030SFabien DESSENNE 
15889d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
15899d3b5030SFabien DESSENNE 			i++;
15909d3b5030SFabien DESSENNE 
15919d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 2, cryp->total_in);
15929d3b5030SFabien DESSENNE 		} else {
15939d3b5030SFabien DESSENNE 			/* Build the two first u32 of B1 */
15949d3b5030SFabien DESSENNE 			d8[0] = 0xFF;
15959d3b5030SFabien DESSENNE 			d8[1] = 0xFE;
15969d3b5030SFabien DESSENNE 			d8[2] = alen & 0xFF000000;
15979d3b5030SFabien DESSENNE 			d8[3] = alen & 0x00FF0000;
15989d3b5030SFabien DESSENNE 
15999d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16009d3b5030SFabien DESSENNE 			i++;
16019d3b5030SFabien DESSENNE 
16029d3b5030SFabien DESSENNE 			d8[0] = alen & 0x0000FF00;
16039d3b5030SFabien DESSENNE 			d8[1] = alen & 0x000000FF;
16049d3b5030SFabien DESSENNE 			d8[2] = *((u8 *)src);
16059d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16069d3b5030SFabien DESSENNE 			d8[3] = *((u8 *)src);
16079d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16089d3b5030SFabien DESSENNE 
16099d3b5030SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16109d3b5030SFabien DESSENNE 			i++;
16119d3b5030SFabien DESSENNE 
16129d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 2, cryp->total_in);
16139d3b5030SFabien DESSENNE 		}
16149d3b5030SFabien DESSENNE 	}
16159d3b5030SFabien DESSENNE 
16169d3b5030SFabien DESSENNE 	/* Write next u32 */
16179d3b5030SFabien DESSENNE 	for (; i < AES_BLOCK_32; i++) {
16189d3b5030SFabien DESSENNE 		/* Build an u32 */
16199d3b5030SFabien DESSENNE 		memset(d8, 0, sizeof(u32));
16209d3b5030SFabien DESSENNE 		for (k = 0; k < sizeof(u32); k++) {
16219d3b5030SFabien DESSENNE 			d8[k] = *((u8 *)src);
16229d3b5030SFabien DESSENNE 			src = stm32_cryp_next_in(cryp, src, 1);
16239d3b5030SFabien DESSENNE 
16249d3b5030SFabien DESSENNE 			cryp->total_in -= min_t(size_t, 1, cryp->total_in);
16259d3b5030SFabien DESSENNE 			if ((cryp->total_in_save - cryp->total_in) == alen)
16269d3b5030SFabien DESSENNE 				break;
16279d3b5030SFabien DESSENNE 		}
16289d3b5030SFabien DESSENNE 
16299d3b5030SFabien DESSENNE 		stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8);
16309d3b5030SFabien DESSENNE 
16319d3b5030SFabien DESSENNE 		if ((cryp->total_in_save - cryp->total_in) == alen) {
16329d3b5030SFabien DESSENNE 			/* Write padding if needed */
16339d3b5030SFabien DESSENNE 			for (j = i + 1; j < AES_BLOCK_32; j++)
16349d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_DIN, 0);
16359d3b5030SFabien DESSENNE 
16369d3b5030SFabien DESSENNE 			/* Wait for completion */
16379d3b5030SFabien DESSENNE 			err = stm32_cryp_wait_busy(cryp);
16389d3b5030SFabien DESSENNE 			if (err) {
16399d3b5030SFabien DESSENNE 				dev_err(cryp->dev, "Timeout (ccm header)\n");
16409d3b5030SFabien DESSENNE 				return stm32_cryp_finish_req(cryp, err);
16419d3b5030SFabien DESSENNE 			}
16429d3b5030SFabien DESSENNE 
16439d3b5030SFabien DESSENNE 			if (stm32_cryp_get_input_text_len(cryp)) {
16449d3b5030SFabien DESSENNE 				/* Phase 3 : payload */
16459d3b5030SFabien DESSENNE 				cfg = stm32_cryp_read(cryp, CRYP_CR);
16469d3b5030SFabien DESSENNE 				cfg &= ~CR_CRYPEN;
16479d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
16489d3b5030SFabien DESSENNE 
16499d3b5030SFabien DESSENNE 				cfg &= ~CR_PH_MASK;
16509d3b5030SFabien DESSENNE 				cfg |= CR_PH_PAYLOAD;
16519d3b5030SFabien DESSENNE 				cfg |= CR_CRYPEN;
16529d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_CR, cfg);
16539d3b5030SFabien DESSENNE 			} else {
16549d3b5030SFabien DESSENNE 				/* Phase 4 : tag */
16559d3b5030SFabien DESSENNE 				stm32_cryp_write(cryp, CRYP_IMSCR, 0);
16569d3b5030SFabien DESSENNE 				stm32_cryp_finish_req(cryp, 0);
16579d3b5030SFabien DESSENNE 			}
16589d3b5030SFabien DESSENNE 
16599d3b5030SFabien DESSENNE 			break;
16609d3b5030SFabien DESSENNE 		}
16619d3b5030SFabien DESSENNE 	}
16629d3b5030SFabien DESSENNE }
16639d3b5030SFabien DESSENNE 
16649e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg)
16659e054ec2SFabien DESSENNE {
16669e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
16679d3b5030SFabien DESSENNE 	u32 ph;
16689e054ec2SFabien DESSENNE 
16699e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_OUT)
16709e054ec2SFabien DESSENNE 		/* Output FIFO IRQ: read data */
16719e054ec2SFabien DESSENNE 		if (unlikely(stm32_cryp_irq_read_data(cryp))) {
16729e054ec2SFabien DESSENNE 			/* All bytes processed, finish */
16739e054ec2SFabien DESSENNE 			stm32_cryp_write(cryp, CRYP_IMSCR, 0);
16749d3b5030SFabien DESSENNE 			stm32_cryp_finish_req(cryp, 0);
16759e054ec2SFabien DESSENNE 			return IRQ_HANDLED;
16769e054ec2SFabien DESSENNE 		}
16779e054ec2SFabien DESSENNE 
16789e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_IN) {
16799d3b5030SFabien DESSENNE 		if (is_gcm(cryp)) {
16809d3b5030SFabien DESSENNE 			ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK;
16819d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
16829d3b5030SFabien DESSENNE 				/* Write Header */
16839d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_gcm_header(cryp);
16849d3b5030SFabien DESSENNE 			else
16859e054ec2SFabien DESSENNE 				/* Input FIFO IRQ: write data */
16869e054ec2SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
16879d3b5030SFabien DESSENNE 			cryp->gcm_ctr++;
16889d3b5030SFabien DESSENNE 		} else if (is_ccm(cryp)) {
16899d3b5030SFabien DESSENNE 			ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK;
16909d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
16919d3b5030SFabien DESSENNE 				/* Write Header */
16929d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_ccm_header(cryp);
16939d3b5030SFabien DESSENNE 			else
16949d3b5030SFabien DESSENNE 				/* Input FIFO IRQ: write data */
16959d3b5030SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
16969d3b5030SFabien DESSENNE 		} else {
16979d3b5030SFabien DESSENNE 			/* Input FIFO IRQ: write data */
16989d3b5030SFabien DESSENNE 			stm32_cryp_irq_write_data(cryp);
16999d3b5030SFabien DESSENNE 		}
17009e054ec2SFabien DESSENNE 	}
17019e054ec2SFabien DESSENNE 
17029e054ec2SFabien DESSENNE 	return IRQ_HANDLED;
17039e054ec2SFabien DESSENNE }
17049e054ec2SFabien DESSENNE 
17059e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg)
17069e054ec2SFabien DESSENNE {
17079e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
17089e054ec2SFabien DESSENNE 
17099e054ec2SFabien DESSENNE 	cryp->irq_status = stm32_cryp_read(cryp, CRYP_MISR);
17109e054ec2SFabien DESSENNE 
17119e054ec2SFabien DESSENNE 	return IRQ_WAKE_THREAD;
17129e054ec2SFabien DESSENNE }
17139e054ec2SFabien DESSENNE 
17149e054ec2SFabien DESSENNE static struct crypto_alg crypto_algs[] = {
17159e054ec2SFabien DESSENNE {
17169e054ec2SFabien DESSENNE 	.cra_name		= "ecb(aes)",
17179e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-ecb-aes",
17189e054ec2SFabien DESSENNE 	.cra_priority		= 200,
17199e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
17209e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
17219e054ec2SFabien DESSENNE 	.cra_blocksize		= AES_BLOCK_SIZE,
17229e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
17239e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
17249e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
17259e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
17269e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
17279e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
17289e054ec2SFabien DESSENNE 		.min_keysize	= AES_MIN_KEY_SIZE,
17299e054ec2SFabien DESSENNE 		.max_keysize	= AES_MAX_KEY_SIZE,
17309e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_aes_setkey,
17319e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_aes_ecb_encrypt,
17329e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_aes_ecb_decrypt,
17339e054ec2SFabien DESSENNE 	}
17349e054ec2SFabien DESSENNE },
17359e054ec2SFabien DESSENNE {
17369e054ec2SFabien DESSENNE 	.cra_name		= "cbc(aes)",
17379e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-cbc-aes",
17389e054ec2SFabien DESSENNE 	.cra_priority		= 200,
17399e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
17409e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
17419e054ec2SFabien DESSENNE 	.cra_blocksize		= AES_BLOCK_SIZE,
17429e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
17439e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
17449e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
17459e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
17469e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
17479e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
17489e054ec2SFabien DESSENNE 		.min_keysize	= AES_MIN_KEY_SIZE,
17499e054ec2SFabien DESSENNE 		.max_keysize	= AES_MAX_KEY_SIZE,
17509e054ec2SFabien DESSENNE 		.ivsize		= AES_BLOCK_SIZE,
17519e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_aes_setkey,
17529e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_aes_cbc_encrypt,
17539e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_aes_cbc_decrypt,
17549e054ec2SFabien DESSENNE 	}
17559e054ec2SFabien DESSENNE },
17569e054ec2SFabien DESSENNE {
17579e054ec2SFabien DESSENNE 	.cra_name		= "ctr(aes)",
17589e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-ctr-aes",
17599e054ec2SFabien DESSENNE 	.cra_priority		= 200,
17609e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
17619e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
17629e054ec2SFabien DESSENNE 	.cra_blocksize		= 1,
17639e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
17649e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
17659e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
17669e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
17679e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
17689e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
17699e054ec2SFabien DESSENNE 		.min_keysize	= AES_MIN_KEY_SIZE,
17709e054ec2SFabien DESSENNE 		.max_keysize	= AES_MAX_KEY_SIZE,
17719e054ec2SFabien DESSENNE 		.ivsize		= AES_BLOCK_SIZE,
17729e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_aes_setkey,
17739e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_aes_ctr_encrypt,
17749e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_aes_ctr_decrypt,
17759e054ec2SFabien DESSENNE 	}
17769e054ec2SFabien DESSENNE },
17779e054ec2SFabien DESSENNE {
17789e054ec2SFabien DESSENNE 	.cra_name		= "ecb(des)",
17799e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-ecb-des",
17809e054ec2SFabien DESSENNE 	.cra_priority		= 200,
17819e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
17829e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
17839e054ec2SFabien DESSENNE 	.cra_blocksize		= DES_BLOCK_SIZE,
17849e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
17859e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
17869e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
17879e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
17889e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
17899e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
17909e054ec2SFabien DESSENNE 		.min_keysize	= DES_BLOCK_SIZE,
17919e054ec2SFabien DESSENNE 		.max_keysize	= DES_BLOCK_SIZE,
17929e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_des_setkey,
17939e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_des_ecb_encrypt,
17949e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_des_ecb_decrypt,
17959e054ec2SFabien DESSENNE 	}
17969e054ec2SFabien DESSENNE },
17979e054ec2SFabien DESSENNE {
17989e054ec2SFabien DESSENNE 	.cra_name		= "cbc(des)",
17999e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-cbc-des",
18009e054ec2SFabien DESSENNE 	.cra_priority		= 200,
18019e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
18029e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
18039e054ec2SFabien DESSENNE 	.cra_blocksize		= DES_BLOCK_SIZE,
18049e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18059e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
18069e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
18079e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
18089e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
18099e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
18109e054ec2SFabien DESSENNE 		.min_keysize	= DES_BLOCK_SIZE,
18119e054ec2SFabien DESSENNE 		.max_keysize	= DES_BLOCK_SIZE,
18129e054ec2SFabien DESSENNE 		.ivsize		= DES_BLOCK_SIZE,
18139e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_des_setkey,
18149e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_des_cbc_encrypt,
18159e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_des_cbc_decrypt,
18169e054ec2SFabien DESSENNE 	}
18179e054ec2SFabien DESSENNE },
18189e054ec2SFabien DESSENNE {
18199e054ec2SFabien DESSENNE 	.cra_name		= "ecb(des3_ede)",
18209e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-ecb-des3",
18219e054ec2SFabien DESSENNE 	.cra_priority		= 200,
18229e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
18239e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
18249e054ec2SFabien DESSENNE 	.cra_blocksize		= DES_BLOCK_SIZE,
18259e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18269e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
18279e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
18289e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
18299e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
18309e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
18319e054ec2SFabien DESSENNE 		.min_keysize	= 3 * DES_BLOCK_SIZE,
18329e054ec2SFabien DESSENNE 		.max_keysize	= 3 * DES_BLOCK_SIZE,
18339e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_tdes_setkey,
18349e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_tdes_ecb_encrypt,
18359e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_tdes_ecb_decrypt,
18369e054ec2SFabien DESSENNE 	}
18379e054ec2SFabien DESSENNE },
18389e054ec2SFabien DESSENNE {
18399e054ec2SFabien DESSENNE 	.cra_name		= "cbc(des3_ede)",
18409e054ec2SFabien DESSENNE 	.cra_driver_name	= "stm32-cbc-des3",
18419e054ec2SFabien DESSENNE 	.cra_priority		= 200,
18429e054ec2SFabien DESSENNE 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
18439e054ec2SFabien DESSENNE 				  CRYPTO_ALG_ASYNC,
18449e054ec2SFabien DESSENNE 	.cra_blocksize		= DES_BLOCK_SIZE,
18459e054ec2SFabien DESSENNE 	.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18469e054ec2SFabien DESSENNE 	.cra_alignmask		= 0xf,
18479e054ec2SFabien DESSENNE 	.cra_type		= &crypto_ablkcipher_type,
18489e054ec2SFabien DESSENNE 	.cra_module		= THIS_MODULE,
18499e054ec2SFabien DESSENNE 	.cra_init		= stm32_cryp_cra_init,
18509e054ec2SFabien DESSENNE 	.cra_ablkcipher = {
18519e054ec2SFabien DESSENNE 		.min_keysize	= 3 * DES_BLOCK_SIZE,
18529e054ec2SFabien DESSENNE 		.max_keysize	= 3 * DES_BLOCK_SIZE,
18539e054ec2SFabien DESSENNE 		.ivsize		= DES_BLOCK_SIZE,
18549e054ec2SFabien DESSENNE 		.setkey		= stm32_cryp_tdes_setkey,
18559e054ec2SFabien DESSENNE 		.encrypt	= stm32_cryp_tdes_cbc_encrypt,
18569e054ec2SFabien DESSENNE 		.decrypt	= stm32_cryp_tdes_cbc_decrypt,
18579e054ec2SFabien DESSENNE 	}
18589e054ec2SFabien DESSENNE },
18599e054ec2SFabien DESSENNE };
18609e054ec2SFabien DESSENNE 
18619d3b5030SFabien DESSENNE static struct aead_alg aead_algs[] = {
18629d3b5030SFabien DESSENNE {
18639d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18649d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_gcm_setauthsize,
18659d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_gcm_encrypt,
18669d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_gcm_decrypt,
18679d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18689d3b5030SFabien DESSENNE 	.ivsize		= 12,
18699d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18709d3b5030SFabien DESSENNE 
18719d3b5030SFabien DESSENNE 	.base = {
18729d3b5030SFabien DESSENNE 		.cra_name		= "gcm(aes)",
18739d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-gcm-aes",
18749d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18759d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18769d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18779d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18789d3b5030SFabien DESSENNE 		.cra_alignmask		= 0xf,
18799d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18809d3b5030SFabien DESSENNE 	},
18819d3b5030SFabien DESSENNE },
18829d3b5030SFabien DESSENNE {
18839d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18849d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_ccm_setauthsize,
18859d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_ccm_encrypt,
18869d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_ccm_decrypt,
18879d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18889d3b5030SFabien DESSENNE 	.ivsize		= AES_BLOCK_SIZE,
18899d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18909d3b5030SFabien DESSENNE 
18919d3b5030SFabien DESSENNE 	.base = {
18929d3b5030SFabien DESSENNE 		.cra_name		= "ccm(aes)",
18939d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-ccm-aes",
18949d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18959d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18969d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18979d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18989d3b5030SFabien DESSENNE 		.cra_alignmask		= 0xf,
18999d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
19009d3b5030SFabien DESSENNE 	},
19019d3b5030SFabien DESSENNE },
19029d3b5030SFabien DESSENNE };
19039d3b5030SFabien DESSENNE 
19049d3b5030SFabien DESSENNE static const struct stm32_cryp_caps f7_data = {
19059d3b5030SFabien DESSENNE 	.swap_final = true,
19069d3b5030SFabien DESSENNE 	.padding_wa = true,
19079d3b5030SFabien DESSENNE };
19089d3b5030SFabien DESSENNE 
1909*a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = {
1910*a43a3484SFabien DESSENNE 	.swap_final = false,
1911*a43a3484SFabien DESSENNE 	.padding_wa = false,
1912*a43a3484SFabien DESSENNE };
1913*a43a3484SFabien DESSENNE 
19149e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = {
19159d3b5030SFabien DESSENNE 	{ .compatible = "st,stm32f756-cryp", .data = &f7_data},
1916*a43a3484SFabien DESSENNE 	{ .compatible = "st,stm32mp1-cryp", .data = &mp1_data},
19179e054ec2SFabien DESSENNE 	{},
19189e054ec2SFabien DESSENNE };
1919761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids);
19209e054ec2SFabien DESSENNE 
19219e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev)
19229e054ec2SFabien DESSENNE {
19239e054ec2SFabien DESSENNE 	struct device *dev = &pdev->dev;
19249e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
19259e054ec2SFabien DESSENNE 	struct resource *res;
19269e054ec2SFabien DESSENNE 	struct reset_control *rst;
19279e054ec2SFabien DESSENNE 	int irq, ret;
19289e054ec2SFabien DESSENNE 
19299e054ec2SFabien DESSENNE 	cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL);
19309e054ec2SFabien DESSENNE 	if (!cryp)
19319e054ec2SFabien DESSENNE 		return -ENOMEM;
19329e054ec2SFabien DESSENNE 
19339d3b5030SFabien DESSENNE 	cryp->caps = of_device_get_match_data(dev);
19349d3b5030SFabien DESSENNE 	if (!cryp->caps)
19359d3b5030SFabien DESSENNE 		return -ENODEV;
19369d3b5030SFabien DESSENNE 
19379e054ec2SFabien DESSENNE 	cryp->dev = dev;
19389e054ec2SFabien DESSENNE 
19399e054ec2SFabien DESSENNE 	mutex_init(&cryp->lock);
19409e054ec2SFabien DESSENNE 
19419e054ec2SFabien DESSENNE 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19429e054ec2SFabien DESSENNE 	cryp->regs = devm_ioremap_resource(dev, res);
194360bcf265Sweiyongjun \(A\) 	if (IS_ERR(cryp->regs))
19449e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->regs);
19459e054ec2SFabien DESSENNE 
19469e054ec2SFabien DESSENNE 	irq = platform_get_irq(pdev, 0);
19479e054ec2SFabien DESSENNE 	if (irq < 0) {
19489e054ec2SFabien DESSENNE 		dev_err(dev, "Cannot get IRQ resource\n");
19499e054ec2SFabien DESSENNE 		return irq;
19509e054ec2SFabien DESSENNE 	}
19519e054ec2SFabien DESSENNE 
19529e054ec2SFabien DESSENNE 	ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq,
19539e054ec2SFabien DESSENNE 					stm32_cryp_irq_thread, IRQF_ONESHOT,
19549e054ec2SFabien DESSENNE 					dev_name(dev), cryp);
19559e054ec2SFabien DESSENNE 	if (ret) {
19569e054ec2SFabien DESSENNE 		dev_err(dev, "Cannot grab IRQ\n");
19579e054ec2SFabien DESSENNE 		return ret;
19589e054ec2SFabien DESSENNE 	}
19599e054ec2SFabien DESSENNE 
19609e054ec2SFabien DESSENNE 	cryp->clk = devm_clk_get(dev, NULL);
19619e054ec2SFabien DESSENNE 	if (IS_ERR(cryp->clk)) {
19629e054ec2SFabien DESSENNE 		dev_err(dev, "Could not get clock\n");
19639e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->clk);
19649e054ec2SFabien DESSENNE 	}
19659e054ec2SFabien DESSENNE 
19669e054ec2SFabien DESSENNE 	ret = clk_prepare_enable(cryp->clk);
19679e054ec2SFabien DESSENNE 	if (ret) {
19689e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Failed to enable clock\n");
19699e054ec2SFabien DESSENNE 		return ret;
19709e054ec2SFabien DESSENNE 	}
19719e054ec2SFabien DESSENNE 
19729e054ec2SFabien DESSENNE 	rst = devm_reset_control_get(dev, NULL);
19739e054ec2SFabien DESSENNE 	if (!IS_ERR(rst)) {
19749e054ec2SFabien DESSENNE 		reset_control_assert(rst);
19759e054ec2SFabien DESSENNE 		udelay(2);
19769e054ec2SFabien DESSENNE 		reset_control_deassert(rst);
19779e054ec2SFabien DESSENNE 	}
19789e054ec2SFabien DESSENNE 
19799e054ec2SFabien DESSENNE 	platform_set_drvdata(pdev, cryp);
19809e054ec2SFabien DESSENNE 
19819e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
19829e054ec2SFabien DESSENNE 	list_add(&cryp->list, &cryp_list.dev_list);
19839e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
19849e054ec2SFabien DESSENNE 
19859e054ec2SFabien DESSENNE 	/* Initialize crypto engine */
19869e054ec2SFabien DESSENNE 	cryp->engine = crypto_engine_alloc_init(dev, 1);
19879e054ec2SFabien DESSENNE 	if (!cryp->engine) {
19889e054ec2SFabien DESSENNE 		dev_err(dev, "Could not init crypto engine\n");
19899e054ec2SFabien DESSENNE 		ret = -ENOMEM;
19909e054ec2SFabien DESSENNE 		goto err_engine1;
19919e054ec2SFabien DESSENNE 	}
19929e054ec2SFabien DESSENNE 
19939e054ec2SFabien DESSENNE 	ret = crypto_engine_start(cryp->engine);
19949e054ec2SFabien DESSENNE 	if (ret) {
19959e054ec2SFabien DESSENNE 		dev_err(dev, "Could not start crypto engine\n");
19969e054ec2SFabien DESSENNE 		goto err_engine2;
19979e054ec2SFabien DESSENNE 	}
19989e054ec2SFabien DESSENNE 
19999e054ec2SFabien DESSENNE 	ret = crypto_register_algs(crypto_algs, ARRAY_SIZE(crypto_algs));
20009e054ec2SFabien DESSENNE 	if (ret) {
20019e054ec2SFabien DESSENNE 		dev_err(dev, "Could not register algs\n");
20029e054ec2SFabien DESSENNE 		goto err_algs;
20039e054ec2SFabien DESSENNE 	}
20049e054ec2SFabien DESSENNE 
20059d3b5030SFabien DESSENNE 	ret = crypto_register_aeads(aead_algs, ARRAY_SIZE(aead_algs));
20069d3b5030SFabien DESSENNE 	if (ret)
20079d3b5030SFabien DESSENNE 		goto err_aead_algs;
20089d3b5030SFabien DESSENNE 
20099e054ec2SFabien DESSENNE 	dev_info(dev, "Initialized\n");
20109e054ec2SFabien DESSENNE 
20119e054ec2SFabien DESSENNE 	return 0;
20129e054ec2SFabien DESSENNE 
20139d3b5030SFabien DESSENNE err_aead_algs:
20149d3b5030SFabien DESSENNE 	crypto_unregister_algs(crypto_algs, ARRAY_SIZE(crypto_algs));
20159e054ec2SFabien DESSENNE err_algs:
20169e054ec2SFabien DESSENNE err_engine2:
20179e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20189e054ec2SFabien DESSENNE err_engine1:
20199e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20209e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20219e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20229e054ec2SFabien DESSENNE 
20239e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20249e054ec2SFabien DESSENNE 
20259e054ec2SFabien DESSENNE 	return ret;
20269e054ec2SFabien DESSENNE }
20279e054ec2SFabien DESSENNE 
20289e054ec2SFabien DESSENNE static int stm32_cryp_remove(struct platform_device *pdev)
20299e054ec2SFabien DESSENNE {
20309e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = platform_get_drvdata(pdev);
20319e054ec2SFabien DESSENNE 
20329e054ec2SFabien DESSENNE 	if (!cryp)
20339e054ec2SFabien DESSENNE 		return -ENODEV;
20349e054ec2SFabien DESSENNE 
20359d3b5030SFabien DESSENNE 	crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
20369e054ec2SFabien DESSENNE 	crypto_unregister_algs(crypto_algs, ARRAY_SIZE(crypto_algs));
20379e054ec2SFabien DESSENNE 
20389e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20399e054ec2SFabien DESSENNE 
20409e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20419e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20429e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20439e054ec2SFabien DESSENNE 
20449e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20459e054ec2SFabien DESSENNE 
20469e054ec2SFabien DESSENNE 	return 0;
20479e054ec2SFabien DESSENNE }
20489e054ec2SFabien DESSENNE 
20499e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = {
20509e054ec2SFabien DESSENNE 	.probe  = stm32_cryp_probe,
20519e054ec2SFabien DESSENNE 	.remove = stm32_cryp_remove,
20529e054ec2SFabien DESSENNE 	.driver = {
20539e054ec2SFabien DESSENNE 		.name           = DRIVER_NAME,
20549e054ec2SFabien DESSENNE 		.of_match_table = stm32_dt_ids,
20559e054ec2SFabien DESSENNE 	},
20569e054ec2SFabien DESSENNE };
20579e054ec2SFabien DESSENNE 
20589e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver);
20599e054ec2SFabien DESSENNE 
20609e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
20619e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver");
20629e054ec2SFabien DESSENNE MODULE_LICENSE("GPL");
2063