xref: /linux/drivers/crypto/stm32/stm32-cryp.c (revision 88b01c8abfc40b473665343ec2b8a353ad9444a4)
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 
8d5e6b48fSHerbert Xu #include <crypto/aes.h>
9d5e6b48fSHerbert Xu #include <crypto/engine.h>
10d5e6b48fSHerbert Xu #include <crypto/internal/aead.h>
11d5e6b48fSHerbert Xu #include <crypto/internal/des.h>
12d5e6b48fSHerbert Xu #include <crypto/internal/skcipher.h>
13d5e6b48fSHerbert Xu #include <crypto/scatterwalk.h>
149e054ec2SFabien DESSENNE #include <linux/clk.h>
159e054ec2SFabien DESSENNE #include <linux/delay.h>
16d5e6b48fSHerbert Xu #include <linux/err.h>
179e054ec2SFabien DESSENNE #include <linux/iopoll.h>
18d5e6b48fSHerbert Xu #include <linux/interrupt.h>
19d5e6b48fSHerbert Xu #include <linux/kernel.h>
209e054ec2SFabien DESSENNE #include <linux/module.h>
21b0cc7491SRob Herring #include <linux/of.h>
229e054ec2SFabien DESSENNE #include <linux/platform_device.h>
2365f9aa36Slionel.debieve@st.com #include <linux/pm_runtime.h>
249e054ec2SFabien DESSENNE #include <linux/reset.h>
25d5e6b48fSHerbert Xu #include <linux/string.h>
269e054ec2SFabien DESSENNE 
279e054ec2SFabien DESSENNE #define DRIVER_NAME             "stm32-cryp"
289e054ec2SFabien DESSENNE 
299e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */
309e054ec2SFabien DESSENNE #define FLG_ENCRYPT             BIT(0)
319e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */
329e054ec2SFabien DESSENNE #define FLG_AES                 BIT(1)
339e054ec2SFabien DESSENNE #define FLG_DES                 BIT(2)
349e054ec2SFabien DESSENNE #define FLG_TDES                BIT(3)
359e054ec2SFabien DESSENNE #define FLG_ECB                 BIT(4)
369e054ec2SFabien DESSENNE #define FLG_CBC                 BIT(5)
379e054ec2SFabien DESSENNE #define FLG_CTR                 BIT(6)
389d3b5030SFabien DESSENNE #define FLG_GCM                 BIT(7)
399d3b5030SFabien DESSENNE #define FLG_CCM                 BIT(8)
409e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */
419e054ec2SFabien DESSENNE #define FLG_MODE_MASK           GENMASK(15, 0)
429d3b5030SFabien DESSENNE /* Bit [31..16] status  */
439e054ec2SFabien DESSENNE 
449e054ec2SFabien DESSENNE /* Registers */
459e054ec2SFabien DESSENNE #define CRYP_CR                 0x00000000
469e054ec2SFabien DESSENNE #define CRYP_SR                 0x00000004
479e054ec2SFabien DESSENNE #define CRYP_DIN                0x00000008
489e054ec2SFabien DESSENNE #define CRYP_DOUT               0x0000000C
499e054ec2SFabien DESSENNE #define CRYP_DMACR              0x00000010
509e054ec2SFabien DESSENNE #define CRYP_IMSCR              0x00000014
519e054ec2SFabien DESSENNE #define CRYP_RISR               0x00000018
529e054ec2SFabien DESSENNE #define CRYP_MISR               0x0000001C
539e054ec2SFabien DESSENNE #define CRYP_K0LR               0x00000020
549e054ec2SFabien DESSENNE #define CRYP_K0RR               0x00000024
559e054ec2SFabien DESSENNE #define CRYP_K1LR               0x00000028
569e054ec2SFabien DESSENNE #define CRYP_K1RR               0x0000002C
579e054ec2SFabien DESSENNE #define CRYP_K2LR               0x00000030
589e054ec2SFabien DESSENNE #define CRYP_K2RR               0x00000034
599e054ec2SFabien DESSENNE #define CRYP_K3LR               0x00000038
609e054ec2SFabien DESSENNE #define CRYP_K3RR               0x0000003C
619e054ec2SFabien DESSENNE #define CRYP_IV0LR              0x00000040
629e054ec2SFabien DESSENNE #define CRYP_IV0RR              0x00000044
639e054ec2SFabien DESSENNE #define CRYP_IV1LR              0x00000048
649e054ec2SFabien DESSENNE #define CRYP_IV1RR              0x0000004C
659d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R         0x00000050
669d3b5030SFabien DESSENNE #define CRYP_CSGCM0R            0x00000070
679e054ec2SFabien DESSENNE 
680b496efbSLinus Walleij #define UX500_CRYP_CR		0x00000000
690b496efbSLinus Walleij #define UX500_CRYP_SR		0x00000004
700b496efbSLinus Walleij #define UX500_CRYP_DIN		0x00000008
710b496efbSLinus Walleij #define UX500_CRYP_DINSIZE	0x0000000C
720b496efbSLinus Walleij #define UX500_CRYP_DOUT		0x00000010
730b496efbSLinus Walleij #define UX500_CRYP_DOUSIZE	0x00000014
740b496efbSLinus Walleij #define UX500_CRYP_DMACR	0x00000018
750b496efbSLinus Walleij #define UX500_CRYP_IMSC		0x0000001C
760b496efbSLinus Walleij #define UX500_CRYP_RIS		0x00000020
770b496efbSLinus Walleij #define UX500_CRYP_MIS		0x00000024
780b496efbSLinus Walleij #define UX500_CRYP_K1L		0x00000028
790b496efbSLinus Walleij #define UX500_CRYP_K1R		0x0000002C
800b496efbSLinus Walleij #define UX500_CRYP_K2L		0x00000030
810b496efbSLinus Walleij #define UX500_CRYP_K2R		0x00000034
820b496efbSLinus Walleij #define UX500_CRYP_K3L		0x00000038
830b496efbSLinus Walleij #define UX500_CRYP_K3R		0x0000003C
840b496efbSLinus Walleij #define UX500_CRYP_K4L		0x00000040
850b496efbSLinus Walleij #define UX500_CRYP_K4R		0x00000044
860b496efbSLinus Walleij #define UX500_CRYP_IV0L		0x00000048
870b496efbSLinus Walleij #define UX500_CRYP_IV0R		0x0000004C
880b496efbSLinus Walleij #define UX500_CRYP_IV1L		0x00000050
890b496efbSLinus Walleij #define UX500_CRYP_IV1R		0x00000054
900b496efbSLinus Walleij 
919e054ec2SFabien DESSENNE /* Registers values */
929e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC          0x00000004
939e054ec2SFabien DESSENNE #define CR_TDES_ECB             0x00000000
949e054ec2SFabien DESSENNE #define CR_TDES_CBC             0x00000008
959e054ec2SFabien DESSENNE #define CR_DES_ECB              0x00000010
969e054ec2SFabien DESSENNE #define CR_DES_CBC              0x00000018
979e054ec2SFabien DESSENNE #define CR_AES_ECB              0x00000020
989e054ec2SFabien DESSENNE #define CR_AES_CBC              0x00000028
999e054ec2SFabien DESSENNE #define CR_AES_CTR              0x00000030
1000b496efbSLinus Walleij #define CR_AES_KP               0x00000038 /* Not on Ux500 */
1010b496efbSLinus Walleij #define CR_AES_XTS              0x00000038 /* Only on Ux500 */
1029d3b5030SFabien DESSENNE #define CR_AES_GCM              0x00080000
1039d3b5030SFabien DESSENNE #define CR_AES_CCM              0x00080008
1049e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN          0xFFFFFFFF
1059e054ec2SFabien DESSENNE #define CR_ALGO_MASK            0x00080038
1069e054ec2SFabien DESSENNE #define CR_DATA32               0x00000000
1079e054ec2SFabien DESSENNE #define CR_DATA16               0x00000040
1089e054ec2SFabien DESSENNE #define CR_DATA8                0x00000080
1099e054ec2SFabien DESSENNE #define CR_DATA1                0x000000C0
1109e054ec2SFabien DESSENNE #define CR_KEY128               0x00000000
1119e054ec2SFabien DESSENNE #define CR_KEY192               0x00000100
1129e054ec2SFabien DESSENNE #define CR_KEY256               0x00000200
1130b496efbSLinus Walleij #define CR_KEYRDEN              0x00000400 /* Only on Ux500 */
1140b496efbSLinus Walleij #define CR_KSE                  0x00000800 /* Only on Ux500 */
1159e054ec2SFabien DESSENNE #define CR_FFLUSH               0x00004000
1169e054ec2SFabien DESSENNE #define CR_CRYPEN               0x00008000
1179d3b5030SFabien DESSENNE #define CR_PH_INIT              0x00000000
1189d3b5030SFabien DESSENNE #define CR_PH_HEADER            0x00010000
1199d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD           0x00020000
1209d3b5030SFabien DESSENNE #define CR_PH_FINAL             0x00030000
1219d3b5030SFabien DESSENNE #define CR_PH_MASK              0x00030000
1229d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT          20
1239e054ec2SFabien DESSENNE 
1249e054ec2SFabien DESSENNE #define SR_BUSY                 0x00000010
1259e054ec2SFabien DESSENNE #define SR_OFNE                 0x00000004
1269e054ec2SFabien DESSENNE 
1279e054ec2SFabien DESSENNE #define IMSCR_IN                BIT(0)
1289e054ec2SFabien DESSENNE #define IMSCR_OUT               BIT(1)
1299e054ec2SFabien DESSENNE 
1309e054ec2SFabien DESSENNE #define MISR_IN                 BIT(0)
1319e054ec2SFabien DESSENNE #define MISR_OUT                BIT(1)
1329e054ec2SFabien DESSENNE 
1339e054ec2SFabien DESSENNE /* Misc */
1349e054ec2SFabien DESSENNE #define AES_BLOCK_32            (AES_BLOCK_SIZE / sizeof(u32))
1359d3b5030SFabien DESSENNE #define GCM_CTR_INIT            2
13665f9aa36Slionel.debieve@st.com #define CRYP_AUTOSUSPEND_DELAY	50
1379e054ec2SFabien DESSENNE 
1389d3b5030SFabien DESSENNE struct stm32_cryp_caps {
1390b496efbSLinus Walleij 	bool			aeads_support;
1400b496efbSLinus Walleij 	bool			linear_aes_key;
1410b496efbSLinus Walleij 	bool			kp_mode;
1420b496efbSLinus Walleij 	bool			iv_protection;
1439d3b5030SFabien DESSENNE 	bool			swap_final;
1449d3b5030SFabien DESSENNE 	bool			padding_wa;
1450b496efbSLinus Walleij 	u32			cr;
1460b496efbSLinus Walleij 	u32			sr;
1470b496efbSLinus Walleij 	u32			din;
1480b496efbSLinus Walleij 	u32			dout;
1490b496efbSLinus Walleij 	u32			imsc;
1500b496efbSLinus Walleij 	u32			mis;
1510b496efbSLinus Walleij 	u32			k1l;
1520b496efbSLinus Walleij 	u32			k1r;
1530b496efbSLinus Walleij 	u32			k3r;
1540b496efbSLinus Walleij 	u32			iv0l;
1550b496efbSLinus Walleij 	u32			iv0r;
1560b496efbSLinus Walleij 	u32			iv1l;
1570b496efbSLinus Walleij 	u32			iv1r;
1589d3b5030SFabien DESSENNE };
1599d3b5030SFabien DESSENNE 
1609e054ec2SFabien DESSENNE struct stm32_cryp_ctx {
1619e054ec2SFabien DESSENNE 	struct stm32_cryp       *cryp;
1629e054ec2SFabien DESSENNE 	int                     keylen;
163bbb28326SHerbert Xu 	__be32                  key[AES_KEYSIZE_256 / sizeof(u32)];
1649e054ec2SFabien DESSENNE 	unsigned long           flags;
1659e054ec2SFabien DESSENNE };
1669e054ec2SFabien DESSENNE 
1679e054ec2SFabien DESSENNE struct stm32_cryp_reqctx {
1689e054ec2SFabien DESSENNE 	unsigned long mode;
1699e054ec2SFabien DESSENNE };
1709e054ec2SFabien DESSENNE 
1719e054ec2SFabien DESSENNE struct stm32_cryp {
1729e054ec2SFabien DESSENNE 	struct list_head        list;
1739e054ec2SFabien DESSENNE 	struct device           *dev;
1749e054ec2SFabien DESSENNE 	void __iomem            *regs;
1759e054ec2SFabien DESSENNE 	struct clk              *clk;
1769e054ec2SFabien DESSENNE 	unsigned long           flags;
1779e054ec2SFabien DESSENNE 	u32                     irq_status;
1789d3b5030SFabien DESSENNE 	const struct stm32_cryp_caps *caps;
1799e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx   *ctx;
1809e054ec2SFabien DESSENNE 
1819e054ec2SFabien DESSENNE 	struct crypto_engine    *engine;
1829e054ec2SFabien DESSENNE 
18347ece481SArd Biesheuvel 	struct skcipher_request *req;
1849d3b5030SFabien DESSENNE 	struct aead_request     *areq;
1859e054ec2SFabien DESSENNE 
1869d3b5030SFabien DESSENNE 	size_t                  authsize;
1879e054ec2SFabien DESSENNE 	size_t                  hw_blocksize;
1889e054ec2SFabien DESSENNE 
1894b898d5cSNicolas Toromanoff 	size_t                  payload_in;
1904b898d5cSNicolas Toromanoff 	size_t                  header_in;
1914b898d5cSNicolas Toromanoff 	size_t                  payload_out;
1929e054ec2SFabien DESSENNE 
1939e054ec2SFabien DESSENNE 	struct scatterlist      *out_sg;
1949e054ec2SFabien DESSENNE 
1959e054ec2SFabien DESSENNE 	struct scatter_walk     in_walk;
1969e054ec2SFabien DESSENNE 	struct scatter_walk     out_walk;
1979e054ec2SFabien DESSENNE 
19841c76690SNicolas Toromanoff 	__be32                  last_ctr[4];
1999d3b5030SFabien DESSENNE 	u32                     gcm_ctr;
2009e054ec2SFabien DESSENNE };
2019e054ec2SFabien DESSENNE 
2029e054ec2SFabien DESSENNE struct stm32_cryp_list {
2039e054ec2SFabien DESSENNE 	struct list_head        dev_list;
2049e054ec2SFabien DESSENNE 	spinlock_t              lock; /* protect dev_list */
2059e054ec2SFabien DESSENNE };
2069e054ec2SFabien DESSENNE 
2079e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = {
2089e054ec2SFabien DESSENNE 	.dev_list = LIST_HEAD_INIT(cryp_list.dev_list),
2099e054ec2SFabien DESSENNE 	.lock     = __SPIN_LOCK_UNLOCKED(cryp_list.lock),
2109e054ec2SFabien DESSENNE };
2119e054ec2SFabien DESSENNE 
2129e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp)
2139e054ec2SFabien DESSENNE {
2149e054ec2SFabien DESSENNE 	return cryp->flags & FLG_AES;
2159e054ec2SFabien DESSENNE }
2169e054ec2SFabien DESSENNE 
2179e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp)
2189e054ec2SFabien DESSENNE {
2199e054ec2SFabien DESSENNE 	return cryp->flags & FLG_DES;
2209e054ec2SFabien DESSENNE }
2219e054ec2SFabien DESSENNE 
2229e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp)
2239e054ec2SFabien DESSENNE {
2249e054ec2SFabien DESSENNE 	return cryp->flags & FLG_TDES;
2259e054ec2SFabien DESSENNE }
2269e054ec2SFabien DESSENNE 
2279e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp)
2289e054ec2SFabien DESSENNE {
2299e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ECB;
2309e054ec2SFabien DESSENNE }
2319e054ec2SFabien DESSENNE 
2329e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp)
2339e054ec2SFabien DESSENNE {
2349e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CBC;
2359e054ec2SFabien DESSENNE }
2369e054ec2SFabien DESSENNE 
2379e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp)
2389e054ec2SFabien DESSENNE {
2399e054ec2SFabien DESSENNE 	return cryp->flags & FLG_CTR;
2409e054ec2SFabien DESSENNE }
2419e054ec2SFabien DESSENNE 
2429d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp)
2439d3b5030SFabien DESSENNE {
2449d3b5030SFabien DESSENNE 	return cryp->flags & FLG_GCM;
2459d3b5030SFabien DESSENNE }
2469d3b5030SFabien DESSENNE 
2479d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp)
2489d3b5030SFabien DESSENNE {
2499d3b5030SFabien DESSENNE 	return cryp->flags & FLG_CCM;
2509d3b5030SFabien DESSENNE }
2519d3b5030SFabien DESSENNE 
2529e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp)
2539e054ec2SFabien DESSENNE {
2549e054ec2SFabien DESSENNE 	return cryp->flags & FLG_ENCRYPT;
2559e054ec2SFabien DESSENNE }
2569e054ec2SFabien DESSENNE 
2579e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp)
2589e054ec2SFabien DESSENNE {
2599e054ec2SFabien DESSENNE 	return !is_encrypt(cryp);
2609e054ec2SFabien DESSENNE }
2619e054ec2SFabien DESSENNE 
2629e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst)
2639e054ec2SFabien DESSENNE {
2649e054ec2SFabien DESSENNE 	return readl_relaxed(cryp->regs + ofst);
2659e054ec2SFabien DESSENNE }
2669e054ec2SFabien DESSENNE 
2679e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val)
2689e054ec2SFabien DESSENNE {
2699e054ec2SFabien DESSENNE 	writel_relaxed(val, cryp->regs + ofst);
2709e054ec2SFabien DESSENNE }
2719e054ec2SFabien DESSENNE 
2729e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
2739e054ec2SFabien DESSENNE {
2749e054ec2SFabien DESSENNE 	u32 status;
2759e054ec2SFabien DESSENNE 
2760b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->sr, status,
2779e054ec2SFabien DESSENNE 			!(status & SR_BUSY), 10, 100000);
2789e054ec2SFabien DESSENNE }
2799e054ec2SFabien DESSENNE 
28095fe2253SNicolas Toromanoff static inline void stm32_cryp_enable(struct stm32_cryp *cryp)
28195fe2253SNicolas Toromanoff {
2820b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_CRYPEN,
2830b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
28495fe2253SNicolas Toromanoff }
28595fe2253SNicolas Toromanoff 
2869d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
2879d3b5030SFabien DESSENNE {
2889d3b5030SFabien DESSENNE 	u32 status;
2899d3b5030SFabien DESSENNE 
2900b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->cr, status,
2919d3b5030SFabien DESSENNE 			!(status & CR_CRYPEN), 10, 100000);
2929d3b5030SFabien DESSENNE }
2939d3b5030SFabien DESSENNE 
2949d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp)
2959d3b5030SFabien DESSENNE {
2969d3b5030SFabien DESSENNE 	u32 status;
2979d3b5030SFabien DESSENNE 
2980b496efbSLinus Walleij 	return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->sr, status,
2999d3b5030SFabien DESSENNE 			status & SR_OFNE, 10, 100000);
3009d3b5030SFabien DESSENNE }
3019d3b5030SFabien DESSENNE 
3020b496efbSLinus Walleij static inline void stm32_cryp_key_read_enable(struct stm32_cryp *cryp)
3030b496efbSLinus Walleij {
3040b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_KEYRDEN,
3050b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
3060b496efbSLinus Walleij }
3070b496efbSLinus Walleij 
3080b496efbSLinus Walleij static inline void stm32_cryp_key_read_disable(struct stm32_cryp *cryp)
3090b496efbSLinus Walleij {
3100b496efbSLinus Walleij 	writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) & ~CR_KEYRDEN,
3110b496efbSLinus Walleij 		       cryp->regs + cryp->caps->cr);
3120b496efbSLinus Walleij }
3130b496efbSLinus Walleij 
3149d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp);
3154b898d5cSNicolas Toromanoff static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err);
3169d3b5030SFabien DESSENNE 
3179e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx)
3189e054ec2SFabien DESSENNE {
3199e054ec2SFabien DESSENNE 	struct stm32_cryp *tmp, *cryp = NULL;
3209e054ec2SFabien DESSENNE 
3219e054ec2SFabien DESSENNE 	spin_lock_bh(&cryp_list.lock);
3229e054ec2SFabien DESSENNE 	if (!ctx->cryp) {
3239e054ec2SFabien DESSENNE 		list_for_each_entry(tmp, &cryp_list.dev_list, list) {
3249e054ec2SFabien DESSENNE 			cryp = tmp;
3259e054ec2SFabien DESSENNE 			break;
3269e054ec2SFabien DESSENNE 		}
3279e054ec2SFabien DESSENNE 		ctx->cryp = cryp;
3289e054ec2SFabien DESSENNE 	} else {
3299e054ec2SFabien DESSENNE 		cryp = ctx->cryp;
3309e054ec2SFabien DESSENNE 	}
3319e054ec2SFabien DESSENNE 
3329e054ec2SFabien DESSENNE 	spin_unlock_bh(&cryp_list.lock);
3339e054ec2SFabien DESSENNE 
3349e054ec2SFabien DESSENNE 	return cryp;
3359e054ec2SFabien DESSENNE }
3369e054ec2SFabien DESSENNE 
337bbb28326SHerbert Xu static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv)
3389e054ec2SFabien DESSENNE {
3399e054ec2SFabien DESSENNE 	if (!iv)
3409e054ec2SFabien DESSENNE 		return;
3419e054ec2SFabien DESSENNE 
3420b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv0l, be32_to_cpu(*iv++));
3430b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv0r, be32_to_cpu(*iv++));
3449e054ec2SFabien DESSENNE 
3459e054ec2SFabien DESSENNE 	if (is_aes(cryp)) {
3460b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->iv1l, be32_to_cpu(*iv++));
3470b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->iv1r, be32_to_cpu(*iv++));
3489e054ec2SFabien DESSENNE 	}
3499e054ec2SFabien DESSENNE }
3509e054ec2SFabien DESSENNE 
3515f49f18dSLionel Debieve static void stm32_cryp_get_iv(struct stm32_cryp *cryp)
3525f49f18dSLionel Debieve {
35347ece481SArd Biesheuvel 	struct skcipher_request *req = cryp->req;
354bbb28326SHerbert Xu 	__be32 *tmp = (void *)req->iv;
3555f49f18dSLionel Debieve 
3565f49f18dSLionel Debieve 	if (!tmp)
3575f49f18dSLionel Debieve 		return;
3585f49f18dSLionel Debieve 
3590b496efbSLinus Walleij 	if (cryp->caps->iv_protection)
3600b496efbSLinus Walleij 		stm32_cryp_key_read_enable(cryp);
3610b496efbSLinus Walleij 
3620b496efbSLinus Walleij 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
3630b496efbSLinus Walleij 	*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
3645f49f18dSLionel Debieve 
3655f49f18dSLionel Debieve 	if (is_aes(cryp)) {
3660b496efbSLinus Walleij 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
3670b496efbSLinus Walleij 		*tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
3680b496efbSLinus Walleij 	}
3690b496efbSLinus Walleij 
3700b496efbSLinus Walleij 	if (cryp->caps->iv_protection)
3710b496efbSLinus Walleij 		stm32_cryp_key_read_disable(cryp);
3720b496efbSLinus Walleij }
3730b496efbSLinus Walleij 
3740b496efbSLinus Walleij /**
3750b496efbSLinus Walleij  * ux500_swap_bits_in_byte() - mirror the bits in a byte
3760b496efbSLinus Walleij  * @b: the byte to be mirrored
3770b496efbSLinus Walleij  *
3780b496efbSLinus Walleij  * The bits are swapped the following way:
3790b496efbSLinus Walleij  *  Byte b include bits 0-7, nibble 1 (n1) include bits 0-3 and
3800b496efbSLinus Walleij  *  nibble 2 (n2) bits 4-7.
3810b496efbSLinus Walleij  *
3820b496efbSLinus Walleij  *  Nibble 1 (n1):
3830b496efbSLinus Walleij  *  (The "old" (moved) bit is replaced with a zero)
3840b496efbSLinus Walleij  *  1. Move bit 6 and 7, 4 positions to the left.
3850b496efbSLinus Walleij  *  2. Move bit 3 and 5, 2 positions to the left.
3860b496efbSLinus Walleij  *  3. Move bit 1-4, 1 position to the left.
3870b496efbSLinus Walleij  *
3880b496efbSLinus Walleij  *  Nibble 2 (n2):
3890b496efbSLinus Walleij  *  1. Move bit 0 and 1, 4 positions to the right.
3900b496efbSLinus Walleij  *  2. Move bit 2 and 4, 2 positions to the right.
3910b496efbSLinus Walleij  *  3. Move bit 3-6, 1 position to the right.
3920b496efbSLinus Walleij  *
3930b496efbSLinus Walleij  *  Combine the two nibbles to a complete and swapped byte.
3940b496efbSLinus Walleij  */
3950b496efbSLinus Walleij static inline u8 ux500_swap_bits_in_byte(u8 b)
3960b496efbSLinus Walleij {
3970b496efbSLinus Walleij #define R_SHIFT_4_MASK  0xc0 /* Bits 6 and 7, right shift 4 */
3980b496efbSLinus Walleij #define R_SHIFT_2_MASK  0x28 /* (After right shift 4) Bits 3 and 5,
3990b496efbSLinus Walleij 				  right shift 2 */
4000b496efbSLinus Walleij #define R_SHIFT_1_MASK  0x1e /* (After right shift 2) Bits 1-4,
4010b496efbSLinus Walleij 				  right shift 1 */
4020b496efbSLinus Walleij #define L_SHIFT_4_MASK  0x03 /* Bits 0 and 1, left shift 4 */
4030b496efbSLinus Walleij #define L_SHIFT_2_MASK  0x14 /* (After left shift 4) Bits 2 and 4,
4040b496efbSLinus Walleij 				  left shift 2 */
4050b496efbSLinus Walleij #define L_SHIFT_1_MASK  0x78 /* (After left shift 1) Bits 3-6,
4060b496efbSLinus Walleij 				  left shift 1 */
4070b496efbSLinus Walleij 
4080b496efbSLinus Walleij 	u8 n1;
4090b496efbSLinus Walleij 	u8 n2;
4100b496efbSLinus Walleij 
4110b496efbSLinus Walleij 	/* Swap most significant nibble */
4120b496efbSLinus Walleij 	/* Right shift 4, bits 6 and 7 */
4130b496efbSLinus Walleij 	n1 = ((b  & R_SHIFT_4_MASK) >> 4) | (b  & ~(R_SHIFT_4_MASK >> 4));
4140b496efbSLinus Walleij 	/* Right shift 2, bits 3 and 5 */
4150b496efbSLinus Walleij 	n1 = ((n1 & R_SHIFT_2_MASK) >> 2) | (n1 & ~(R_SHIFT_2_MASK >> 2));
4160b496efbSLinus Walleij 	/* Right shift 1, bits 1-4 */
4170b496efbSLinus Walleij 	n1 = (n1  & R_SHIFT_1_MASK) >> 1;
4180b496efbSLinus Walleij 
4190b496efbSLinus Walleij 	/* Swap least significant nibble */
4200b496efbSLinus Walleij 	/* Left shift 4, bits 0 and 1 */
4210b496efbSLinus Walleij 	n2 = ((b  & L_SHIFT_4_MASK) << 4) | (b  & ~(L_SHIFT_4_MASK << 4));
4220b496efbSLinus Walleij 	/* Left shift 2, bits 2 and 4 */
4230b496efbSLinus Walleij 	n2 = ((n2 & L_SHIFT_2_MASK) << 2) | (n2 & ~(L_SHIFT_2_MASK << 2));
4240b496efbSLinus Walleij 	/* Left shift 1, bits 3-6 */
4250b496efbSLinus Walleij 	n2 = (n2  & L_SHIFT_1_MASK) << 1;
4260b496efbSLinus Walleij 
4270b496efbSLinus Walleij 	return n1 | n2;
4280b496efbSLinus Walleij }
4290b496efbSLinus Walleij 
4300b496efbSLinus Walleij /**
4310b496efbSLinus Walleij  * ux500_swizzle_key() - Shuffle around words and bits in the AES key
4320b496efbSLinus Walleij  * @in: key to swizzle
4330b496efbSLinus Walleij  * @out: swizzled key
4340b496efbSLinus Walleij  * @len: length of key, in bytes
4350b496efbSLinus Walleij  *
4360b496efbSLinus Walleij  * This "key swizzling procedure" is described in the examples in the
4370b496efbSLinus Walleij  * DB8500 design specification. There is no real description of why
4380b496efbSLinus Walleij  * the bits have been arranged like this in the hardware.
4390b496efbSLinus Walleij  */
4400b496efbSLinus Walleij static inline void ux500_swizzle_key(const u8 *in, u8 *out, u32 len)
4410b496efbSLinus Walleij {
4420b496efbSLinus Walleij 	int i = 0;
4430b496efbSLinus Walleij 	int bpw = sizeof(u32);
4440b496efbSLinus Walleij 	int j;
4450b496efbSLinus Walleij 	int index = 0;
4460b496efbSLinus Walleij 
4470b496efbSLinus Walleij 	j = len - bpw;
4480b496efbSLinus Walleij 	while (j >= 0) {
4490b496efbSLinus Walleij 		for (i = 0; i < bpw; i++) {
4500b496efbSLinus Walleij 			index = len - j - bpw + i;
4510b496efbSLinus Walleij 			out[j + i] =
4520b496efbSLinus Walleij 				ux500_swap_bits_in_byte(in[index]);
4530b496efbSLinus Walleij 		}
4540b496efbSLinus Walleij 		j -= bpw;
4555f49f18dSLionel Debieve 	}
4565f49f18dSLionel Debieve }
4575f49f18dSLionel Debieve 
4589e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c)
4599e054ec2SFabien DESSENNE {
4609e054ec2SFabien DESSENNE 	unsigned int i;
4619e054ec2SFabien DESSENNE 	int r_id;
4629e054ec2SFabien DESSENNE 
4639e054ec2SFabien DESSENNE 	if (is_des(c)) {
4640b496efbSLinus Walleij 		stm32_cryp_write(c, c->caps->k1l, be32_to_cpu(c->ctx->key[0]));
4650b496efbSLinus Walleij 		stm32_cryp_write(c, c->caps->k1r, be32_to_cpu(c->ctx->key[1]));
4660b496efbSLinus Walleij 		return;
4679e054ec2SFabien DESSENNE 	}
4680b496efbSLinus Walleij 
4690b496efbSLinus Walleij 	/*
4700b496efbSLinus Walleij 	 * On the Ux500 the AES key is considered as a single bit sequence
4710b496efbSLinus Walleij 	 * of 128, 192 or 256 bits length. It is written linearly into the
4720b496efbSLinus Walleij 	 * registers from K1L and down, and need to be processed to become
4730b496efbSLinus Walleij 	 * a proper big-endian bit sequence.
4740b496efbSLinus Walleij 	 */
4750b496efbSLinus Walleij 	if (is_aes(c) && c->caps->linear_aes_key) {
4760b496efbSLinus Walleij 		u32 tmpkey[8];
4770b496efbSLinus Walleij 
4780b496efbSLinus Walleij 		ux500_swizzle_key((u8 *)c->ctx->key,
4790b496efbSLinus Walleij 				  (u8 *)tmpkey, c->ctx->keylen);
4800b496efbSLinus Walleij 
4810b496efbSLinus Walleij 		r_id = c->caps->k1l;
4820b496efbSLinus Walleij 		for (i = 0; i < c->ctx->keylen / sizeof(u32); i++, r_id += 4)
4830b496efbSLinus Walleij 			stm32_cryp_write(c, r_id, tmpkey[i]);
4840b496efbSLinus Walleij 
4850b496efbSLinus Walleij 		return;
4860b496efbSLinus Walleij 	}
4870b496efbSLinus Walleij 
4880b496efbSLinus Walleij 	r_id = c->caps->k3r;
4890b496efbSLinus Walleij 	for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4)
4900b496efbSLinus Walleij 		stm32_cryp_write(c, r_id, be32_to_cpu(c->ctx->key[i - 1]));
4919e054ec2SFabien DESSENNE }
4929e054ec2SFabien DESSENNE 
4939e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp)
4949e054ec2SFabien DESSENNE {
4959e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ecb(cryp))
4969e054ec2SFabien DESSENNE 		return CR_AES_ECB;
4979e054ec2SFabien DESSENNE 
4989e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_cbc(cryp))
4999e054ec2SFabien DESSENNE 		return CR_AES_CBC;
5009e054ec2SFabien DESSENNE 
5019e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
5029e054ec2SFabien DESSENNE 		return CR_AES_CTR;
5039e054ec2SFabien DESSENNE 
5049d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_gcm(cryp))
5059d3b5030SFabien DESSENNE 		return CR_AES_GCM;
5069d3b5030SFabien DESSENNE 
5079d3b5030SFabien DESSENNE 	if (is_aes(cryp) && is_ccm(cryp))
5089d3b5030SFabien DESSENNE 		return CR_AES_CCM;
5099d3b5030SFabien DESSENNE 
5109e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_ecb(cryp))
5119e054ec2SFabien DESSENNE 		return CR_DES_ECB;
5129e054ec2SFabien DESSENNE 
5139e054ec2SFabien DESSENNE 	if (is_des(cryp) && is_cbc(cryp))
5149e054ec2SFabien DESSENNE 		return CR_DES_CBC;
5159e054ec2SFabien DESSENNE 
5169e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_ecb(cryp))
5179e054ec2SFabien DESSENNE 		return CR_TDES_ECB;
5189e054ec2SFabien DESSENNE 
5199e054ec2SFabien DESSENNE 	if (is_tdes(cryp) && is_cbc(cryp))
5209e054ec2SFabien DESSENNE 		return CR_TDES_CBC;
5219e054ec2SFabien DESSENNE 
5229e054ec2SFabien DESSENNE 	dev_err(cryp->dev, "Unknown mode\n");
5239e054ec2SFabien DESSENNE 	return CR_AES_UNKNOWN;
5249e054ec2SFabien DESSENNE }
5259e054ec2SFabien DESSENNE 
5269d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp)
5279d3b5030SFabien DESSENNE {
5289d3b5030SFabien DESSENNE 	return is_encrypt(cryp) ? cryp->areq->cryptlen :
5299d3b5030SFabien DESSENNE 				  cryp->areq->cryptlen - cryp->authsize;
5309d3b5030SFabien DESSENNE }
5319d3b5030SFabien DESSENNE 
5329d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg)
5339d3b5030SFabien DESSENNE {
5349d3b5030SFabien DESSENNE 	int ret;
535bbb28326SHerbert Xu 	__be32 iv[4];
5369d3b5030SFabien DESSENNE 
5379d3b5030SFabien DESSENNE 	/* Phase 1 : init */
5389d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, 12);
5399d3b5030SFabien DESSENNE 	iv[3] = cpu_to_be32(GCM_CTR_INIT);
5409d3b5030SFabien DESSENNE 	cryp->gcm_ctr = GCM_CTR_INIT;
5419d3b5030SFabien DESSENNE 	stm32_cryp_hw_write_iv(cryp, iv);
5429d3b5030SFabien DESSENNE 
5430b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
5449d3b5030SFabien DESSENNE 
5459d3b5030SFabien DESSENNE 	/* Wait for end of processing */
5469d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
5474b898d5cSNicolas Toromanoff 	if (ret) {
5489d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (gcm init)\n");
5499d3b5030SFabien DESSENNE 		return ret;
5509d3b5030SFabien DESSENNE 	}
5519d3b5030SFabien DESSENNE 
5524b898d5cSNicolas Toromanoff 	/* Prepare next phase */
5534b898d5cSNicolas Toromanoff 	if (cryp->areq->assoclen) {
5544b898d5cSNicolas Toromanoff 		cfg |= CR_PH_HEADER;
5550b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5564b898d5cSNicolas Toromanoff 	} else if (stm32_cryp_get_input_text_len(cryp)) {
5574b898d5cSNicolas Toromanoff 		cfg |= CR_PH_PAYLOAD;
5580b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5594b898d5cSNicolas Toromanoff 	}
5604b898d5cSNicolas Toromanoff 
5614b898d5cSNicolas Toromanoff 	return 0;
5624b898d5cSNicolas Toromanoff }
5634b898d5cSNicolas Toromanoff 
5644b898d5cSNicolas Toromanoff static void stm32_crypt_gcmccm_end_header(struct stm32_cryp *cryp)
5654b898d5cSNicolas Toromanoff {
5664b898d5cSNicolas Toromanoff 	u32 cfg;
5674b898d5cSNicolas Toromanoff 	int err;
5684b898d5cSNicolas Toromanoff 
5694b898d5cSNicolas Toromanoff 	/* Check if whole header written */
5704b898d5cSNicolas Toromanoff 	if (!cryp->header_in) {
5714b898d5cSNicolas Toromanoff 		/* Wait for completion */
5724b898d5cSNicolas Toromanoff 		err = stm32_cryp_wait_busy(cryp);
5734b898d5cSNicolas Toromanoff 		if (err) {
5744b898d5cSNicolas Toromanoff 			dev_err(cryp->dev, "Timeout (gcm/ccm header)\n");
5750b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->imsc, 0);
5764b898d5cSNicolas Toromanoff 			stm32_cryp_finish_req(cryp, err);
5774b898d5cSNicolas Toromanoff 			return;
5784b898d5cSNicolas Toromanoff 		}
5794b898d5cSNicolas Toromanoff 
5804b898d5cSNicolas Toromanoff 		if (stm32_cryp_get_input_text_len(cryp)) {
5814b898d5cSNicolas Toromanoff 			/* Phase 3 : payload */
5820b496efbSLinus Walleij 			cfg = stm32_cryp_read(cryp, cryp->caps->cr);
5834b898d5cSNicolas Toromanoff 			cfg &= ~CR_CRYPEN;
5840b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5854b898d5cSNicolas Toromanoff 
5864b898d5cSNicolas Toromanoff 			cfg &= ~CR_PH_MASK;
5874b898d5cSNicolas Toromanoff 			cfg |= CR_PH_PAYLOAD | CR_CRYPEN;
5880b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr, cfg);
5894b898d5cSNicolas Toromanoff 		} else {
5904b898d5cSNicolas Toromanoff 			/*
5914b898d5cSNicolas Toromanoff 			 * Phase 4 : tag.
5924b898d5cSNicolas Toromanoff 			 * Nothing to read, nothing to write, caller have to
5934b898d5cSNicolas Toromanoff 			 * end request
5944b898d5cSNicolas Toromanoff 			 */
5954b898d5cSNicolas Toromanoff 		}
5964b898d5cSNicolas Toromanoff 	}
5974b898d5cSNicolas Toromanoff }
5984b898d5cSNicolas Toromanoff 
5994b898d5cSNicolas Toromanoff static void stm32_cryp_write_ccm_first_header(struct stm32_cryp *cryp)
6004b898d5cSNicolas Toromanoff {
6014b898d5cSNicolas Toromanoff 	size_t written;
6024b898d5cSNicolas Toromanoff 	size_t len;
6034b898d5cSNicolas Toromanoff 	u32 alen = cryp->areq->assoclen;
6044b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
6054b898d5cSNicolas Toromanoff 	u8 *b8 = (u8 *)block;
6064b898d5cSNicolas Toromanoff 
6074b898d5cSNicolas Toromanoff 	if (alen <= 65280) {
6084b898d5cSNicolas Toromanoff 		/* Write first u32 of B1 */
6094b898d5cSNicolas Toromanoff 		b8[0] = (alen >> 8) & 0xFF;
6104b898d5cSNicolas Toromanoff 		b8[1] = alen & 0xFF;
6114b898d5cSNicolas Toromanoff 		len = 2;
6124b898d5cSNicolas Toromanoff 	} else {
6134b898d5cSNicolas Toromanoff 		/* Build the two first u32 of B1 */
6144b898d5cSNicolas Toromanoff 		b8[0] = 0xFF;
6154b898d5cSNicolas Toromanoff 		b8[1] = 0xFE;
6164b898d5cSNicolas Toromanoff 		b8[2] = (alen & 0xFF000000) >> 24;
6174b898d5cSNicolas Toromanoff 		b8[3] = (alen & 0x00FF0000) >> 16;
6184b898d5cSNicolas Toromanoff 		b8[4] = (alen & 0x0000FF00) >> 8;
6194b898d5cSNicolas Toromanoff 		b8[5] = alen & 0x000000FF;
6204b898d5cSNicolas Toromanoff 		len = 6;
6214b898d5cSNicolas Toromanoff 	}
6224b898d5cSNicolas Toromanoff 
6234b898d5cSNicolas Toromanoff 	written = min_t(size_t, AES_BLOCK_SIZE - len, alen);
6244b898d5cSNicolas Toromanoff 
6254b898d5cSNicolas Toromanoff 	scatterwalk_copychunks((char *)block + len, &cryp->in_walk, written, 0);
626319ad16dSLinus Walleij 
627319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
6284b898d5cSNicolas Toromanoff 
6294b898d5cSNicolas Toromanoff 	cryp->header_in -= written;
6304b898d5cSNicolas Toromanoff 
6314b898d5cSNicolas Toromanoff 	stm32_crypt_gcmccm_end_header(cryp);
6324b898d5cSNicolas Toromanoff }
6334b898d5cSNicolas Toromanoff 
6349d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg)
6359d3b5030SFabien DESSENNE {
6369d3b5030SFabien DESSENNE 	int ret;
6374b898d5cSNicolas Toromanoff 	u32 iv_32[AES_BLOCK_32], b0_32[AES_BLOCK_32];
6384b898d5cSNicolas Toromanoff 	u8 *iv = (u8 *)iv_32, *b0 = (u8 *)b0_32;
639bbb28326SHerbert Xu 	__be32 *bd;
6409d3b5030SFabien DESSENNE 	u32 *d;
6419d3b5030SFabien DESSENNE 	unsigned int i, textlen;
6429d3b5030SFabien DESSENNE 
6439d3b5030SFabien DESSENNE 	/* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */
6449d3b5030SFabien DESSENNE 	memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
6459d3b5030SFabien DESSENNE 	memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
6469d3b5030SFabien DESSENNE 	iv[AES_BLOCK_SIZE - 1] = 1;
647bbb28326SHerbert Xu 	stm32_cryp_hw_write_iv(cryp, (__be32 *)iv);
6489d3b5030SFabien DESSENNE 
6499d3b5030SFabien DESSENNE 	/* Build B0 */
6509d3b5030SFabien DESSENNE 	memcpy(b0, iv, AES_BLOCK_SIZE);
6519d3b5030SFabien DESSENNE 
6529d3b5030SFabien DESSENNE 	b0[0] |= (8 * ((cryp->authsize - 2) / 2));
6539d3b5030SFabien DESSENNE 
6549d3b5030SFabien DESSENNE 	if (cryp->areq->assoclen)
6559d3b5030SFabien DESSENNE 		b0[0] |= 0x40;
6569d3b5030SFabien DESSENNE 
6579d3b5030SFabien DESSENNE 	textlen = stm32_cryp_get_input_text_len(cryp);
6589d3b5030SFabien DESSENNE 
6599d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 2] = textlen >> 8;
6609d3b5030SFabien DESSENNE 	b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF;
6619d3b5030SFabien DESSENNE 
6629d3b5030SFabien DESSENNE 	/* Enable HW */
6630b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
6649d3b5030SFabien DESSENNE 
6659d3b5030SFabien DESSENNE 	/* Write B0 */
6669d3b5030SFabien DESSENNE 	d = (u32 *)b0;
667bbb28326SHerbert Xu 	bd = (__be32 *)b0;
6689d3b5030SFabien DESSENNE 
6699d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++) {
670bbb28326SHerbert Xu 		u32 xd = d[i];
671bbb28326SHerbert Xu 
6729d3b5030SFabien DESSENNE 		if (!cryp->caps->padding_wa)
673bbb28326SHerbert Xu 			xd = be32_to_cpu(bd[i]);
6740b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, xd);
6759d3b5030SFabien DESSENNE 	}
6769d3b5030SFabien DESSENNE 
6779d3b5030SFabien DESSENNE 	/* Wait for end of processing */
6789d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_enable(cryp);
6794b898d5cSNicolas Toromanoff 	if (ret) {
6809d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (ccm init)\n");
6819d3b5030SFabien DESSENNE 		return ret;
6829d3b5030SFabien DESSENNE 	}
6839d3b5030SFabien DESSENNE 
6844b898d5cSNicolas Toromanoff 	/* Prepare next phase */
6854b898d5cSNicolas Toromanoff 	if (cryp->areq->assoclen) {
6864b898d5cSNicolas Toromanoff 		cfg |= CR_PH_HEADER | CR_CRYPEN;
6870b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6884b898d5cSNicolas Toromanoff 
6894b898d5cSNicolas Toromanoff 		/* Write first (special) block (may move to next phase [payload]) */
6904b898d5cSNicolas Toromanoff 		stm32_cryp_write_ccm_first_header(cryp);
6914b898d5cSNicolas Toromanoff 	} else if (stm32_cryp_get_input_text_len(cryp)) {
6924b898d5cSNicolas Toromanoff 		cfg |= CR_PH_PAYLOAD;
6930b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6944b898d5cSNicolas Toromanoff 	}
6954b898d5cSNicolas Toromanoff 
6964b898d5cSNicolas Toromanoff 	return 0;
6974b898d5cSNicolas Toromanoff }
6984b898d5cSNicolas Toromanoff 
6999e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
7009e054ec2SFabien DESSENNE {
7019e054ec2SFabien DESSENNE 	int ret;
7029e054ec2SFabien DESSENNE 	u32 cfg, hw_mode;
7033d6b6613SHerbert Xu 
7043d6b6613SHerbert Xu 	pm_runtime_get_sync(cryp->dev);
70565f9aa36Slionel.debieve@st.com 
7069e054ec2SFabien DESSENNE 	/* Disable interrupt */
7070b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
7089e054ec2SFabien DESSENNE 
7099e054ec2SFabien DESSENNE 	/* Set configuration */
7109e054ec2SFabien DESSENNE 	cfg = CR_DATA8 | CR_FFLUSH;
7119e054ec2SFabien DESSENNE 
7129e054ec2SFabien DESSENNE 	switch (cryp->ctx->keylen) {
7139e054ec2SFabien DESSENNE 	case AES_KEYSIZE_128:
7149e054ec2SFabien DESSENNE 		cfg |= CR_KEY128;
7159e054ec2SFabien DESSENNE 		break;
7169e054ec2SFabien DESSENNE 
7179e054ec2SFabien DESSENNE 	case AES_KEYSIZE_192:
7189e054ec2SFabien DESSENNE 		cfg |= CR_KEY192;
7199e054ec2SFabien DESSENNE 		break;
7209e054ec2SFabien DESSENNE 
7219e054ec2SFabien DESSENNE 	default:
7229e054ec2SFabien DESSENNE 	case AES_KEYSIZE_256:
7239e054ec2SFabien DESSENNE 		cfg |= CR_KEY256;
7249e054ec2SFabien DESSENNE 		break;
7259e054ec2SFabien DESSENNE 	}
7269e054ec2SFabien DESSENNE 
7279e054ec2SFabien DESSENNE 	hw_mode = stm32_cryp_get_hw_mode(cryp);
7289e054ec2SFabien DESSENNE 	if (hw_mode == CR_AES_UNKNOWN)
7299e054ec2SFabien DESSENNE 		return -EINVAL;
7309e054ec2SFabien DESSENNE 
7319e054ec2SFabien DESSENNE 	/* AES ECB/CBC decrypt: run key preparation first */
7329e054ec2SFabien DESSENNE 	if (is_decrypt(cryp) &&
7339e054ec2SFabien DESSENNE 	    ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
73495fe2253SNicolas Toromanoff 		/* Configure in key preparation mode */
7350b496efbSLinus Walleij 		if (cryp->caps->kp_mode)
7360b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->cr,
7370b496efbSLinus Walleij 				cfg | CR_AES_KP);
7380b496efbSLinus Walleij 		else
7390b496efbSLinus Walleij 			stm32_cryp_write(cryp,
7400b496efbSLinus Walleij 				cryp->caps->cr, cfg | CR_AES_ECB | CR_KSE);
7419e054ec2SFabien DESSENNE 
74295fe2253SNicolas Toromanoff 		/* Set key only after full configuration done */
74395fe2253SNicolas Toromanoff 		stm32_cryp_hw_write_key(cryp);
74495fe2253SNicolas Toromanoff 
74595fe2253SNicolas Toromanoff 		/* Start prepare key */
74695fe2253SNicolas Toromanoff 		stm32_cryp_enable(cryp);
7479e054ec2SFabien DESSENNE 		/* Wait for end of processing */
7489e054ec2SFabien DESSENNE 		ret = stm32_cryp_wait_busy(cryp);
7499e054ec2SFabien DESSENNE 		if (ret) {
7509e054ec2SFabien DESSENNE 			dev_err(cryp->dev, "Timeout (key preparation)\n");
7519e054ec2SFabien DESSENNE 			return ret;
7529e054ec2SFabien DESSENNE 		}
7539e054ec2SFabien DESSENNE 
75495fe2253SNicolas Toromanoff 		cfg |= hw_mode | CR_DEC_NOT_ENC;
75595fe2253SNicolas Toromanoff 
75695fe2253SNicolas Toromanoff 		/* Apply updated config (Decrypt + algo) and flush */
7570b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
75895fe2253SNicolas Toromanoff 	} else {
7599e054ec2SFabien DESSENNE 		cfg |= hw_mode;
7609e054ec2SFabien DESSENNE 		if (is_decrypt(cryp))
7619e054ec2SFabien DESSENNE 			cfg |= CR_DEC_NOT_ENC;
7629e054ec2SFabien DESSENNE 
76395fe2253SNicolas Toromanoff 		/* Apply config and flush */
7640b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cfg);
7659e054ec2SFabien DESSENNE 
76695fe2253SNicolas Toromanoff 		/* Set key only after configuration done */
76795fe2253SNicolas Toromanoff 		stm32_cryp_hw_write_key(cryp);
76895fe2253SNicolas Toromanoff 	}
76995fe2253SNicolas Toromanoff 
7709e054ec2SFabien DESSENNE 	switch (hw_mode) {
7719d3b5030SFabien DESSENNE 	case CR_AES_GCM:
7729d3b5030SFabien DESSENNE 	case CR_AES_CCM:
7739d3b5030SFabien DESSENNE 		/* Phase 1 : init */
7749d3b5030SFabien DESSENNE 		if (hw_mode == CR_AES_CCM)
7759d3b5030SFabien DESSENNE 			ret = stm32_cryp_ccm_init(cryp, cfg);
7769d3b5030SFabien DESSENNE 		else
7779d3b5030SFabien DESSENNE 			ret = stm32_cryp_gcm_init(cryp, cfg);
7789d3b5030SFabien DESSENNE 
7799d3b5030SFabien DESSENNE 		if (ret)
7809d3b5030SFabien DESSENNE 			return ret;
7819d3b5030SFabien DESSENNE 
7829d3b5030SFabien DESSENNE 		break;
7839d3b5030SFabien DESSENNE 
7849e054ec2SFabien DESSENNE 	case CR_DES_CBC:
7859e054ec2SFabien DESSENNE 	case CR_TDES_CBC:
7869e054ec2SFabien DESSENNE 	case CR_AES_CBC:
7879e054ec2SFabien DESSENNE 	case CR_AES_CTR:
788bbb28326SHerbert Xu 		stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->req->iv);
7899e054ec2SFabien DESSENNE 		break;
7909e054ec2SFabien DESSENNE 
7919e054ec2SFabien DESSENNE 	default:
7929e054ec2SFabien DESSENNE 		break;
7939e054ec2SFabien DESSENNE 	}
7949e054ec2SFabien DESSENNE 
7959e054ec2SFabien DESSENNE 	/* Enable now */
79695fe2253SNicolas Toromanoff 	stm32_cryp_enable(cryp);
7979e054ec2SFabien DESSENNE 
7989e054ec2SFabien DESSENNE 	return 0;
7999e054ec2SFabien DESSENNE }
8009e054ec2SFabien DESSENNE 
8019d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
8029e054ec2SFabien DESSENNE {
8039d3b5030SFabien DESSENNE 	if (!err && (is_gcm(cryp) || is_ccm(cryp)))
8049d3b5030SFabien DESSENNE 		/* Phase 4 : output tag */
8059d3b5030SFabien DESSENNE 		err = stm32_cryp_read_auth_tag(cryp);
8069e054ec2SFabien DESSENNE 
807fa97dc2dSNicolas Toromanoff 	if (!err && (!(is_gcm(cryp) || is_ccm(cryp) || is_ecb(cryp))))
8085f49f18dSLionel Debieve 		stm32_cryp_get_iv(cryp);
8095f49f18dSLionel Debieve 
81065f9aa36Slionel.debieve@st.com 	pm_runtime_mark_last_busy(cryp->dev);
81165f9aa36Slionel.debieve@st.com 	pm_runtime_put_autosuspend(cryp->dev);
81265f9aa36Slionel.debieve@st.com 
81329aed438SLionel Debieve 	if (is_gcm(cryp) || is_ccm(cryp))
8149d3b5030SFabien DESSENNE 		crypto_finalize_aead_request(cryp->engine, cryp->areq, err);
81529aed438SLionel Debieve 	else
81647ece481SArd Biesheuvel 		crypto_finalize_skcipher_request(cryp->engine, cryp->req,
8179d3b5030SFabien DESSENNE 						   err);
8189e054ec2SFabien DESSENNE }
8199e054ec2SFabien DESSENNE 
8209e054ec2SFabien DESSENNE static int stm32_cryp_cpu_start(struct stm32_cryp *cryp)
8219e054ec2SFabien DESSENNE {
8229e054ec2SFabien DESSENNE 	/* Enable interrupt and let the IRQ handler do everything */
8230b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, IMSCR_IN | IMSCR_OUT);
8249e054ec2SFabien DESSENNE 
8259e054ec2SFabien DESSENNE 	return 0;
8269e054ec2SFabien DESSENNE }
8279e054ec2SFabien DESSENNE 
828dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq);
829dc7bcef5SCorentin LABBE 
83047ece481SArd Biesheuvel static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm)
8319e054ec2SFabien DESSENNE {
83247ece481SArd Biesheuvel 	crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx));
8339e054ec2SFabien DESSENNE 
8349e054ec2SFabien DESSENNE 	return 0;
8359e054ec2SFabien DESSENNE }
8369e054ec2SFabien DESSENNE 
8379d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq);
8389d3b5030SFabien DESSENNE 
8399d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm)
8409d3b5030SFabien DESSENNE {
8419d3b5030SFabien DESSENNE 	tfm->reqsize = sizeof(struct stm32_cryp_reqctx);
8429d3b5030SFabien DESSENNE 
8439d3b5030SFabien DESSENNE 	return 0;
8449d3b5030SFabien DESSENNE }
8459d3b5030SFabien DESSENNE 
84647ece481SArd Biesheuvel static int stm32_cryp_crypt(struct skcipher_request *req, unsigned long mode)
8479e054ec2SFabien DESSENNE {
84847ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
84947ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
85047ece481SArd Biesheuvel 	struct stm32_cryp_reqctx *rctx = skcipher_request_ctx(req);
8519e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
8529e054ec2SFabien DESSENNE 
8539e054ec2SFabien DESSENNE 	if (!cryp)
8549e054ec2SFabien DESSENNE 		return -ENODEV;
8559e054ec2SFabien DESSENNE 
8569e054ec2SFabien DESSENNE 	rctx->mode = mode;
8579e054ec2SFabien DESSENNE 
85847ece481SArd Biesheuvel 	return crypto_transfer_skcipher_request_to_engine(cryp->engine, req);
8599e054ec2SFabien DESSENNE }
8609e054ec2SFabien DESSENNE 
8619d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode)
8629d3b5030SFabien DESSENNE {
8639d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
8649d3b5030SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx = aead_request_ctx(req);
8659d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
8669d3b5030SFabien DESSENNE 
8679d3b5030SFabien DESSENNE 	if (!cryp)
8689d3b5030SFabien DESSENNE 		return -ENODEV;
8699d3b5030SFabien DESSENNE 
8709d3b5030SFabien DESSENNE 	rctx->mode = mode;
8719d3b5030SFabien DESSENNE 
8729d3b5030SFabien DESSENNE 	return crypto_transfer_aead_request_to_engine(cryp->engine, req);
8739d3b5030SFabien DESSENNE }
8749d3b5030SFabien DESSENNE 
87547ece481SArd Biesheuvel static int stm32_cryp_setkey(struct crypto_skcipher *tfm, const u8 *key,
8769e054ec2SFabien DESSENNE 			     unsigned int keylen)
8779e054ec2SFabien DESSENNE {
87847ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
8799e054ec2SFabien DESSENNE 
8809e054ec2SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
8819e054ec2SFabien DESSENNE 	ctx->keylen = keylen;
8829e054ec2SFabien DESSENNE 
8839e054ec2SFabien DESSENNE 	return 0;
8849e054ec2SFabien DESSENNE }
8859e054ec2SFabien DESSENNE 
88647ece481SArd Biesheuvel static int stm32_cryp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
8879e054ec2SFabien DESSENNE 				 unsigned int keylen)
8889e054ec2SFabien DESSENNE {
8899e054ec2SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
8909e054ec2SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
8919e054ec2SFabien DESSENNE 		return -EINVAL;
8929e054ec2SFabien DESSENNE 	else
8939e054ec2SFabien DESSENNE 		return stm32_cryp_setkey(tfm, key, keylen);
8949e054ec2SFabien DESSENNE }
8959e054ec2SFabien DESSENNE 
89647ece481SArd Biesheuvel static int stm32_cryp_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
8979e054ec2SFabien DESSENNE 				 unsigned int keylen)
8989e054ec2SFabien DESSENNE {
89947ece481SArd Biesheuvel 	return verify_skcipher_des_key(tfm, key) ?:
900b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
9019e054ec2SFabien DESSENNE }
9029e054ec2SFabien DESSENNE 
90347ece481SArd Biesheuvel static int stm32_cryp_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key,
9049e054ec2SFabien DESSENNE 				  unsigned int keylen)
9059e054ec2SFabien DESSENNE {
90647ece481SArd Biesheuvel 	return verify_skcipher_des3_key(tfm, key) ?:
907b5d0ba83SArd Biesheuvel 	       stm32_cryp_setkey(tfm, key, keylen);
9089e054ec2SFabien DESSENNE }
9099e054ec2SFabien DESSENNE 
9109d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
9119d3b5030SFabien DESSENNE 				      unsigned int keylen)
9129d3b5030SFabien DESSENNE {
9139d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
9149d3b5030SFabien DESSENNE 
9159d3b5030SFabien DESSENNE 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
9169d3b5030SFabien DESSENNE 	    keylen != AES_KEYSIZE_256)
9179d3b5030SFabien DESSENNE 		return -EINVAL;
9189d3b5030SFabien DESSENNE 
9199d3b5030SFabien DESSENNE 	memcpy(ctx->key, key, keylen);
9209d3b5030SFabien DESSENNE 	ctx->keylen = keylen;
9219d3b5030SFabien DESSENNE 
9229d3b5030SFabien DESSENNE 	return 0;
9239d3b5030SFabien DESSENNE }
9249d3b5030SFabien DESSENNE 
9259d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
9269d3b5030SFabien DESSENNE 					  unsigned int authsize)
9279d3b5030SFabien DESSENNE {
92839e6e699SNicolas Toromanoff 	switch (authsize) {
92939e6e699SNicolas Toromanoff 	case 4:
93039e6e699SNicolas Toromanoff 	case 8:
93139e6e699SNicolas Toromanoff 	case 12:
93239e6e699SNicolas Toromanoff 	case 13:
93339e6e699SNicolas Toromanoff 	case 14:
93439e6e699SNicolas Toromanoff 	case 15:
93539e6e699SNicolas Toromanoff 	case 16:
93639e6e699SNicolas Toromanoff 		break;
93739e6e699SNicolas Toromanoff 	default:
93839e6e699SNicolas Toromanoff 		return -EINVAL;
93939e6e699SNicolas Toromanoff 	}
94039e6e699SNicolas Toromanoff 
94139e6e699SNicolas Toromanoff 	return 0;
9429d3b5030SFabien DESSENNE }
9439d3b5030SFabien DESSENNE 
9449d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
9459d3b5030SFabien DESSENNE 					  unsigned int authsize)
9469d3b5030SFabien DESSENNE {
9479d3b5030SFabien DESSENNE 	switch (authsize) {
9489d3b5030SFabien DESSENNE 	case 4:
9499d3b5030SFabien DESSENNE 	case 6:
9509d3b5030SFabien DESSENNE 	case 8:
9519d3b5030SFabien DESSENNE 	case 10:
9529d3b5030SFabien DESSENNE 	case 12:
9539d3b5030SFabien DESSENNE 	case 14:
9549d3b5030SFabien DESSENNE 	case 16:
9559d3b5030SFabien DESSENNE 		break;
9569d3b5030SFabien DESSENNE 	default:
9579d3b5030SFabien DESSENNE 		return -EINVAL;
9589d3b5030SFabien DESSENNE 	}
9599d3b5030SFabien DESSENNE 
9609d3b5030SFabien DESSENNE 	return 0;
9619d3b5030SFabien DESSENNE }
9629d3b5030SFabien DESSENNE 
96347ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req)
9649e054ec2SFabien DESSENNE {
96539e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
96639e6e699SNicolas Toromanoff 		return -EINVAL;
96739e6e699SNicolas Toromanoff 
96839e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
96939e6e699SNicolas Toromanoff 		return 0;
97039e6e699SNicolas Toromanoff 
9719e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
9729e054ec2SFabien DESSENNE }
9739e054ec2SFabien DESSENNE 
97447ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req)
9759e054ec2SFabien DESSENNE {
97639e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
97739e6e699SNicolas Toromanoff 		return -EINVAL;
97839e6e699SNicolas Toromanoff 
97939e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
98039e6e699SNicolas Toromanoff 		return 0;
98139e6e699SNicolas Toromanoff 
9829e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
9839e054ec2SFabien DESSENNE }
9849e054ec2SFabien DESSENNE 
98547ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req)
9869e054ec2SFabien DESSENNE {
98739e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
98839e6e699SNicolas Toromanoff 		return -EINVAL;
98939e6e699SNicolas Toromanoff 
99039e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
99139e6e699SNicolas Toromanoff 		return 0;
99239e6e699SNicolas Toromanoff 
9939e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
9949e054ec2SFabien DESSENNE }
9959e054ec2SFabien DESSENNE 
99647ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req)
9979e054ec2SFabien DESSENNE {
99839e6e699SNicolas Toromanoff 	if (req->cryptlen % AES_BLOCK_SIZE)
99939e6e699SNicolas Toromanoff 		return -EINVAL;
100039e6e699SNicolas Toromanoff 
100139e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
100239e6e699SNicolas Toromanoff 		return 0;
100339e6e699SNicolas Toromanoff 
10049e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
10059e054ec2SFabien DESSENNE }
10069e054ec2SFabien DESSENNE 
100747ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req)
10089e054ec2SFabien DESSENNE {
100939e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
101039e6e699SNicolas Toromanoff 		return 0;
101139e6e699SNicolas Toromanoff 
10129e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
10139e054ec2SFabien DESSENNE }
10149e054ec2SFabien DESSENNE 
101547ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req)
10169e054ec2SFabien DESSENNE {
101739e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
101839e6e699SNicolas Toromanoff 		return 0;
101939e6e699SNicolas Toromanoff 
10209e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
10219e054ec2SFabien DESSENNE }
10229e054ec2SFabien DESSENNE 
10239d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req)
10249d3b5030SFabien DESSENNE {
10259d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT);
10269d3b5030SFabien DESSENNE }
10279d3b5030SFabien DESSENNE 
10289d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
10299d3b5030SFabien DESSENNE {
10309d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
10319d3b5030SFabien DESSENNE }
10329d3b5030SFabien DESSENNE 
103339e6e699SNicolas Toromanoff static inline int crypto_ccm_check_iv(const u8 *iv)
103439e6e699SNicolas Toromanoff {
103539e6e699SNicolas Toromanoff 	/* 2 <= L <= 8, so 1 <= L' <= 7. */
103639e6e699SNicolas Toromanoff 	if (iv[0] < 1 || iv[0] > 7)
103739e6e699SNicolas Toromanoff 		return -EINVAL;
103839e6e699SNicolas Toromanoff 
103939e6e699SNicolas Toromanoff 	return 0;
104039e6e699SNicolas Toromanoff }
104139e6e699SNicolas Toromanoff 
10429d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req)
10439d3b5030SFabien DESSENNE {
104439e6e699SNicolas Toromanoff 	int err;
104539e6e699SNicolas Toromanoff 
104639e6e699SNicolas Toromanoff 	err = crypto_ccm_check_iv(req->iv);
104739e6e699SNicolas Toromanoff 	if (err)
104839e6e699SNicolas Toromanoff 		return err;
104939e6e699SNicolas Toromanoff 
10509d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT);
10519d3b5030SFabien DESSENNE }
10529d3b5030SFabien DESSENNE 
10539d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req)
10549d3b5030SFabien DESSENNE {
105539e6e699SNicolas Toromanoff 	int err;
105639e6e699SNicolas Toromanoff 
105739e6e699SNicolas Toromanoff 	err = crypto_ccm_check_iv(req->iv);
105839e6e699SNicolas Toromanoff 	if (err)
105939e6e699SNicolas Toromanoff 		return err;
106039e6e699SNicolas Toromanoff 
10619d3b5030SFabien DESSENNE 	return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
10629d3b5030SFabien DESSENNE }
10639d3b5030SFabien DESSENNE 
106447ece481SArd Biesheuvel static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req)
10659e054ec2SFabien DESSENNE {
106639e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
106739e6e699SNicolas Toromanoff 		return -EINVAL;
106839e6e699SNicolas Toromanoff 
106939e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
107039e6e699SNicolas Toromanoff 		return 0;
107139e6e699SNicolas Toromanoff 
10729e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
10739e054ec2SFabien DESSENNE }
10749e054ec2SFabien DESSENNE 
107547ece481SArd Biesheuvel static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req)
10769e054ec2SFabien DESSENNE {
107739e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
107839e6e699SNicolas Toromanoff 		return -EINVAL;
107939e6e699SNicolas Toromanoff 
108039e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
108139e6e699SNicolas Toromanoff 		return 0;
108239e6e699SNicolas Toromanoff 
10839e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
10849e054ec2SFabien DESSENNE }
10859e054ec2SFabien DESSENNE 
108647ece481SArd Biesheuvel static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req)
10879e054ec2SFabien DESSENNE {
108839e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
108939e6e699SNicolas Toromanoff 		return -EINVAL;
109039e6e699SNicolas Toromanoff 
109139e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
109239e6e699SNicolas Toromanoff 		return 0;
109339e6e699SNicolas Toromanoff 
10949e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
10959e054ec2SFabien DESSENNE }
10969e054ec2SFabien DESSENNE 
109747ece481SArd Biesheuvel static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req)
10989e054ec2SFabien DESSENNE {
109939e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
110039e6e699SNicolas Toromanoff 		return -EINVAL;
110139e6e699SNicolas Toromanoff 
110239e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
110339e6e699SNicolas Toromanoff 		return 0;
110439e6e699SNicolas Toromanoff 
11059e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
11069e054ec2SFabien DESSENNE }
11079e054ec2SFabien DESSENNE 
110847ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req)
11099e054ec2SFabien DESSENNE {
111039e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
111139e6e699SNicolas Toromanoff 		return -EINVAL;
111239e6e699SNicolas Toromanoff 
111339e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
111439e6e699SNicolas Toromanoff 		return 0;
111539e6e699SNicolas Toromanoff 
11169e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
11179e054ec2SFabien DESSENNE }
11189e054ec2SFabien DESSENNE 
111947ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req)
11209e054ec2SFabien DESSENNE {
112139e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
112239e6e699SNicolas Toromanoff 		return -EINVAL;
112339e6e699SNicolas Toromanoff 
112439e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
112539e6e699SNicolas Toromanoff 		return 0;
112639e6e699SNicolas Toromanoff 
11279e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
11289e054ec2SFabien DESSENNE }
11299e054ec2SFabien DESSENNE 
113047ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req)
11319e054ec2SFabien DESSENNE {
113239e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
113339e6e699SNicolas Toromanoff 		return -EINVAL;
113439e6e699SNicolas Toromanoff 
113539e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
113639e6e699SNicolas Toromanoff 		return 0;
113739e6e699SNicolas Toromanoff 
11389e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
11399e054ec2SFabien DESSENNE }
11409e054ec2SFabien DESSENNE 
114147ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req)
11429e054ec2SFabien DESSENNE {
114339e6e699SNicolas Toromanoff 	if (req->cryptlen % DES_BLOCK_SIZE)
114439e6e699SNicolas Toromanoff 		return -EINVAL;
114539e6e699SNicolas Toromanoff 
114639e6e699SNicolas Toromanoff 	if (req->cryptlen == 0)
114739e6e699SNicolas Toromanoff 		return 0;
114839e6e699SNicolas Toromanoff 
11499e054ec2SFabien DESSENNE 	return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
11509e054ec2SFabien DESSENNE }
11519e054ec2SFabien DESSENNE 
115247ece481SArd Biesheuvel static int stm32_cryp_prepare_req(struct skcipher_request *req,
11539d3b5030SFabien DESSENNE 				  struct aead_request *areq)
11549e054ec2SFabien DESSENNE {
11559e054ec2SFabien DESSENNE 	struct stm32_cryp_ctx *ctx;
11569e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
11579e054ec2SFabien DESSENNE 	struct stm32_cryp_reqctx *rctx;
11584b898d5cSNicolas Toromanoff 	struct scatterlist *in_sg;
11599e054ec2SFabien DESSENNE 	int ret;
11609e054ec2SFabien DESSENNE 
11619d3b5030SFabien DESSENNE 	if (!req && !areq)
11629e054ec2SFabien DESSENNE 		return -EINVAL;
11639e054ec2SFabien DESSENNE 
116447ece481SArd Biesheuvel 	ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) :
11659d3b5030SFabien DESSENNE 		    crypto_aead_ctx(crypto_aead_reqtfm(areq));
11669e054ec2SFabien DESSENNE 
11679e054ec2SFabien DESSENNE 	cryp = ctx->cryp;
11689e054ec2SFabien DESSENNE 
116947ece481SArd Biesheuvel 	rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq);
11709e054ec2SFabien DESSENNE 	rctx->mode &= FLG_MODE_MASK;
11719e054ec2SFabien DESSENNE 
11729e054ec2SFabien DESSENNE 	ctx->cryp = cryp;
11739e054ec2SFabien DESSENNE 
11749e054ec2SFabien DESSENNE 	cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode;
11759e054ec2SFabien DESSENNE 	cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE;
11769e054ec2SFabien DESSENNE 	cryp->ctx = ctx;
11779e054ec2SFabien DESSENNE 
11789d3b5030SFabien DESSENNE 	if (req) {
11799e054ec2SFabien DESSENNE 		cryp->req = req;
118029aed438SLionel Debieve 		cryp->areq = NULL;
11814b898d5cSNicolas Toromanoff 		cryp->header_in = 0;
11824b898d5cSNicolas Toromanoff 		cryp->payload_in = req->cryptlen;
11834b898d5cSNicolas Toromanoff 		cryp->payload_out = req->cryptlen;
11844b898d5cSNicolas Toromanoff 		cryp->authsize = 0;
11859d3b5030SFabien DESSENNE 	} else {
11869d3b5030SFabien DESSENNE 		/*
11879d3b5030SFabien DESSENNE 		 * Length of input and output data:
11889d3b5030SFabien DESSENNE 		 * Encryption case:
11899d3b5030SFabien DESSENNE 		 *  INPUT  = AssocData   ||     PlainText
11909d3b5030SFabien DESSENNE 		 *          <- assoclen ->  <- cryptlen ->
11919d3b5030SFabien DESSENNE 		 *
11929d3b5030SFabien DESSENNE 		 *  OUTPUT = AssocData    ||   CipherText   ||      AuthTag
11934b898d5cSNicolas Toromanoff 		 *          <- assoclen ->  <-- cryptlen -->  <- authsize ->
11949d3b5030SFabien DESSENNE 		 *
11959d3b5030SFabien DESSENNE 		 * Decryption case:
11964b898d5cSNicolas Toromanoff 		 *  INPUT  =  AssocData     ||    CipherTex   ||       AuthTag
11974b898d5cSNicolas Toromanoff 		 *          <- assoclen --->  <---------- cryptlen ---------->
11989d3b5030SFabien DESSENNE 		 *
11999d3b5030SFabien DESSENNE 		 *  OUTPUT = AssocData    ||               PlainText
12004b898d5cSNicolas Toromanoff 		 *          <- assoclen ->  <- cryptlen - authsize ->
12019d3b5030SFabien DESSENNE 		 */
12029d3b5030SFabien DESSENNE 		cryp->areq = areq;
120329aed438SLionel Debieve 		cryp->req = NULL;
12049d3b5030SFabien DESSENNE 		cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
12054b898d5cSNicolas Toromanoff 		if (is_encrypt(cryp)) {
12064b898d5cSNicolas Toromanoff 			cryp->payload_in = areq->cryptlen;
12074b898d5cSNicolas Toromanoff 			cryp->header_in = areq->assoclen;
12084b898d5cSNicolas Toromanoff 			cryp->payload_out = areq->cryptlen;
12094b898d5cSNicolas Toromanoff 		} else {
12104b898d5cSNicolas Toromanoff 			cryp->payload_in = areq->cryptlen - cryp->authsize;
12114b898d5cSNicolas Toromanoff 			cryp->header_in = areq->assoclen;
12124b898d5cSNicolas Toromanoff 			cryp->payload_out = cryp->payload_in;
12134b898d5cSNicolas Toromanoff 		}
12149d3b5030SFabien DESSENNE 	}
12159e054ec2SFabien DESSENNE 
12164b898d5cSNicolas Toromanoff 	in_sg = req ? req->src : areq->src;
12174b898d5cSNicolas Toromanoff 	scatterwalk_start(&cryp->in_walk, in_sg);
12189e054ec2SFabien DESSENNE 
12199d3b5030SFabien DESSENNE 	cryp->out_sg = req ? req->dst : areq->dst;
12209e054ec2SFabien DESSENNE 	scatterwalk_start(&cryp->out_walk, cryp->out_sg);
12219e054ec2SFabien DESSENNE 
12229d3b5030SFabien DESSENNE 	if (is_gcm(cryp) || is_ccm(cryp)) {
12239d3b5030SFabien DESSENNE 		/* In output, jump after assoc data */
12244b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->areq->assoclen, 2);
12259d3b5030SFabien DESSENNE 	}
12269d3b5030SFabien DESSENNE 
12274b898d5cSNicolas Toromanoff 	if (is_ctr(cryp))
12284b898d5cSNicolas Toromanoff 		memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr));
12294b898d5cSNicolas Toromanoff 
12309e054ec2SFabien DESSENNE 	ret = stm32_cryp_hw_init(cryp);
12319e054ec2SFabien DESSENNE 	return ret;
12329e054ec2SFabien DESSENNE }
12339e054ec2SFabien DESSENNE 
1234dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq)
12359e054ec2SFabien DESSENNE {
123647ece481SArd Biesheuvel 	struct skcipher_request *req = container_of(areq,
123747ece481SArd Biesheuvel 						      struct skcipher_request,
1238dc7bcef5SCorentin LABBE 						      base);
123947ece481SArd Biesheuvel 	struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
124047ece481SArd Biesheuvel 			crypto_skcipher_reqtfm(req));
12419e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
12429e054ec2SFabien DESSENNE 
12439e054ec2SFabien DESSENNE 	if (!cryp)
12449e054ec2SFabien DESSENNE 		return -ENODEV;
12459e054ec2SFabien DESSENNE 
12466912b79dSHerbert Xu 	return stm32_cryp_prepare_req(req, NULL) ?:
12476912b79dSHerbert Xu 	       stm32_cryp_cpu_start(cryp);
12489d3b5030SFabien DESSENNE }
12499d3b5030SFabien DESSENNE 
12509d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq)
12519d3b5030SFabien DESSENNE {
12529d3b5030SFabien DESSENNE 	struct aead_request *req = container_of(areq, struct aead_request,
12539d3b5030SFabien DESSENNE 						base);
12549d3b5030SFabien DESSENNE 	struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
12559d3b5030SFabien DESSENNE 	struct stm32_cryp *cryp = ctx->cryp;
12566912b79dSHerbert Xu 	int err;
12579d3b5030SFabien DESSENNE 
12589d3b5030SFabien DESSENNE 	if (!cryp)
12599d3b5030SFabien DESSENNE 		return -ENODEV;
12609d3b5030SFabien DESSENNE 
12616912b79dSHerbert Xu 	err = stm32_cryp_prepare_req(NULL, req);
12626912b79dSHerbert Xu 	if (err)
12636912b79dSHerbert Xu 		return err;
12646912b79dSHerbert Xu 
12654b898d5cSNicolas Toromanoff 	if (unlikely(!cryp->payload_in && !cryp->header_in)) {
12669d3b5030SFabien DESSENNE 		/* No input data to process: get tag and finish */
12679d3b5030SFabien DESSENNE 		stm32_cryp_finish_req(cryp, 0);
12689d3b5030SFabien DESSENNE 		return 0;
12699d3b5030SFabien DESSENNE 	}
12709d3b5030SFabien DESSENNE 
12719d3b5030SFabien DESSENNE 	return stm32_cryp_cpu_start(cryp);
12729d3b5030SFabien DESSENNE }
12739d3b5030SFabien DESSENNE 
12749d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
12759d3b5030SFabien DESSENNE {
12764b898d5cSNicolas Toromanoff 	u32 cfg, size_bit;
12774b898d5cSNicolas Toromanoff 	unsigned int i;
12789d3b5030SFabien DESSENNE 	int ret = 0;
12799d3b5030SFabien DESSENNE 
12809d3b5030SFabien DESSENNE 	/* Update Config */
12810b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
12829d3b5030SFabien DESSENNE 
12839d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
12849d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
12859d3b5030SFabien DESSENNE 	cfg &= ~CR_DEC_NOT_ENC;
12869d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
12879d3b5030SFabien DESSENNE 
12880b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
12899d3b5030SFabien DESSENNE 
12909d3b5030SFabien DESSENNE 	if (is_gcm(cryp)) {
12919d3b5030SFabien DESSENNE 		/* GCM: write aad and payload size (in bits) */
12929d3b5030SFabien DESSENNE 		size_bit = cryp->areq->assoclen * 8;
12939d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1294bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
12959d3b5030SFabien DESSENNE 
12960b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, 0);
12970b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, size_bit);
12989d3b5030SFabien DESSENNE 
12999d3b5030SFabien DESSENNE 		size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
13004b898d5cSNicolas Toromanoff 				cryp->areq->cryptlen - cryp->authsize;
13019d3b5030SFabien DESSENNE 		size_bit *= 8;
13029d3b5030SFabien DESSENNE 		if (cryp->caps->swap_final)
1303bbb28326SHerbert Xu 			size_bit = (__force u32)cpu_to_be32(size_bit);
13049d3b5030SFabien DESSENNE 
13050b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, 0);
13060b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, size_bit);
13079d3b5030SFabien DESSENNE 	} else {
13089d3b5030SFabien DESSENNE 		/* CCM: write CTR0 */
13094b898d5cSNicolas Toromanoff 		u32 iv32[AES_BLOCK_32];
13104b898d5cSNicolas Toromanoff 		u8 *iv = (u8 *)iv32;
13114b898d5cSNicolas Toromanoff 		__be32 *biv = (__be32 *)iv32;
13129d3b5030SFabien DESSENNE 
13139d3b5030SFabien DESSENNE 		memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
13149d3b5030SFabien DESSENNE 		memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
13159d3b5030SFabien DESSENNE 
13169d3b5030SFabien DESSENNE 		for (i = 0; i < AES_BLOCK_32; i++) {
1317bbb28326SHerbert Xu 			u32 xiv = iv32[i];
1318bbb28326SHerbert Xu 
13199d3b5030SFabien DESSENNE 			if (!cryp->caps->padding_wa)
1320bbb28326SHerbert Xu 				xiv = be32_to_cpu(biv[i]);
13210b496efbSLinus Walleij 			stm32_cryp_write(cryp, cryp->caps->din, xiv);
13229d3b5030SFabien DESSENNE 		}
13239d3b5030SFabien DESSENNE 	}
13249d3b5030SFabien DESSENNE 
13259d3b5030SFabien DESSENNE 	/* Wait for output data */
13269d3b5030SFabien DESSENNE 	ret = stm32_cryp_wait_output(cryp);
13279d3b5030SFabien DESSENNE 	if (ret) {
13289d3b5030SFabien DESSENNE 		dev_err(cryp->dev, "Timeout (read tag)\n");
13299d3b5030SFabien DESSENNE 		return ret;
13309d3b5030SFabien DESSENNE 	}
13319d3b5030SFabien DESSENNE 
13329d3b5030SFabien DESSENNE 	if (is_encrypt(cryp)) {
13334b898d5cSNicolas Toromanoff 		u32 out_tag[AES_BLOCK_32];
13344b898d5cSNicolas Toromanoff 
13359d3b5030SFabien DESSENNE 		/* Get and write tag */
1336319ad16dSLinus Walleij 		readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
13374b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(out_tag, &cryp->out_walk, cryp->authsize, 1);
13389d3b5030SFabien DESSENNE 	} else {
13399d3b5030SFabien DESSENNE 		/* Get and check tag */
13409d3b5030SFabien DESSENNE 		u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
13419d3b5030SFabien DESSENNE 
13424b898d5cSNicolas Toromanoff 		scatterwalk_copychunks(in_tag, &cryp->in_walk, cryp->authsize, 0);
1343319ad16dSLinus Walleij 		readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
13449d3b5030SFabien DESSENNE 
13459d3b5030SFabien DESSENNE 		if (crypto_memneq(in_tag, out_tag, cryp->authsize))
13469d3b5030SFabien DESSENNE 			ret = -EBADMSG;
13479d3b5030SFabien DESSENNE 	}
13489d3b5030SFabien DESSENNE 
13499d3b5030SFabien DESSENNE 	/* Disable cryp */
13509d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
13510b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
13529d3b5030SFabien DESSENNE 
13539d3b5030SFabien DESSENNE 	return ret;
13549d3b5030SFabien DESSENNE }
13559d3b5030SFabien DESSENNE 
13569e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp)
13579e054ec2SFabien DESSENNE {
13589e054ec2SFabien DESSENNE 	u32 cr;
13599e054ec2SFabien DESSENNE 
136041c76690SNicolas Toromanoff 	if (unlikely(cryp->last_ctr[3] == cpu_to_be32(0xFFFFFFFF))) {
136141c76690SNicolas Toromanoff 		/*
136241c76690SNicolas Toromanoff 		 * In this case, we need to increment manually the ctr counter,
136341c76690SNicolas Toromanoff 		 * as HW doesn't handle the U32 carry.
136441c76690SNicolas Toromanoff 		 */
136541c76690SNicolas Toromanoff 		crypto_inc((u8 *)cryp->last_ctr, sizeof(cryp->last_ctr));
13669e054ec2SFabien DESSENNE 
13670b496efbSLinus Walleij 		cr = stm32_cryp_read(cryp, cryp->caps->cr);
13680b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cr & ~CR_CRYPEN);
13699e054ec2SFabien DESSENNE 
137041c76690SNicolas Toromanoff 		stm32_cryp_hw_write_iv(cryp, cryp->last_ctr);
13719e054ec2SFabien DESSENNE 
13720b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->cr, cr);
13739e054ec2SFabien DESSENNE 	}
13749e054ec2SFabien DESSENNE 
137541c76690SNicolas Toromanoff 	/* The IV registers are BE  */
13760b496efbSLinus Walleij 	cryp->last_ctr[0] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
13770b496efbSLinus Walleij 	cryp->last_ctr[1] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
13780b496efbSLinus Walleij 	cryp->last_ctr[2] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
13790b496efbSLinus Walleij 	cryp->last_ctr[3] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
13809e054ec2SFabien DESSENNE }
13819e054ec2SFabien DESSENNE 
13824b898d5cSNicolas Toromanoff static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
13839e054ec2SFabien DESSENNE {
13844b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32];
13859d3b5030SFabien DESSENNE 
1386319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
13874b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
13884b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
13894b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
13904b898d5cSNicolas Toromanoff 				   cryp->payload_out);
13919e054ec2SFabien DESSENNE }
13929e054ec2SFabien DESSENNE 
13939e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
13949e054ec2SFabien DESSENNE {
13954b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
13969d3b5030SFabien DESSENNE 
13974b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, cryp->hw_blocksize,
13984b898d5cSNicolas Toromanoff 							    cryp->payload_in), 0);
1399319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, cryp->hw_blocksize / sizeof(u32));
14004b898d5cSNicolas Toromanoff 	cryp->payload_in -= min_t(size_t, cryp->hw_blocksize, cryp->payload_in);
14019e054ec2SFabien DESSENNE }
14029e054ec2SFabien DESSENNE 
14039d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
14049d3b5030SFabien DESSENNE {
14059d3b5030SFabien DESSENNE 	int err;
14064b898d5cSNicolas Toromanoff 	u32 cfg, block[AES_BLOCK_32] = {0};
14079d3b5030SFabien DESSENNE 	unsigned int i;
14089d3b5030SFabien DESSENNE 
14099d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
14109d3b5030SFabien DESSENNE 
14119d3b5030SFabien DESSENNE 	/* a) disable ip */
14120b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
14130b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
14149d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14150b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14169d3b5030SFabien DESSENNE 
14179d3b5030SFabien DESSENNE 	/* b) Update IV1R */
14180b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv1r, cryp->gcm_ctr - 2);
14199d3b5030SFabien DESSENNE 
14209d3b5030SFabien DESSENNE 	/* c) change mode to CTR */
14219d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14229d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
14230b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14249d3b5030SFabien DESSENNE 
14259d3b5030SFabien DESSENNE 	/* a) enable IP */
14269d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14270b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14289d3b5030SFabien DESSENNE 
14299d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
14309d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
14314b898d5cSNicolas Toromanoff 	/* wait end of process */
14329d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14339d3b5030SFabien DESSENNE 	if (err) {
14344b898d5cSNicolas Toromanoff 		dev_err(cryp->dev, "Timeout (write gcm last data)\n");
14359d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14369d3b5030SFabien DESSENNE 	}
14379d3b5030SFabien DESSENNE 
14389d3b5030SFabien DESSENNE 	/* c) get and store encrypted data */
14394b898d5cSNicolas Toromanoff 	/*
14404b898d5cSNicolas Toromanoff 	 * Same code as stm32_cryp_irq_read_data(), but we want to store
14414b898d5cSNicolas Toromanoff 	 * block value
14424b898d5cSNicolas Toromanoff 	 */
1443319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
14444b898d5cSNicolas Toromanoff 
14454b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
14464b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
14474b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
14484b898d5cSNicolas Toromanoff 				   cryp->payload_out);
14499d3b5030SFabien DESSENNE 
14509d3b5030SFabien DESSENNE 	/* d) change mode back to AES GCM */
14519d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
14529d3b5030SFabien DESSENNE 	cfg |= CR_AES_GCM;
14530b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14549d3b5030SFabien DESSENNE 
14559d3b5030SFabien DESSENNE 	/* e) change phase to Final */
14569d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
14579d3b5030SFabien DESSENNE 	cfg |= CR_PH_FINAL;
14580b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14599d3b5030SFabien DESSENNE 
14609d3b5030SFabien DESSENNE 	/* f) write padded data */
1461319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
14629d3b5030SFabien DESSENNE 
14639d3b5030SFabien DESSENNE 	/* g) Empty fifo out */
14649d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
14659d3b5030SFabien DESSENNE 	if (err) {
14664b898d5cSNicolas Toromanoff 		dev_err(cryp->dev, "Timeout (write gcm padded data)\n");
14679d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
14689d3b5030SFabien DESSENNE 	}
14699d3b5030SFabien DESSENNE 
14709d3b5030SFabien DESSENNE 	for (i = 0; i < AES_BLOCK_32; i++)
14710b496efbSLinus Walleij 		stm32_cryp_read(cryp, cryp->caps->dout);
14729d3b5030SFabien DESSENNE 
14739d3b5030SFabien DESSENNE 	/* h) run the he normal Final phase */
14749d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, 0);
14759d3b5030SFabien DESSENNE }
14769d3b5030SFabien DESSENNE 
14779d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
14789d3b5030SFabien DESSENNE {
14794b898d5cSNicolas Toromanoff 	u32 cfg;
14809d3b5030SFabien DESSENNE 
14819d3b5030SFabien DESSENNE 	/* disable ip, set NPBLB and reneable ip */
14820b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
14839d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
14840b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14859d3b5030SFabien DESSENNE 
14864b898d5cSNicolas Toromanoff 	cfg |= (cryp->hw_blocksize - cryp->payload_in) << CR_NBPBL_SHIFT;
14879d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
14880b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
14899d3b5030SFabien DESSENNE }
14909d3b5030SFabien DESSENNE 
14919d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
14929d3b5030SFabien DESSENNE {
14939d3b5030SFabien DESSENNE 	int err = 0;
14949d3b5030SFabien DESSENNE 	u32 cfg, iv1tmp;
14954b898d5cSNicolas Toromanoff 	u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32];
14964b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
14979d3b5030SFabien DESSENNE 	unsigned int i;
14989d3b5030SFabien DESSENNE 
14999d3b5030SFabien DESSENNE 	/* 'Special workaround' procedure described in the datasheet */
15009d3b5030SFabien DESSENNE 
15019d3b5030SFabien DESSENNE 	/* a) disable ip */
15020b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, 0);
15039d3b5030SFabien DESSENNE 
15040b496efbSLinus Walleij 	cfg = stm32_cryp_read(cryp, cryp->caps->cr);
15059d3b5030SFabien DESSENNE 	cfg &= ~CR_CRYPEN;
15060b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15079d3b5030SFabien DESSENNE 
15089d3b5030SFabien DESSENNE 	/* b) get IV1 from CRYP_CSGCMCCM7 */
15099d3b5030SFabien DESSENNE 	iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4);
15109d3b5030SFabien DESSENNE 
15119d3b5030SFabien DESSENNE 	/* c) Load CRYP_CSGCMCCMxR */
15129d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp1); i++)
15139d3b5030SFabien DESSENNE 		cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
15149d3b5030SFabien DESSENNE 
15159d3b5030SFabien DESSENNE 	/* d) Write IV1R */
15160b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->iv1r, iv1tmp);
15179d3b5030SFabien DESSENNE 
15189d3b5030SFabien DESSENNE 	/* e) change mode to CTR */
15199d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
15209d3b5030SFabien DESSENNE 	cfg |= CR_AES_CTR;
15210b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15229d3b5030SFabien DESSENNE 
15239d3b5030SFabien DESSENNE 	/* a) enable IP */
15249d3b5030SFabien DESSENNE 	cfg |= CR_CRYPEN;
15250b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15269d3b5030SFabien DESSENNE 
15279d3b5030SFabien DESSENNE 	/* b) pad and write the last block */
15289d3b5030SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
15294b898d5cSNicolas Toromanoff 	/* wait end of process */
15309d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_output(cryp);
15319d3b5030SFabien DESSENNE 	if (err) {
1532be7f5ef9SColin Ian King 		dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
15339d3b5030SFabien DESSENNE 		return stm32_cryp_finish_req(cryp, err);
15349d3b5030SFabien DESSENNE 	}
15359d3b5030SFabien DESSENNE 
15369d3b5030SFabien DESSENNE 	/* c) get and store decrypted data */
15374b898d5cSNicolas Toromanoff 	/*
15384b898d5cSNicolas Toromanoff 	 * Same code as stm32_cryp_irq_read_data(), but we want to store
15394b898d5cSNicolas Toromanoff 	 * block value
15404b898d5cSNicolas Toromanoff 	 */
1541319ad16dSLinus Walleij 	readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
15429d3b5030SFabien DESSENNE 
15434b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
15444b898d5cSNicolas Toromanoff 							     cryp->payload_out), 1);
15454b898d5cSNicolas Toromanoff 	cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, cryp->payload_out);
15469d3b5030SFabien DESSENNE 
15479d3b5030SFabien DESSENNE 	/* d) Load again CRYP_CSGCMCCMxR */
15489d3b5030SFabien DESSENNE 	for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
15499d3b5030SFabien DESSENNE 		cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
15509d3b5030SFabien DESSENNE 
15519d3b5030SFabien DESSENNE 	/* e) change mode back to AES CCM */
15529d3b5030SFabien DESSENNE 	cfg &= ~CR_ALGO_MASK;
15539d3b5030SFabien DESSENNE 	cfg |= CR_AES_CCM;
15540b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15559d3b5030SFabien DESSENNE 
15569d3b5030SFabien DESSENNE 	/* f) change phase to header */
15579d3b5030SFabien DESSENNE 	cfg &= ~CR_PH_MASK;
15589d3b5030SFabien DESSENNE 	cfg |= CR_PH_HEADER;
15590b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->cr, cfg);
15609d3b5030SFabien DESSENNE 
15619d3b5030SFabien DESSENNE 	/* g) XOR and write padded data */
15624b898d5cSNicolas Toromanoff 	for (i = 0; i < ARRAY_SIZE(block); i++) {
15634b898d5cSNicolas Toromanoff 		block[i] ^= cstmp1[i];
15644b898d5cSNicolas Toromanoff 		block[i] ^= cstmp2[i];
15650b496efbSLinus Walleij 		stm32_cryp_write(cryp, cryp->caps->din, block[i]);
15669d3b5030SFabien DESSENNE 	}
15679d3b5030SFabien DESSENNE 
15689d3b5030SFabien DESSENNE 	/* h) wait for completion */
15699d3b5030SFabien DESSENNE 	err = stm32_cryp_wait_busy(cryp);
15709d3b5030SFabien DESSENNE 	if (err)
1571be7f5ef9SColin Ian King 		dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
15729d3b5030SFabien DESSENNE 
15739d3b5030SFabien DESSENNE 	/* i) run the he normal Final phase */
15749d3b5030SFabien DESSENNE 	stm32_cryp_finish_req(cryp, err);
15759d3b5030SFabien DESSENNE }
15769d3b5030SFabien DESSENNE 
15779e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
15789e054ec2SFabien DESSENNE {
15794b898d5cSNicolas Toromanoff 	if (unlikely(!cryp->payload_in)) {
15809e054ec2SFabien DESSENNE 		dev_warn(cryp->dev, "No more data to process\n");
15819e054ec2SFabien DESSENNE 		return;
15829e054ec2SFabien DESSENNE 	}
15839e054ec2SFabien DESSENNE 
15844b898d5cSNicolas Toromanoff 	if (unlikely(cryp->payload_in < AES_BLOCK_SIZE &&
15859d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
15869d3b5030SFabien DESSENNE 		     is_encrypt(cryp))) {
15879d3b5030SFabien DESSENNE 		/* Padding for AES GCM encryption */
15884b898d5cSNicolas Toromanoff 		if (cryp->caps->padding_wa) {
15899d3b5030SFabien DESSENNE 			/* Special case 1 */
15904b898d5cSNicolas Toromanoff 			stm32_cryp_irq_write_gcm_padded_data(cryp);
15914b898d5cSNicolas Toromanoff 			return;
15924b898d5cSNicolas Toromanoff 		}
15939d3b5030SFabien DESSENNE 
15949d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
15959d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
15969d3b5030SFabien DESSENNE 	}
15979d3b5030SFabien DESSENNE 
15984b898d5cSNicolas Toromanoff 	if (unlikely((cryp->payload_in < AES_BLOCK_SIZE) &&
15999d3b5030SFabien DESSENNE 		     (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
16009d3b5030SFabien DESSENNE 		     is_decrypt(cryp))) {
16019d3b5030SFabien DESSENNE 		/* Padding for AES CCM decryption */
16024b898d5cSNicolas Toromanoff 		if (cryp->caps->padding_wa) {
16039d3b5030SFabien DESSENNE 			/* Special case 2 */
16044b898d5cSNicolas Toromanoff 			stm32_cryp_irq_write_ccm_padded_data(cryp);
16054b898d5cSNicolas Toromanoff 			return;
16064b898d5cSNicolas Toromanoff 		}
16079d3b5030SFabien DESSENNE 
16089d3b5030SFabien DESSENNE 		/* Setting padding bytes (NBBLB) */
16099d3b5030SFabien DESSENNE 		stm32_cryp_irq_set_npblb(cryp);
16109d3b5030SFabien DESSENNE 	}
16119d3b5030SFabien DESSENNE 
16129e054ec2SFabien DESSENNE 	if (is_aes(cryp) && is_ctr(cryp))
16139e054ec2SFabien DESSENNE 		stm32_cryp_check_ctr_counter(cryp);
16149e054ec2SFabien DESSENNE 
16159e054ec2SFabien DESSENNE 	stm32_cryp_irq_write_block(cryp);
16169e054ec2SFabien DESSENNE }
16179e054ec2SFabien DESSENNE 
16184b898d5cSNicolas Toromanoff static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp)
16199d3b5030SFabien DESSENNE {
16204b898d5cSNicolas Toromanoff 	u32 block[AES_BLOCK_32] = {0};
16214b898d5cSNicolas Toromanoff 	size_t written;
16229d3b5030SFabien DESSENNE 
16234b898d5cSNicolas Toromanoff 	written = min_t(size_t, AES_BLOCK_SIZE, cryp->header_in);
16249d3b5030SFabien DESSENNE 
16254b898d5cSNicolas Toromanoff 	scatterwalk_copychunks(block, &cryp->in_walk, written, 0);
1626319ad16dSLinus Walleij 
1627319ad16dSLinus Walleij 	writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
16289d3b5030SFabien DESSENNE 
16294b898d5cSNicolas Toromanoff 	cryp->header_in -= written;
16309d3b5030SFabien DESSENNE 
16314b898d5cSNicolas Toromanoff 	stm32_crypt_gcmccm_end_header(cryp);
16329d3b5030SFabien DESSENNE }
16339d3b5030SFabien DESSENNE 
16349e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg)
16359e054ec2SFabien DESSENNE {
16369e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
16379d3b5030SFabien DESSENNE 	u32 ph;
16380b496efbSLinus Walleij 	u32 it_mask = stm32_cryp_read(cryp, cryp->caps->imsc);
16399e054ec2SFabien DESSENNE 
16409e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_OUT)
16419e054ec2SFabien DESSENNE 		/* Output FIFO IRQ: read data */
16424b898d5cSNicolas Toromanoff 		stm32_cryp_irq_read_data(cryp);
16439e054ec2SFabien DESSENNE 
16449e054ec2SFabien DESSENNE 	if (cryp->irq_status & MISR_IN) {
16454b898d5cSNicolas Toromanoff 		if (is_gcm(cryp) || is_ccm(cryp)) {
16460b496efbSLinus Walleij 			ph = stm32_cryp_read(cryp, cryp->caps->cr) & CR_PH_MASK;
16479d3b5030SFabien DESSENNE 			if (unlikely(ph == CR_PH_HEADER))
16489d3b5030SFabien DESSENNE 				/* Write Header */
16494b898d5cSNicolas Toromanoff 				stm32_cryp_irq_write_gcmccm_header(cryp);
16509d3b5030SFabien DESSENNE 			else
16519e054ec2SFabien DESSENNE 				/* Input FIFO IRQ: write data */
16529e054ec2SFabien DESSENNE 				stm32_cryp_irq_write_data(cryp);
16534b898d5cSNicolas Toromanoff 			if (is_gcm(cryp))
16549d3b5030SFabien DESSENNE 				cryp->gcm_ctr++;
16559d3b5030SFabien DESSENNE 		} else {
16569d3b5030SFabien DESSENNE 			/* Input FIFO IRQ: write data */
16579d3b5030SFabien DESSENNE 			stm32_cryp_irq_write_data(cryp);
16589d3b5030SFabien DESSENNE 		}
16599e054ec2SFabien DESSENNE 	}
16609e054ec2SFabien DESSENNE 
16614b898d5cSNicolas Toromanoff 	/* Mask useless interrupts */
16624b898d5cSNicolas Toromanoff 	if (!cryp->payload_in && !cryp->header_in)
16634b898d5cSNicolas Toromanoff 		it_mask &= ~IMSCR_IN;
16644b898d5cSNicolas Toromanoff 	if (!cryp->payload_out)
16654b898d5cSNicolas Toromanoff 		it_mask &= ~IMSCR_OUT;
16660b496efbSLinus Walleij 	stm32_cryp_write(cryp, cryp->caps->imsc, it_mask);
16674b898d5cSNicolas Toromanoff 
16684b898d5cSNicolas Toromanoff 	if (!cryp->payload_in && !cryp->header_in && !cryp->payload_out)
16694b898d5cSNicolas Toromanoff 		stm32_cryp_finish_req(cryp, 0);
16704b898d5cSNicolas Toromanoff 
16719e054ec2SFabien DESSENNE 	return IRQ_HANDLED;
16729e054ec2SFabien DESSENNE }
16739e054ec2SFabien DESSENNE 
16749e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg)
16759e054ec2SFabien DESSENNE {
16769e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = arg;
16779e054ec2SFabien DESSENNE 
16780b496efbSLinus Walleij 	cryp->irq_status = stm32_cryp_read(cryp, cryp->caps->mis);
16799e054ec2SFabien DESSENNE 
16809e054ec2SFabien DESSENNE 	return IRQ_WAKE_THREAD;
16819e054ec2SFabien DESSENNE }
16829e054ec2SFabien DESSENNE 
1683d5e6b48fSHerbert Xu static struct skcipher_engine_alg crypto_algs[] = {
16849e054ec2SFabien DESSENNE {
1685d5e6b48fSHerbert Xu 	.base = {
168647ece481SArd Biesheuvel 		.base.cra_name		= "ecb(aes)",
168747ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-ecb-aes",
168847ece481SArd Biesheuvel 		.base.cra_priority	= 200,
168947ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
169047ece481SArd Biesheuvel 		.base.cra_blocksize	= AES_BLOCK_SIZE,
169147ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
16924b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
169347ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
169447ece481SArd Biesheuvel 
169547ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
16969e054ec2SFabien DESSENNE 		.min_keysize		= AES_MIN_KEY_SIZE,
16979e054ec2SFabien DESSENNE 		.max_keysize		= AES_MAX_KEY_SIZE,
16989e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_aes_setkey,
16999e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_aes_ecb_encrypt,
17009e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_aes_ecb_decrypt,
17019e054ec2SFabien DESSENNE 	},
1702d5e6b48fSHerbert Xu 	.op = {
1703d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1704d5e6b48fSHerbert Xu 	},
1705d5e6b48fSHerbert Xu },
17069e054ec2SFabien DESSENNE {
1707d5e6b48fSHerbert Xu 	.base = {
170847ece481SArd Biesheuvel 		.base.cra_name		= "cbc(aes)",
170947ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-cbc-aes",
171047ece481SArd Biesheuvel 		.base.cra_priority	= 200,
171147ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
171247ece481SArd Biesheuvel 		.base.cra_blocksize	= AES_BLOCK_SIZE,
171347ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17144b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
171547ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
171647ece481SArd Biesheuvel 
171747ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
17189e054ec2SFabien DESSENNE 		.min_keysize		= AES_MIN_KEY_SIZE,
17199e054ec2SFabien DESSENNE 		.max_keysize		= AES_MAX_KEY_SIZE,
17209e054ec2SFabien DESSENNE 		.ivsize			= AES_BLOCK_SIZE,
17219e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_aes_setkey,
17229e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_aes_cbc_encrypt,
17239e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_aes_cbc_decrypt,
17249e054ec2SFabien DESSENNE 	},
1725d5e6b48fSHerbert Xu 	.op = {
1726d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1727d5e6b48fSHerbert Xu 	},
1728d5e6b48fSHerbert Xu },
17299e054ec2SFabien DESSENNE {
1730d5e6b48fSHerbert Xu 	.base = {
173147ece481SArd Biesheuvel 		.base.cra_name		= "ctr(aes)",
173247ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-ctr-aes",
173347ece481SArd Biesheuvel 		.base.cra_priority	= 200,
173447ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
173547ece481SArd Biesheuvel 		.base.cra_blocksize	= 1,
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_ctr_encrypt,
17469e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_aes_ctr_decrypt,
17479e054ec2SFabien DESSENNE 	},
1748d5e6b48fSHerbert Xu 	.op = {
1749d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1750d5e6b48fSHerbert Xu 	},
1751d5e6b48fSHerbert Xu },
17529e054ec2SFabien DESSENNE {
1753d5e6b48fSHerbert Xu 	.base = {
175447ece481SArd Biesheuvel 		.base.cra_name		= "ecb(des)",
175547ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-ecb-des",
175647ece481SArd Biesheuvel 		.base.cra_priority	= 200,
175747ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
175847ece481SArd Biesheuvel 		.base.cra_blocksize	= DES_BLOCK_SIZE,
175947ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17604b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
176147ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
176247ece481SArd Biesheuvel 
176347ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
17649e054ec2SFabien DESSENNE 		.min_keysize		= DES_BLOCK_SIZE,
17659e054ec2SFabien DESSENNE 		.max_keysize		= DES_BLOCK_SIZE,
17669e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_des_setkey,
17679e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_des_ecb_encrypt,
17689e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_des_ecb_decrypt,
17699e054ec2SFabien DESSENNE 	},
1770d5e6b48fSHerbert Xu 	.op = {
1771d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1772d5e6b48fSHerbert Xu 	},
1773d5e6b48fSHerbert Xu },
17749e054ec2SFabien DESSENNE {
1775d5e6b48fSHerbert Xu 	.base = {
177647ece481SArd Biesheuvel 		.base.cra_name		= "cbc(des)",
177747ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-cbc-des",
177847ece481SArd Biesheuvel 		.base.cra_priority	= 200,
177947ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
178047ece481SArd Biesheuvel 		.base.cra_blocksize	= DES_BLOCK_SIZE,
178147ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
17824b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
178347ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
178447ece481SArd Biesheuvel 
178547ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
17869e054ec2SFabien DESSENNE 		.min_keysize		= DES_BLOCK_SIZE,
17879e054ec2SFabien DESSENNE 		.max_keysize		= DES_BLOCK_SIZE,
17889e054ec2SFabien DESSENNE 		.ivsize			= DES_BLOCK_SIZE,
17899e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_des_setkey,
17909e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_des_cbc_encrypt,
17919e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_des_cbc_decrypt,
17929e054ec2SFabien DESSENNE 	},
1793d5e6b48fSHerbert Xu 	.op = {
1794d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1795d5e6b48fSHerbert Xu 	},
1796d5e6b48fSHerbert Xu },
17979e054ec2SFabien DESSENNE {
1798d5e6b48fSHerbert Xu 	.base = {
179947ece481SArd Biesheuvel 		.base.cra_name		= "ecb(des3_ede)",
180047ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-ecb-des3",
180147ece481SArd Biesheuvel 		.base.cra_priority	= 200,
180247ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
180347ece481SArd Biesheuvel 		.base.cra_blocksize	= DES_BLOCK_SIZE,
180447ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
18054b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
180647ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
180747ece481SArd Biesheuvel 
180847ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
18099e054ec2SFabien DESSENNE 		.min_keysize		= 3 * DES_BLOCK_SIZE,
18109e054ec2SFabien DESSENNE 		.max_keysize		= 3 * DES_BLOCK_SIZE,
18119e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_tdes_setkey,
18129e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_tdes_ecb_encrypt,
18139e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_tdes_ecb_decrypt,
18149e054ec2SFabien DESSENNE 	},
1815d5e6b48fSHerbert Xu 	.op = {
1816d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1817d5e6b48fSHerbert Xu 	},
1818d5e6b48fSHerbert Xu },
18199e054ec2SFabien DESSENNE {
1820d5e6b48fSHerbert Xu 	.base = {
182147ece481SArd Biesheuvel 		.base.cra_name		= "cbc(des3_ede)",
182247ece481SArd Biesheuvel 		.base.cra_driver_name	= "stm32-cbc-des3",
182347ece481SArd Biesheuvel 		.base.cra_priority	= 200,
182447ece481SArd Biesheuvel 		.base.cra_flags		= CRYPTO_ALG_ASYNC,
182547ece481SArd Biesheuvel 		.base.cra_blocksize	= DES_BLOCK_SIZE,
182647ece481SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct stm32_cryp_ctx),
18274b898d5cSNicolas Toromanoff 		.base.cra_alignmask	= 0,
182847ece481SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
182947ece481SArd Biesheuvel 
183047ece481SArd Biesheuvel 		.init			= stm32_cryp_init_tfm,
18319e054ec2SFabien DESSENNE 		.min_keysize		= 3 * DES_BLOCK_SIZE,
18329e054ec2SFabien DESSENNE 		.max_keysize		= 3 * DES_BLOCK_SIZE,
18339e054ec2SFabien DESSENNE 		.ivsize			= DES_BLOCK_SIZE,
18349e054ec2SFabien DESSENNE 		.setkey			= stm32_cryp_tdes_setkey,
18359e054ec2SFabien DESSENNE 		.encrypt		= stm32_cryp_tdes_cbc_encrypt,
18369e054ec2SFabien DESSENNE 		.decrypt		= stm32_cryp_tdes_cbc_decrypt,
18379e054ec2SFabien DESSENNE 	},
1838d5e6b48fSHerbert Xu 	.op = {
1839d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_cipher_one_req,
1840d5e6b48fSHerbert Xu 	},
1841d5e6b48fSHerbert Xu },
18429e054ec2SFabien DESSENNE };
18439e054ec2SFabien DESSENNE 
1844d5e6b48fSHerbert Xu static struct aead_engine_alg aead_algs[] = {
18459d3b5030SFabien DESSENNE {
1846d5e6b48fSHerbert Xu 	.base.setkey		= stm32_cryp_aes_aead_setkey,
1847d5e6b48fSHerbert Xu 	.base.setauthsize	= stm32_cryp_aes_gcm_setauthsize,
1848d5e6b48fSHerbert Xu 	.base.encrypt		= stm32_cryp_aes_gcm_encrypt,
1849d5e6b48fSHerbert Xu 	.base.decrypt		= stm32_cryp_aes_gcm_decrypt,
1850d5e6b48fSHerbert Xu 	.base.init		= stm32_cryp_aes_aead_init,
1851d5e6b48fSHerbert Xu 	.base.ivsize		= 12,
1852d5e6b48fSHerbert Xu 	.base.maxauthsize	= AES_BLOCK_SIZE,
18539d3b5030SFabien DESSENNE 
1854d5e6b48fSHerbert Xu 	.base.base = {
18559d3b5030SFabien DESSENNE 		.cra_name		= "gcm(aes)",
18569d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-gcm-aes",
18579d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18589d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18599d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18609d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18614b898d5cSNicolas Toromanoff 		.cra_alignmask		= 0,
18629d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18639d3b5030SFabien DESSENNE 	},
1864d5e6b48fSHerbert Xu 	.op = {
1865d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_aead_one_req,
1866d5e6b48fSHerbert Xu 	},
18679d3b5030SFabien DESSENNE },
18689d3b5030SFabien DESSENNE {
1869d5e6b48fSHerbert Xu 	.base.setkey		= stm32_cryp_aes_aead_setkey,
1870d5e6b48fSHerbert Xu 	.base.setauthsize	= stm32_cryp_aes_ccm_setauthsize,
1871d5e6b48fSHerbert Xu 	.base.encrypt		= stm32_cryp_aes_ccm_encrypt,
1872d5e6b48fSHerbert Xu 	.base.decrypt		= stm32_cryp_aes_ccm_decrypt,
1873d5e6b48fSHerbert Xu 	.base.init		= stm32_cryp_aes_aead_init,
1874d5e6b48fSHerbert Xu 	.base.ivsize		= AES_BLOCK_SIZE,
1875d5e6b48fSHerbert Xu 	.base.maxauthsize	= AES_BLOCK_SIZE,
18769d3b5030SFabien DESSENNE 
1877d5e6b48fSHerbert Xu 	.base.base = {
18789d3b5030SFabien DESSENNE 		.cra_name		= "ccm(aes)",
18799d3b5030SFabien DESSENNE 		.cra_driver_name	= "stm32-ccm-aes",
18809d3b5030SFabien DESSENNE 		.cra_priority		= 200,
18819d3b5030SFabien DESSENNE 		.cra_flags		= CRYPTO_ALG_ASYNC,
18829d3b5030SFabien DESSENNE 		.cra_blocksize		= 1,
18839d3b5030SFabien DESSENNE 		.cra_ctxsize		= sizeof(struct stm32_cryp_ctx),
18844b898d5cSNicolas Toromanoff 		.cra_alignmask		= 0,
18859d3b5030SFabien DESSENNE 		.cra_module		= THIS_MODULE,
18869d3b5030SFabien DESSENNE 	},
1887d5e6b48fSHerbert Xu 	.op = {
1888d5e6b48fSHerbert Xu 		.do_one_request = stm32_cryp_aead_one_req,
1889d5e6b48fSHerbert Xu 	},
18909d3b5030SFabien DESSENNE },
18919d3b5030SFabien DESSENNE };
18929d3b5030SFabien DESSENNE 
18930b496efbSLinus Walleij static const struct stm32_cryp_caps ux500_data = {
18940b496efbSLinus Walleij 	.aeads_support = false,
18950b496efbSLinus Walleij 	.linear_aes_key = true,
18960b496efbSLinus Walleij 	.kp_mode = false,
18970b496efbSLinus Walleij 	.iv_protection = true,
18989d3b5030SFabien DESSENNE 	.swap_final = true,
18999d3b5030SFabien DESSENNE 	.padding_wa = true,
19000b496efbSLinus Walleij 	.cr = UX500_CRYP_CR,
19010b496efbSLinus Walleij 	.sr = UX500_CRYP_SR,
19020b496efbSLinus Walleij 	.din = UX500_CRYP_DIN,
19030b496efbSLinus Walleij 	.dout = UX500_CRYP_DOUT,
19040b496efbSLinus Walleij 	.imsc = UX500_CRYP_IMSC,
19050b496efbSLinus Walleij 	.mis = UX500_CRYP_MIS,
19060b496efbSLinus Walleij 	.k1l = UX500_CRYP_K1L,
19070b496efbSLinus Walleij 	.k1r = UX500_CRYP_K1R,
19080b496efbSLinus Walleij 	.k3r = UX500_CRYP_K3R,
19090b496efbSLinus Walleij 	.iv0l = UX500_CRYP_IV0L,
19100b496efbSLinus Walleij 	.iv0r = UX500_CRYP_IV0R,
19110b496efbSLinus Walleij 	.iv1l = UX500_CRYP_IV1L,
19120b496efbSLinus Walleij 	.iv1r = UX500_CRYP_IV1R,
19130b496efbSLinus Walleij };
19140b496efbSLinus Walleij 
19150b496efbSLinus Walleij static const struct stm32_cryp_caps f7_data = {
19160b496efbSLinus Walleij 	.aeads_support = true,
19170b496efbSLinus Walleij 	.linear_aes_key = false,
19180b496efbSLinus Walleij 	.kp_mode = true,
19190b496efbSLinus Walleij 	.iv_protection = false,
19200b496efbSLinus Walleij 	.swap_final = true,
19210b496efbSLinus Walleij 	.padding_wa = true,
19220b496efbSLinus Walleij 	.cr = CRYP_CR,
19230b496efbSLinus Walleij 	.sr = CRYP_SR,
19240b496efbSLinus Walleij 	.din = CRYP_DIN,
19250b496efbSLinus Walleij 	.dout = CRYP_DOUT,
19260b496efbSLinus Walleij 	.imsc = CRYP_IMSCR,
19270b496efbSLinus Walleij 	.mis = CRYP_MISR,
19280b496efbSLinus Walleij 	.k1l = CRYP_K1LR,
19290b496efbSLinus Walleij 	.k1r = CRYP_K1RR,
19300b496efbSLinus Walleij 	.k3r = CRYP_K3RR,
19310b496efbSLinus Walleij 	.iv0l = CRYP_IV0LR,
19320b496efbSLinus Walleij 	.iv0r = CRYP_IV0RR,
19330b496efbSLinus Walleij 	.iv1l = CRYP_IV1LR,
19340b496efbSLinus Walleij 	.iv1r = CRYP_IV1RR,
19359d3b5030SFabien DESSENNE };
19369d3b5030SFabien DESSENNE 
1937a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = {
19380b496efbSLinus Walleij 	.aeads_support = true,
19390b496efbSLinus Walleij 	.linear_aes_key = false,
19400b496efbSLinus Walleij 	.kp_mode = true,
19410b496efbSLinus Walleij 	.iv_protection = false,
1942a43a3484SFabien DESSENNE 	.swap_final = false,
1943a43a3484SFabien DESSENNE 	.padding_wa = false,
19440b496efbSLinus Walleij 	.cr = CRYP_CR,
19450b496efbSLinus Walleij 	.sr = CRYP_SR,
19460b496efbSLinus Walleij 	.din = CRYP_DIN,
19470b496efbSLinus Walleij 	.dout = CRYP_DOUT,
19480b496efbSLinus Walleij 	.imsc = CRYP_IMSCR,
19490b496efbSLinus Walleij 	.mis = CRYP_MISR,
19500b496efbSLinus Walleij 	.k1l = CRYP_K1LR,
19510b496efbSLinus Walleij 	.k1r = CRYP_K1RR,
19520b496efbSLinus Walleij 	.k3r = CRYP_K3RR,
19530b496efbSLinus Walleij 	.iv0l = CRYP_IV0LR,
19540b496efbSLinus Walleij 	.iv0r = CRYP_IV0RR,
19550b496efbSLinus Walleij 	.iv1l = CRYP_IV1LR,
19560b496efbSLinus Walleij 	.iv1r = CRYP_IV1RR,
1957a43a3484SFabien DESSENNE };
1958a43a3484SFabien DESSENNE 
19599e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = {
19600b496efbSLinus Walleij 	{ .compatible = "stericsson,ux500-cryp", .data = &ux500_data},
19619d3b5030SFabien DESSENNE 	{ .compatible = "st,stm32f756-cryp", .data = &f7_data},
1962a43a3484SFabien DESSENNE 	{ .compatible = "st,stm32mp1-cryp", .data = &mp1_data},
19639e054ec2SFabien DESSENNE 	{},
19649e054ec2SFabien DESSENNE };
1965761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids);
19669e054ec2SFabien DESSENNE 
19679e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev)
19689e054ec2SFabien DESSENNE {
19699e054ec2SFabien DESSENNE 	struct device *dev = &pdev->dev;
19709e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp;
19719e054ec2SFabien DESSENNE 	struct reset_control *rst;
19729e054ec2SFabien DESSENNE 	int irq, ret;
19739e054ec2SFabien DESSENNE 
19749e054ec2SFabien DESSENNE 	cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL);
19759e054ec2SFabien DESSENNE 	if (!cryp)
19769e054ec2SFabien DESSENNE 		return -ENOMEM;
19779e054ec2SFabien DESSENNE 
19789d3b5030SFabien DESSENNE 	cryp->caps = of_device_get_match_data(dev);
19799d3b5030SFabien DESSENNE 	if (!cryp->caps)
19809d3b5030SFabien DESSENNE 		return -ENODEV;
19819d3b5030SFabien DESSENNE 
19829e054ec2SFabien DESSENNE 	cryp->dev = dev;
19839e054ec2SFabien DESSENNE 
1984473b4d99SYueHaibing 	cryp->regs = devm_platform_ioremap_resource(pdev, 0);
198560bcf265Sweiyongjun \(A\) 	if (IS_ERR(cryp->regs))
19869e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->regs);
19879e054ec2SFabien DESSENNE 
19889e054ec2SFabien DESSENNE 	irq = platform_get_irq(pdev, 0);
1989514838e9SStephen Boyd 	if (irq < 0)
19909e054ec2SFabien DESSENNE 		return irq;
19919e054ec2SFabien DESSENNE 
19929e054ec2SFabien DESSENNE 	ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq,
19939e054ec2SFabien DESSENNE 					stm32_cryp_irq_thread, IRQF_ONESHOT,
19949e054ec2SFabien DESSENNE 					dev_name(dev), cryp);
19959e054ec2SFabien DESSENNE 	if (ret) {
19969e054ec2SFabien DESSENNE 		dev_err(dev, "Cannot grab IRQ\n");
19979e054ec2SFabien DESSENNE 		return ret;
19989e054ec2SFabien DESSENNE 	}
19999e054ec2SFabien DESSENNE 
20009e054ec2SFabien DESSENNE 	cryp->clk = devm_clk_get(dev, NULL);
20019e054ec2SFabien DESSENNE 	if (IS_ERR(cryp->clk)) {
2002029812aeSEtienne Carriere 		dev_err_probe(dev, PTR_ERR(cryp->clk), "Could not get clock\n");
2003029812aeSEtienne Carriere 
20049e054ec2SFabien DESSENNE 		return PTR_ERR(cryp->clk);
20059e054ec2SFabien DESSENNE 	}
20069e054ec2SFabien DESSENNE 
20079e054ec2SFabien DESSENNE 	ret = clk_prepare_enable(cryp->clk);
20089e054ec2SFabien DESSENNE 	if (ret) {
20099e054ec2SFabien DESSENNE 		dev_err(cryp->dev, "Failed to enable clock\n");
20109e054ec2SFabien DESSENNE 		return ret;
20119e054ec2SFabien DESSENNE 	}
20129e054ec2SFabien DESSENNE 
201365f9aa36Slionel.debieve@st.com 	pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY);
201465f9aa36Slionel.debieve@st.com 	pm_runtime_use_autosuspend(dev);
201565f9aa36Slionel.debieve@st.com 
201665f9aa36Slionel.debieve@st.com 	pm_runtime_get_noresume(dev);
201765f9aa36Slionel.debieve@st.com 	pm_runtime_set_active(dev);
201865f9aa36Slionel.debieve@st.com 	pm_runtime_enable(dev);
201965f9aa36Slionel.debieve@st.com 
20209e054ec2SFabien DESSENNE 	rst = devm_reset_control_get(dev, NULL);
20210a2f9f57SEtienne Carriere 	if (IS_ERR(rst)) {
20220a2f9f57SEtienne Carriere 		ret = PTR_ERR(rst);
20230a2f9f57SEtienne Carriere 		if (ret == -EPROBE_DEFER)
20240a2f9f57SEtienne Carriere 			goto err_rst;
20250a2f9f57SEtienne Carriere 	} else {
20269e054ec2SFabien DESSENNE 		reset_control_assert(rst);
20279e054ec2SFabien DESSENNE 		udelay(2);
20289e054ec2SFabien DESSENNE 		reset_control_deassert(rst);
20299e054ec2SFabien DESSENNE 	}
20309e054ec2SFabien DESSENNE 
20319e054ec2SFabien DESSENNE 	platform_set_drvdata(pdev, cryp);
20329e054ec2SFabien DESSENNE 
20339e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20349e054ec2SFabien DESSENNE 	list_add(&cryp->list, &cryp_list.dev_list);
20359e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20369e054ec2SFabien DESSENNE 
20379e054ec2SFabien DESSENNE 	/* Initialize crypto engine */
20389e054ec2SFabien DESSENNE 	cryp->engine = crypto_engine_alloc_init(dev, 1);
20399e054ec2SFabien DESSENNE 	if (!cryp->engine) {
20409e054ec2SFabien DESSENNE 		dev_err(dev, "Could not init crypto engine\n");
20419e054ec2SFabien DESSENNE 		ret = -ENOMEM;
20429e054ec2SFabien DESSENNE 		goto err_engine1;
20439e054ec2SFabien DESSENNE 	}
20449e054ec2SFabien DESSENNE 
20459e054ec2SFabien DESSENNE 	ret = crypto_engine_start(cryp->engine);
20469e054ec2SFabien DESSENNE 	if (ret) {
20479e054ec2SFabien DESSENNE 		dev_err(dev, "Could not start crypto engine\n");
20489e054ec2SFabien DESSENNE 		goto err_engine2;
20499e054ec2SFabien DESSENNE 	}
20509e054ec2SFabien DESSENNE 
2051d5e6b48fSHerbert Xu 	ret = crypto_engine_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20529e054ec2SFabien DESSENNE 	if (ret) {
20539e054ec2SFabien DESSENNE 		dev_err(dev, "Could not register algs\n");
20549e054ec2SFabien DESSENNE 		goto err_algs;
20559e054ec2SFabien DESSENNE 	}
20569e054ec2SFabien DESSENNE 
20570b496efbSLinus Walleij 	if (cryp->caps->aeads_support) {
2058d5e6b48fSHerbert Xu 		ret = crypto_engine_register_aeads(aead_algs, ARRAY_SIZE(aead_algs));
20599d3b5030SFabien DESSENNE 		if (ret)
20609d3b5030SFabien DESSENNE 			goto err_aead_algs;
20610b496efbSLinus Walleij 	}
20629d3b5030SFabien DESSENNE 
20639e054ec2SFabien DESSENNE 	dev_info(dev, "Initialized\n");
20649e054ec2SFabien DESSENNE 
206565f9aa36Slionel.debieve@st.com 	pm_runtime_put_sync(dev);
206665f9aa36Slionel.debieve@st.com 
20679e054ec2SFabien DESSENNE 	return 0;
20689e054ec2SFabien DESSENNE 
20699d3b5030SFabien DESSENNE err_aead_algs:
2070d5e6b48fSHerbert Xu 	crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20719e054ec2SFabien DESSENNE err_algs:
20729e054ec2SFabien DESSENNE err_engine2:
20739e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20749e054ec2SFabien DESSENNE err_engine1:
20759e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
20769e054ec2SFabien DESSENNE 	list_del(&cryp->list);
20779e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
20780a2f9f57SEtienne Carriere err_rst:
207965f9aa36Slionel.debieve@st.com 	pm_runtime_disable(dev);
208065f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(dev);
208165f9aa36Slionel.debieve@st.com 
20829e054ec2SFabien DESSENNE 	clk_disable_unprepare(cryp->clk);
20839e054ec2SFabien DESSENNE 
20849e054ec2SFabien DESSENNE 	return ret;
20859e054ec2SFabien DESSENNE }
20869e054ec2SFabien DESSENNE 
2087*88b01c8aSUwe Kleine-König static void stm32_cryp_remove(struct platform_device *pdev)
20889e054ec2SFabien DESSENNE {
20899e054ec2SFabien DESSENNE 	struct stm32_cryp *cryp = platform_get_drvdata(pdev);
209065f9aa36Slionel.debieve@st.com 	int ret;
20919e054ec2SFabien DESSENNE 
2092*88b01c8aSUwe Kleine-König 	ret = pm_runtime_get_sync(cryp->dev);
209365f9aa36Slionel.debieve@st.com 
20940b496efbSLinus Walleij 	if (cryp->caps->aeads_support)
2095d5e6b48fSHerbert Xu 		crypto_engine_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
2096d5e6b48fSHerbert Xu 	crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
20979e054ec2SFabien DESSENNE 
20989e054ec2SFabien DESSENNE 	crypto_engine_exit(cryp->engine);
20999e054ec2SFabien DESSENNE 
21009e054ec2SFabien DESSENNE 	spin_lock(&cryp_list.lock);
21019e054ec2SFabien DESSENNE 	list_del(&cryp->list);
21029e054ec2SFabien DESSENNE 	spin_unlock(&cryp_list.lock);
21039e054ec2SFabien DESSENNE 
210465f9aa36Slionel.debieve@st.com 	pm_runtime_disable(cryp->dev);
210565f9aa36Slionel.debieve@st.com 	pm_runtime_put_noidle(cryp->dev);
210665f9aa36Slionel.debieve@st.com 
2107*88b01c8aSUwe Kleine-König 	if (ret >= 0)
21089e054ec2SFabien DESSENNE 		clk_disable_unprepare(cryp->clk);
21099e054ec2SFabien DESSENNE }
21109e054ec2SFabien DESSENNE 
211165f9aa36Slionel.debieve@st.com #ifdef CONFIG_PM
211265f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_suspend(struct device *dev)
211365f9aa36Slionel.debieve@st.com {
211465f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
211565f9aa36Slionel.debieve@st.com 
211665f9aa36Slionel.debieve@st.com 	clk_disable_unprepare(cryp->clk);
211765f9aa36Slionel.debieve@st.com 
211865f9aa36Slionel.debieve@st.com 	return 0;
211965f9aa36Slionel.debieve@st.com }
212065f9aa36Slionel.debieve@st.com 
212165f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_resume(struct device *dev)
212265f9aa36Slionel.debieve@st.com {
212365f9aa36Slionel.debieve@st.com 	struct stm32_cryp *cryp = dev_get_drvdata(dev);
212465f9aa36Slionel.debieve@st.com 	int ret;
212565f9aa36Slionel.debieve@st.com 
212665f9aa36Slionel.debieve@st.com 	ret = clk_prepare_enable(cryp->clk);
212765f9aa36Slionel.debieve@st.com 	if (ret) {
212865f9aa36Slionel.debieve@st.com 		dev_err(cryp->dev, "Failed to prepare_enable clock\n");
212965f9aa36Slionel.debieve@st.com 		return ret;
213065f9aa36Slionel.debieve@st.com 	}
213165f9aa36Slionel.debieve@st.com 
213265f9aa36Slionel.debieve@st.com 	return 0;
213365f9aa36Slionel.debieve@st.com }
213465f9aa36Slionel.debieve@st.com #endif
213565f9aa36Slionel.debieve@st.com 
213665f9aa36Slionel.debieve@st.com static const struct dev_pm_ops stm32_cryp_pm_ops = {
213765f9aa36Slionel.debieve@st.com 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
213865f9aa36Slionel.debieve@st.com 				pm_runtime_force_resume)
213965f9aa36Slionel.debieve@st.com 	SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend,
214065f9aa36Slionel.debieve@st.com 			   stm32_cryp_runtime_resume, NULL)
214165f9aa36Slionel.debieve@st.com };
214265f9aa36Slionel.debieve@st.com 
21439e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = {
21449e054ec2SFabien DESSENNE 	.probe  = stm32_cryp_probe,
2145*88b01c8aSUwe Kleine-König 	.remove_new = stm32_cryp_remove,
21469e054ec2SFabien DESSENNE 	.driver = {
21479e054ec2SFabien DESSENNE 		.name           = DRIVER_NAME,
214865f9aa36Slionel.debieve@st.com 		.pm		= &stm32_cryp_pm_ops,
21499e054ec2SFabien DESSENNE 		.of_match_table = stm32_dt_ids,
21509e054ec2SFabien DESSENNE 	},
21519e054ec2SFabien DESSENNE };
21529e054ec2SFabien DESSENNE 
21539e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver);
21549e054ec2SFabien DESSENNE 
21559e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
21569e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver");
21579e054ec2SFabien DESSENNE MODULE_LICENSE("GPL");
2158