xref: /linux/drivers/crypto/stm32/stm32-cryp.c (revision 319ad16d62d3da695faebd2d5def6be0d542f586)
1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e054ec2SFabien DESSENNE /*
39e054ec2SFabien DESSENNE  * Copyright (C) STMicroelectronics SA 2017
49e054ec2SFabien DESSENNE  * Author: Fabien Dessenne <fabien.dessenne@st.com>
50b496efbSLinus Walleij  * Ux500 support taken from snippets in the old Ux500 cryp driver
69e054ec2SFabien DESSENNE  */
79e054ec2SFabien DESSENNE 
89e054ec2SFabien DESSENNE #include <linux/clk.h>
99e054ec2SFabien DESSENNE #include <linux/delay.h>
109e054ec2SFabien DESSENNE #include <linux/interrupt.h>
119e054ec2SFabien DESSENNE #include <linux/iopoll.h>
129e054ec2SFabien DESSENNE #include <linux/module.h>
139e054ec2SFabien DESSENNE #include <linux/of_device.h>
149e054ec2SFabien DESSENNE #include <linux/platform_device.h>
1565f9aa36Slionel.debieve@st.com #include <linux/pm_runtime.h>
169e054ec2SFabien DESSENNE #include <linux/reset.h>
179e054ec2SFabien DESSENNE 
189e054ec2SFabien DESSENNE #include <crypto/aes.h>
19b5d0ba83SArd Biesheuvel #include <crypto/internal/des.h>
209e054ec2SFabien DESSENNE #include <crypto/engine.h>
219e054ec2SFabien DESSENNE #include <crypto/scatterwalk.h>
229d3b5030SFabien DESSENNE #include <crypto/internal/aead.h>
2347ece481SArd Biesheuvel #include <crypto/internal/skcipher.h>
249e054ec2SFabien DESSENNE 
259e054ec2SFabien DESSENNE #define DRIVER_NAME             "stm32-cryp"
269e054ec2SFabien DESSENNE 
279e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */
289e054ec2SFabien DESSENNE #define FLG_ENCRYPT             BIT(0)
299e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */
309e054ec2SFabien DESSENNE #define FLG_AES                 BIT(1)
319e054ec2SFabien DESSENNE #define FLG_DES                 BIT(2)
329e054ec2SFabien DESSENNE #define FLG_TDES                BIT(3)
339e054ec2SFabien DESSENNE #define FLG_ECB                 BIT(4)
349e054ec2SFabien DESSENNE #define FLG_CBC                 BIT(5)
359e054ec2SFabien DESSENNE #define FLG_CTR                 BIT(6)
369d3b5030SFabien DESSENNE #define FLG_GCM                 BIT(7)
379d3b5030SFabien DESSENNE #define FLG_CCM                 BIT(8)
389e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */
399e054ec2SFabien DESSENNE #define FLG_MODE_MASK           GENMASK(15, 0)
409d3b5030SFabien DESSENNE /* Bit [31..16] status  */
419e054ec2SFabien DESSENNE 
429e054ec2SFabien DESSENNE /* Registers */
439e054ec2SFabien DESSENNE #define CRYP_CR                 0x00000000
449e054ec2SFabien DESSENNE #define CRYP_SR                 0x00000004
459e054ec2SFabien DESSENNE #define CRYP_DIN                0x00000008
469e054ec2SFabien DESSENNE #define CRYP_DOUT               0x0000000C
479e054ec2SFabien DESSENNE #define CRYP_DMACR              0x00000010
489e054ec2SFabien DESSENNE #define CRYP_IMSCR              0x00000014
499e054ec2SFabien DESSENNE #define CRYP_RISR               0x00000018
509e054ec2SFabien DESSENNE #define CRYP_MISR               0x0000001C
519e054ec2SFabien DESSENNE #define CRYP_K0LR               0x00000020
529e054ec2SFabien DESSENNE #define CRYP_K0RR               0x00000024
539e054ec2SFabien DESSENNE #define CRYP_K1LR               0x00000028
549e054ec2SFabien DESSENNE #define CRYP_K1RR               0x0000002C
559e054ec2SFabien DESSENNE #define CRYP_K2LR               0x00000030
569e054ec2SFabien DESSENNE #define CRYP_K2RR               0x00000034
579e054ec2SFabien DESSENNE #define CRYP_K3LR               0x00000038
589e054ec2SFabien DESSENNE #define CRYP_K3RR               0x0000003C
599e054ec2SFabien DESSENNE #define CRYP_IV0LR              0x00000040
609e054ec2SFabien DESSENNE #define CRYP_IV0RR              0x00000044
619e054ec2SFabien DESSENNE #define CRYP_IV1LR              0x00000048
629e054ec2SFabien DESSENNE #define CRYP_IV1RR              0x0000004C
639d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R         0x00000050
649d3b5030SFabien DESSENNE #define CRYP_CSGCM0R            0x00000070
659e054ec2SFabien DESSENNE 
660b496efbSLinus Walleij #define UX500_CRYP_CR		0x00000000
670b496efbSLinus Walleij #define UX500_CRYP_SR		0x00000004
680b496efbSLinus Walleij #define UX500_CRYP_DIN		0x00000008
690b496efbSLinus Walleij #define UX500_CRYP_DINSIZE	0x0000000C
700b496efbSLinus Walleij #define UX500_CRYP_DOUT		0x00000010
710b496efbSLinus Walleij #define UX500_CRYP_DOUSIZE	0x00000014
720b496efbSLinus Walleij #define UX500_CRYP_DMACR	0x00000018
730b496efbSLinus Walleij #define UX500_CRYP_IMSC		0x0000001C
740b496efbSLinus Walleij #define UX500_CRYP_RIS		0x00000020
750b496efbSLinus Walleij #define UX500_CRYP_MIS		0x00000024
760b496efbSLinus Walleij #define UX500_CRYP_K1L		0x00000028
770b496efbSLinus Walleij #define UX500_CRYP_K1R		0x0000002C
780b496efbSLinus Walleij #define UX500_CRYP_K2L		0x00000030
790b496efbSLinus Walleij #define UX500_CRYP_K2R		0x00000034
800b496efbSLinus Walleij #define UX500_CRYP_K3L		0x00000038
810b496efbSLinus Walleij #define UX500_CRYP_K3R		0x0000003C
820b496efbSLinus Walleij #define UX500_CRYP_K4L		0x00000040
830b496efbSLinus Walleij #define UX500_CRYP_K4R		0x00000044
840b496efbSLinus Walleij #define UX500_CRYP_IV0L		0x00000048
850b496efbSLinus Walleij #define UX500_CRYP_IV0R		0x0000004C
860b496efbSLinus Walleij #define UX500_CRYP_IV1L		0x00000050
870b496efbSLinus Walleij #define UX500_CRYP_IV1R		0x00000054
880b496efbSLinus Walleij 
899e054ec2SFabien DESSENNE /* Registers values */
909e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC          0x00000004
919e054ec2SFabien DESSENNE #define CR_TDES_ECB             0x00000000
929e054ec2SFabien DESSENNE #define CR_TDES_CBC             0x00000008
939e054ec2SFabien DESSENNE #define CR_DES_ECB              0x00000010
949e054ec2SFabien DESSENNE #define CR_DES_CBC              0x00000018
959e054ec2SFabien DESSENNE #define CR_AES_ECB              0x00000020
969e054ec2SFabien DESSENNE #define CR_AES_CBC              0x00000028
979e054ec2SFabien DESSENNE #define CR_AES_CTR              0x00000030
980b496efbSLinus Walleij #define CR_AES_KP               0x00000038 /* Not on Ux500 */
990b496efbSLinus Walleij #define CR_AES_XTS              0x00000038 /* Only on Ux500 */
1009d3b5030SFabien DESSENNE #define CR_AES_GCM              0x00080000
1019d3b5030SFabien DESSENNE #define CR_AES_CCM              0x00080008
1029e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN          0xFFFFFFFF
1039e054ec2SFabien DESSENNE #define CR_ALGO_MASK            0x00080038
1049e054ec2SFabien DESSENNE #define CR_DATA32               0x00000000
1059e054ec2SFabien DESSENNE #define CR_DATA16               0x00000040
1069e054ec2SFabien DESSENNE #define CR_DATA8                0x00000080
1079e054ec2SFabien DESSENNE #define CR_DATA1                0x000000C0
1089e054ec2SFabien DESSENNE #define CR_KEY128               0x00000000
1099e054ec2SFabien DESSENNE #define CR_KEY192               0x00000100
1109e054ec2SFabien DESSENNE #define CR_KEY256               0x00000200
1110b496efbSLinus Walleij #define CR_KEYRDEN              0x00000400 /* Only on Ux500 */
1120b496efbSLinus Walleij #define CR_KSE                  0x00000800 /* Only on Ux500 */
1139e054ec2SFabien DESSENNE #define CR_FFLUSH               0x00004000
1149e054ec2SFabien DESSENNE #define CR_CRYPEN               0x00008000
1159d3b5030SFabien DESSENNE #define CR_PH_INIT              0x00000000
1169d3b5030SFabien DESSENNE #define CR_PH_HEADER            0x00010000
1179d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD           0x00020000
1189d3b5030SFabien DESSENNE #define CR_PH_FINAL             0x00030000
1199d3b5030SFabien DESSENNE #define CR_PH_MASK              0x00030000
1209d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT          20
1219e054ec2SFabien DESSENNE 
1229e054ec2SFabien DESSENNE #define SR_BUSY                 0x00000010
1239e054ec2SFabien DESSENNE #define SR_OFNE                 0x00000004
1249e054ec2SFabien DESSENNE 
1259e054ec2SFabien DESSENNE #define IMSCR_IN                BIT(0)
1269e054ec2SFabien DESSENNE #define IMSCR_OUT               BIT(1)
1279e054ec2SFabien DESSENNE 
1289e054ec2SFabien DESSENNE #define MISR_IN                 BIT(0)
1299e054ec2SFabien DESSENNE #define MISR_OUT                BIT(1)
1309e054ec2SFabien DESSENNE 
1319e054ec2SFabien DESSENNE /* Misc */
1329e054ec2SFabien DESSENNE #define AES_BLOCK_32            (AES_BLOCK_SIZE / sizeof(u32))
1339d3b5030SFabien DESSENNE #define GCM_CTR_INIT            2
13465f9aa36Slionel.debieve@st.com #define CRYP_AUTOSUSPEND_DELAY	50
1359e054ec2SFabien DESSENNE 
1369d3b5030SFabien DESSENNE struct stm32_cryp_caps {
1370b496efbSLinus Walleij 	bool			aeads_support;
1380b496efbSLinus Walleij 	bool			linear_aes_key;
1390b496efbSLinus Walleij 	bool			kp_mode;
1400b496efbSLinus Walleij 	bool			iv_protection;
1419d3b5030SFabien DESSENNE 	bool			swap_final;
1429d3b5030SFabien DESSENNE 	bool			padding_wa;
1430b496efbSLinus Walleij 	u32			cr;
1440b496efbSLinus Walleij 	u32			sr;
1450b496efbSLinus Walleij 	u32			din;
1460b496efbSLinus Walleij 	u32			dout;
1470b496efbSLinus Walleij 	u32			imsc;
1480b496efbSLinus Walleij 	u32			mis;
1490b496efbSLinus Walleij 	u32			k1l;
1500b496efbSLinus Walleij 	u32			k1r;
1510b496efbSLinus Walleij 	u32			k3r;
1520b496efbSLinus Walleij 	u32			iv0l;
1530b496efbSLinus Walleij 	u32			iv0r;
1540b496efbSLinus Walleij 	u32			iv1l;
1550b496efbSLinus Walleij 	u32			iv1r;
1569d3b5030SFabien DESSENNE };
1579d3b5030SFabien DESSENNE 
1589e054ec2SFabien DESSENNE struct stm32_cryp_ctx {
159dc7bcef5SCorentin LABBE 	struct crypto_engine_ctx enginectx;
1609e054ec2SFabien DESSENNE 	struct stm32_cryp       *cryp;
1619e054ec2SFabien DESSENNE 	int                     keylen;
162bbb28326SHerbert Xu 	__be32                  key[AES_KEYSIZE_256 / sizeof(u32)];
1639e054ec2SFabien DESSENNE 	unsigned long           flags;
1649e054ec2SFabien DESSENNE };
1659e054ec2SFabien DESSENNE 
1669e054ec2SFabien DESSENNE struct stm32_cryp_reqctx {
1679e054ec2SFabien DESSENNE 	unsigned long mode;
1689e054ec2SFabien DESSENNE };
1699e054ec2SFabien DESSENNE 
1709e054ec2SFabien DESSENNE struct stm32_cryp {
1719e054ec2SFabien DESSENNE 	struct list_head        list;
1729e054ec2SFabien DESSENNE 	struct device           *dev;
1739e054ec2SFabien DESSENNE 	void __iomem            *regs;
1749e054ec2SFabien DESSENNE 	struct clk              *clk;
1759e054ec2SFabien DESSENNE 	unsigned long           flags;
1769e054ec2SFabien DESSENNE 	u32                     irq_status;
1779d3b5030SFabien DESSENNE 	const struct stm32_cryp_caps *caps;
1789e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx   *ctx;
1799e054ec2SFabien DESSENNE 
1809e054ec2SFabien DESSENNE 	struct crypto_engine    *engine;
1819e054ec2SFabien DESSENNE 
18247ece481SArd Biesheuvel 	struct skcipher_request *req;
1839d3b5030SFabien DESSENNE 	struct aead_request     *areq;
1849e054ec2SFabien DESSENNE 
1859d3b5030SFabien DESSENNE 	size_t                  authsize;
1869e054ec2SFabien DESSENNE 	size_t                  hw_blocksize;
1879e054ec2SFabien DESSENNE 
1884b898d5cSNicolas Toromanoff 	size_t                  payload_in;
1894b898d5cSNicolas Toromanoff 	size_t                  header_in;
1904b898d5cSNicolas Toromanoff 	size_t                  payload_out;
1919e054ec2SFabien DESSENNE 
1929e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg;
1939e054ec2SFabien DESSENNE 
1949e054ec2SFabien DESSENNE 	struct scatter_walk     in_walk;
1959e054ec2SFabien DESSENNE 	struct scatter_walk     out_walk;
1969e054ec2SFabien DESSENNE 
19741c76690SNicolas Toromanoff 	__be32                  last_ctr[4];
1989d3b5030SFabien DESSENNE 	u32                     gcm_ctr;
1999e054ec2SFabien DESSENNE };
2009e054ec2SFabien DESSENNE 
2019e054ec2SFabien DESSENNE struct stm32_cryp_list {
2029e054ec2SFabien DESSENNE 	struct list_head        dev_list;
2039e054ec2SFabien DESSENNE 	spinlock_t              lock; /* protect dev_list */
2049e054ec2SFabien DESSENNE };
2059e054ec2SFabien DESSENNE 
2069e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = {
2079e054ec2SFabien DESSENNE 	.dev_list = LIST_HEAD_INIT(cryp_list.dev_list),
2089e054ec2SFabien DESSENNE 	.lock     = __SPIN_LOCK_UNLOCKED(cryp_list.lock),
2099e054ec2SFabien DESSENNE };
2109e054ec2SFabien DESSENNE 
2119e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp)
2129e054ec2SFabien DESSENNE {
2139e054ec2SFabien DESSENNE 	return cryp->flags & FLG_AES;
2149e054ec2SFabien DESSENNE }
2159e054ec2SFabien DESSENNE 
2169e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp)
2179e054ec2SFabien DESSENNE {
2189e054ec2SFabien DESSENNE 	return cryp->flags & FLG_DES;
2199e054ec2SFabien DESSENNE }
2209e054ec2SFabien DESSENNE 
2219e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp)
2229e054ec2SFabien DESSENNE {
2239e054ec2SFabien DESSENNE 	return cryp->flags & FLG_TDES;
2249e054ec2SFabien DESSENNE }
2259e054ec2SFabien DESSENNE 
2269e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp)
2279e054ec2SFabien DESSENNE {
2289e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ECB;
2299e054ec2SFabien DESSENNE }
2309e054ec2SFabien DESSENNE 
2319e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp)
2329e054ec2SFabien DESSENNE {
2339e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CBC;
2349e054ec2SFabien DESSENNE }
2359e054ec2SFabien DESSENNE 
2369e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp)
2379e054ec2SFabien DESSENNE {
2389e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CTR;
2399e054ec2SFabien DESSENNE }
2409e054ec2SFabien DESSENNE 
2419d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp)
2429d3b5030SFabien DESSENNE {
2439d3b5030SFabien DESSENNE 	return cryp->flags & FLG_GCM;
2449d3b5030SFabien DESSENNE }
2459d3b5030SFabien DESSENNE 
2469d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp)
2479d3b5030SFabien DESSENNE {
2489d3b5030SFabien DESSENNE 	return cryp->flags & FLG_CCM;
2499d3b5030SFabien DESSENNE }
2509d3b5030SFabien DESSENNE 
2519e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp)
2529e054ec2SFabien DESSENNE {
2539e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ENCRYPT;
2549e054ec2SFabien DESSENNE }
2559e054ec2SFabien DESSENNE 
2569e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp)
2579e054ec2SFabien DESSENNE {
2589e054ec2SFabien DESSENNE 	return !is_encrypt(cryp);
2599e054ec2SFabien DESSENNE }
2609e054ec2SFabien DESSENNE 
2619e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst)
2629e054ec2SFabien DESSENNE {
2639e054ec2SFabien DESSENNE 	return readl_relaxed(cryp->regs + ofst);
2649e054ec2SFabien DESSENNE }
2659e054ec2SFabien DESSENNE 
2669e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val)
2679e054ec2SFabien DESSENNE {
2689e054ec2SFabien DESSENNE 	writel_relaxed(val, cryp->regs + ofst);
2699e054ec2SFabien DESSENNE }
2709e054ec2SFabien DESSENNE 
2719e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
2729e054ec2SFabien DESSENNE {
2739e054ec2SFabien DESSENNE 	u32 status;
2749e054ec2SFabien DESSENNE 
2750b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->sr, status,
2769e054ec2SFabien DESSENNE 			!(status & SR_BUSY), 10, 100000);
2779e054ec2SFabien DESSENNE }
2789e054ec2SFabien DESSENNE 
27995fe2253SNicolas Toromanoff static inline void stm32_cryp_enable(struct stm32_cryp *cryp)
28095fe2253SNicolas Toromanoff {
2810b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_CRYPEN,
2820b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
28395fe2253SNicolas Toromanoff }
28495fe2253SNicolas Toromanoff 
2859d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
2869d3b5030SFabien DESSENNE {
2879d3b5030SFabien DESSENNE 	u32 status;
2889d3b5030SFabien DESSENNE 
2890b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->cr, status,
2909d3b5030SFabien DESSENNE 			!(status & CR_CRYPEN), 10, 100000);
2919d3b5030SFabien DESSENNE }
2929d3b5030SFabien DESSENNE 
2939d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp)
2949d3b5030SFabien DESSENNE {
2959d3b5030SFabien DESSENNE 	u32 status;
2969d3b5030SFabien DESSENNE 
2970b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->sr, status,
2989d3b5030SFabien DESSENNE 			status & SR_OFNE, 10, 100000);
2999d3b5030SFabien DESSENNE }
3009d3b5030SFabien DESSENNE 
3010b496efbSLinus Walleij static inline void stm32_cryp_key_read_enable(struct stm32_cryp *cryp)
3020b496efbSLinus Walleij {
3030b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_KEYRDEN,
3040b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
3050b496efbSLinus Walleij }
3060b496efbSLinus Walleij 
3070b496efbSLinus Walleij static inline void stm32_cryp_key_read_disable(struct stm32_cryp *cryp)
3080b496efbSLinus Walleij {
3090b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) & ~CR_KEYRDEN,
3100b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
3110b496efbSLinus Walleij }
3120b496efbSLinus Walleij 
3139d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp);
3144b898d5cSNicolas Toromanoff static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err);
3159d3b5030SFabien DESSENNE 
3169e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx)
3179e054ec2SFabien DESSENNE {
3189e054ec2SFabien DESSENNE 	struct stm32_cryp *tmp, *cryp = NULL;
3199e054ec2SFabien DESSENNE 
3209e054ec2SFabien DESSENNE 	spin_lock_bh(&cryp_list.lock);
3219e054ec2SFabien DESSENNE 	if (!ctx->cryp) {
3229e054ec2SFabien DESSENNE 		list_for_each_entry(tmp, &cryp_list.dev_list, list) {
3239e054ec2SFabien DESSENNE 			cryp = tmp;
3249e054ec2SFabien DESSENNE 			break;
3259e054ec2SFabien DESSENNE 		}
3269e054ec2SFabien DESSENNE 		ctx->cryp = cryp;
3279e054ec2SFabien DESSENNE 	} else {
3289e054ec2SFabien DESSENNE 		cryp = ctx->cryp;
3299e054ec2SFabien DESSENNE 	}
3309e054ec2SFabien DESSENNE 
3319e054ec2SFabien DESSENNE 	spin_unlock_bh(&cryp_list.lock);
3329e054ec2SFabien DESSENNE 
3339e054ec2SFabien DESSENNE 	return cryp;
3349e054ec2SFabien DESSENNE }
3359e054ec2SFabien DESSENNE 
336bbb28326SHerbert Xu static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv)
3379e054ec2SFabien DESSENNE {
3389e054ec2SFabien DESSENNE 	if (!iv)
3399e054ec2SFabien DESSENNE 		return;
3409e054ec2SFabien DESSENNE 
3410b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv0l, be32_to_cpu(*iv++));
3420b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv0r, be32_to_cpu(*iv++));
3439e054ec2SFabien DESSENNE 
3449e054ec2SFabien DESSENNE 	if (is_aes(cryp)) {
3450b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->iv1l, be32_to_cpu(*iv++));
3460b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->iv1r, be32_to_cpu(*iv++));
3479e054ec2SFabien DESSENNE 	}
3489e054ec2SFabien DESSENNE }
3499e054ec2SFabien DESSENNE 
3505f49f18dSLionel Debieve static void stm32_cryp_get_iv(struct stm32_cryp *cryp)
3515f49f18dSLionel Debieve {
35247ece481SArd Biesheuvel 	struct skcipher_request *req = cryp->req;
353bbb28326SHerbert Xu 	__be32 *tmp = (void *)req->iv;
3545f49f18dSLionel Debieve 
3555f49f18dSLionel Debieve 	if (!tmp)
3565f49f18dSLionel Debieve 		return;
3575f49f18dSLionel Debieve 
3580b496efbSLinus Walleij 	if (cryp->caps->iv_protection)
3590b496efbSLinus Walleij 		stm32_cryp_key_read_enable(cryp);
3600b496efbSLinus Walleij 
3610b496efbSLinus Walleij 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
3620b496efbSLinus Walleij 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
3635f49f18dSLionel Debieve 
3645f49f18dSLionel Debieve 	if (is_aes(cryp)) {
3650b496efbSLinus Walleij 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
3660b496efbSLinus Walleij 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
3670b496efbSLinus Walleij 	}
3680b496efbSLinus Walleij 
3690b496efbSLinus Walleij 	if (cryp->caps->iv_protection)
3700b496efbSLinus Walleij 		stm32_cryp_key_read_disable(cryp);
3710b496efbSLinus Walleij }
3720b496efbSLinus Walleij 
3730b496efbSLinus Walleij /**
3740b496efbSLinus Walleij  * ux500_swap_bits_in_byte() - mirror the bits in a byte
3750b496efbSLinus Walleij  * @b: the byte to be mirrored
3760b496efbSLinus Walleij  *
3770b496efbSLinus Walleij  * The bits are swapped the following way:
3780b496efbSLinus Walleij  *  Byte b include bits 0-7, nibble 1 (n1) include bits 0-3 and
3790b496efbSLinus Walleij  *  nibble 2 (n2) bits 4-7.
3800b496efbSLinus Walleij  *
3810b496efbSLinus Walleij  *  Nibble 1 (n1):
3820b496efbSLinus Walleij  *  (The "old" (moved) bit is replaced with a zero)
3830b496efbSLinus Walleij  *  1. Move bit 6 and 7, 4 positions to the left.
3840b496efbSLinus Walleij  *  2. Move bit 3 and 5, 2 positions to the left.
3850b496efbSLinus Walleij  *  3. Move bit 1-4, 1 position to the left.
3860b496efbSLinus Walleij  *
3870b496efbSLinus Walleij  *  Nibble 2 (n2):
3880b496efbSLinus Walleij  *  1. Move bit 0 and 1, 4 positions to the right.
3890b496efbSLinus Walleij  *  2. Move bit 2 and 4, 2 positions to the right.
3900b496efbSLinus Walleij  *  3. Move bit 3-6, 1 position to the right.
3910b496efbSLinus Walleij  *
3920b496efbSLinus Walleij  *  Combine the two nibbles to a complete and swapped byte.
3930b496efbSLinus Walleij  */
3940b496efbSLinus Walleij static inline u8 ux500_swap_bits_in_byte(u8 b)
3950b496efbSLinus Walleij {
3960b496efbSLinus Walleij #define R_SHIFT_4_MASK  0xc0 /* Bits 6 and 7, right shift 4 */
3970b496efbSLinus Walleij #define R_SHIFT_2_MASK  0x28 /* (After right shift 4) Bits 3 and 5,
3980b496efbSLinus Walleij 				  right shift 2 */
3990b496efbSLinus Walleij #define R_SHIFT_1_MASK  0x1e /* (After right shift 2) Bits 1-4,
4000b496efbSLinus Walleij 				  right shift 1 */
4010b496efbSLinus Walleij #define L_SHIFT_4_MASK  0x03 /* Bits 0 and 1, left shift 4 */
4020b496efbSLinus Walleij #define L_SHIFT_2_MASK  0x14 /* (After left shift 4) Bits 2 and 4,
4030b496efbSLinus Walleij 				  left shift 2 */
4040b496efbSLinus Walleij #define L_SHIFT_1_MASK  0x78 /* (After left shift 1) Bits 3-6,
4050b496efbSLinus Walleij 				  left shift 1 */
4060b496efbSLinus Walleij 
4070b496efbSLinus Walleij 	u8 n1;
4080b496efbSLinus Walleij 	u8 n2;
4090b496efbSLinus Walleij 
4100b496efbSLinus Walleij 	/* Swap most significant nibble */
4110b496efbSLinus Walleij 	/* Right shift 4, bits 6 and 7 */
4120b496efbSLinus Walleij 	n1 = ((b  & R_SHIFT_4_MASK) >> 4) | (b  & ~(R_SHIFT_4_MASK >> 4));
4130b496efbSLinus Walleij 	/* Right shift 2, bits 3 and 5 */
4140b496efbSLinus Walleij 	n1 = ((n1 & R_SHIFT_2_MASK) >> 2) | (n1 & ~(R_SHIFT_2_MASK >> 2));
4150b496efbSLinus Walleij 	/* Right shift 1, bits 1-4 */
4160b496efbSLinus Walleij 	n1 = (n1  & R_SHIFT_1_MASK) >> 1;
4170b496efbSLinus Walleij 
4180b496efbSLinus Walleij 	/* Swap least significant nibble */
4190b496efbSLinus Walleij 	/* Left shift 4, bits 0 and 1 */
4200b496efbSLinus Walleij 	n2 = ((b  & L_SHIFT_4_MASK) << 4) | (b  & ~(L_SHIFT_4_MASK << 4));
4210b496efbSLinus Walleij 	/* Left shift 2, bits 2 and 4 */
4220b496efbSLinus Walleij 	n2 = ((n2 & L_SHIFT_2_MASK) << 2) | (n2 & ~(L_SHIFT_2_MASK << 2));
4230b496efbSLinus Walleij 	/* Left shift 1, bits 3-6 */
4240b496efbSLinus Walleij 	n2 = (n2  & L_SHIFT_1_MASK) << 1;
4250b496efbSLinus Walleij 
4260b496efbSLinus Walleij 	return n1 | n2;
4270b496efbSLinus Walleij }
4280b496efbSLinus Walleij 
4290b496efbSLinus Walleij /**
4300b496efbSLinus Walleij  * ux500_swizzle_key() - Shuffle around words and bits in the AES key
4310b496efbSLinus Walleij  * @in: key to swizzle
4320b496efbSLinus Walleij  * @out: swizzled key
4330b496efbSLinus Walleij  * @len: length of key, in bytes
4340b496efbSLinus Walleij  *
4350b496efbSLinus Walleij  * This "key swizzling procedure" is described in the examples in the
4360b496efbSLinus Walleij  * DB8500 design specification. There is no real description of why
4370b496efbSLinus Walleij  * the bits have been arranged like this in the hardware.
4380b496efbSLinus Walleij  */
4390b496efbSLinus Walleij static inline void ux500_swizzle_key(const u8 *in, u8 *out, u32 len)
4400b496efbSLinus Walleij {
4410b496efbSLinus Walleij 	int i = 0;
4420b496efbSLinus Walleij 	int bpw = sizeof(u32);
4430b496efbSLinus Walleij 	int j;
4440b496efbSLinus Walleij 	int index = 0;
4450b496efbSLinus Walleij 
4460b496efbSLinus Walleij 	j = len - bpw;
4470b496efbSLinus Walleij 	while (j >= 0) {
4480b496efbSLinus Walleij 		for (i = 0; i < bpw; i++) {
4490b496efbSLinus Walleij 			index = len - j - bpw + i;
4500b496efbSLinus Walleij 			out[j + i] =
4510b496efbSLinus Walleij 				ux500_swap_bits_in_byte(in[index]);
4520b496efbSLinus Walleij 		}
4530b496efbSLinus Walleij 		j -= bpw;
4545f49f18dSLionel Debieve 	}
4555f49f18dSLionel Debieve }
4565f49f18dSLionel Debieve 
4579e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c)
4589e054ec2SFabien DESSENNE {
4599e054ec2SFabien DESSENNE 	unsigned int i;
4609e054ec2SFabien DESSENNE 	int r_id;
4619e054ec2SFabien DESSENNE 
4629e054ec2SFabien DESSENNE 	if (is_des(c)) {
4630b496efbSLinus Walleij 		stm32_cryp_write(c, c->caps->k1l, be32_to_cpu(c->ctx->key[0]));
4640b496efbSLinus Walleij 		stm32_cryp_write(c, c->caps->k1r, be32_to_cpu(c->ctx->key[1]));
4650b496efbSLinus Walleij 		return;
4669e054ec2SFabien DESSENNE 	}
4670b496efbSLinus Walleij 
4680b496efbSLinus Walleij 	/*
4690b496efbSLinus Walleij 	 * On the Ux500 the AES key is considered as a single bit sequence
4700b496efbSLinus Walleij 	 * of 128, 192 or 256 bits length. It is written linearly into the
4710b496efbSLinus Walleij 	 * registers from K1L and down, and need to be processed to become
4720b496efbSLinus Walleij 	 * a proper big-endian bit sequence.
4730b496efbSLinus Walleij 	 */
4740b496efbSLinus Walleij 	if (is_aes(c) && c->caps->linear_aes_key) {
4750b496efbSLinus Walleij 		u32 tmpkey[8];
4760b496efbSLinus Walleij 
4770b496efbSLinus Walleij 		ux500_swizzle_key((u8 *)c->ctx->key,
4780b496efbSLinus Walleij 				  (u8 *)tmpkey, c->ctx->keylen);
4790b496efbSLinus Walleij 
4800b496efbSLinus Walleij 		r_id = c->caps->k1l;
4810b496efbSLinus Walleij 		for (i = 0; i < c->ctx->keylen / sizeof(u32); i++, r_id += 4)
4820b496efbSLinus Walleij 			stm32_cryp_write(c, r_id, tmpkey[i]);
4830b496efbSLinus Walleij 
4840b496efbSLinus Walleij 		return;
4850b496efbSLinus Walleij 	}
4860b496efbSLinus Walleij 
4870b496efbSLinus Walleij 	r_id = c->caps->k3r;
4880b496efbSLinus Walleij 	for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4)
4890b496efbSLinus Walleij 		stm32_cryp_write(c, r_id, be32_to_cpu(c->ctx->key[i - 1]));
4909e054ec2SFabien DESSENNE }
4919e054ec2SFabien DESSENNE 
4929e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp)
4939e054ec2SFabien DESSENNE {
4949e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ecb(cryp))
4959e054ec2SFabien DESSENNE 		return CR_AES_ECB;
4969e054ec2SFabien DESSENNE 
4979e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_cbc(cryp))
4989e054ec2SFabien DESSENNE 		return CR_AES_CBC;
4999e054ec2SFabien DESSENNE 
5009e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
5019e054ec2SFabien DESSENNE 		return CR_AES_CTR;
5029e054ec2SFabien DESSENNE 
5039d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_gcm(cryp))
5049d3b5030SFabien DESSENNE 		return CR_AES_GCM;
5059d3b5030SFabien DESSENNE 
5069d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_ccm(cryp))
5079d3b5030SFabien DESSENNE 		return CR_AES_CCM;
5089d3b5030SFabien DESSENNE 
5099e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_ecb(cryp))
5109e054ec2SFabien DESSENNE 		return CR_DES_ECB;
5119e054ec2SFabien DESSENNE 
5129e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_cbc(cryp))
5139e054ec2SFabien DESSENNE 		return CR_DES_CBC;
5149e054ec2SFabien DESSENNE 
5159e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_ecb(cryp))
5169e054ec2SFabien DESSENNE 		return CR_TDES_ECB;
5179e054ec2SFabien DESSENNE 
5189e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_cbc(cryp))
5199e054ec2SFabien DESSENNE 		return CR_TDES_CBC;
5209e054ec2SFabien DESSENNE 
5219e054ec2SFabien DESSENNE 	dev_err(cryp->dev, "Unknown mode\n");
5229e054ec2SFabien DESSENNE 	return CR_AES_UNKNOWN;
5239e054ec2SFabien DESSENNE }
5249e054ec2SFabien DESSENNE 
5259d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp)
5269d3b5030SFabien DESSENNE {
5279d3b5030SFabien DESSENNE 	return is_encrypt(cryp) ? cryp->areq->cryptlen :
5289d3b5030SFabien DESSENNE 				  cryp->areq->cryptlen - cryp->authsize;
5299d3b5030SFabien DESSENNE }
5309d3b5030SFabien DESSENNE 
5319d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg)
5329d3b5030SFabien DESSENNE {
5339d3b5030SFabien DESSENNE 	int ret;
534bbb28326SHerbert Xu 	__be32 iv[4];
5359d3b5030SFabien DESSENNE 
5369d3b5030SFabien DESSENNE 	/* Phase 1 : init */
5379d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, 12);
5389d3b5030SFabien DESSENNE 	iv[3] = cpu_to_be32(GCM_CTR_INIT);
5399d3b5030SFabien DESSENNE 	cryp->gcm_ctr = GCM_CTR_INIT;
5409d3b5030SFabien DESSENNE 	stm32_cryp_hw_write_iv(cryp, iv);
5419d3b5030SFabien DESSENNE 
5420b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
5439d3b5030SFabien DESSENNE 
5449d3b5030SFabien DESSENNE 	/* Wait for end of processing */
5459d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
5464b898d5cSNicolas Toromanoff 	if (ret) {
5479d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (gcm init)\n");
5489d3b5030SFabien DESSENNE 		return ret;
5499d3b5030SFabien DESSENNE 	}
5509d3b5030SFabien DESSENNE 
5514b898d5cSNicolas Toromanoff 	/* Prepare next phase */
5524b898d5cSNicolas Toromanoff 	if (cryp->areq->assoclen) {
5534b898d5cSNicolas Toromanoff 		cfg |= CR_PH_HEADER;
5540b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5554b898d5cSNicolas Toromanoff 	} else if (stm32_cryp_get_input_text_len(cryp)) {
5564b898d5cSNicolas Toromanoff 		cfg |= CR_PH_PAYLOAD;
5570b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5584b898d5cSNicolas Toromanoff 	}
5594b898d5cSNicolas Toromanoff 
5604b898d5cSNicolas Toromanoff 	return 0;
5614b898d5cSNicolas Toromanoff }
5624b898d5cSNicolas Toromanoff 
5634b898d5cSNicolas Toromanoff static void stm32_crypt_gcmccm_end_header(struct stm32_cryp *cryp)
5644b898d5cSNicolas Toromanoff {
5654b898d5cSNicolas Toromanoff 	u32 cfg;
5664b898d5cSNicolas Toromanoff 	int err;
5674b898d5cSNicolas Toromanoff 
5684b898d5cSNicolas Toromanoff 	/* Check if whole header written */
5694b898d5cSNicolas Toromanoff 	if (!cryp->header_in) {
5704b898d5cSNicolas Toromanoff 		/* Wait for completion */
5714b898d5cSNicolas Toromanoff 		err = stm32_cryp_wait_busy(cryp);
5724b898d5cSNicolas Toromanoff 		if (err) {
5734b898d5cSNicolas Toromanoff 			dev_err(cryp->dev, "Timeout (gcm/ccm header)\n");
5740b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->imsc, 0);
5754b898d5cSNicolas Toromanoff 			stm32_cryp_finish_req(cryp, err);
5764b898d5cSNicolas Toromanoff 			return;
5774b898d5cSNicolas Toromanoff 		}
5784b898d5cSNicolas Toromanoff 
5794b898d5cSNicolas Toromanoff 		if (stm32_cryp_get_input_text_len(cryp)) {
5804b898d5cSNicolas Toromanoff 			/* Phase 3 : payload */
5810b496efbSLinus Walleij 			cfg = stm32_cryp_read(cryp, cryp->caps->cr);
5824b898d5cSNicolas Toromanoff 			cfg &= ~CR_CRYPEN;
5830b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5844b898d5cSNicolas Toromanoff 
5854b898d5cSNicolas Toromanoff 			cfg &= ~CR_PH_MASK;
5864b898d5cSNicolas Toromanoff 			cfg |= CR_PH_PAYLOAD | CR_CRYPEN;
5870b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5884b898d5cSNicolas Toromanoff 		} else {
5894b898d5cSNicolas Toromanoff 			/*
5904b898d5cSNicolas Toromanoff 			 * Phase 4 : tag.
5914b898d5cSNicolas Toromanoff 			 * Nothing to read, nothing to write, caller have to
5924b898d5cSNicolas Toromanoff 			 * end request
5934b898d5cSNicolas Toromanoff 			 */
5944b898d5cSNicolas Toromanoff 		}
5954b898d5cSNicolas Toromanoff 	}
5964b898d5cSNicolas Toromanoff }
5974b898d5cSNicolas Toromanoff 
5984b898d5cSNicolas Toromanoff static void stm32_cryp_write_ccm_first_header(struct stm32_cryp *cryp)
5994b898d5cSNicolas Toromanoff {
6004b898d5cSNicolas Toromanoff 	size_t written;
6014b898d5cSNicolas Toromanoff 	size_t len;
6024b898d5cSNicolas Toromanoff 	u32 alen = cryp->areq->assoclen;
6034b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
6044b898d5cSNicolas Toromanoff 	u8 *b8 = (u8 *)block;
6054b898d5cSNicolas Toromanoff 
6064b898d5cSNicolas Toromanoff 	if (alen <= 65280) {
6074b898d5cSNicolas Toromanoff 		/* Write first u32 of B1 */
6084b898d5cSNicolas Toromanoff 		b8[0] = (alen >> 8) & 0xFF;
6094b898d5cSNicolas Toromanoff 		b8[1] = alen & 0xFF;
6104b898d5cSNicolas Toromanoff 		len = 2;
6114b898d5cSNicolas Toromanoff 	} else {
6124b898d5cSNicolas Toromanoff 		/* Build the two first u32 of B1 */
6134b898d5cSNicolas Toromanoff 		b8[0] = 0xFF;
6144b898d5cSNicolas Toromanoff 		b8[1] = 0xFE;
6154b898d5cSNicolas Toromanoff 		b8[2] = (alen & 0xFF000000) >> 24;
6164b898d5cSNicolas Toromanoff 		b8[3] = (alen & 0x00FF0000) >> 16;
6174b898d5cSNicolas Toromanoff 		b8[4] = (alen & 0x0000FF00) >> 8;
6184b898d5cSNicolas Toromanoff 		b8[5] = alen & 0x000000FF;
6194b898d5cSNicolas Toromanoff 		len = 6;
6204b898d5cSNicolas Toromanoff 	}
6214b898d5cSNicolas Toromanoff 
6224b898d5cSNicolas Toromanoff 	written = min_t(size_t, AES_BLOCK_SIZE - len, alen);
6234b898d5cSNicolas Toromanoff 
6244b898d5cSNicolas Toromanoff 	scatterwalk_copychunks((char *)block + len, &cryp->in_walk, written, 0);
625*319ad16dSLinus Walleij 
626*319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
6274b898d5cSNicolas Toromanoff 
6284b898d5cSNicolas Toromanoff 	cryp->header_in -= written;
6294b898d5cSNicolas Toromanoff 
6304b898d5cSNicolas Toromanoff 	stm32_crypt_gcmccm_end_header(cryp);
6314b898d5cSNicolas Toromanoff }
6324b898d5cSNicolas Toromanoff 
6339d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg)
6349d3b5030SFabien DESSENNE {
6359d3b5030SFabien DESSENNE 	int ret;
6364b898d5cSNicolas Toromanoff 	u32 iv_32[AES_BLOCK_32], b0_32[AES_BLOCK_32];
6374b898d5cSNicolas Toromanoff 	u8 *iv = (u8 *)iv_32, *b0 = (u8 *)b0_32;
638bbb28326SHerbert Xu 	__be32 *bd;
6399d3b5030SFabien DESSENNE 	u32 *d;
6409d3b5030SFabien DESSENNE 	unsigned int i, textlen;
6419d3b5030SFabien DESSENNE 
6429d3b5030SFabien DESSENNE 	/* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */
6439d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
6449d3b5030SFabien DESSENNE 	memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
6459d3b5030SFabien DESSENNE 	iv[AES_BLOCK_SIZE - 1] = 1;
646bbb28326SHerbert Xu 	stm32_cryp_hw_write_iv(cryp, (__be32 *)iv);
6479d3b5030SFabien DESSENNE 
6489d3b5030SFabien DESSENNE 	/* Build B0 */
6499d3b5030SFabien DESSENNE 	memcpy(b0, iv, AES_BLOCK_SIZE);
6509d3b5030SFabien DESSENNE 
6519d3b5030SFabien DESSENNE 	b0[0] |= (8 * ((cryp->authsize - 2) / 2));
6529d3b5030SFabien DESSENNE 
6539d3b5030SFabien DESSENNE 	if (cryp->areq->assoclen)
6549d3b5030SFabien DESSENNE 		b0[0] |= 0x40;
6559d3b5030SFabien DESSENNE 
6569d3b5030SFabien DESSENNE 	textlen = stm32_cryp_get_input_text_len(cryp);
6579d3b5030SFabien DESSENNE 
6589d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 2] = textlen >> 8;
6599d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF;
6609d3b5030SFabien DESSENNE 
6619d3b5030SFabien DESSENNE 	/* Enable HW */
6620b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
6639d3b5030SFabien DESSENNE 
6649d3b5030SFabien DESSENNE 	/* Write B0 */
6659d3b5030SFabien DESSENNE 	d = (u32 *)b0;
666bbb28326SHerbert Xu 	bd = (__be32 *)b0;
6679d3b5030SFabien DESSENNE 
6689d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
669bbb28326SHerbert Xu 		u32 xd = d[i];
670bbb28326SHerbert Xu 
6719d3b5030SFabien DESSENNE 		if (!cryp->caps->padding_wa)
672bbb28326SHerbert Xu 			xd = be32_to_cpu(bd[i]);
6730b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, xd);
6749d3b5030SFabien DESSENNE 	}
6759d3b5030SFabien DESSENNE 
6769d3b5030SFabien DESSENNE 	/* Wait for end of processing */
6779d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
6784b898d5cSNicolas Toromanoff 	if (ret) {
6799d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (ccm init)\n");
6809d3b5030SFabien DESSENNE 		return ret;
6819d3b5030SFabien DESSENNE 	}
6829d3b5030SFabien DESSENNE 
6834b898d5cSNicolas Toromanoff 	/* Prepare next phase */
6844b898d5cSNicolas Toromanoff 	if (cryp->areq->assoclen) {
6854b898d5cSNicolas Toromanoff 		cfg |= CR_PH_HEADER | CR_CRYPEN;
6860b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6874b898d5cSNicolas Toromanoff 
6884b898d5cSNicolas Toromanoff 		/* Write first (special) block (may move to next phase [payload]) */
6894b898d5cSNicolas Toromanoff 		stm32_cryp_write_ccm_first_header(cryp);
6904b898d5cSNicolas Toromanoff 	} else if (stm32_cryp_get_input_text_len(cryp)) {
6914b898d5cSNicolas Toromanoff 		cfg |= CR_PH_PAYLOAD;
6920b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6934b898d5cSNicolas Toromanoff 	}
6944b898d5cSNicolas Toromanoff 
6954b898d5cSNicolas Toromanoff 	return 0;
6964b898d5cSNicolas Toromanoff }
6974b898d5cSNicolas Toromanoff 
6989e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
6999e054ec2SFabien DESSENNE {
7009e054ec2SFabien DESSENNE 	int ret;
7019e054ec2SFabien DESSENNE 	u32 cfg, hw_mode;
7023d6b6613SHerbert Xu 
7033d6b6613SHerbert Xu 	pm_runtime_get_sync(cryp->dev);
70465f9aa36Slionel.debieve@st.com 
7059e054ec2SFabien DESSENNE 	/* Disable interrupt */
7060b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
7079e054ec2SFabien DESSENNE 
7089e054ec2SFabien DESSENNE 	/* Set configuration */
7099e054ec2SFabien DESSENNE 	cfg = CR_DATA8 | CR_FFLUSH;
7109e054ec2SFabien DESSENNE 
7119e054ec2SFabien DESSENNE 	switch (cryp->ctx->keylen) {
7129e054ec2SFabien DESSENNE 	case AES_KEYSIZE_128:
7139e054ec2SFabien DESSENNE 		cfg |= CR_KEY128;
7149e054ec2SFabien DESSENNE 		break;
7159e054ec2SFabien DESSENNE 
7169e054ec2SFabien DESSENNE 	case AES_KEYSIZE_192:
7179e054ec2SFabien DESSENNE 		cfg |= CR_KEY192;
7189e054ec2SFabien DESSENNE 		break;
7199e054ec2SFabien DESSENNE 
7209e054ec2SFabien DESSENNE 	default:
7219e054ec2SFabien DESSENNE 	case AES_KEYSIZE_256:
7229e054ec2SFabien DESSENNE 		cfg |= CR_KEY256;
7239e054ec2SFabien DESSENNE 		break;
7249e054ec2SFabien DESSENNE 	}
7259e054ec2SFabien DESSENNE 
7269e054ec2SFabien DESSENNE 	hw_mode = stm32_cryp_get_hw_mode(cryp);
7279e054ec2SFabien DESSENNE 	if (hw_mode == CR_AES_UNKNOWN)
7289e054ec2SFabien DESSENNE 		return -EINVAL;
7299e054ec2SFabien DESSENNE 
7309e054ec2SFabien DESSENNE 	/* AES ECB/CBC decrypt: run key preparation first */
7319e054ec2SFabien DESSENNE 	if (is_decrypt(cryp) &&
7329e054ec2SFabien DESSENNE 	    ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
73395fe2253SNicolas Toromanoff 		/* Configure in key preparation mode */
7340b496efbSLinus Walleij 		if (cryp->caps->kp_mode)
7350b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr,
7360b496efbSLinus Walleij 				cfg | CR_AES_KP);
7370b496efbSLinus Walleij 		else
7380b496efbSLinus Walleij 			stm32_cryp_write(cryp,
7390b496efbSLinus Walleij 				cryp->caps->cr, cfg | CR_AES_ECB | CR_KSE);
7409e054ec2SFabien DESSENNE 
74195fe2253SNicolas Toromanoff 		/* Set key only after full configuration done */
74295fe2253SNicolas Toromanoff 		stm32_cryp_hw_write_key(cryp);
74395fe2253SNicolas Toromanoff 
74495fe2253SNicolas Toromanoff 		/* Start prepare key */
74595fe2253SNicolas Toromanoff 		stm32_cryp_enable(cryp);
7469e054ec2SFabien DESSENNE 		/* Wait for end of processing */
7479e054ec2SFabien DESSENNE 		ret = stm32_cryp_wait_busy(cryp);
7489e054ec2SFabien DESSENNE 		if (ret) {
7499e054ec2SFabien DESSENNE 			dev_err(cryp->dev, "Timeout (key preparation)\n");
7509e054ec2SFabien DESSENNE 			return ret;
7519e054ec2SFabien DESSENNE 		}
7529e054ec2SFabien DESSENNE 
75395fe2253SNicolas Toromanoff 		cfg |= hw_mode | CR_DEC_NOT_ENC;
75495fe2253SNicolas Toromanoff 
75595fe2253SNicolas Toromanoff 		/* Apply updated config (Decrypt + algo) and flush */
7560b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
75795fe2253SNicolas Toromanoff 	} else {
7589e054ec2SFabien DESSENNE 		cfg |= hw_mode;
7599e054ec2SFabien DESSENNE 		if (is_decrypt(cryp))
7609e054ec2SFabien DESSENNE 			cfg |= CR_DEC_NOT_ENC;
7619e054ec2SFabien DESSENNE 
76295fe2253SNicolas Toromanoff 		/* Apply config and flush */
7630b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
7649e054ec2SFabien DESSENNE 
76595fe2253SNicolas Toromanoff 		/* Set key only after configuration done */
76695fe2253SNicolas Toromanoff 		stm32_cryp_hw_write_key(cryp);
76795fe2253SNicolas Toromanoff 	}
76895fe2253SNicolas Toromanoff 
7699e054ec2SFabien DESSENNE 	switch (hw_mode) {
7709d3b5030SFabien DESSENNE 	case CR_AES_GCM:
7719d3b5030SFabien DESSENNE 	case CR_AES_CCM:
7729d3b5030SFabien DESSENNE 		/* Phase 1 : init */
7739d3b5030SFabien DESSENNE 		if (hw_mode == CR_AES_CCM)
7749d3b5030SFabien DESSENNE 			ret = stm32_cryp_ccm_init(cryp, cfg);
7759d3b5030SFabien DESSENNE 		else
7769d3b5030SFabien DESSENNE 			ret = stm32_cryp_gcm_init(cryp, cfg);
7779d3b5030SFabien DESSENNE 
7789d3b5030SFabien DESSENNE 		if (ret)
7799d3b5030SFabien DESSENNE 			return ret;
7809d3b5030SFabien DESSENNE 
7819d3b5030SFabien DESSENNE 		break;
7829d3b5030SFabien DESSENNE 
7839e054ec2SFabien DESSENNE 	case CR_DES_CBC:
7849e054ec2SFabien DESSENNE 	case CR_TDES_CBC:
7859e054ec2SFabien DESSENNE 	case CR_AES_CBC:
7869e054ec2SFabien DESSENNE 	case CR_AES_CTR:
787bbb28326SHerbert Xu 		stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->req->iv);
7889e054ec2SFabien DESSENNE 		break;
7899e054ec2SFabien DESSENNE 
7909e054ec2SFabien DESSENNE 	default:
7919e054ec2SFabien DESSENNE 		break;
7929e054ec2SFabien DESSENNE 	}
7939e054ec2SFabien DESSENNE 
7949e054ec2SFabien DESSENNE 	/* Enable now */
79595fe2253SNicolas Toromanoff 	stm32_cryp_enable(cryp);
7969e054ec2SFabien DESSENNE 
7979e054ec2SFabien DESSENNE 	return 0;
7989e054ec2SFabien DESSENNE }
7999e054ec2SFabien DESSENNE 
8009d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
8019e054ec2SFabien DESSENNE {
8029d3b5030SFabien DESSENNE 	if (!err && (is_gcm(cryp) || is_ccm(cryp)))
8039d3b5030SFabien DESSENNE 		/* Phase 4 : output tag */
8049d3b5030SFabien DESSENNE 		err = stm32_cryp_read_auth_tag(cryp);
8059e054ec2SFabien DESSENNE 
806fa97dc2dSNicolas Toromanoff 	if (!err && (!(is_gcm(cryp) || is_ccm(cryp) || is_ecb(cryp))))
8075f49f18dSLionel Debieve 		stm32_cryp_get_iv(cryp);
8085f49f18dSLionel Debieve 
80965f9aa36Slionel.debieve@st.com 	pm_runtime_mark_last_busy(cryp->dev);
81065f9aa36Slionel.debieve@st.com 	pm_runtime_put_autosuspend(cryp->dev);
81165f9aa36Slionel.debieve@st.com 
81229aed438SLionel Debieve 	if (is_gcm(cryp) || is_ccm(cryp))
8139d3b5030SFabien DESSENNE 		crypto_finalize_aead_request(cryp->engine, cryp->areq, err);
81429aed438SLionel Debieve 	else
81547ece481SArd Biesheuvel 		crypto_finalize_skcipher_request(cryp->engine, cryp->req,
8169d3b5030SFabien DESSENNE 						   err);
8179e054ec2SFabien DESSENNE }
8189e054ec2SFabien DESSENNE 
8199e054ec2SFabien DESSENNE static int stm32_cryp_cpu_start(struct stm32_cryp *cryp)
8209e054ec2SFabien DESSENNE {
8219e054ec2SFabien DESSENNE 	/* Enable interrupt and let the IRQ handler do everything */
8220b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, IMSCR_IN | IMSCR_OUT);
8239e054ec2SFabien DESSENNE 
8249e054ec2SFabien DESSENNE 	return 0;
8259e054ec2SFabien DESSENNE }
8269e054ec2SFabien DESSENNE 
827dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq);
828dc7bcef5SCorentin LABBE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
829dc7bcef5SCorentin LABBE 					 void *areq);
830dc7bcef5SCorentin LABBE 
83147ece481SArd Biesheuvel static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm)
8329e054ec2SFabien DESSENNE {
83347ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
834dc7bcef5SCorentin LABBE 
83547ece481SArd Biesheuvel 	crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx));
8369e054ec2SFabien DESSENNE 
837dc7bcef5SCorentin LABBE 	ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req;
838dc7bcef5SCorentin LABBE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req;
839dc7bcef5SCorentin LABBE 	ctx->enginectx.op.unprepare_request = NULL;
8409e054ec2SFabien DESSENNE 	return 0;
8419e054ec2SFabien DESSENNE }
8429e054ec2SFabien DESSENNE 
8439d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq);
8449d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine,
8459d3b5030SFabien DESSENNE 				       void *areq);
8469d3b5030SFabien DESSENNE 
8479d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm)
8489d3b5030SFabien DESSENNE {
8499d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
8509d3b5030SFabien DESSENNE 
8519d3b5030SFabien DESSENNE 	tfm->reqsize = sizeof(struct stm32_cryp_reqctx);
8529d3b5030SFabien DESSENNE 
8539d3b5030SFabien DESSENNE 	ctx->enginectx.op.do_one_request = stm32_cryp_aead_one_req;
8549d3b5030SFabien DESSENNE 	ctx->enginectx.op.prepare_request = stm32_cryp_prepare_aead_req;
8559d3b5030SFabien DESSENNE 	ctx->enginectx.op.unprepare_request = NULL;
8569d3b5030SFabien DESSENNE 
8579d3b5030SFabien DESSENNE 	return 0;
8589d3b5030SFabien DESSENNE }
8599d3b5030SFabien DESSENNE 
86047ece481SArd Biesheuvel static int stm32_cryp_crypt(struct skcipher_request *req, unsigned long mode)
8619e054ec2SFabien DESSENNE {
86247ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
86347ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
86447ece481SArd Biesheuvel 	struct stm32_cryp_reqctx *rctx = skcipher_request_ctx(req);
8659e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
8669e054ec2SFabien DESSENNE 
8679e054ec2SFabien DESSENNE 	if (!cryp)
8689e054ec2SFabien DESSENNE 		return -ENODEV;
8699e054ec2SFabien DESSENNE 
8709e054ec2SFabien DESSENNE 	rctx->mode = mode;
8719e054ec2SFabien DESSENNE 
87247ece481SArd Biesheuvel 	return crypto_transfer_skcipher_request_to_engine(cryp->engine, req);
8739e054ec2SFabien DESSENNE }
8749e054ec2SFabien DESSENNE 
8759d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode)
8769d3b5030SFabien DESSENNE {
8779d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
8789d3b5030SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx = aead_request_ctx(req);
8799d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
8809d3b5030SFabien DESSENNE 
8819d3b5030SFabien DESSENNE 	if (!cryp)
8829d3b5030SFabien DESSENNE 		return -ENODEV;
8839d3b5030SFabien DESSENNE 
8849d3b5030SFabien DESSENNE 	rctx->mode = mode;
8859d3b5030SFabien DESSENNE 
8869d3b5030SFabien DESSENNE 	return crypto_transfer_aead_request_to_engine(cryp->engine, req);
8879d3b5030SFabien DESSENNE }
8889d3b5030SFabien DESSENNE 
88947ece481SArd Biesheuvel static int stm32_cryp_setkey(struct crypto_skcipher *tfm, const u8 *key,
8909e054ec2SFabien DESSENNE 			     unsigned int keylen)
8919e054ec2SFabien DESSENNE {
89247ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
8939e054ec2SFabien DESSENNE 
8949e054ec2SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
8959e054ec2SFabien DESSENNE 	ctx->keylen = keylen;
8969e054ec2SFabien DESSENNE 
8979e054ec2SFabien DESSENNE 	return 0;
8989e054ec2SFabien DESSENNE }
8999e054ec2SFabien DESSENNE 
90047ece481SArd Biesheuvel static int stm32_cryp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
9019e054ec2SFabien DESSENNE 				 unsigned int keylen)
9029e054ec2SFabien DESSENNE {
9039e054ec2SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
9049e054ec2SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
9059e054ec2SFabien DESSENNE 		return -EINVAL;
9069e054ec2SFabien DESSENNE 	else
9079e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
9089e054ec2SFabien DESSENNE }
9099e054ec2SFabien DESSENNE 
91047ece481SArd Biesheuvel static int stm32_cryp_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
9119e054ec2SFabien DESSENNE 				 unsigned int keylen)
9129e054ec2SFabien DESSENNE {
91347ece481SArd Biesheuvel 	return verify_skcipher_des_key(tfm, key) ?:
914b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
9159e054ec2SFabien DESSENNE }
9169e054ec2SFabien DESSENNE 
91747ece481SArd Biesheuvel static int stm32_cryp_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key,
9189e054ec2SFabien DESSENNE 				  unsigned int keylen)
9199e054ec2SFabien DESSENNE {
92047ece481SArd Biesheuvel 	return verify_skcipher_des3_key(tfm, key) ?:
921b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
9229e054ec2SFabien DESSENNE }
9239e054ec2SFabien DESSENNE 
9249d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
9259d3b5030SFabien DESSENNE 				      unsigned int keylen)
9269d3b5030SFabien DESSENNE {
9279d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
9289d3b5030SFabien DESSENNE 
9299d3b5030SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
9309d3b5030SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
9319d3b5030SFabien DESSENNE 		return -EINVAL;
9329d3b5030SFabien DESSENNE 
9339d3b5030SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
9349d3b5030SFabien DESSENNE 	ctx->keylen = keylen;
9359d3b5030SFabien DESSENNE 
9369d3b5030SFabien DESSENNE 	return 0;
9379d3b5030SFabien DESSENNE }
9389d3b5030SFabien DESSENNE 
9399d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
9409d3b5030SFabien DESSENNE 					  unsigned int authsize)
9419d3b5030SFabien DESSENNE {
94239e6e699SNicolas Toromanoff 	switch (authsize) {
94339e6e699SNicolas Toromanoff 	case 4:
94439e6e699SNicolas Toromanoff 	case 8:
94539e6e699SNicolas Toromanoff 	case 12:
94639e6e699SNicolas Toromanoff 	case 13:
94739e6e699SNicolas Toromanoff 	case 14:
94839e6e699SNicolas Toromanoff 	case 15:
94939e6e699SNicolas Toromanoff 	case 16:
95039e6e699SNicolas Toromanoff 		break;
95139e6e699SNicolas Toromanoff 	default:
95239e6e699SNicolas Toromanoff 		return -EINVAL;
95339e6e699SNicolas Toromanoff 	}
95439e6e699SNicolas Toromanoff 
95539e6e699SNicolas Toromanoff 	return 0;
9569d3b5030SFabien DESSENNE }
9579d3b5030SFabien DESSENNE 
9589d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
9599d3b5030SFabien DESSENNE 					  unsigned int authsize)
9609d3b5030SFabien DESSENNE {
9619d3b5030SFabien DESSENNE 	switch (authsize) {
9629d3b5030SFabien DESSENNE 	case 4:
9639d3b5030SFabien DESSENNE 	case 6:
9649d3b5030SFabien DESSENNE 	case 8:
9659d3b5030SFabien DESSENNE 	case 10:
9669d3b5030SFabien DESSENNE 	case 12:
9679d3b5030SFabien DESSENNE 	case 14:
9689d3b5030SFabien DESSENNE 	case 16:
9699d3b5030SFabien DESSENNE 		break;
9709d3b5030SFabien DESSENNE 	default:
9719d3b5030SFabien DESSENNE 		return -EINVAL;
9729d3b5030SFabien DESSENNE 	}
9739d3b5030SFabien DESSENNE 
9749d3b5030SFabien DESSENNE 	return 0;
9759d3b5030SFabien DESSENNE }
9769d3b5030SFabien DESSENNE 
97747ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req)
9789e054ec2SFabien DESSENNE {
97939e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
98039e6e699SNicolas Toromanoff 		return -EINVAL;
98139e6e699SNicolas Toromanoff 
98239e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
98339e6e699SNicolas Toromanoff 		return 0;
98439e6e699SNicolas Toromanoff 
9859e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
9869e054ec2SFabien DESSENNE }
9879e054ec2SFabien DESSENNE 
98847ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req)
9899e054ec2SFabien DESSENNE {
99039e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
99139e6e699SNicolas Toromanoff 		return -EINVAL;
99239e6e699SNicolas Toromanoff 
99339e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
99439e6e699SNicolas Toromanoff 		return 0;
99539e6e699SNicolas Toromanoff 
9969e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
9979e054ec2SFabien DESSENNE }
9989e054ec2SFabien DESSENNE 
99947ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req)
10009e054ec2SFabien DESSENNE {
100139e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
100239e6e699SNicolas Toromanoff 		return -EINVAL;
100339e6e699SNicolas Toromanoff 
100439e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
100539e6e699SNicolas Toromanoff 		return 0;
100639e6e699SNicolas Toromanoff 
10079e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
10089e054ec2SFabien DESSENNE }
10099e054ec2SFabien DESSENNE 
101047ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req)
10119e054ec2SFabien DESSENNE {
101239e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
101339e6e699SNicolas Toromanoff 		return -EINVAL;
101439e6e699SNicolas Toromanoff 
101539e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
101639e6e699SNicolas Toromanoff 		return 0;
101739e6e699SNicolas Toromanoff 
10189e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
10199e054ec2SFabien DESSENNE }
10209e054ec2SFabien DESSENNE 
102147ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req)
10229e054ec2SFabien DESSENNE {
102339e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
102439e6e699SNicolas Toromanoff 		return 0;
102539e6e699SNicolas Toromanoff 
10269e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
10279e054ec2SFabien DESSENNE }
10289e054ec2SFabien DESSENNE 
102947ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req)
10309e054ec2SFabien DESSENNE {
103139e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
103239e6e699SNicolas Toromanoff 		return 0;
103339e6e699SNicolas Toromanoff 
10349e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
10359e054ec2SFabien DESSENNE }
10369e054ec2SFabien DESSENNE 
10379d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req)
10389d3b5030SFabien DESSENNE {
10399d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT);
10409d3b5030SFabien DESSENNE }
10419d3b5030SFabien DESSENNE 
10429d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
10439d3b5030SFabien DESSENNE {
10449d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
10459d3b5030SFabien DESSENNE }
10469d3b5030SFabien DESSENNE 
104739e6e699SNicolas Toromanoff static inline int crypto_ccm_check_iv(const u8 *iv)
104839e6e699SNicolas Toromanoff {
104939e6e699SNicolas Toromanoff 	/* 2 <= L <= 8, so 1 <= L' <= 7. */
105039e6e699SNicolas Toromanoff 	if (iv[0] < 1 || iv[0] > 7)
105139e6e699SNicolas Toromanoff 		return -EINVAL;
105239e6e699SNicolas Toromanoff 
105339e6e699SNicolas Toromanoff 	return 0;
105439e6e699SNicolas Toromanoff }
105539e6e699SNicolas Toromanoff 
10569d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req)
10579d3b5030SFabien DESSENNE {
105839e6e699SNicolas Toromanoff 	int err;
105939e6e699SNicolas Toromanoff 
106039e6e699SNicolas Toromanoff 	err = crypto_ccm_check_iv(req->iv);
106139e6e699SNicolas Toromanoff 	if (err)
106239e6e699SNicolas Toromanoff 		return err;
106339e6e699SNicolas Toromanoff 
10649d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT);
10659d3b5030SFabien DESSENNE }
10669d3b5030SFabien DESSENNE 
10679d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req)
10689d3b5030SFabien DESSENNE {
106939e6e699SNicolas Toromanoff 	int err;
107039e6e699SNicolas Toromanoff 
107139e6e699SNicolas Toromanoff 	err = crypto_ccm_check_iv(req->iv);
107239e6e699SNicolas Toromanoff 	if (err)
107339e6e699SNicolas Toromanoff 		return err;
107439e6e699SNicolas Toromanoff 
10759d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
10769d3b5030SFabien DESSENNE }
10779d3b5030SFabien DESSENNE 
107847ece481SArd Biesheuvel static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req)
10799e054ec2SFabien DESSENNE {
108039e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
108139e6e699SNicolas Toromanoff 		return -EINVAL;
108239e6e699SNicolas Toromanoff 
108339e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
108439e6e699SNicolas Toromanoff 		return 0;
108539e6e699SNicolas Toromanoff 
10869e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
10879e054ec2SFabien DESSENNE }
10889e054ec2SFabien DESSENNE 
108947ece481SArd Biesheuvel static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req)
10909e054ec2SFabien DESSENNE {
109139e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
109239e6e699SNicolas Toromanoff 		return -EINVAL;
109339e6e699SNicolas Toromanoff 
109439e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
109539e6e699SNicolas Toromanoff 		return 0;
109639e6e699SNicolas Toromanoff 
10979e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
10989e054ec2SFabien DESSENNE }
10999e054ec2SFabien DESSENNE 
110047ece481SArd Biesheuvel static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req)
11019e054ec2SFabien DESSENNE {
110239e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
110339e6e699SNicolas Toromanoff 		return -EINVAL;
110439e6e699SNicolas Toromanoff 
110539e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
110639e6e699SNicolas Toromanoff 		return 0;
110739e6e699SNicolas Toromanoff 
11089e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
11099e054ec2SFabien DESSENNE }
11109e054ec2SFabien DESSENNE 
111147ece481SArd Biesheuvel static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req)
11129e054ec2SFabien DESSENNE {
111339e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
111439e6e699SNicolas Toromanoff 		return -EINVAL;
111539e6e699SNicolas Toromanoff 
111639e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
111739e6e699SNicolas Toromanoff 		return 0;
111839e6e699SNicolas Toromanoff 
11199e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
11209e054ec2SFabien DESSENNE }
11219e054ec2SFabien DESSENNE 
112247ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req)
11239e054ec2SFabien DESSENNE {
112439e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
112539e6e699SNicolas Toromanoff 		return -EINVAL;
112639e6e699SNicolas Toromanoff 
112739e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
112839e6e699SNicolas Toromanoff 		return 0;
112939e6e699SNicolas Toromanoff 
11309e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
11319e054ec2SFabien DESSENNE }
11329e054ec2SFabien DESSENNE 
113347ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req)
11349e054ec2SFabien DESSENNE {
113539e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
113639e6e699SNicolas Toromanoff 		return -EINVAL;
113739e6e699SNicolas Toromanoff 
113839e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
113939e6e699SNicolas Toromanoff 		return 0;
114039e6e699SNicolas Toromanoff 
11419e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
11429e054ec2SFabien DESSENNE }
11439e054ec2SFabien DESSENNE 
114447ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req)
11459e054ec2SFabien DESSENNE {
114639e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
114739e6e699SNicolas Toromanoff 		return -EINVAL;
114839e6e699SNicolas Toromanoff 
114939e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
115039e6e699SNicolas Toromanoff 		return 0;
115139e6e699SNicolas Toromanoff 
11529e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
11539e054ec2SFabien DESSENNE }
11549e054ec2SFabien DESSENNE 
115547ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req)
11569e054ec2SFabien DESSENNE {
115739e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
115839e6e699SNicolas Toromanoff 		return -EINVAL;
115939e6e699SNicolas Toromanoff 
116039e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
116139e6e699SNicolas Toromanoff 		return 0;
116239e6e699SNicolas Toromanoff 
11639e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
11649e054ec2SFabien DESSENNE }
11659e054ec2SFabien DESSENNE 
116647ece481SArd Biesheuvel static int stm32_cryp_prepare_req(struct skcipher_request *req,
11679d3b5030SFabien DESSENNE 				  struct aead_request *areq)
11689e054ec2SFabien DESSENNE {
11699e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx;
11709e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
11719e054ec2SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx;
11724b898d5cSNicolas Toromanoff 	struct scatterlist *in_sg;
11739e054ec2SFabien DESSENNE 	int ret;
11749e054ec2SFabien DESSENNE 
11759d3b5030SFabien DESSENNE 	if (!req && !areq)
11769e054ec2SFabien DESSENNE 		return -EINVAL;
11779e054ec2SFabien DESSENNE 
117847ece481SArd Biesheuvel 	ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) :
11799d3b5030SFabien DESSENNE 		    crypto_aead_ctx(crypto_aead_reqtfm(areq));
11809e054ec2SFabien DESSENNE 
11819e054ec2SFabien DESSENNE 	cryp = ctx->cryp;
11829e054ec2SFabien DESSENNE 
11839e054ec2SFabien DESSENNE 	if (!cryp)
11849e054ec2SFabien DESSENNE 		return -ENODEV;
11859e054ec2SFabien DESSENNE 
118647ece481SArd Biesheuvel 	rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq);
11879e054ec2SFabien DESSENNE 	rctx->mode &= FLG_MODE_MASK;
11889e054ec2SFabien DESSENNE 
11899e054ec2SFabien DESSENNE 	ctx->cryp = cryp;
11909e054ec2SFabien DESSENNE 
11919e054ec2SFabien DESSENNE 	cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode;
11929e054ec2SFabien DESSENNE 	cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE;
11939e054ec2SFabien DESSENNE 	cryp->ctx = ctx;
11949e054ec2SFabien DESSENNE 
11959d3b5030SFabien DESSENNE 	if (req) {
11969e054ec2SFabien DESSENNE 		cryp->req = req;
119729aed438SLionel Debieve 		cryp->areq = NULL;
11984b898d5cSNicolas Toromanoff 		cryp->header_in = 0;
11994b898d5cSNicolas Toromanoff 		cryp->payload_in = req->cryptlen;
12004b898d5cSNicolas Toromanoff 		cryp->payload_out = req->cryptlen;
12014b898d5cSNicolas Toromanoff 		cryp->authsize = 0;
12029d3b5030SFabien DESSENNE 	} else {
12039d3b5030SFabien DESSENNE 		/*
12049d3b5030SFabien DESSENNE 		 * Length of input and output data:
12059d3b5030SFabien DESSENNE 		 * Encryption case:
12069d3b5030SFabien DESSENNE 		 *  INPUT  = AssocData   ||     PlainText
12079d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->
12089d3b5030SFabien DESSENNE 		 *
12099d3b5030SFabien DESSENNE 		 *  OUTPUT = AssocData    ||   CipherText   ||      AuthTag
12104b898d5cSNicolas Toromanoff 		 *          <- assoclen ->  <-- cryptlen -->  <- authsize ->
12119d3b5030SFabien DESSENNE 		 *
12129d3b5030SFabien DESSENNE 		 * Decryption case:
12134b898d5cSNicolas Toromanoff 		 *  INPUT  =  AssocData     ||    CipherTex   ||       AuthTag
12144b898d5cSNicolas Toromanoff 		 *          <- assoclen --->  <---------- cryptlen ---------->
12159d3b5030SFabien DESSENNE 		 *
12169d3b5030SFabien DESSENNE 		 *  OUTPUT = AssocData    ||               PlainText
12174b898d5cSNicolas Toromanoff 		 *          <- assoclen ->  <- cryptlen - authsize ->
12189d3b5030SFabien DESSENNE 		 */
12199d3b5030SFabien DESSENNE 		cryp->areq = areq;
122029aed438SLionel Debieve 		cryp->req = NULL;
12219d3b5030SFabien DESSENNE 		cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
12224b898d5cSNicolas Toromanoff 		if (is_encrypt(cryp)) {
12234b898d5cSNicolas Toromanoff 			cryp->payload_in = areq->cryptlen;
12244b898d5cSNicolas Toromanoff 			cryp->header_in = areq->assoclen;
12254b898d5cSNicolas Toromanoff 			cryp->payload_out = areq->cryptlen;
12264b898d5cSNicolas Toromanoff 		} else {
12274b898d5cSNicolas Toromanoff 			cryp->payload_in = areq->cryptlen - cryp->authsize;
12284b898d5cSNicolas Toromanoff 			cryp->header_in = areq->assoclen;
12294b898d5cSNicolas Toromanoff 			cryp->payload_out = cryp->payload_in;
12304b898d5cSNicolas Toromanoff 		}
12319d3b5030SFabien DESSENNE 	}
12329e054ec2SFabien DESSENNE 
12334b898d5cSNicolas Toromanoff 	in_sg = req ? req->src : areq->src;
12344b898d5cSNicolas Toromanoff 	scatterwalk_start(&cryp->in_walk, in_sg);
12359e054ec2SFabien DESSENNE 
12369d3b5030SFabien DESSENNE 	cryp->out_sg = req ? req->dst : areq->dst;
12379e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->out_walk, cryp->out_sg);
12389e054ec2SFabien DESSENNE 
12399d3b5030SFabien DESSENNE 	if (is_gcm(cryp) || is_ccm(cryp)) {
12409d3b5030SFabien DESSENNE 		/* In output, jump after assoc data */
12414b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->areq->assoclen, 2);
12429d3b5030SFabien DESSENNE 	}
12439d3b5030SFabien DESSENNE 
12444b898d5cSNicolas Toromanoff 	if (is_ctr(cryp))
12454b898d5cSNicolas Toromanoff 		memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr));
12464b898d5cSNicolas Toromanoff 
12479e054ec2SFabien DESSENNE 	ret = stm32_cryp_hw_init(cryp);
12489e054ec2SFabien DESSENNE 	return ret;
12499e054ec2SFabien DESSENNE }
12509e054ec2SFabien DESSENNE 
12519e054ec2SFabien DESSENNE static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine,
1252dc7bcef5SCorentin LABBE 					 void *areq)
12539e054ec2SFabien DESSENNE {
125447ece481SArd Biesheuvel 	struct skcipher_request *req = container_of(areq,
125547ece481SArd Biesheuvel 						      struct skcipher_request,
1256dc7bcef5SCorentin LABBE 						      base);
1257dc7bcef5SCorentin LABBE 
12589d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(req, NULL);
12599e054ec2SFabien DESSENNE }
12609e054ec2SFabien DESSENNE 
1261dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq)
12629e054ec2SFabien DESSENNE {
126347ece481SArd Biesheuvel 	struct skcipher_request *req = container_of(areq,
126447ece481SArd Biesheuvel 						      struct skcipher_request,
1265dc7bcef5SCorentin LABBE 						      base);
126647ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
126747ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
12689e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
12699e054ec2SFabien DESSENNE 
12709e054ec2SFabien DESSENNE 	if (!cryp)
12719e054ec2SFabien DESSENNE 		return -ENODEV;
12729e054ec2SFabien DESSENNE 
12739e054ec2SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
12749e054ec2SFabien DESSENNE }
12759e054ec2SFabien DESSENNE 
12769d3b5030SFabien DESSENNE static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq)
12779d3b5030SFabien DESSENNE {
12789d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
12799d3b5030SFabien DESSENNE 						base);
12809d3b5030SFabien DESSENNE 
12819d3b5030SFabien DESSENNE 	return stm32_cryp_prepare_req(NULL, req);
12829d3b5030SFabien DESSENNE }
12839d3b5030SFabien DESSENNE 
12849d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq)
12859d3b5030SFabien DESSENNE {
12869d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
12879d3b5030SFabien DESSENNE 						base);
12889d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
12899d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
12909d3b5030SFabien DESSENNE 
12919d3b5030SFabien DESSENNE 	if (!cryp)
12929d3b5030SFabien DESSENNE 		return -ENODEV;
12939d3b5030SFabien DESSENNE 
12944b898d5cSNicolas Toromanoff 	if (unlikely(!cryp->payload_in && !cryp->header_in)) {
12959d3b5030SFabien DESSENNE 		/* No input data to process: get tag and finish */
12969d3b5030SFabien DESSENNE 		stm32_cryp_finish_req(cryp, 0);
12979d3b5030SFabien DESSENNE 		return 0;
12989d3b5030SFabien DESSENNE 	}
12999d3b5030SFabien DESSENNE 
13009d3b5030SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
13019d3b5030SFabien DESSENNE }
13029d3b5030SFabien DESSENNE 
13039d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
13049d3b5030SFabien DESSENNE {
13054b898d5cSNicolas Toromanoff 	u32 cfg, size_bit;
13064b898d5cSNicolas Toromanoff 	unsigned int i;
13079d3b5030SFabien DESSENNE 	int ret = 0;
13089d3b5030SFabien DESSENNE 
13099d3b5030SFabien DESSENNE 	/* Update Config */
13100b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
13119d3b5030SFabien DESSENNE 
13129d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
13139d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
13149d3b5030SFabien DESSENNE 	cfg &= ~CR_DEC_NOT_ENC;
13159d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
13169d3b5030SFabien DESSENNE 
13170b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
13189d3b5030SFabien DESSENNE 
13199d3b5030SFabien DESSENNE 	if (is_gcm(cryp)) {
13209d3b5030SFabien DESSENNE 		/* GCM: write aad and payload size (in bits) */
13219d3b5030SFabien DESSENNE 		size_bit = cryp->areq->assoclen * 8;
13229d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1323bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
13249d3b5030SFabien DESSENNE 
13250b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, 0);
13260b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, size_bit);
13279d3b5030SFabien DESSENNE 
13289d3b5030SFabien DESSENNE 		size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
13294b898d5cSNicolas Toromanoff 				cryp->areq->cryptlen - cryp->authsize;
13309d3b5030SFabien DESSENNE 		size_bit *= 8;
13319d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1332bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
13339d3b5030SFabien DESSENNE 
13340b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, 0);
13350b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, size_bit);
13369d3b5030SFabien DESSENNE 	} else {
13379d3b5030SFabien DESSENNE 		/* CCM: write CTR0 */
13384b898d5cSNicolas Toromanoff 		u32 iv32[AES_BLOCK_32];
13394b898d5cSNicolas Toromanoff 		u8 *iv = (u8 *)iv32;
13404b898d5cSNicolas Toromanoff 		__be32 *biv = (__be32 *)iv32;
13419d3b5030SFabien DESSENNE 
13429d3b5030SFabien DESSENNE 		memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
13439d3b5030SFabien DESSENNE 		memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
13449d3b5030SFabien DESSENNE 
13459d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
1346bbb28326SHerbert Xu 			u32 xiv = iv32[i];
1347bbb28326SHerbert Xu 
13489d3b5030SFabien DESSENNE 			if (!cryp->caps->padding_wa)
1349bbb28326SHerbert Xu 				xiv = be32_to_cpu(biv[i]);
13500b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->din, xiv);
13519d3b5030SFabien DESSENNE 		}
13529d3b5030SFabien DESSENNE 	}
13539d3b5030SFabien DESSENNE 
13549d3b5030SFabien DESSENNE 	/* Wait for output data */
13559d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_output(cryp);
13569d3b5030SFabien DESSENNE 	if (ret) {
13579d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (read tag)\n");
13589d3b5030SFabien DESSENNE 		return ret;
13599d3b5030SFabien DESSENNE 	}
13609d3b5030SFabien DESSENNE 
13619d3b5030SFabien DESSENNE 	if (is_encrypt(cryp)) {
13624b898d5cSNicolas Toromanoff 		u32 out_tag[AES_BLOCK_32];
13634b898d5cSNicolas Toromanoff 
13649d3b5030SFabien DESSENNE 		/* Get and write tag */
1365*319ad16dSLinus Walleij 		readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
13664b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(out_tag, &cryp->out_walk, cryp->authsize, 1);
13679d3b5030SFabien DESSENNE 	} else {
13689d3b5030SFabien DESSENNE 		/* Get and check tag */
13699d3b5030SFabien DESSENNE 		u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
13709d3b5030SFabien DESSENNE 
13714b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(in_tag, &cryp->in_walk, cryp->authsize, 0);
1372*319ad16dSLinus Walleij 		readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
13739d3b5030SFabien DESSENNE 
13749d3b5030SFabien DESSENNE 		if (crypto_memneq(in_tag, out_tag, cryp->authsize))
13759d3b5030SFabien DESSENNE 			ret = -EBADMSG;
13769d3b5030SFabien DESSENNE 	}
13779d3b5030SFabien DESSENNE 
13789d3b5030SFabien DESSENNE 	/* Disable cryp */
13799d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
13800b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
13819d3b5030SFabien DESSENNE 
13829d3b5030SFabien DESSENNE 	return ret;
13839d3b5030SFabien DESSENNE }
13849d3b5030SFabien DESSENNE 
13859e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp)
13869e054ec2SFabien DESSENNE {
13879e054ec2SFabien DESSENNE 	u32 cr;
13889e054ec2SFabien DESSENNE 
138941c76690SNicolas Toromanoff 	if (unlikely(cryp->last_ctr[3] == cpu_to_be32(0xFFFFFFFF))) {
139041c76690SNicolas Toromanoff 		/*
139141c76690SNicolas Toromanoff 		 * In this case, we need to increment manually the ctr counter,
139241c76690SNicolas Toromanoff 		 * as HW doesn't handle the U32 carry.
139341c76690SNicolas Toromanoff 		 */
139441c76690SNicolas Toromanoff 		crypto_inc((u8 *)cryp->last_ctr, sizeof(cryp->last_ctr));
13959e054ec2SFabien DESSENNE 
13960b496efbSLinus Walleij 		cr = stm32_cryp_read(cryp, cryp->caps->cr);
13970b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cr & ~CR_CRYPEN);
13989e054ec2SFabien DESSENNE 
139941c76690SNicolas Toromanoff 		stm32_cryp_hw_write_iv(cryp, cryp->last_ctr);
14009e054ec2SFabien DESSENNE 
14010b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cr);
14029e054ec2SFabien DESSENNE 	}
14039e054ec2SFabien DESSENNE 
140441c76690SNicolas Toromanoff 	/* The IV registers are BE  */
14050b496efbSLinus Walleij 	cryp->last_ctr[0] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
14060b496efbSLinus Walleij 	cryp->last_ctr[1] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
14070b496efbSLinus Walleij 	cryp->last_ctr[2] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
14080b496efbSLinus Walleij 	cryp->last_ctr[3] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
14099e054ec2SFabien DESSENNE }
14109e054ec2SFabien DESSENNE 
14114b898d5cSNicolas Toromanoff static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
14129e054ec2SFabien DESSENNE {
14134b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32];
14149d3b5030SFabien DESSENNE 
1415*319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
14164b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
14174b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
14184b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
14194b898d5cSNicolas Toromanoff 				   cryp->payload_out);
14209e054ec2SFabien DESSENNE }
14219e054ec2SFabien DESSENNE 
14229e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
14239e054ec2SFabien DESSENNE {
14244b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
14259d3b5030SFabien DESSENNE 
14264b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, cryp->hw_blocksize,
14274b898d5cSNicolas Toromanoff 							    cryp->payload_in), 0);
1428*319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, cryp->hw_blocksize / sizeof(u32));
14294b898d5cSNicolas Toromanoff 	cryp->payload_in -= min_t(size_t, cryp->hw_blocksize, cryp->payload_in);
14309e054ec2SFabien DESSENNE }
14319e054ec2SFabien DESSENNE 
14329d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
14339d3b5030SFabien DESSENNE {
14349d3b5030SFabien DESSENNE 	int err;
14354b898d5cSNicolas Toromanoff 	u32 cfg, block[AES_BLOCK_32] = {0};
14369d3b5030SFabien DESSENNE 	unsigned int i;
14379d3b5030SFabien DESSENNE 
14389d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
14399d3b5030SFabien DESSENNE 
14409d3b5030SFabien DESSENNE 	/* a) disable ip */
14410b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
14420b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
14439d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14440b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14459d3b5030SFabien DESSENNE 
14469d3b5030SFabien DESSENNE 	/* b) Update IV1R */
14470b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv1r, cryp->gcm_ctr - 2);
14489d3b5030SFabien DESSENNE 
14499d3b5030SFabien DESSENNE 	/* c) change mode to CTR */
14509d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14519d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
14520b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14539d3b5030SFabien DESSENNE 
14549d3b5030SFabien DESSENNE 	/* a) enable IP */
14559d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14560b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14579d3b5030SFabien DESSENNE 
14589d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
14599d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
14604b898d5cSNicolas Toromanoff 	/* wait end of process */
14619d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14629d3b5030SFabien DESSENNE 	if (err) {
14634b898d5cSNicolas Toromanoff 		dev_err(cryp->dev, "Timeout (write gcm last data)\n");
14649d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14659d3b5030SFabien DESSENNE 	}
14669d3b5030SFabien DESSENNE 
14679d3b5030SFabien DESSENNE 	/* c) get and store encrypted data */
14684b898d5cSNicolas Toromanoff 	/*
14694b898d5cSNicolas Toromanoff 	 * Same code as stm32_cryp_irq_read_data(), but we want to store
14704b898d5cSNicolas Toromanoff 	 * block value
14714b898d5cSNicolas Toromanoff 	 */
1472*319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
14734b898d5cSNicolas Toromanoff 
14744b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
14754b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
14764b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
14774b898d5cSNicolas Toromanoff 				   cryp->payload_out);
14789d3b5030SFabien DESSENNE 
14799d3b5030SFabien DESSENNE 	/* d) change mode back to AES GCM */
14809d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14819d3b5030SFabien DESSENNE 	cfg |= CR_AES_GCM;
14820b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14839d3b5030SFabien DESSENNE 
14849d3b5030SFabien DESSENNE 	/* e) change phase to Final */
14859d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
14869d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
14870b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14889d3b5030SFabien DESSENNE 
14899d3b5030SFabien DESSENNE 	/* f) write padded data */
1490*319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
14919d3b5030SFabien DESSENNE 
14929d3b5030SFabien DESSENNE 	/* g) Empty fifo out */
14939d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14949d3b5030SFabien DESSENNE 	if (err) {
14954b898d5cSNicolas Toromanoff 		dev_err(cryp->dev, "Timeout (write gcm padded data)\n");
14969d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14979d3b5030SFabien DESSENNE 	}
14989d3b5030SFabien DESSENNE 
14999d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++)
15000b496efbSLinus Walleij 		stm32_cryp_read(cryp, cryp->caps->dout);
15019d3b5030SFabien DESSENNE 
15029d3b5030SFabien DESSENNE 	/* h) run the he normal Final phase */
15039d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, 0);
15049d3b5030SFabien DESSENNE }
15059d3b5030SFabien DESSENNE 
15069d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
15079d3b5030SFabien DESSENNE {
15084b898d5cSNicolas Toromanoff 	u32 cfg;
15099d3b5030SFabien DESSENNE 
15109d3b5030SFabien DESSENNE 	/* disable ip, set NPBLB and reneable ip */
15110b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
15129d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
15130b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15149d3b5030SFabien DESSENNE 
15154b898d5cSNicolas Toromanoff 	cfg |= (cryp->hw_blocksize - cryp->payload_in) << CR_NBPBL_SHIFT;
15169d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
15170b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15189d3b5030SFabien DESSENNE }
15199d3b5030SFabien DESSENNE 
15209d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
15219d3b5030SFabien DESSENNE {
15229d3b5030SFabien DESSENNE 	int err = 0;
15239d3b5030SFabien DESSENNE 	u32 cfg, iv1tmp;
15244b898d5cSNicolas Toromanoff 	u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32];
15254b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
15269d3b5030SFabien DESSENNE 	unsigned int i;
15279d3b5030SFabien DESSENNE 
15289d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
15299d3b5030SFabien DESSENNE 
15309d3b5030SFabien DESSENNE 	/* a) disable ip */
15310b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
15329d3b5030SFabien DESSENNE 
15330b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
15349d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
15350b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15369d3b5030SFabien DESSENNE 
15379d3b5030SFabien DESSENNE 	/* b) get IV1 from CRYP_CSGCMCCM7 */
15389d3b5030SFabien DESSENNE 	iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4);
15399d3b5030SFabien DESSENNE 
15409d3b5030SFabien DESSENNE 	/* c) Load CRYP_CSGCMCCMxR */
15419d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp1); i++)
15429d3b5030SFabien DESSENNE 		cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
15439d3b5030SFabien DESSENNE 
15449d3b5030SFabien DESSENNE 	/* d) Write IV1R */
15450b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv1r, iv1tmp);
15469d3b5030SFabien DESSENNE 
15479d3b5030SFabien DESSENNE 	/* e) change mode to CTR */
15489d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
15499d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
15500b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15519d3b5030SFabien DESSENNE 
15529d3b5030SFabien DESSENNE 	/* a) enable IP */
15539d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
15540b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15559d3b5030SFabien DESSENNE 
15569d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
15579d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
15584b898d5cSNicolas Toromanoff 	/* wait end of process */
15599d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
15609d3b5030SFabien DESSENNE 	if (err) {
1561be7f5ef9SColin Ian King 		dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
15629d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
15639d3b5030SFabien DESSENNE 	}
15649d3b5030SFabien DESSENNE 
15659d3b5030SFabien DESSENNE 	/* c) get and store decrypted data */
15664b898d5cSNicolas Toromanoff 	/*
15674b898d5cSNicolas Toromanoff 	 * Same code as stm32_cryp_irq_read_data(), but we want to store
15684b898d5cSNicolas Toromanoff 	 * block value
15694b898d5cSNicolas Toromanoff 	 */
1570*319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
15719d3b5030SFabien DESSENNE 
15724b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
15734b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
15744b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, cryp->payload_out);
15759d3b5030SFabien DESSENNE 
15769d3b5030SFabien DESSENNE 	/* d) Load again CRYP_CSGCMCCMxR */
15779d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
15789d3b5030SFabien DESSENNE 		cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
15799d3b5030SFabien DESSENNE 
15809d3b5030SFabien DESSENNE 	/* e) change mode back to AES CCM */
15819d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
15829d3b5030SFabien DESSENNE 	cfg |= CR_AES_CCM;
15830b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15849d3b5030SFabien DESSENNE 
15859d3b5030SFabien DESSENNE 	/* f) change phase to header */
15869d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
15879d3b5030SFabien DESSENNE 	cfg |= CR_PH_HEADER;
15880b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15899d3b5030SFabien DESSENNE 
15909d3b5030SFabien DESSENNE 	/* g) XOR and write padded data */
15914b898d5cSNicolas Toromanoff 	for (i = 0; i < ARRAY_SIZE(block); i++) {
15924b898d5cSNicolas Toromanoff 		block[i] ^= cstmp1[i];
15934b898d5cSNicolas Toromanoff 		block[i] ^= cstmp2[i];
15940b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, block[i]);
15959d3b5030SFabien DESSENNE 	}
15969d3b5030SFabien DESSENNE 
15979d3b5030SFabien DESSENNE 	/* h) wait for completion */
15989d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_busy(cryp);
15999d3b5030SFabien DESSENNE 	if (err)
1600be7f5ef9SColin Ian King 		dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
16019d3b5030SFabien DESSENNE 
16029d3b5030SFabien DESSENNE 	/* i) run the he normal Final phase */
16039d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, err);
16049d3b5030SFabien DESSENNE }
16059d3b5030SFabien DESSENNE 
16069e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
16079e054ec2SFabien DESSENNE {
16084b898d5cSNicolas Toromanoff 	if (unlikely(!cryp->payload_in)) {
16099e054ec2SFabien DESSENNE 		dev_warn(cryp->dev, "No more data to process\n");
16109e054ec2SFabien DESSENNE 		return;
16119e054ec2SFabien DESSENNE 	}
16129e054ec2SFabien DESSENNE 
16134b898d5cSNicolas Toromanoff 	if (unlikely(cryp->payload_in < AES_BLOCK_SIZE &&
16149d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
16159d3b5030SFabien DESSENNE 		     is_encrypt(cryp))) {
16169d3b5030SFabien DESSENNE 		/* Padding for AES GCM encryption */
16174b898d5cSNicolas Toromanoff 		if (cryp->caps->padding_wa) {
16189d3b5030SFabien DESSENNE 			/* Special case 1 */
16194b898d5cSNicolas Toromanoff 			stm32_cryp_irq_write_gcm_padded_data(cryp);
16204b898d5cSNicolas Toromanoff 			return;
16214b898d5cSNicolas Toromanoff 		}
16229d3b5030SFabien DESSENNE 
16239d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
16249d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
16259d3b5030SFabien DESSENNE 	}
16269d3b5030SFabien DESSENNE 
16274b898d5cSNicolas Toromanoff 	if (unlikely((cryp->payload_in < AES_BLOCK_SIZE) &&
16289d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
16299d3b5030SFabien DESSENNE 		     is_decrypt(cryp))) {
16309d3b5030SFabien DESSENNE 		/* Padding for AES CCM decryption */
16314b898d5cSNicolas Toromanoff 		if (cryp->caps->padding_wa) {
16329d3b5030SFabien DESSENNE 			/* Special case 2 */
16334b898d5cSNicolas Toromanoff 			stm32_cryp_irq_write_ccm_padded_data(cryp);
16344b898d5cSNicolas Toromanoff 			return;
16354b898d5cSNicolas Toromanoff 		}
16369d3b5030SFabien DESSENNE 
16379d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
16389d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
16399d3b5030SFabien DESSENNE 	}
16409d3b5030SFabien DESSENNE 
16419e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
16429e054ec2SFabien DESSENNE 		stm32_cryp_check_ctr_counter(cryp);
16439e054ec2SFabien DESSENNE 
16449e054ec2SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
16459e054ec2SFabien DESSENNE }
16469e054ec2SFabien DESSENNE 
16474b898d5cSNicolas Toromanoff static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp)
16489d3b5030SFabien DESSENNE {
16494b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
16504b898d5cSNicolas Toromanoff 	size_t written;
16519d3b5030SFabien DESSENNE 
16524b898d5cSNicolas Toromanoff 	written = min_t(size_t, AES_BLOCK_SIZE, cryp->header_in);
16539d3b5030SFabien DESSENNE 
16544b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->in_walk, written, 0);
1655*319ad16dSLinus Walleij 
1656*319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
16579d3b5030SFabien DESSENNE 
16584b898d5cSNicolas Toromanoff 	cryp->header_in -= written;
16599d3b5030SFabien DESSENNE 
16604b898d5cSNicolas Toromanoff 	stm32_crypt_gcmccm_end_header(cryp);
16619d3b5030SFabien DESSENNE }
16629d3b5030SFabien DESSENNE 
16639e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg)
16649e054ec2SFabien DESSENNE {
16659e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
16669d3b5030SFabien DESSENNE 	u32 ph;
16670b496efbSLinus Walleij 	u32 it_mask = stm32_cryp_read(cryp, cryp->caps->imsc);
16689e054ec2SFabien DESSENNE 
16699e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_OUT)
16709e054ec2SFabien DESSENNE 		/* Output FIFO IRQ: read data */
16714b898d5cSNicolas Toromanoff 		stm32_cryp_irq_read_data(cryp);
16729e054ec2SFabien DESSENNE 
16739e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_IN) {
16744b898d5cSNicolas Toromanoff 		if (is_gcm(cryp) || is_ccm(cryp)) {
16750b496efbSLinus Walleij 			ph = stm32_cryp_read(cryp, cryp->caps->cr) & CR_PH_MASK;
16769d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
16779d3b5030SFabien DESSENNE 				/* Write Header */
16784b898d5cSNicolas Toromanoff 				stm32_cryp_irq_write_gcmccm_header(cryp);
16799d3b5030SFabien DESSENNE 			else
16809e054ec2SFabien DESSENNE 				/* Input FIFO IRQ: write data */
16819e054ec2SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
16824b898d5cSNicolas Toromanoff 			if (is_gcm(cryp))
16839d3b5030SFabien DESSENNE 				cryp->gcm_ctr++;
16849d3b5030SFabien DESSENNE 		} else {
16859d3b5030SFabien DESSENNE 			/* Input FIFO IRQ: write data */
16869d3b5030SFabien DESSENNE 			stm32_cryp_irq_write_data(cryp);
16879d3b5030SFabien DESSENNE 		}
16889e054ec2SFabien DESSENNE 	}
16899e054ec2SFabien DESSENNE 
16904b898d5cSNicolas Toromanoff 	/* Mask useless interrupts */
16914b898d5cSNicolas Toromanoff 	if (!cryp->payload_in && !cryp->header_in)
16924b898d5cSNicolas Toromanoff 		it_mask &= ~IMSCR_IN;
16934b898d5cSNicolas Toromanoff 	if (!cryp->payload_out)
16944b898d5cSNicolas Toromanoff 		it_mask &= ~IMSCR_OUT;
16950b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, it_mask);
16964b898d5cSNicolas Toromanoff 
16974b898d5cSNicolas Toromanoff 	if (!cryp->payload_in && !cryp->header_in && !cryp->payload_out)
16984b898d5cSNicolas Toromanoff 		stm32_cryp_finish_req(cryp, 0);
16994b898d5cSNicolas Toromanoff 
17009e054ec2SFabien DESSENNE 	return IRQ_HANDLED;
17019e054ec2SFabien DESSENNE }
17029e054ec2SFabien DESSENNE 
17039e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg)
17049e054ec2SFabien DESSENNE {
17059e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
17069e054ec2SFabien DESSENNE 
17070b496efbSLinus Walleij 	cryp->irq_status = stm32_cryp_read(cryp, cryp->caps->mis);
17089e054ec2SFabien DESSENNE 
17099e054ec2SFabien DESSENNE 	return IRQ_WAKE_THREAD;
17109e054ec2SFabien DESSENNE }
17119e054ec2SFabien DESSENNE 
171247ece481SArd Biesheuvel static struct skcipher_alg crypto_algs[] = {
17139e054ec2SFabien DESSENNE {
171447ece481SArd Biesheuvel 	.base.cra_name		= "ecb(aes)",
171547ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-aes",
171647ece481SArd Biesheuvel 	.base.cra_priority	= 200,
171747ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
171847ece481SArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
171947ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17204b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
172147ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
172247ece481SArd Biesheuvel 
172347ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17249e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17259e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17269e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17279e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_ecb_encrypt,
17289e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_ecb_decrypt,
17299e054ec2SFabien DESSENNE },
17309e054ec2SFabien DESSENNE {
173147ece481SArd Biesheuvel 	.base.cra_name		= "cbc(aes)",
173247ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-aes",
173347ece481SArd Biesheuvel 	.base.cra_priority	= 200,
173447ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
173547ece481SArd Biesheuvel 	.base.cra_blocksize	= AES_BLOCK_SIZE,
173647ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17374b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
173847ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
173947ece481SArd Biesheuvel 
174047ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17419e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17429e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17439e054ec2SFabien DESSENNE 	.ivsize			= AES_BLOCK_SIZE,
17449e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17459e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_cbc_encrypt,
17469e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_cbc_decrypt,
17479e054ec2SFabien DESSENNE },
17489e054ec2SFabien DESSENNE {
174947ece481SArd Biesheuvel 	.base.cra_name		= "ctr(aes)",
175047ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ctr-aes",
175147ece481SArd Biesheuvel 	.base.cra_priority	= 200,
175247ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
175347ece481SArd Biesheuvel 	.base.cra_blocksize	= 1,
175447ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17554b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
175647ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
175747ece481SArd Biesheuvel 
175847ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17599e054ec2SFabien DESSENNE 	.min_keysize		= AES_MIN_KEY_SIZE,
17609e054ec2SFabien DESSENNE 	.max_keysize		= AES_MAX_KEY_SIZE,
17619e054ec2SFabien DESSENNE 	.ivsize			= AES_BLOCK_SIZE,
17629e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_aes_setkey,
17639e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_aes_ctr_encrypt,
17649e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_aes_ctr_decrypt,
17659e054ec2SFabien DESSENNE },
17669e054ec2SFabien DESSENNE {
176747ece481SArd Biesheuvel 	.base.cra_name		= "ecb(des)",
176847ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-des",
176947ece481SArd Biesheuvel 	.base.cra_priority	= 200,
177047ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
177147ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
177247ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17734b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
177447ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
177547ece481SArd Biesheuvel 
177647ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17779e054ec2SFabien DESSENNE 	.min_keysize		= DES_BLOCK_SIZE,
17789e054ec2SFabien DESSENNE 	.max_keysize		= DES_BLOCK_SIZE,
17799e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_des_setkey,
17809e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_des_ecb_encrypt,
17819e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_des_ecb_decrypt,
17829e054ec2SFabien DESSENNE },
17839e054ec2SFabien DESSENNE {
178447ece481SArd Biesheuvel 	.base.cra_name		= "cbc(des)",
178547ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-des",
178647ece481SArd Biesheuvel 	.base.cra_priority	= 200,
178747ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
178847ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
178947ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17904b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
179147ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
179247ece481SArd Biesheuvel 
179347ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
17949e054ec2SFabien DESSENNE 	.min_keysize		= DES_BLOCK_SIZE,
17959e054ec2SFabien DESSENNE 	.max_keysize		= DES_BLOCK_SIZE,
17969e054ec2SFabien DESSENNE 	.ivsize			= DES_BLOCK_SIZE,
17979e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_des_setkey,
17989e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_des_cbc_encrypt,
17999e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_des_cbc_decrypt,
18009e054ec2SFabien DESSENNE },
18019e054ec2SFabien DESSENNE {
180247ece481SArd Biesheuvel 	.base.cra_name		= "ecb(des3_ede)",
180347ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-ecb-des3",
180447ece481SArd Biesheuvel 	.base.cra_priority	= 200,
180547ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
180647ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
180747ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
18084b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
180947ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
181047ece481SArd Biesheuvel 
181147ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18129e054ec2SFabien DESSENNE 	.min_keysize		= 3 * DES_BLOCK_SIZE,
18139e054ec2SFabien DESSENNE 	.max_keysize		= 3 * DES_BLOCK_SIZE,
18149e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_tdes_setkey,
18159e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_tdes_ecb_encrypt,
18169e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_tdes_ecb_decrypt,
18179e054ec2SFabien DESSENNE },
18189e054ec2SFabien DESSENNE {
181947ece481SArd Biesheuvel 	.base.cra_name		= "cbc(des3_ede)",
182047ece481SArd Biesheuvel 	.base.cra_driver_name	= "stm32-cbc-des3",
182147ece481SArd Biesheuvel 	.base.cra_priority	= 200,
182247ece481SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_ASYNC,
182347ece481SArd Biesheuvel 	.base.cra_blocksize	= DES_BLOCK_SIZE,
182447ece481SArd Biesheuvel 	.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
18254b898d5cSNicolas Toromanoff 	.base.cra_alignmask	= 0,
182647ece481SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
182747ece481SArd Biesheuvel 
182847ece481SArd Biesheuvel 	.init			= stm32_cryp_init_tfm,
18299e054ec2SFabien DESSENNE 	.min_keysize		= 3 * DES_BLOCK_SIZE,
18309e054ec2SFabien DESSENNE 	.max_keysize		= 3 * DES_BLOCK_SIZE,
18319e054ec2SFabien DESSENNE 	.ivsize			= DES_BLOCK_SIZE,
18329e054ec2SFabien DESSENNE 	.setkey			= stm32_cryp_tdes_setkey,
18339e054ec2SFabien DESSENNE 	.encrypt		= stm32_cryp_tdes_cbc_encrypt,
18349e054ec2SFabien DESSENNE 	.decrypt		= stm32_cryp_tdes_cbc_decrypt,
18359e054ec2SFabien DESSENNE },
18369e054ec2SFabien DESSENNE };
18379e054ec2SFabien DESSENNE 
18389d3b5030SFabien DESSENNE static struct aead_alg aead_algs[] = {
18399d3b5030SFabien DESSENNE {
18409d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18419d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_gcm_setauthsize,
18429d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_gcm_encrypt,
18439d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_gcm_decrypt,
18449d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18459d3b5030SFabien DESSENNE 	.ivsize		= 12,
18469d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18479d3b5030SFabien DESSENNE 
18489d3b5030SFabien DESSENNE 	.base = {
18499d3b5030SFabien DESSENNE 		.cra_name		= "gcm(aes)",
18509d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-gcm-aes",
18519d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18529d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18539d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18549d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18554b898d5cSNicolas Toromanoff 		.cra_alignmask		= 0,
18569d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18579d3b5030SFabien DESSENNE 	},
18589d3b5030SFabien DESSENNE },
18599d3b5030SFabien DESSENNE {
18609d3b5030SFabien DESSENNE 	.setkey		= stm32_cryp_aes_aead_setkey,
18619d3b5030SFabien DESSENNE 	.setauthsize	= stm32_cryp_aes_ccm_setauthsize,
18629d3b5030SFabien DESSENNE 	.encrypt	= stm32_cryp_aes_ccm_encrypt,
18639d3b5030SFabien DESSENNE 	.decrypt	= stm32_cryp_aes_ccm_decrypt,
18649d3b5030SFabien DESSENNE 	.init		= stm32_cryp_aes_aead_init,
18659d3b5030SFabien DESSENNE 	.ivsize		= AES_BLOCK_SIZE,
18669d3b5030SFabien DESSENNE 	.maxauthsize	= AES_BLOCK_SIZE,
18679d3b5030SFabien DESSENNE 
18689d3b5030SFabien DESSENNE 	.base = {
18699d3b5030SFabien DESSENNE 		.cra_name		= "ccm(aes)",
18709d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-ccm-aes",
18719d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18729d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18739d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18749d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18754b898d5cSNicolas Toromanoff 		.cra_alignmask		= 0,
18769d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18779d3b5030SFabien DESSENNE 	},
18789d3b5030SFabien DESSENNE },
18799d3b5030SFabien DESSENNE };
18809d3b5030SFabien DESSENNE 
18810b496efbSLinus Walleij static const struct stm32_cryp_caps ux500_data = {
18820b496efbSLinus Walleij 	.aeads_support = false,
18830b496efbSLinus Walleij 	.linear_aes_key = true,
18840b496efbSLinus Walleij 	.kp_mode = false,
18850b496efbSLinus Walleij 	.iv_protection = true,
18869d3b5030SFabien DESSENNE 	.swap_final = true,
18879d3b5030SFabien DESSENNE 	.padding_wa = true,
18880b496efbSLinus Walleij 	.cr = UX500_CRYP_CR,
18890b496efbSLinus Walleij 	.sr = UX500_CRYP_SR,
18900b496efbSLinus Walleij 	.din = UX500_CRYP_DIN,
18910b496efbSLinus Walleij 	.dout = UX500_CRYP_DOUT,
18920b496efbSLinus Walleij 	.imsc = UX500_CRYP_IMSC,
18930b496efbSLinus Walleij 	.mis = UX500_CRYP_MIS,
18940b496efbSLinus Walleij 	.k1l = UX500_CRYP_K1L,
18950b496efbSLinus Walleij 	.k1r = UX500_CRYP_K1R,
18960b496efbSLinus Walleij 	.k3r = UX500_CRYP_K3R,
18970b496efbSLinus Walleij 	.iv0l = UX500_CRYP_IV0L,
18980b496efbSLinus Walleij 	.iv0r = UX500_CRYP_IV0R,
18990b496efbSLinus Walleij 	.iv1l = UX500_CRYP_IV1L,
19000b496efbSLinus Walleij 	.iv1r = UX500_CRYP_IV1R,
19010b496efbSLinus Walleij };
19020b496efbSLinus Walleij 
19030b496efbSLinus Walleij static const struct stm32_cryp_caps f7_data = {
19040b496efbSLinus Walleij 	.aeads_support = true,
19050b496efbSLinus Walleij 	.linear_aes_key = false,
19060b496efbSLinus Walleij 	.kp_mode = true,
19070b496efbSLinus Walleij 	.iv_protection = false,
19080b496efbSLinus Walleij 	.swap_final = true,
19090b496efbSLinus Walleij 	.padding_wa = true,
19100b496efbSLinus Walleij 	.cr = CRYP_CR,
19110b496efbSLinus Walleij 	.sr = CRYP_SR,
19120b496efbSLinus Walleij 	.din = CRYP_DIN,
19130b496efbSLinus Walleij 	.dout = CRYP_DOUT,
19140b496efbSLinus Walleij 	.imsc = CRYP_IMSCR,
19150b496efbSLinus Walleij 	.mis = CRYP_MISR,
19160b496efbSLinus Walleij 	.k1l = CRYP_K1LR,
19170b496efbSLinus Walleij 	.k1r = CRYP_K1RR,
19180b496efbSLinus Walleij 	.k3r = CRYP_K3RR,
19190b496efbSLinus Walleij 	.iv0l = CRYP_IV0LR,
19200b496efbSLinus Walleij 	.iv0r = CRYP_IV0RR,
19210b496efbSLinus Walleij 	.iv1l = CRYP_IV1LR,
19220b496efbSLinus Walleij 	.iv1r = CRYP_IV1RR,
19239d3b5030SFabien DESSENNE };
19249d3b5030SFabien DESSENNE 
1925a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = {
19260b496efbSLinus Walleij 	.aeads_support = true,
19270b496efbSLinus Walleij 	.linear_aes_key = false,
19280b496efbSLinus Walleij 	.kp_mode = true,
19290b496efbSLinus Walleij 	.iv_protection = false,
1930a43a3484SFabien DESSENNE 	.swap_final = false,
1931a43a3484SFabien DESSENNE 	.padding_wa = false,
19320b496efbSLinus Walleij 	.cr = CRYP_CR,
19330b496efbSLinus Walleij 	.sr = CRYP_SR,
19340b496efbSLinus Walleij 	.din = CRYP_DIN,
19350b496efbSLinus Walleij 	.dout = CRYP_DOUT,
19360b496efbSLinus Walleij 	.imsc = CRYP_IMSCR,
19370b496efbSLinus Walleij 	.mis = CRYP_MISR,
19380b496efbSLinus Walleij 	.k1l = CRYP_K1LR,
19390b496efbSLinus Walleij 	.k1r = CRYP_K1RR,
19400b496efbSLinus Walleij 	.k3r = CRYP_K3RR,
19410b496efbSLinus Walleij 	.iv0l = CRYP_IV0LR,
19420b496efbSLinus Walleij 	.iv0r = CRYP_IV0RR,
19430b496efbSLinus Walleij 	.iv1l = CRYP_IV1LR,
19440b496efbSLinus Walleij 	.iv1r = CRYP_IV1RR,
1945a43a3484SFabien DESSENNE };
1946a43a3484SFabien DESSENNE 
19479e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = {
19480b496efbSLinus Walleij 	{ .compatible = "stericsson,ux500-cryp", .data = &ux500_data},
19499d3b5030SFabien DESSENNE 	{ .compatible = "st,stm32f756-cryp", .data = &f7_data},
1950a43a3484SFabien DESSENNE 	{ .compatible = "st,stm32mp1-cryp", .data = &mp1_data},
19519e054ec2SFabien DESSENNE 	{},
19529e054ec2SFabien DESSENNE };
1953761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids);
19549e054ec2SFabien DESSENNE 
19559e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev)
19569e054ec2SFabien DESSENNE {
19579e054ec2SFabien DESSENNE 	struct device *dev = &pdev->dev;
19589e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
19599e054ec2SFabien DESSENNE 	struct reset_control *rst;
19609e054ec2SFabien DESSENNE 	int irq, ret;
19619e054ec2SFabien DESSENNE 
19629e054ec2SFabien DESSENNE 	cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL);
19639e054ec2SFabien DESSENNE 	if (!cryp)
19649e054ec2SFabien DESSENNE 		return -ENOMEM;
19659e054ec2SFabien DESSENNE 
19669d3b5030SFabien DESSENNE 	cryp->caps = of_device_get_match_data(dev);
19679d3b5030SFabien DESSENNE 	if (!cryp->caps)
19689d3b5030SFabien DESSENNE 		return -ENODEV;
19699d3b5030SFabien DESSENNE 
19709e054ec2SFabien DESSENNE 	cryp->dev = dev;
19719e054ec2SFabien DESSENNE 
1972473b4d99SYueHaibing 	cryp->regs = devm_platform_ioremap_resource(pdev, 0);
197360bcf265Sweiyongjun \(A\) 	if (IS_ERR(cryp->regs))
19749e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->regs);
19759e054ec2SFabien DESSENNE 
19769e054ec2SFabien DESSENNE 	irq = platform_get_irq(pdev, 0);
1977514838e9SStephen Boyd 	if (irq < 0)
19789e054ec2SFabien DESSENNE 		return irq;
19799e054ec2SFabien DESSENNE 
19809e054ec2SFabien DESSENNE 	ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq,
19819e054ec2SFabien DESSENNE 					stm32_cryp_irq_thread, IRQF_ONESHOT,
19829e054ec2SFabien DESSENNE 					dev_name(dev), cryp);
19839e054ec2SFabien DESSENNE 	if (ret) {
19849e054ec2SFabien DESSENNE 		dev_err(dev, "Cannot grab IRQ\n");
19859e054ec2SFabien DESSENNE 		return ret;
19869e054ec2SFabien DESSENNE 	}
19879e054ec2SFabien DESSENNE 
19889e054ec2SFabien DESSENNE 	cryp->clk = devm_clk_get(dev, NULL);
19899e054ec2SFabien DESSENNE 	if (IS_ERR(cryp->clk)) {
1990029812aeSEtienne Carriere 		dev_err_probe(dev, PTR_ERR(cryp->clk), "Could not get clock\n");
1991029812aeSEtienne Carriere 
19929e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->clk);
19939e054ec2SFabien DESSENNE 	}
19949e054ec2SFabien DESSENNE 
19959e054ec2SFabien DESSENNE 	ret = clk_prepare_enable(cryp->clk);
19969e054ec2SFabien DESSENNE 	if (ret) {
19979e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Failed to enable clock\n");
19989e054ec2SFabien DESSENNE 		return ret;
19999e054ec2SFabien DESSENNE 	}
20009e054ec2SFabien DESSENNE 
200165f9aa36Slionel.debieve@st.com 	pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY);
200265f9aa36Slionel.debieve@st.com 	pm_runtime_use_autosuspend(dev);
200365f9aa36Slionel.debieve@st.com 
200465f9aa36Slionel.debieve@st.com 	pm_runtime_get_noresume(dev);
200565f9aa36Slionel.debieve@st.com 	pm_runtime_set_active(dev);
200665f9aa36Slionel.debieve@st.com 	pm_runtime_enable(dev);
200765f9aa36Slionel.debieve@st.com 
20089e054ec2SFabien DESSENNE 	rst = devm_reset_control_get(dev, NULL);
20090a2f9f57SEtienne Carriere 	if (IS_ERR(rst)) {
20100a2f9f57SEtienne Carriere 		ret = PTR_ERR(rst);
20110a2f9f57SEtienne Carriere 		if (ret == -EPROBE_DEFER)
20120a2f9f57SEtienne Carriere 			goto err_rst;
20130a2f9f57SEtienne Carriere 	} else {
20149e054ec2SFabien DESSENNE 		reset_control_assert(rst);
20159e054ec2SFabien DESSENNE 		udelay(2);
20169e054ec2SFabien DESSENNE 		reset_control_deassert(rst);
20179e054ec2SFabien DESSENNE 	}
20189e054ec2SFabien DESSENNE 
20199e054ec2SFabien DESSENNE 	platform_set_drvdata(pdev, cryp);
20209e054ec2SFabien DESSENNE 
20219e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20229e054ec2SFabien DESSENNE 	list_add(&cryp->list, &cryp_list.dev_list);
20239e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20249e054ec2SFabien DESSENNE 
20259e054ec2SFabien DESSENNE 	/* Initialize crypto engine */
20269e054ec2SFabien DESSENNE 	cryp->engine = crypto_engine_alloc_init(dev, 1);
20279e054ec2SFabien DESSENNE 	if (!cryp->engine) {
20289e054ec2SFabien DESSENNE 		dev_err(dev, "Could not init crypto engine\n");
20299e054ec2SFabien DESSENNE 		ret = -ENOMEM;
20309e054ec2SFabien DESSENNE 		goto err_engine1;
20319e054ec2SFabien DESSENNE 	}
20329e054ec2SFabien DESSENNE 
20339e054ec2SFabien DESSENNE 	ret = crypto_engine_start(cryp->engine);
20349e054ec2SFabien DESSENNE 	if (ret) {
20359e054ec2SFabien DESSENNE 		dev_err(dev, "Could not start crypto engine\n");
20369e054ec2SFabien DESSENNE 		goto err_engine2;
20379e054ec2SFabien DESSENNE 	}
20389e054ec2SFabien DESSENNE 
203947ece481SArd Biesheuvel 	ret = crypto_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20409e054ec2SFabien DESSENNE 	if (ret) {
20419e054ec2SFabien DESSENNE 		dev_err(dev, "Could not register algs\n");
20429e054ec2SFabien DESSENNE 		goto err_algs;
20439e054ec2SFabien DESSENNE 	}
20449e054ec2SFabien DESSENNE 
20450b496efbSLinus Walleij 	if (cryp->caps->aeads_support) {
20469d3b5030SFabien DESSENNE 		ret = crypto_register_aeads(aead_algs, ARRAY_SIZE(aead_algs));
20479d3b5030SFabien DESSENNE 		if (ret)
20489d3b5030SFabien DESSENNE 			goto err_aead_algs;
20490b496efbSLinus Walleij 	}
20509d3b5030SFabien DESSENNE 
20519e054ec2SFabien DESSENNE 	dev_info(dev, "Initialized\n");
20529e054ec2SFabien DESSENNE 
205365f9aa36Slionel.debieve@st.com 	pm_runtime_put_sync(dev);
205465f9aa36Slionel.debieve@st.com 
20559e054ec2SFabien DESSENNE 	return 0;
20569e054ec2SFabien DESSENNE 
20579d3b5030SFabien DESSENNE err_aead_algs:
205847ece481SArd Biesheuvel 	crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20599e054ec2SFabien DESSENNE err_algs:
20609e054ec2SFabien DESSENNE err_engine2:
20619e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20629e054ec2SFabien DESSENNE err_engine1:
20639e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20649e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20659e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20660a2f9f57SEtienne Carriere err_rst:
206765f9aa36Slionel.debieve@st.com 	pm_runtime_disable(dev);
206865f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(dev);
206965f9aa36Slionel.debieve@st.com 
20709e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20719e054ec2SFabien DESSENNE 
20729e054ec2SFabien DESSENNE 	return ret;
20739e054ec2SFabien DESSENNE }
20749e054ec2SFabien DESSENNE 
20759e054ec2SFabien DESSENNE static int stm32_cryp_remove(struct platform_device *pdev)
20769e054ec2SFabien DESSENNE {
20779e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = platform_get_drvdata(pdev);
207865f9aa36Slionel.debieve@st.com 	int ret;
20799e054ec2SFabien DESSENNE 
20809e054ec2SFabien DESSENNE 	if (!cryp)
20819e054ec2SFabien DESSENNE 		return -ENODEV;
20829e054ec2SFabien DESSENNE 
2083747bf30fSShixin Liu 	ret = pm_runtime_resume_and_get(cryp->dev);
208465f9aa36Slionel.debieve@st.com 	if (ret < 0)
208565f9aa36Slionel.debieve@st.com 		return ret;
208665f9aa36Slionel.debieve@st.com 
20870b496efbSLinus Walleij 	if (cryp->caps->aeads_support)
20889d3b5030SFabien DESSENNE 		crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
208947ece481SArd Biesheuvel 	crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20909e054ec2SFabien DESSENNE 
20919e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20929e054ec2SFabien DESSENNE 
20939e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20949e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20959e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20969e054ec2SFabien DESSENNE 
209765f9aa36Slionel.debieve@st.com 	pm_runtime_disable(cryp->dev);
209865f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(cryp->dev);
209965f9aa36Slionel.debieve@st.com 
21009e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
21019e054ec2SFabien DESSENNE 
21029e054ec2SFabien DESSENNE 	return 0;
21039e054ec2SFabien DESSENNE }
21049e054ec2SFabien DESSENNE 
210565f9aa36Slionel.debieve@st.com #ifdef CONFIG_PM
210665f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_suspend(struct device *dev)
210765f9aa36Slionel.debieve@st.com {
210865f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
210965f9aa36Slionel.debieve@st.com 
211065f9aa36Slionel.debieve@st.com 	clk_disable_unprepare(cryp->clk);
211165f9aa36Slionel.debieve@st.com 
211265f9aa36Slionel.debieve@st.com 	return 0;
211365f9aa36Slionel.debieve@st.com }
211465f9aa36Slionel.debieve@st.com 
211565f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_resume(struct device *dev)
211665f9aa36Slionel.debieve@st.com {
211765f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
211865f9aa36Slionel.debieve@st.com 	int ret;
211965f9aa36Slionel.debieve@st.com 
212065f9aa36Slionel.debieve@st.com 	ret = clk_prepare_enable(cryp->clk);
212165f9aa36Slionel.debieve@st.com 	if (ret) {
212265f9aa36Slionel.debieve@st.com 		dev_err(cryp->dev, "Failed to prepare_enable clock\n");
212365f9aa36Slionel.debieve@st.com 		return ret;
212465f9aa36Slionel.debieve@st.com 	}
212565f9aa36Slionel.debieve@st.com 
212665f9aa36Slionel.debieve@st.com 	return 0;
212765f9aa36Slionel.debieve@st.com }
212865f9aa36Slionel.debieve@st.com #endif
212965f9aa36Slionel.debieve@st.com 
213065f9aa36Slionel.debieve@st.com static const struct dev_pm_ops stm32_cryp_pm_ops = {
213165f9aa36Slionel.debieve@st.com 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
213265f9aa36Slionel.debieve@st.com 				pm_runtime_force_resume)
213365f9aa36Slionel.debieve@st.com 	SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend,
213465f9aa36Slionel.debieve@st.com 			   stm32_cryp_runtime_resume, NULL)
213565f9aa36Slionel.debieve@st.com };
213665f9aa36Slionel.debieve@st.com 
21379e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = {
21389e054ec2SFabien DESSENNE 	.probe  = stm32_cryp_probe,
21399e054ec2SFabien DESSENNE 	.remove = stm32_cryp_remove,
21409e054ec2SFabien DESSENNE 	.driver = {
21419e054ec2SFabien DESSENNE 		.name           = DRIVER_NAME,
214265f9aa36Slionel.debieve@st.com 		.pm		= &stm32_cryp_pm_ops,
21439e054ec2SFabien DESSENNE 		.of_match_table = stm32_dt_ids,
21449e054ec2SFabien DESSENNE 	},
21459e054ec2SFabien DESSENNE };
21469e054ec2SFabien DESSENNE 
21479e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver);
21489e054ec2SFabien DESSENNE 
21499e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
21509e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver");
21519e054ec2SFabien DESSENNE MODULE_LICENSE("GPL");
2152