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>
14*56ddb9aaSMaxime Méré #include <linux/bottom_half.h>
159e054ec2SFabien DESSENNE #include <linux/clk.h>
169e054ec2SFabien DESSENNE #include <linux/delay.h>
17fb11a4f6SMaxime Méré #include <linux/dma-mapping.h>
18fb11a4f6SMaxime Méré #include <linux/dmaengine.h>
19d5e6b48fSHerbert Xu #include <linux/err.h>
209e054ec2SFabien DESSENNE #include <linux/iopoll.h>
21d5e6b48fSHerbert Xu #include <linux/interrupt.h>
22d5e6b48fSHerbert Xu #include <linux/kernel.h>
239e054ec2SFabien DESSENNE #include <linux/module.h>
24b0cc7491SRob Herring #include <linux/of.h>
259e054ec2SFabien DESSENNE #include <linux/platform_device.h>
2665f9aa36Slionel.debieve@st.com #include <linux/pm_runtime.h>
279e054ec2SFabien DESSENNE #include <linux/reset.h>
28d5e6b48fSHerbert Xu #include <linux/string.h>
299e054ec2SFabien DESSENNE
309e054ec2SFabien DESSENNE #define DRIVER_NAME "stm32-cryp"
319e054ec2SFabien DESSENNE
329e054ec2SFabien DESSENNE /* Bit [0] encrypt / decrypt */
339e054ec2SFabien DESSENNE #define FLG_ENCRYPT BIT(0)
349e054ec2SFabien DESSENNE /* Bit [8..1] algo & operation mode */
359e054ec2SFabien DESSENNE #define FLG_AES BIT(1)
369e054ec2SFabien DESSENNE #define FLG_DES BIT(2)
379e054ec2SFabien DESSENNE #define FLG_TDES BIT(3)
389e054ec2SFabien DESSENNE #define FLG_ECB BIT(4)
399e054ec2SFabien DESSENNE #define FLG_CBC BIT(5)
409e054ec2SFabien DESSENNE #define FLG_CTR BIT(6)
419d3b5030SFabien DESSENNE #define FLG_GCM BIT(7)
429d3b5030SFabien DESSENNE #define FLG_CCM BIT(8)
439e054ec2SFabien DESSENNE /* Mode mask = bits [15..0] */
449e054ec2SFabien DESSENNE #define FLG_MODE_MASK GENMASK(15, 0)
459d3b5030SFabien DESSENNE /* Bit [31..16] status */
46fb11a4f6SMaxime Méré #define FLG_IN_OUT_DMA BIT(16)
47fb11a4f6SMaxime Méré #define FLG_HEADER_DMA BIT(17)
489e054ec2SFabien DESSENNE
499e054ec2SFabien DESSENNE /* Registers */
509e054ec2SFabien DESSENNE #define CRYP_CR 0x00000000
519e054ec2SFabien DESSENNE #define CRYP_SR 0x00000004
529e054ec2SFabien DESSENNE #define CRYP_DIN 0x00000008
539e054ec2SFabien DESSENNE #define CRYP_DOUT 0x0000000C
549e054ec2SFabien DESSENNE #define CRYP_DMACR 0x00000010
559e054ec2SFabien DESSENNE #define CRYP_IMSCR 0x00000014
569e054ec2SFabien DESSENNE #define CRYP_RISR 0x00000018
579e054ec2SFabien DESSENNE #define CRYP_MISR 0x0000001C
589e054ec2SFabien DESSENNE #define CRYP_K0LR 0x00000020
599e054ec2SFabien DESSENNE #define CRYP_K0RR 0x00000024
609e054ec2SFabien DESSENNE #define CRYP_K1LR 0x00000028
619e054ec2SFabien DESSENNE #define CRYP_K1RR 0x0000002C
629e054ec2SFabien DESSENNE #define CRYP_K2LR 0x00000030
639e054ec2SFabien DESSENNE #define CRYP_K2RR 0x00000034
649e054ec2SFabien DESSENNE #define CRYP_K3LR 0x00000038
659e054ec2SFabien DESSENNE #define CRYP_K3RR 0x0000003C
669e054ec2SFabien DESSENNE #define CRYP_IV0LR 0x00000040
679e054ec2SFabien DESSENNE #define CRYP_IV0RR 0x00000044
689e054ec2SFabien DESSENNE #define CRYP_IV1LR 0x00000048
699e054ec2SFabien DESSENNE #define CRYP_IV1RR 0x0000004C
709d3b5030SFabien DESSENNE #define CRYP_CSGCMCCM0R 0x00000050
719d3b5030SFabien DESSENNE #define CRYP_CSGCM0R 0x00000070
729e054ec2SFabien DESSENNE
730b496efbSLinus Walleij #define UX500_CRYP_CR 0x00000000
740b496efbSLinus Walleij #define UX500_CRYP_SR 0x00000004
750b496efbSLinus Walleij #define UX500_CRYP_DIN 0x00000008
760b496efbSLinus Walleij #define UX500_CRYP_DINSIZE 0x0000000C
770b496efbSLinus Walleij #define UX500_CRYP_DOUT 0x00000010
780b496efbSLinus Walleij #define UX500_CRYP_DOUSIZE 0x00000014
790b496efbSLinus Walleij #define UX500_CRYP_DMACR 0x00000018
800b496efbSLinus Walleij #define UX500_CRYP_IMSC 0x0000001C
810b496efbSLinus Walleij #define UX500_CRYP_RIS 0x00000020
820b496efbSLinus Walleij #define UX500_CRYP_MIS 0x00000024
830b496efbSLinus Walleij #define UX500_CRYP_K1L 0x00000028
840b496efbSLinus Walleij #define UX500_CRYP_K1R 0x0000002C
850b496efbSLinus Walleij #define UX500_CRYP_K2L 0x00000030
860b496efbSLinus Walleij #define UX500_CRYP_K2R 0x00000034
870b496efbSLinus Walleij #define UX500_CRYP_K3L 0x00000038
880b496efbSLinus Walleij #define UX500_CRYP_K3R 0x0000003C
890b496efbSLinus Walleij #define UX500_CRYP_K4L 0x00000040
900b496efbSLinus Walleij #define UX500_CRYP_K4R 0x00000044
910b496efbSLinus Walleij #define UX500_CRYP_IV0L 0x00000048
920b496efbSLinus Walleij #define UX500_CRYP_IV0R 0x0000004C
930b496efbSLinus Walleij #define UX500_CRYP_IV1L 0x00000050
940b496efbSLinus Walleij #define UX500_CRYP_IV1R 0x00000054
950b496efbSLinus Walleij
969e054ec2SFabien DESSENNE /* Registers values */
979e054ec2SFabien DESSENNE #define CR_DEC_NOT_ENC 0x00000004
989e054ec2SFabien DESSENNE #define CR_TDES_ECB 0x00000000
999e054ec2SFabien DESSENNE #define CR_TDES_CBC 0x00000008
1009e054ec2SFabien DESSENNE #define CR_DES_ECB 0x00000010
1019e054ec2SFabien DESSENNE #define CR_DES_CBC 0x00000018
1029e054ec2SFabien DESSENNE #define CR_AES_ECB 0x00000020
1039e054ec2SFabien DESSENNE #define CR_AES_CBC 0x00000028
1049e054ec2SFabien DESSENNE #define CR_AES_CTR 0x00000030
1050b496efbSLinus Walleij #define CR_AES_KP 0x00000038 /* Not on Ux500 */
1060b496efbSLinus Walleij #define CR_AES_XTS 0x00000038 /* Only on Ux500 */
1079d3b5030SFabien DESSENNE #define CR_AES_GCM 0x00080000
1089d3b5030SFabien DESSENNE #define CR_AES_CCM 0x00080008
1099e054ec2SFabien DESSENNE #define CR_AES_UNKNOWN 0xFFFFFFFF
1109e054ec2SFabien DESSENNE #define CR_ALGO_MASK 0x00080038
1119e054ec2SFabien DESSENNE #define CR_DATA32 0x00000000
1129e054ec2SFabien DESSENNE #define CR_DATA16 0x00000040
1139e054ec2SFabien DESSENNE #define CR_DATA8 0x00000080
1149e054ec2SFabien DESSENNE #define CR_DATA1 0x000000C0
1159e054ec2SFabien DESSENNE #define CR_KEY128 0x00000000
1169e054ec2SFabien DESSENNE #define CR_KEY192 0x00000100
1179e054ec2SFabien DESSENNE #define CR_KEY256 0x00000200
1180b496efbSLinus Walleij #define CR_KEYRDEN 0x00000400 /* Only on Ux500 */
1190b496efbSLinus Walleij #define CR_KSE 0x00000800 /* Only on Ux500 */
1209e054ec2SFabien DESSENNE #define CR_FFLUSH 0x00004000
1219e054ec2SFabien DESSENNE #define CR_CRYPEN 0x00008000
1229d3b5030SFabien DESSENNE #define CR_PH_INIT 0x00000000
1239d3b5030SFabien DESSENNE #define CR_PH_HEADER 0x00010000
1249d3b5030SFabien DESSENNE #define CR_PH_PAYLOAD 0x00020000
1259d3b5030SFabien DESSENNE #define CR_PH_FINAL 0x00030000
1269d3b5030SFabien DESSENNE #define CR_PH_MASK 0x00030000
1279d3b5030SFabien DESSENNE #define CR_NBPBL_SHIFT 20
1289e054ec2SFabien DESSENNE
129fb11a4f6SMaxime Méré #define SR_IFNF BIT(1)
130fb11a4f6SMaxime Méré #define SR_OFNE BIT(2)
131fb11a4f6SMaxime Méré #define SR_BUSY BIT(8)
132fb11a4f6SMaxime Méré
133fb11a4f6SMaxime Méré #define DMACR_DIEN BIT(0)
134fb11a4f6SMaxime Méré #define DMACR_DOEN BIT(1)
1359e054ec2SFabien DESSENNE
1369e054ec2SFabien DESSENNE #define IMSCR_IN BIT(0)
1379e054ec2SFabien DESSENNE #define IMSCR_OUT BIT(1)
1389e054ec2SFabien DESSENNE
1399e054ec2SFabien DESSENNE #define MISR_IN BIT(0)
1409e054ec2SFabien DESSENNE #define MISR_OUT BIT(1)
1419e054ec2SFabien DESSENNE
1429e054ec2SFabien DESSENNE /* Misc */
1439e054ec2SFabien DESSENNE #define AES_BLOCK_32 (AES_BLOCK_SIZE / sizeof(u32))
1449d3b5030SFabien DESSENNE #define GCM_CTR_INIT 2
14565f9aa36Slionel.debieve@st.com #define CRYP_AUTOSUSPEND_DELAY 50
1469e054ec2SFabien DESSENNE
147fb11a4f6SMaxime Méré #define CRYP_DMA_BURST_REG 4
148fb11a4f6SMaxime Méré
149fb11a4f6SMaxime Méré enum stm32_dma_mode {
150fb11a4f6SMaxime Méré NO_DMA,
151fb11a4f6SMaxime Méré DMA_PLAIN_SG,
152fb11a4f6SMaxime Méré DMA_NEED_SG_TRUNC
153fb11a4f6SMaxime Méré };
154fb11a4f6SMaxime Méré
1559d3b5030SFabien DESSENNE struct stm32_cryp_caps {
1560b496efbSLinus Walleij bool aeads_support;
1570b496efbSLinus Walleij bool linear_aes_key;
1580b496efbSLinus Walleij bool kp_mode;
1590b496efbSLinus Walleij bool iv_protection;
1609d3b5030SFabien DESSENNE bool swap_final;
1619d3b5030SFabien DESSENNE bool padding_wa;
1620b496efbSLinus Walleij u32 cr;
1630b496efbSLinus Walleij u32 sr;
1640b496efbSLinus Walleij u32 din;
1650b496efbSLinus Walleij u32 dout;
166fb11a4f6SMaxime Méré u32 dmacr;
1670b496efbSLinus Walleij u32 imsc;
1680b496efbSLinus Walleij u32 mis;
1690b496efbSLinus Walleij u32 k1l;
1700b496efbSLinus Walleij u32 k1r;
1710b496efbSLinus Walleij u32 k3r;
1720b496efbSLinus Walleij u32 iv0l;
1730b496efbSLinus Walleij u32 iv0r;
1740b496efbSLinus Walleij u32 iv1l;
1750b496efbSLinus Walleij u32 iv1r;
1769d3b5030SFabien DESSENNE };
1779d3b5030SFabien DESSENNE
1789e054ec2SFabien DESSENNE struct stm32_cryp_ctx {
1799e054ec2SFabien DESSENNE struct stm32_cryp *cryp;
1809e054ec2SFabien DESSENNE int keylen;
181bbb28326SHerbert Xu __be32 key[AES_KEYSIZE_256 / sizeof(u32)];
1829e054ec2SFabien DESSENNE unsigned long flags;
1839e054ec2SFabien DESSENNE };
1849e054ec2SFabien DESSENNE
1859e054ec2SFabien DESSENNE struct stm32_cryp_reqctx {
1869e054ec2SFabien DESSENNE unsigned long mode;
1879e054ec2SFabien DESSENNE };
1889e054ec2SFabien DESSENNE
1899e054ec2SFabien DESSENNE struct stm32_cryp {
1909e054ec2SFabien DESSENNE struct list_head list;
1919e054ec2SFabien DESSENNE struct device *dev;
1929e054ec2SFabien DESSENNE void __iomem *regs;
193fb11a4f6SMaxime Méré phys_addr_t phys_base;
1949e054ec2SFabien DESSENNE struct clk *clk;
1959e054ec2SFabien DESSENNE unsigned long flags;
1969e054ec2SFabien DESSENNE u32 irq_status;
1979d3b5030SFabien DESSENNE const struct stm32_cryp_caps *caps;
1989e054ec2SFabien DESSENNE struct stm32_cryp_ctx *ctx;
1999e054ec2SFabien DESSENNE
2009e054ec2SFabien DESSENNE struct crypto_engine *engine;
2019e054ec2SFabien DESSENNE
20247ece481SArd Biesheuvel struct skcipher_request *req;
2039d3b5030SFabien DESSENNE struct aead_request *areq;
2049e054ec2SFabien DESSENNE
2059d3b5030SFabien DESSENNE size_t authsize;
2069e054ec2SFabien DESSENNE size_t hw_blocksize;
2079e054ec2SFabien DESSENNE
2084b898d5cSNicolas Toromanoff size_t payload_in;
2094b898d5cSNicolas Toromanoff size_t header_in;
2104b898d5cSNicolas Toromanoff size_t payload_out;
2119e054ec2SFabien DESSENNE
212fb11a4f6SMaxime Méré /* DMA process fields */
213fb11a4f6SMaxime Méré struct scatterlist *in_sg;
214fb11a4f6SMaxime Méré struct scatterlist *header_sg;
2159e054ec2SFabien DESSENNE struct scatterlist *out_sg;
216fb11a4f6SMaxime Méré size_t in_sg_len;
217fb11a4f6SMaxime Méré size_t header_sg_len;
218fb11a4f6SMaxime Méré size_t out_sg_len;
219fb11a4f6SMaxime Méré struct completion dma_completion;
2209e054ec2SFabien DESSENNE
221fb11a4f6SMaxime Méré struct dma_chan *dma_lch_in;
222fb11a4f6SMaxime Méré struct dma_chan *dma_lch_out;
223fb11a4f6SMaxime Méré enum stm32_dma_mode dma_mode;
224fb11a4f6SMaxime Méré
225fb11a4f6SMaxime Méré /* IT process fields */
2269e054ec2SFabien DESSENNE struct scatter_walk in_walk;
2279e054ec2SFabien DESSENNE struct scatter_walk out_walk;
2289e054ec2SFabien DESSENNE
22941c76690SNicolas Toromanoff __be32 last_ctr[4];
2309d3b5030SFabien DESSENNE u32 gcm_ctr;
2319e054ec2SFabien DESSENNE };
2329e054ec2SFabien DESSENNE
2339e054ec2SFabien DESSENNE struct stm32_cryp_list {
2349e054ec2SFabien DESSENNE struct list_head dev_list;
2359e054ec2SFabien DESSENNE spinlock_t lock; /* protect dev_list */
2369e054ec2SFabien DESSENNE };
2379e054ec2SFabien DESSENNE
2389e054ec2SFabien DESSENNE static struct stm32_cryp_list cryp_list = {
2399e054ec2SFabien DESSENNE .dev_list = LIST_HEAD_INIT(cryp_list.dev_list),
2409e054ec2SFabien DESSENNE .lock = __SPIN_LOCK_UNLOCKED(cryp_list.lock),
2419e054ec2SFabien DESSENNE };
2429e054ec2SFabien DESSENNE
is_aes(struct stm32_cryp * cryp)2439e054ec2SFabien DESSENNE static inline bool is_aes(struct stm32_cryp *cryp)
2449e054ec2SFabien DESSENNE {
2459e054ec2SFabien DESSENNE return cryp->flags & FLG_AES;
2469e054ec2SFabien DESSENNE }
2479e054ec2SFabien DESSENNE
is_des(struct stm32_cryp * cryp)2489e054ec2SFabien DESSENNE static inline bool is_des(struct stm32_cryp *cryp)
2499e054ec2SFabien DESSENNE {
2509e054ec2SFabien DESSENNE return cryp->flags & FLG_DES;
2519e054ec2SFabien DESSENNE }
2529e054ec2SFabien DESSENNE
is_tdes(struct stm32_cryp * cryp)2539e054ec2SFabien DESSENNE static inline bool is_tdes(struct stm32_cryp *cryp)
2549e054ec2SFabien DESSENNE {
2559e054ec2SFabien DESSENNE return cryp->flags & FLG_TDES;
2569e054ec2SFabien DESSENNE }
2579e054ec2SFabien DESSENNE
is_ecb(struct stm32_cryp * cryp)2589e054ec2SFabien DESSENNE static inline bool is_ecb(struct stm32_cryp *cryp)
2599e054ec2SFabien DESSENNE {
2609e054ec2SFabien DESSENNE return cryp->flags & FLG_ECB;
2619e054ec2SFabien DESSENNE }
2629e054ec2SFabien DESSENNE
is_cbc(struct stm32_cryp * cryp)2639e054ec2SFabien DESSENNE static inline bool is_cbc(struct stm32_cryp *cryp)
2649e054ec2SFabien DESSENNE {
2659e054ec2SFabien DESSENNE return cryp->flags & FLG_CBC;
2669e054ec2SFabien DESSENNE }
2679e054ec2SFabien DESSENNE
is_ctr(struct stm32_cryp * cryp)2689e054ec2SFabien DESSENNE static inline bool is_ctr(struct stm32_cryp *cryp)
2699e054ec2SFabien DESSENNE {
2709e054ec2SFabien DESSENNE return cryp->flags & FLG_CTR;
2719e054ec2SFabien DESSENNE }
2729e054ec2SFabien DESSENNE
is_gcm(struct stm32_cryp * cryp)2739d3b5030SFabien DESSENNE static inline bool is_gcm(struct stm32_cryp *cryp)
2749d3b5030SFabien DESSENNE {
2759d3b5030SFabien DESSENNE return cryp->flags & FLG_GCM;
2769d3b5030SFabien DESSENNE }
2779d3b5030SFabien DESSENNE
is_ccm(struct stm32_cryp * cryp)2789d3b5030SFabien DESSENNE static inline bool is_ccm(struct stm32_cryp *cryp)
2799d3b5030SFabien DESSENNE {
2809d3b5030SFabien DESSENNE return cryp->flags & FLG_CCM;
2819d3b5030SFabien DESSENNE }
2829d3b5030SFabien DESSENNE
is_encrypt(struct stm32_cryp * cryp)2839e054ec2SFabien DESSENNE static inline bool is_encrypt(struct stm32_cryp *cryp)
2849e054ec2SFabien DESSENNE {
2859e054ec2SFabien DESSENNE return cryp->flags & FLG_ENCRYPT;
2869e054ec2SFabien DESSENNE }
2879e054ec2SFabien DESSENNE
is_decrypt(struct stm32_cryp * cryp)2889e054ec2SFabien DESSENNE static inline bool is_decrypt(struct stm32_cryp *cryp)
2899e054ec2SFabien DESSENNE {
2909e054ec2SFabien DESSENNE return !is_encrypt(cryp);
2919e054ec2SFabien DESSENNE }
2929e054ec2SFabien DESSENNE
stm32_cryp_read(struct stm32_cryp * cryp,u32 ofst)2939e054ec2SFabien DESSENNE static inline u32 stm32_cryp_read(struct stm32_cryp *cryp, u32 ofst)
2949e054ec2SFabien DESSENNE {
2959e054ec2SFabien DESSENNE return readl_relaxed(cryp->regs + ofst);
2969e054ec2SFabien DESSENNE }
2979e054ec2SFabien DESSENNE
stm32_cryp_write(struct stm32_cryp * cryp,u32 ofst,u32 val)2989e054ec2SFabien DESSENNE static inline void stm32_cryp_write(struct stm32_cryp *cryp, u32 ofst, u32 val)
2999e054ec2SFabien DESSENNE {
3009e054ec2SFabien DESSENNE writel_relaxed(val, cryp->regs + ofst);
3019e054ec2SFabien DESSENNE }
3029e054ec2SFabien DESSENNE
stm32_cryp_wait_busy(struct stm32_cryp * cryp)3039e054ec2SFabien DESSENNE static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
3049e054ec2SFabien DESSENNE {
3059e054ec2SFabien DESSENNE u32 status;
3069e054ec2SFabien DESSENNE
3070b496efbSLinus Walleij return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->sr, status,
3089e054ec2SFabien DESSENNE !(status & SR_BUSY), 10, 100000);
3099e054ec2SFabien DESSENNE }
3109e054ec2SFabien DESSENNE
stm32_cryp_enable(struct stm32_cryp * cryp)31195fe2253SNicolas Toromanoff static inline void stm32_cryp_enable(struct stm32_cryp *cryp)
31295fe2253SNicolas Toromanoff {
3130b496efbSLinus Walleij writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_CRYPEN,
3140b496efbSLinus Walleij cryp->regs + cryp->caps->cr);
31595fe2253SNicolas Toromanoff }
31695fe2253SNicolas Toromanoff
stm32_cryp_wait_enable(struct stm32_cryp * cryp)3179d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
3189d3b5030SFabien DESSENNE {
3199d3b5030SFabien DESSENNE u32 status;
3209d3b5030SFabien DESSENNE
3210b496efbSLinus Walleij return readl_relaxed_poll_timeout(cryp->regs + cryp->caps->cr, status,
3229d3b5030SFabien DESSENNE !(status & CR_CRYPEN), 10, 100000);
3239d3b5030SFabien DESSENNE }
3249d3b5030SFabien DESSENNE
stm32_cryp_wait_input(struct stm32_cryp * cryp)325fb11a4f6SMaxime Méré static inline int stm32_cryp_wait_input(struct stm32_cryp *cryp)
326fb11a4f6SMaxime Méré {
327fb11a4f6SMaxime Méré u32 status;
328fb11a4f6SMaxime Méré
329fb11a4f6SMaxime Méré return readl_relaxed_poll_timeout_atomic(cryp->regs + cryp->caps->sr, status,
330fb11a4f6SMaxime Méré status & SR_IFNF, 1, 10);
331fb11a4f6SMaxime Méré }
332fb11a4f6SMaxime Méré
stm32_cryp_wait_output(struct stm32_cryp * cryp)3339d3b5030SFabien DESSENNE static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp)
3349d3b5030SFabien DESSENNE {
3359d3b5030SFabien DESSENNE u32 status;
3369d3b5030SFabien DESSENNE
337fb11a4f6SMaxime Méré return readl_relaxed_poll_timeout_atomic(cryp->regs + cryp->caps->sr, status,
338fb11a4f6SMaxime Méré status & SR_OFNE, 1, 10);
3399d3b5030SFabien DESSENNE }
3409d3b5030SFabien DESSENNE
stm32_cryp_key_read_enable(struct stm32_cryp * cryp)3410b496efbSLinus Walleij static inline void stm32_cryp_key_read_enable(struct stm32_cryp *cryp)
3420b496efbSLinus Walleij {
3430b496efbSLinus Walleij writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) | CR_KEYRDEN,
3440b496efbSLinus Walleij cryp->regs + cryp->caps->cr);
3450b496efbSLinus Walleij }
3460b496efbSLinus Walleij
stm32_cryp_key_read_disable(struct stm32_cryp * cryp)3470b496efbSLinus Walleij static inline void stm32_cryp_key_read_disable(struct stm32_cryp *cryp)
3480b496efbSLinus Walleij {
3490b496efbSLinus Walleij writel_relaxed(readl_relaxed(cryp->regs + cryp->caps->cr) & ~CR_KEYRDEN,
3500b496efbSLinus Walleij cryp->regs + cryp->caps->cr);
3510b496efbSLinus Walleij }
3520b496efbSLinus Walleij
353fb11a4f6SMaxime Méré static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp);
354fb11a4f6SMaxime Méré static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp);
355fb11a4f6SMaxime Méré static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp);
3569d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp);
3574b898d5cSNicolas Toromanoff static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err);
358fb11a4f6SMaxime Méré static int stm32_cryp_dma_start(struct stm32_cryp *cryp);
359fb11a4f6SMaxime Méré static int stm32_cryp_it_start(struct stm32_cryp *cryp);
3609d3b5030SFabien DESSENNE
stm32_cryp_find_dev(struct stm32_cryp_ctx * ctx)3619e054ec2SFabien DESSENNE static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx)
3629e054ec2SFabien DESSENNE {
3639e054ec2SFabien DESSENNE struct stm32_cryp *tmp, *cryp = NULL;
3649e054ec2SFabien DESSENNE
3659e054ec2SFabien DESSENNE spin_lock_bh(&cryp_list.lock);
3669e054ec2SFabien DESSENNE if (!ctx->cryp) {
3679e054ec2SFabien DESSENNE list_for_each_entry(tmp, &cryp_list.dev_list, list) {
3689e054ec2SFabien DESSENNE cryp = tmp;
3699e054ec2SFabien DESSENNE break;
3709e054ec2SFabien DESSENNE }
3719e054ec2SFabien DESSENNE ctx->cryp = cryp;
3729e054ec2SFabien DESSENNE } else {
3739e054ec2SFabien DESSENNE cryp = ctx->cryp;
3749e054ec2SFabien DESSENNE }
3759e054ec2SFabien DESSENNE
3769e054ec2SFabien DESSENNE spin_unlock_bh(&cryp_list.lock);
3779e054ec2SFabien DESSENNE
3789e054ec2SFabien DESSENNE return cryp;
3799e054ec2SFabien DESSENNE }
3809e054ec2SFabien DESSENNE
stm32_cryp_hw_write_iv(struct stm32_cryp * cryp,__be32 * iv)381bbb28326SHerbert Xu static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv)
3829e054ec2SFabien DESSENNE {
3839e054ec2SFabien DESSENNE if (!iv)
3849e054ec2SFabien DESSENNE return;
3859e054ec2SFabien DESSENNE
3860b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv0l, be32_to_cpu(*iv++));
3870b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv0r, be32_to_cpu(*iv++));
3889e054ec2SFabien DESSENNE
3899e054ec2SFabien DESSENNE if (is_aes(cryp)) {
3900b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv1l, be32_to_cpu(*iv++));
3910b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv1r, be32_to_cpu(*iv++));
3929e054ec2SFabien DESSENNE }
3939e054ec2SFabien DESSENNE }
3949e054ec2SFabien DESSENNE
stm32_cryp_get_iv(struct stm32_cryp * cryp)3955f49f18dSLionel Debieve static void stm32_cryp_get_iv(struct stm32_cryp *cryp)
3965f49f18dSLionel Debieve {
39747ece481SArd Biesheuvel struct skcipher_request *req = cryp->req;
398bbb28326SHerbert Xu __be32 *tmp = (void *)req->iv;
3995f49f18dSLionel Debieve
4005f49f18dSLionel Debieve if (!tmp)
4015f49f18dSLionel Debieve return;
4025f49f18dSLionel Debieve
4030b496efbSLinus Walleij if (cryp->caps->iv_protection)
4040b496efbSLinus Walleij stm32_cryp_key_read_enable(cryp);
4050b496efbSLinus Walleij
4060b496efbSLinus Walleij *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
4070b496efbSLinus Walleij *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
4085f49f18dSLionel Debieve
4095f49f18dSLionel Debieve if (is_aes(cryp)) {
4100b496efbSLinus Walleij *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
4110b496efbSLinus Walleij *tmp++ = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
4120b496efbSLinus Walleij }
4130b496efbSLinus Walleij
4140b496efbSLinus Walleij if (cryp->caps->iv_protection)
4150b496efbSLinus Walleij stm32_cryp_key_read_disable(cryp);
4160b496efbSLinus Walleij }
4170b496efbSLinus Walleij
4180b496efbSLinus Walleij /**
4190b496efbSLinus Walleij * ux500_swap_bits_in_byte() - mirror the bits in a byte
4200b496efbSLinus Walleij * @b: the byte to be mirrored
4210b496efbSLinus Walleij *
4220b496efbSLinus Walleij * The bits are swapped the following way:
4230b496efbSLinus Walleij * Byte b include bits 0-7, nibble 1 (n1) include bits 0-3 and
4240b496efbSLinus Walleij * nibble 2 (n2) bits 4-7.
4250b496efbSLinus Walleij *
4260b496efbSLinus Walleij * Nibble 1 (n1):
4270b496efbSLinus Walleij * (The "old" (moved) bit is replaced with a zero)
4280b496efbSLinus Walleij * 1. Move bit 6 and 7, 4 positions to the left.
4290b496efbSLinus Walleij * 2. Move bit 3 and 5, 2 positions to the left.
4300b496efbSLinus Walleij * 3. Move bit 1-4, 1 position to the left.
4310b496efbSLinus Walleij *
4320b496efbSLinus Walleij * Nibble 2 (n2):
4330b496efbSLinus Walleij * 1. Move bit 0 and 1, 4 positions to the right.
4340b496efbSLinus Walleij * 2. Move bit 2 and 4, 2 positions to the right.
4350b496efbSLinus Walleij * 3. Move bit 3-6, 1 position to the right.
4360b496efbSLinus Walleij *
4370b496efbSLinus Walleij * Combine the two nibbles to a complete and swapped byte.
4380b496efbSLinus Walleij */
ux500_swap_bits_in_byte(u8 b)4390b496efbSLinus Walleij static inline u8 ux500_swap_bits_in_byte(u8 b)
4400b496efbSLinus Walleij {
4410b496efbSLinus Walleij #define R_SHIFT_4_MASK 0xc0 /* Bits 6 and 7, right shift 4 */
4420b496efbSLinus Walleij #define R_SHIFT_2_MASK 0x28 /* (After right shift 4) Bits 3 and 5,
4430b496efbSLinus Walleij right shift 2 */
4440b496efbSLinus Walleij #define R_SHIFT_1_MASK 0x1e /* (After right shift 2) Bits 1-4,
4450b496efbSLinus Walleij right shift 1 */
4460b496efbSLinus Walleij #define L_SHIFT_4_MASK 0x03 /* Bits 0 and 1, left shift 4 */
4470b496efbSLinus Walleij #define L_SHIFT_2_MASK 0x14 /* (After left shift 4) Bits 2 and 4,
4480b496efbSLinus Walleij left shift 2 */
4490b496efbSLinus Walleij #define L_SHIFT_1_MASK 0x78 /* (After left shift 1) Bits 3-6,
4500b496efbSLinus Walleij left shift 1 */
4510b496efbSLinus Walleij
4520b496efbSLinus Walleij u8 n1;
4530b496efbSLinus Walleij u8 n2;
4540b496efbSLinus Walleij
4550b496efbSLinus Walleij /* Swap most significant nibble */
4560b496efbSLinus Walleij /* Right shift 4, bits 6 and 7 */
4570b496efbSLinus Walleij n1 = ((b & R_SHIFT_4_MASK) >> 4) | (b & ~(R_SHIFT_4_MASK >> 4));
4580b496efbSLinus Walleij /* Right shift 2, bits 3 and 5 */
4590b496efbSLinus Walleij n1 = ((n1 & R_SHIFT_2_MASK) >> 2) | (n1 & ~(R_SHIFT_2_MASK >> 2));
4600b496efbSLinus Walleij /* Right shift 1, bits 1-4 */
4610b496efbSLinus Walleij n1 = (n1 & R_SHIFT_1_MASK) >> 1;
4620b496efbSLinus Walleij
4630b496efbSLinus Walleij /* Swap least significant nibble */
4640b496efbSLinus Walleij /* Left shift 4, bits 0 and 1 */
4650b496efbSLinus Walleij n2 = ((b & L_SHIFT_4_MASK) << 4) | (b & ~(L_SHIFT_4_MASK << 4));
4660b496efbSLinus Walleij /* Left shift 2, bits 2 and 4 */
4670b496efbSLinus Walleij n2 = ((n2 & L_SHIFT_2_MASK) << 2) | (n2 & ~(L_SHIFT_2_MASK << 2));
4680b496efbSLinus Walleij /* Left shift 1, bits 3-6 */
4690b496efbSLinus Walleij n2 = (n2 & L_SHIFT_1_MASK) << 1;
4700b496efbSLinus Walleij
4710b496efbSLinus Walleij return n1 | n2;
4720b496efbSLinus Walleij }
4730b496efbSLinus Walleij
4740b496efbSLinus Walleij /**
4750b496efbSLinus Walleij * ux500_swizzle_key() - Shuffle around words and bits in the AES key
4760b496efbSLinus Walleij * @in: key to swizzle
4770b496efbSLinus Walleij * @out: swizzled key
4780b496efbSLinus Walleij * @len: length of key, in bytes
4790b496efbSLinus Walleij *
4800b496efbSLinus Walleij * This "key swizzling procedure" is described in the examples in the
4810b496efbSLinus Walleij * DB8500 design specification. There is no real description of why
4820b496efbSLinus Walleij * the bits have been arranged like this in the hardware.
4830b496efbSLinus Walleij */
ux500_swizzle_key(const u8 * in,u8 * out,u32 len)4840b496efbSLinus Walleij static inline void ux500_swizzle_key(const u8 *in, u8 *out, u32 len)
4850b496efbSLinus Walleij {
4860b496efbSLinus Walleij int i = 0;
4870b496efbSLinus Walleij int bpw = sizeof(u32);
4880b496efbSLinus Walleij int j;
4890b496efbSLinus Walleij int index = 0;
4900b496efbSLinus Walleij
4910b496efbSLinus Walleij j = len - bpw;
4920b496efbSLinus Walleij while (j >= 0) {
4930b496efbSLinus Walleij for (i = 0; i < bpw; i++) {
4940b496efbSLinus Walleij index = len - j - bpw + i;
4950b496efbSLinus Walleij out[j + i] =
4960b496efbSLinus Walleij ux500_swap_bits_in_byte(in[index]);
4970b496efbSLinus Walleij }
4980b496efbSLinus Walleij j -= bpw;
4995f49f18dSLionel Debieve }
5005f49f18dSLionel Debieve }
5015f49f18dSLionel Debieve
stm32_cryp_hw_write_key(struct stm32_cryp * c)5029e054ec2SFabien DESSENNE static void stm32_cryp_hw_write_key(struct stm32_cryp *c)
5039e054ec2SFabien DESSENNE {
5049e054ec2SFabien DESSENNE unsigned int i;
5059e054ec2SFabien DESSENNE int r_id;
5069e054ec2SFabien DESSENNE
5079e054ec2SFabien DESSENNE if (is_des(c)) {
5080b496efbSLinus Walleij stm32_cryp_write(c, c->caps->k1l, be32_to_cpu(c->ctx->key[0]));
5090b496efbSLinus Walleij stm32_cryp_write(c, c->caps->k1r, be32_to_cpu(c->ctx->key[1]));
5100b496efbSLinus Walleij return;
5119e054ec2SFabien DESSENNE }
5120b496efbSLinus Walleij
5130b496efbSLinus Walleij /*
5140b496efbSLinus Walleij * On the Ux500 the AES key is considered as a single bit sequence
5150b496efbSLinus Walleij * of 128, 192 or 256 bits length. It is written linearly into the
5160b496efbSLinus Walleij * registers from K1L and down, and need to be processed to become
5170b496efbSLinus Walleij * a proper big-endian bit sequence.
5180b496efbSLinus Walleij */
5190b496efbSLinus Walleij if (is_aes(c) && c->caps->linear_aes_key) {
5200b496efbSLinus Walleij u32 tmpkey[8];
5210b496efbSLinus Walleij
5220b496efbSLinus Walleij ux500_swizzle_key((u8 *)c->ctx->key,
5230b496efbSLinus Walleij (u8 *)tmpkey, c->ctx->keylen);
5240b496efbSLinus Walleij
5250b496efbSLinus Walleij r_id = c->caps->k1l;
5260b496efbSLinus Walleij for (i = 0; i < c->ctx->keylen / sizeof(u32); i++, r_id += 4)
5270b496efbSLinus Walleij stm32_cryp_write(c, r_id, tmpkey[i]);
5280b496efbSLinus Walleij
5290b496efbSLinus Walleij return;
5300b496efbSLinus Walleij }
5310b496efbSLinus Walleij
5320b496efbSLinus Walleij r_id = c->caps->k3r;
5330b496efbSLinus Walleij for (i = c->ctx->keylen / sizeof(u32); i > 0; i--, r_id -= 4)
5340b496efbSLinus Walleij stm32_cryp_write(c, r_id, be32_to_cpu(c->ctx->key[i - 1]));
5359e054ec2SFabien DESSENNE }
5369e054ec2SFabien DESSENNE
stm32_cryp_get_hw_mode(struct stm32_cryp * cryp)5379e054ec2SFabien DESSENNE static u32 stm32_cryp_get_hw_mode(struct stm32_cryp *cryp)
5389e054ec2SFabien DESSENNE {
5399e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ecb(cryp))
5409e054ec2SFabien DESSENNE return CR_AES_ECB;
5419e054ec2SFabien DESSENNE
5429e054ec2SFabien DESSENNE if (is_aes(cryp) && is_cbc(cryp))
5439e054ec2SFabien DESSENNE return CR_AES_CBC;
5449e054ec2SFabien DESSENNE
5459e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ctr(cryp))
5469e054ec2SFabien DESSENNE return CR_AES_CTR;
5479e054ec2SFabien DESSENNE
5489d3b5030SFabien DESSENNE if (is_aes(cryp) && is_gcm(cryp))
5499d3b5030SFabien DESSENNE return CR_AES_GCM;
5509d3b5030SFabien DESSENNE
5519d3b5030SFabien DESSENNE if (is_aes(cryp) && is_ccm(cryp))
5529d3b5030SFabien DESSENNE return CR_AES_CCM;
5539d3b5030SFabien DESSENNE
5549e054ec2SFabien DESSENNE if (is_des(cryp) && is_ecb(cryp))
5559e054ec2SFabien DESSENNE return CR_DES_ECB;
5569e054ec2SFabien DESSENNE
5579e054ec2SFabien DESSENNE if (is_des(cryp) && is_cbc(cryp))
5589e054ec2SFabien DESSENNE return CR_DES_CBC;
5599e054ec2SFabien DESSENNE
5609e054ec2SFabien DESSENNE if (is_tdes(cryp) && is_ecb(cryp))
5619e054ec2SFabien DESSENNE return CR_TDES_ECB;
5629e054ec2SFabien DESSENNE
5639e054ec2SFabien DESSENNE if (is_tdes(cryp) && is_cbc(cryp))
5649e054ec2SFabien DESSENNE return CR_TDES_CBC;
5659e054ec2SFabien DESSENNE
5669e054ec2SFabien DESSENNE dev_err(cryp->dev, "Unknown mode\n");
5679e054ec2SFabien DESSENNE return CR_AES_UNKNOWN;
5689e054ec2SFabien DESSENNE }
5699e054ec2SFabien DESSENNE
stm32_cryp_get_input_text_len(struct stm32_cryp * cryp)5709d3b5030SFabien DESSENNE static unsigned int stm32_cryp_get_input_text_len(struct stm32_cryp *cryp)
5719d3b5030SFabien DESSENNE {
5729d3b5030SFabien DESSENNE return is_encrypt(cryp) ? cryp->areq->cryptlen :
5739d3b5030SFabien DESSENNE cryp->areq->cryptlen - cryp->authsize;
5749d3b5030SFabien DESSENNE }
5759d3b5030SFabien DESSENNE
stm32_cryp_gcm_init(struct stm32_cryp * cryp,u32 cfg)5769d3b5030SFabien DESSENNE static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg)
5779d3b5030SFabien DESSENNE {
5789d3b5030SFabien DESSENNE int ret;
579bbb28326SHerbert Xu __be32 iv[4];
5809d3b5030SFabien DESSENNE
5819d3b5030SFabien DESSENNE /* Phase 1 : init */
5829d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, 12);
5839d3b5030SFabien DESSENNE iv[3] = cpu_to_be32(GCM_CTR_INIT);
5849d3b5030SFabien DESSENNE cryp->gcm_ctr = GCM_CTR_INIT;
5859d3b5030SFabien DESSENNE stm32_cryp_hw_write_iv(cryp, iv);
5869d3b5030SFabien DESSENNE
5870b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
5889d3b5030SFabien DESSENNE
5899d3b5030SFabien DESSENNE /* Wait for end of processing */
5909d3b5030SFabien DESSENNE ret = stm32_cryp_wait_enable(cryp);
5914b898d5cSNicolas Toromanoff if (ret) {
5929d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (gcm init)\n");
5939d3b5030SFabien DESSENNE return ret;
5949d3b5030SFabien DESSENNE }
5959d3b5030SFabien DESSENNE
5964b898d5cSNicolas Toromanoff /* Prepare next phase */
5974b898d5cSNicolas Toromanoff if (cryp->areq->assoclen) {
5984b898d5cSNicolas Toromanoff cfg |= CR_PH_HEADER;
5990b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6004b898d5cSNicolas Toromanoff } else if (stm32_cryp_get_input_text_len(cryp)) {
6014b898d5cSNicolas Toromanoff cfg |= CR_PH_PAYLOAD;
6020b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6034b898d5cSNicolas Toromanoff }
6044b898d5cSNicolas Toromanoff
6054b898d5cSNicolas Toromanoff return 0;
6064b898d5cSNicolas Toromanoff }
6074b898d5cSNicolas Toromanoff
stm32_crypt_gcmccm_end_header(struct stm32_cryp * cryp)6084b898d5cSNicolas Toromanoff static void stm32_crypt_gcmccm_end_header(struct stm32_cryp *cryp)
6094b898d5cSNicolas Toromanoff {
6104b898d5cSNicolas Toromanoff u32 cfg;
6114b898d5cSNicolas Toromanoff int err;
6124b898d5cSNicolas Toromanoff
6134b898d5cSNicolas Toromanoff /* Check if whole header written */
6144b898d5cSNicolas Toromanoff if (!cryp->header_in) {
6154b898d5cSNicolas Toromanoff /* Wait for completion */
6164b898d5cSNicolas Toromanoff err = stm32_cryp_wait_busy(cryp);
6174b898d5cSNicolas Toromanoff if (err) {
6184b898d5cSNicolas Toromanoff dev_err(cryp->dev, "Timeout (gcm/ccm header)\n");
6190b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, 0);
6204b898d5cSNicolas Toromanoff stm32_cryp_finish_req(cryp, err);
6214b898d5cSNicolas Toromanoff return;
6224b898d5cSNicolas Toromanoff }
6234b898d5cSNicolas Toromanoff
6244b898d5cSNicolas Toromanoff if (stm32_cryp_get_input_text_len(cryp)) {
6254b898d5cSNicolas Toromanoff /* Phase 3 : payload */
6260b496efbSLinus Walleij cfg = stm32_cryp_read(cryp, cryp->caps->cr);
6274b898d5cSNicolas Toromanoff cfg &= ~CR_CRYPEN;
6280b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6294b898d5cSNicolas Toromanoff
6304b898d5cSNicolas Toromanoff cfg &= ~CR_PH_MASK;
6314b898d5cSNicolas Toromanoff cfg |= CR_PH_PAYLOAD | CR_CRYPEN;
6320b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
6334b898d5cSNicolas Toromanoff } else {
6344b898d5cSNicolas Toromanoff /*
6354b898d5cSNicolas Toromanoff * Phase 4 : tag.
6364b898d5cSNicolas Toromanoff * Nothing to read, nothing to write, caller have to
6374b898d5cSNicolas Toromanoff * end request
6384b898d5cSNicolas Toromanoff */
6394b898d5cSNicolas Toromanoff }
6404b898d5cSNicolas Toromanoff }
6414b898d5cSNicolas Toromanoff }
6424b898d5cSNicolas Toromanoff
stm32_cryp_write_ccm_first_header(struct stm32_cryp * cryp)6434b898d5cSNicolas Toromanoff static void stm32_cryp_write_ccm_first_header(struct stm32_cryp *cryp)
6444b898d5cSNicolas Toromanoff {
6454b898d5cSNicolas Toromanoff size_t written;
6464b898d5cSNicolas Toromanoff size_t len;
6474b898d5cSNicolas Toromanoff u32 alen = cryp->areq->assoclen;
6484b898d5cSNicolas Toromanoff u32 block[AES_BLOCK_32] = {0};
6494b898d5cSNicolas Toromanoff u8 *b8 = (u8 *)block;
6504b898d5cSNicolas Toromanoff
6514b898d5cSNicolas Toromanoff if (alen <= 65280) {
6524b898d5cSNicolas Toromanoff /* Write first u32 of B1 */
6534b898d5cSNicolas Toromanoff b8[0] = (alen >> 8) & 0xFF;
6544b898d5cSNicolas Toromanoff b8[1] = alen & 0xFF;
6554b898d5cSNicolas Toromanoff len = 2;
6564b898d5cSNicolas Toromanoff } else {
6574b898d5cSNicolas Toromanoff /* Build the two first u32 of B1 */
6584b898d5cSNicolas Toromanoff b8[0] = 0xFF;
6594b898d5cSNicolas Toromanoff b8[1] = 0xFE;
6604b898d5cSNicolas Toromanoff b8[2] = (alen & 0xFF000000) >> 24;
6614b898d5cSNicolas Toromanoff b8[3] = (alen & 0x00FF0000) >> 16;
6624b898d5cSNicolas Toromanoff b8[4] = (alen & 0x0000FF00) >> 8;
6634b898d5cSNicolas Toromanoff b8[5] = alen & 0x000000FF;
6644b898d5cSNicolas Toromanoff len = 6;
6654b898d5cSNicolas Toromanoff }
6664b898d5cSNicolas Toromanoff
6674b898d5cSNicolas Toromanoff written = min_t(size_t, AES_BLOCK_SIZE - len, alen);
6684b898d5cSNicolas Toromanoff
6694b898d5cSNicolas Toromanoff scatterwalk_copychunks((char *)block + len, &cryp->in_walk, written, 0);
670319ad16dSLinus Walleij
671319ad16dSLinus Walleij writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
6724b898d5cSNicolas Toromanoff
6734b898d5cSNicolas Toromanoff cryp->header_in -= written;
6744b898d5cSNicolas Toromanoff
6754b898d5cSNicolas Toromanoff stm32_crypt_gcmccm_end_header(cryp);
6764b898d5cSNicolas Toromanoff }
6774b898d5cSNicolas Toromanoff
stm32_cryp_ccm_init(struct stm32_cryp * cryp,u32 cfg)6789d3b5030SFabien DESSENNE static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg)
6799d3b5030SFabien DESSENNE {
6809d3b5030SFabien DESSENNE int ret;
6814b898d5cSNicolas Toromanoff u32 iv_32[AES_BLOCK_32], b0_32[AES_BLOCK_32];
6824b898d5cSNicolas Toromanoff u8 *iv = (u8 *)iv_32, *b0 = (u8 *)b0_32;
683bbb28326SHerbert Xu __be32 *bd;
6849d3b5030SFabien DESSENNE u32 *d;
6859d3b5030SFabien DESSENNE unsigned int i, textlen;
6869d3b5030SFabien DESSENNE
6879d3b5030SFabien DESSENNE /* Phase 1 : init. Firstly set the CTR value to 1 (not 0) */
6889d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
6899d3b5030SFabien DESSENNE memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
6909d3b5030SFabien DESSENNE iv[AES_BLOCK_SIZE - 1] = 1;
691bbb28326SHerbert Xu stm32_cryp_hw_write_iv(cryp, (__be32 *)iv);
6929d3b5030SFabien DESSENNE
6939d3b5030SFabien DESSENNE /* Build B0 */
6949d3b5030SFabien DESSENNE memcpy(b0, iv, AES_BLOCK_SIZE);
6959d3b5030SFabien DESSENNE
6969d3b5030SFabien DESSENNE b0[0] |= (8 * ((cryp->authsize - 2) / 2));
6979d3b5030SFabien DESSENNE
6989d3b5030SFabien DESSENNE if (cryp->areq->assoclen)
6999d3b5030SFabien DESSENNE b0[0] |= 0x40;
7009d3b5030SFabien DESSENNE
7019d3b5030SFabien DESSENNE textlen = stm32_cryp_get_input_text_len(cryp);
7029d3b5030SFabien DESSENNE
7039d3b5030SFabien DESSENNE b0[AES_BLOCK_SIZE - 2] = textlen >> 8;
7049d3b5030SFabien DESSENNE b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF;
7059d3b5030SFabien DESSENNE
7069d3b5030SFabien DESSENNE /* Enable HW */
7070b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg | CR_PH_INIT | CR_CRYPEN);
7089d3b5030SFabien DESSENNE
7099d3b5030SFabien DESSENNE /* Write B0 */
7109d3b5030SFabien DESSENNE d = (u32 *)b0;
711bbb28326SHerbert Xu bd = (__be32 *)b0;
7129d3b5030SFabien DESSENNE
7139d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) {
714bbb28326SHerbert Xu u32 xd = d[i];
715bbb28326SHerbert Xu
7169d3b5030SFabien DESSENNE if (!cryp->caps->padding_wa)
717bbb28326SHerbert Xu xd = be32_to_cpu(bd[i]);
7180b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, xd);
7199d3b5030SFabien DESSENNE }
7209d3b5030SFabien DESSENNE
7219d3b5030SFabien DESSENNE /* Wait for end of processing */
7229d3b5030SFabien DESSENNE ret = stm32_cryp_wait_enable(cryp);
7234b898d5cSNicolas Toromanoff if (ret) {
7249d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (ccm init)\n");
7259d3b5030SFabien DESSENNE return ret;
7269d3b5030SFabien DESSENNE }
7279d3b5030SFabien DESSENNE
7284b898d5cSNicolas Toromanoff /* Prepare next phase */
7294b898d5cSNicolas Toromanoff if (cryp->areq->assoclen) {
7304b898d5cSNicolas Toromanoff cfg |= CR_PH_HEADER | CR_CRYPEN;
7310b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
7324b898d5cSNicolas Toromanoff
7334b898d5cSNicolas Toromanoff /* Write first (special) block (may move to next phase [payload]) */
7344b898d5cSNicolas Toromanoff stm32_cryp_write_ccm_first_header(cryp);
7354b898d5cSNicolas Toromanoff } else if (stm32_cryp_get_input_text_len(cryp)) {
7364b898d5cSNicolas Toromanoff cfg |= CR_PH_PAYLOAD;
7370b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
7384b898d5cSNicolas Toromanoff }
7394b898d5cSNicolas Toromanoff
7404b898d5cSNicolas Toromanoff return 0;
7414b898d5cSNicolas Toromanoff }
7424b898d5cSNicolas Toromanoff
stm32_cryp_hw_init(struct stm32_cryp * cryp)7439e054ec2SFabien DESSENNE static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
7449e054ec2SFabien DESSENNE {
7459e054ec2SFabien DESSENNE int ret;
7469e054ec2SFabien DESSENNE u32 cfg, hw_mode;
7473d6b6613SHerbert Xu
7483d6b6613SHerbert Xu pm_runtime_get_sync(cryp->dev);
74965f9aa36Slionel.debieve@st.com
7509e054ec2SFabien DESSENNE /* Disable interrupt */
7510b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, 0);
7529e054ec2SFabien DESSENNE
7539e054ec2SFabien DESSENNE /* Set configuration */
7549e054ec2SFabien DESSENNE cfg = CR_DATA8 | CR_FFLUSH;
7559e054ec2SFabien DESSENNE
7569e054ec2SFabien DESSENNE switch (cryp->ctx->keylen) {
7579e054ec2SFabien DESSENNE case AES_KEYSIZE_128:
7589e054ec2SFabien DESSENNE cfg |= CR_KEY128;
7599e054ec2SFabien DESSENNE break;
7609e054ec2SFabien DESSENNE
7619e054ec2SFabien DESSENNE case AES_KEYSIZE_192:
7629e054ec2SFabien DESSENNE cfg |= CR_KEY192;
7639e054ec2SFabien DESSENNE break;
7649e054ec2SFabien DESSENNE
7659e054ec2SFabien DESSENNE default:
7669e054ec2SFabien DESSENNE case AES_KEYSIZE_256:
7679e054ec2SFabien DESSENNE cfg |= CR_KEY256;
7689e054ec2SFabien DESSENNE break;
7699e054ec2SFabien DESSENNE }
7709e054ec2SFabien DESSENNE
7719e054ec2SFabien DESSENNE hw_mode = stm32_cryp_get_hw_mode(cryp);
7729e054ec2SFabien DESSENNE if (hw_mode == CR_AES_UNKNOWN)
7739e054ec2SFabien DESSENNE return -EINVAL;
7749e054ec2SFabien DESSENNE
7759e054ec2SFabien DESSENNE /* AES ECB/CBC decrypt: run key preparation first */
7769e054ec2SFabien DESSENNE if (is_decrypt(cryp) &&
7779e054ec2SFabien DESSENNE ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
77895fe2253SNicolas Toromanoff /* Configure in key preparation mode */
7790b496efbSLinus Walleij if (cryp->caps->kp_mode)
7800b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr,
7810b496efbSLinus Walleij cfg | CR_AES_KP);
7820b496efbSLinus Walleij else
7830b496efbSLinus Walleij stm32_cryp_write(cryp,
7840b496efbSLinus Walleij cryp->caps->cr, cfg | CR_AES_ECB | CR_KSE);
7859e054ec2SFabien DESSENNE
78695fe2253SNicolas Toromanoff /* Set key only after full configuration done */
78795fe2253SNicolas Toromanoff stm32_cryp_hw_write_key(cryp);
78895fe2253SNicolas Toromanoff
78995fe2253SNicolas Toromanoff /* Start prepare key */
79095fe2253SNicolas Toromanoff stm32_cryp_enable(cryp);
7919e054ec2SFabien DESSENNE /* Wait for end of processing */
7929e054ec2SFabien DESSENNE ret = stm32_cryp_wait_busy(cryp);
7939e054ec2SFabien DESSENNE if (ret) {
7949e054ec2SFabien DESSENNE dev_err(cryp->dev, "Timeout (key preparation)\n");
7959e054ec2SFabien DESSENNE return ret;
7969e054ec2SFabien DESSENNE }
7979e054ec2SFabien DESSENNE
79895fe2253SNicolas Toromanoff cfg |= hw_mode | CR_DEC_NOT_ENC;
79995fe2253SNicolas Toromanoff
80095fe2253SNicolas Toromanoff /* Apply updated config (Decrypt + algo) and flush */
8010b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
80295fe2253SNicolas Toromanoff } else {
8039e054ec2SFabien DESSENNE cfg |= hw_mode;
8049e054ec2SFabien DESSENNE if (is_decrypt(cryp))
8059e054ec2SFabien DESSENNE cfg |= CR_DEC_NOT_ENC;
8069e054ec2SFabien DESSENNE
80795fe2253SNicolas Toromanoff /* Apply config and flush */
8080b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
8099e054ec2SFabien DESSENNE
81095fe2253SNicolas Toromanoff /* Set key only after configuration done */
81195fe2253SNicolas Toromanoff stm32_cryp_hw_write_key(cryp);
81295fe2253SNicolas Toromanoff }
81395fe2253SNicolas Toromanoff
8149e054ec2SFabien DESSENNE switch (hw_mode) {
8159d3b5030SFabien DESSENNE case CR_AES_GCM:
8169d3b5030SFabien DESSENNE case CR_AES_CCM:
8179d3b5030SFabien DESSENNE /* Phase 1 : init */
8189d3b5030SFabien DESSENNE if (hw_mode == CR_AES_CCM)
8199d3b5030SFabien DESSENNE ret = stm32_cryp_ccm_init(cryp, cfg);
8209d3b5030SFabien DESSENNE else
8219d3b5030SFabien DESSENNE ret = stm32_cryp_gcm_init(cryp, cfg);
8229d3b5030SFabien DESSENNE
8239d3b5030SFabien DESSENNE if (ret)
8249d3b5030SFabien DESSENNE return ret;
8259d3b5030SFabien DESSENNE
8269d3b5030SFabien DESSENNE break;
8279d3b5030SFabien DESSENNE
8289e054ec2SFabien DESSENNE case CR_DES_CBC:
8299e054ec2SFabien DESSENNE case CR_TDES_CBC:
8309e054ec2SFabien DESSENNE case CR_AES_CBC:
8319e054ec2SFabien DESSENNE case CR_AES_CTR:
832bbb28326SHerbert Xu stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->req->iv);
8339e054ec2SFabien DESSENNE break;
8349e054ec2SFabien DESSENNE
8359e054ec2SFabien DESSENNE default:
8369e054ec2SFabien DESSENNE break;
8379e054ec2SFabien DESSENNE }
8389e054ec2SFabien DESSENNE
8399e054ec2SFabien DESSENNE /* Enable now */
84095fe2253SNicolas Toromanoff stm32_cryp_enable(cryp);
8419e054ec2SFabien DESSENNE
8429e054ec2SFabien DESSENNE return 0;
8439e054ec2SFabien DESSENNE }
8449e054ec2SFabien DESSENNE
stm32_cryp_finish_req(struct stm32_cryp * cryp,int err)8459d3b5030SFabien DESSENNE static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err)
8469e054ec2SFabien DESSENNE {
8479d3b5030SFabien DESSENNE if (!err && (is_gcm(cryp) || is_ccm(cryp)))
8489d3b5030SFabien DESSENNE /* Phase 4 : output tag */
8499d3b5030SFabien DESSENNE err = stm32_cryp_read_auth_tag(cryp);
8509e054ec2SFabien DESSENNE
851fa97dc2dSNicolas Toromanoff if (!err && (!(is_gcm(cryp) || is_ccm(cryp) || is_ecb(cryp))))
8525f49f18dSLionel Debieve stm32_cryp_get_iv(cryp);
8535f49f18dSLionel Debieve
85465f9aa36Slionel.debieve@st.com pm_runtime_mark_last_busy(cryp->dev);
85565f9aa36Slionel.debieve@st.com pm_runtime_put_autosuspend(cryp->dev);
85665f9aa36Slionel.debieve@st.com
85729aed438SLionel Debieve if (is_gcm(cryp) || is_ccm(cryp))
8589d3b5030SFabien DESSENNE crypto_finalize_aead_request(cryp->engine, cryp->areq, err);
85929aed438SLionel Debieve else
860fb11a4f6SMaxime Méré crypto_finalize_skcipher_request(cryp->engine, cryp->req, err);
8619e054ec2SFabien DESSENNE }
8629e054ec2SFabien DESSENNE
stm32_cryp_header_dma_callback(void * param)863fb11a4f6SMaxime Méré static void stm32_cryp_header_dma_callback(void *param)
864fb11a4f6SMaxime Méré {
865fb11a4f6SMaxime Méré struct stm32_cryp *cryp = (struct stm32_cryp *)param;
866fb11a4f6SMaxime Méré int ret;
867fb11a4f6SMaxime Méré u32 reg;
868fb11a4f6SMaxime Méré
869fb11a4f6SMaxime Méré dma_unmap_sg(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE);
870fb11a4f6SMaxime Méré
871fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->dmacr);
872fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->dmacr, reg & ~(DMACR_DOEN | DMACR_DIEN));
873fb11a4f6SMaxime Méré
874fb11a4f6SMaxime Méré kfree(cryp->header_sg);
875fb11a4f6SMaxime Méré
876fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->cr);
877fb11a4f6SMaxime Méré
878fb11a4f6SMaxime Méré if (cryp->header_in) {
879fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->cr, reg | CR_CRYPEN);
880fb11a4f6SMaxime Méré
881fb11a4f6SMaxime Méré ret = stm32_cryp_wait_input(cryp);
882fb11a4f6SMaxime Méré if (ret) {
883fb11a4f6SMaxime Méré dev_err(cryp->dev, "input header ready timeout after dma\n");
884fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, ret);
885fb11a4f6SMaxime Méré return;
886fb11a4f6SMaxime Méré }
887fb11a4f6SMaxime Méré stm32_cryp_irq_write_gcmccm_header(cryp);
888fb11a4f6SMaxime Méré WARN_ON(cryp->header_in);
889fb11a4f6SMaxime Méré }
890fb11a4f6SMaxime Méré
891fb11a4f6SMaxime Méré if (stm32_cryp_get_input_text_len(cryp)) {
892fb11a4f6SMaxime Méré /* Phase 3 : payload */
893fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->cr);
894fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->cr, reg & ~CR_CRYPEN);
895fb11a4f6SMaxime Méré
896fb11a4f6SMaxime Méré reg &= ~CR_PH_MASK;
897fb11a4f6SMaxime Méré reg |= CR_PH_PAYLOAD | CR_CRYPEN;
898fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->cr, reg);
899fb11a4f6SMaxime Méré
900fb11a4f6SMaxime Méré if (cryp->flags & FLG_IN_OUT_DMA) {
901fb11a4f6SMaxime Méré ret = stm32_cryp_dma_start(cryp);
902fb11a4f6SMaxime Méré if (ret)
903fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, ret);
904fb11a4f6SMaxime Méré } else {
905fb11a4f6SMaxime Méré stm32_cryp_it_start(cryp);
906fb11a4f6SMaxime Méré }
907fb11a4f6SMaxime Méré } else {
908fb11a4f6SMaxime Méré /*
909fb11a4f6SMaxime Méré * Phase 4 : tag.
910fb11a4f6SMaxime Méré * Nothing to read, nothing to write => end request
911fb11a4f6SMaxime Méré */
912fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, 0);
913fb11a4f6SMaxime Méré }
914fb11a4f6SMaxime Méré }
915fb11a4f6SMaxime Méré
stm32_cryp_dma_callback(void * param)916fb11a4f6SMaxime Méré static void stm32_cryp_dma_callback(void *param)
917fb11a4f6SMaxime Méré {
918fb11a4f6SMaxime Méré struct stm32_cryp *cryp = (struct stm32_cryp *)param;
919fb11a4f6SMaxime Méré int ret;
920fb11a4f6SMaxime Méré u32 reg;
921fb11a4f6SMaxime Méré
922fb11a4f6SMaxime Méré complete(&cryp->dma_completion); /* completion to indicate no timeout */
923fb11a4f6SMaxime Méré
924fb11a4f6SMaxime Méré dma_sync_sg_for_device(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE);
925fb11a4f6SMaxime Méré
926fb11a4f6SMaxime Méré if (cryp->in_sg != cryp->out_sg)
927fb11a4f6SMaxime Méré dma_unmap_sg(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE);
928fb11a4f6SMaxime Méré
929fb11a4f6SMaxime Méré dma_unmap_sg(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE);
930fb11a4f6SMaxime Méré
931fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->dmacr);
932fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->dmacr, reg & ~(DMACR_DOEN | DMACR_DIEN));
933fb11a4f6SMaxime Méré
934fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->cr);
935fb11a4f6SMaxime Méré
936fb11a4f6SMaxime Méré if (is_gcm(cryp) || is_ccm(cryp)) {
937fb11a4f6SMaxime Méré kfree(cryp->in_sg);
938fb11a4f6SMaxime Méré kfree(cryp->out_sg);
939fb11a4f6SMaxime Méré } else {
940fb11a4f6SMaxime Méré if (cryp->in_sg != cryp->req->src)
941fb11a4f6SMaxime Méré kfree(cryp->in_sg);
942fb11a4f6SMaxime Méré if (cryp->out_sg != cryp->req->dst)
943fb11a4f6SMaxime Méré kfree(cryp->out_sg);
944fb11a4f6SMaxime Méré }
945fb11a4f6SMaxime Méré
946fb11a4f6SMaxime Méré if (cryp->payload_in) {
947fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->cr, reg | CR_CRYPEN);
948fb11a4f6SMaxime Méré
949fb11a4f6SMaxime Méré ret = stm32_cryp_wait_input(cryp);
950fb11a4f6SMaxime Méré if (ret) {
951fb11a4f6SMaxime Méré dev_err(cryp->dev, "input ready timeout after dma\n");
952fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, ret);
953fb11a4f6SMaxime Méré return;
954fb11a4f6SMaxime Méré }
955fb11a4f6SMaxime Méré stm32_cryp_irq_write_data(cryp);
956fb11a4f6SMaxime Méré
957fb11a4f6SMaxime Méré ret = stm32_cryp_wait_output(cryp);
958fb11a4f6SMaxime Méré if (ret) {
959fb11a4f6SMaxime Méré dev_err(cryp->dev, "output ready timeout after dma\n");
960fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, ret);
961fb11a4f6SMaxime Méré return;
962fb11a4f6SMaxime Méré }
963fb11a4f6SMaxime Méré stm32_cryp_irq_read_data(cryp);
964fb11a4f6SMaxime Méré }
965fb11a4f6SMaxime Méré
966fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, 0);
967fb11a4f6SMaxime Méré }
968fb11a4f6SMaxime Méré
stm32_cryp_header_dma_start(struct stm32_cryp * cryp)969fb11a4f6SMaxime Méré static int stm32_cryp_header_dma_start(struct stm32_cryp *cryp)
970fb11a4f6SMaxime Méré {
971fb11a4f6SMaxime Méré int ret;
972fb11a4f6SMaxime Méré struct dma_async_tx_descriptor *tx_in;
973fb11a4f6SMaxime Méré u32 reg;
974fb11a4f6SMaxime Méré size_t align_size;
975fb11a4f6SMaxime Méré
976fb11a4f6SMaxime Méré ret = dma_map_sg(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE);
977fb11a4f6SMaxime Méré if (!ret) {
978fb11a4f6SMaxime Méré dev_err(cryp->dev, "dma_map_sg() error\n");
979fb11a4f6SMaxime Méré return -ENOMEM;
980fb11a4f6SMaxime Méré }
981fb11a4f6SMaxime Méré
982fb11a4f6SMaxime Méré dma_sync_sg_for_device(cryp->dev, cryp->header_sg, cryp->header_sg_len, DMA_TO_DEVICE);
983fb11a4f6SMaxime Méré
984fb11a4f6SMaxime Méré tx_in = dmaengine_prep_slave_sg(cryp->dma_lch_in, cryp->header_sg, cryp->header_sg_len,
985fb11a4f6SMaxime Méré DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
986fb11a4f6SMaxime Méré if (!tx_in) {
987fb11a4f6SMaxime Méré dev_err(cryp->dev, "IN prep_slave_sg() failed\n");
988fb11a4f6SMaxime Méré return -EINVAL;
989fb11a4f6SMaxime Méré }
990fb11a4f6SMaxime Méré
991fb11a4f6SMaxime Méré tx_in->callback_param = cryp;
992fb11a4f6SMaxime Méré tx_in->callback = stm32_cryp_header_dma_callback;
993fb11a4f6SMaxime Méré
994fb11a4f6SMaxime Méré /* Advance scatterwalk to not DMA'ed data */
995fb11a4f6SMaxime Méré align_size = ALIGN_DOWN(cryp->header_in, cryp->hw_blocksize);
996fb11a4f6SMaxime Méré scatterwalk_copychunks(NULL, &cryp->in_walk, align_size, 2);
997fb11a4f6SMaxime Méré cryp->header_in -= align_size;
998fb11a4f6SMaxime Méré
999fb11a4f6SMaxime Méré ret = dma_submit_error(dmaengine_submit(tx_in));
1000fb11a4f6SMaxime Méré if (ret < 0) {
1001fb11a4f6SMaxime Méré dev_err(cryp->dev, "DMA in submit failed\n");
1002fb11a4f6SMaxime Méré return ret;
1003fb11a4f6SMaxime Méré }
1004fb11a4f6SMaxime Méré dma_async_issue_pending(cryp->dma_lch_in);
1005fb11a4f6SMaxime Méré
1006fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->dmacr);
1007fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->dmacr, reg | DMACR_DIEN);
1008fb11a4f6SMaxime Méré
1009fb11a4f6SMaxime Méré return 0;
1010fb11a4f6SMaxime Méré }
1011fb11a4f6SMaxime Méré
stm32_cryp_dma_start(struct stm32_cryp * cryp)1012fb11a4f6SMaxime Méré static int stm32_cryp_dma_start(struct stm32_cryp *cryp)
1013fb11a4f6SMaxime Méré {
1014fb11a4f6SMaxime Méré int ret;
1015fb11a4f6SMaxime Méré size_t align_size;
1016fb11a4f6SMaxime Méré struct dma_async_tx_descriptor *tx_in, *tx_out;
1017fb11a4f6SMaxime Méré u32 reg;
1018fb11a4f6SMaxime Méré
1019fb11a4f6SMaxime Méré if (cryp->in_sg != cryp->out_sg) {
1020fb11a4f6SMaxime Méré ret = dma_map_sg(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE);
1021fb11a4f6SMaxime Méré if (!ret) {
1022fb11a4f6SMaxime Méré dev_err(cryp->dev, "dma_map_sg() error\n");
1023fb11a4f6SMaxime Méré return -ENOMEM;
1024fb11a4f6SMaxime Méré }
1025fb11a4f6SMaxime Méré }
1026fb11a4f6SMaxime Méré
1027fb11a4f6SMaxime Méré ret = dma_map_sg(cryp->dev, cryp->out_sg, cryp->out_sg_len, DMA_FROM_DEVICE);
1028fb11a4f6SMaxime Méré if (!ret) {
1029fb11a4f6SMaxime Méré dev_err(cryp->dev, "dma_map_sg() error\n");
1030fb11a4f6SMaxime Méré return -ENOMEM;
1031fb11a4f6SMaxime Méré }
1032fb11a4f6SMaxime Méré
1033fb11a4f6SMaxime Méré dma_sync_sg_for_device(cryp->dev, cryp->in_sg, cryp->in_sg_len, DMA_TO_DEVICE);
1034fb11a4f6SMaxime Méré
1035fb11a4f6SMaxime Méré tx_in = dmaengine_prep_slave_sg(cryp->dma_lch_in, cryp->in_sg, cryp->in_sg_len,
1036fb11a4f6SMaxime Méré DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1037fb11a4f6SMaxime Méré if (!tx_in) {
1038fb11a4f6SMaxime Méré dev_err(cryp->dev, "IN prep_slave_sg() failed\n");
1039fb11a4f6SMaxime Méré return -EINVAL;
1040fb11a4f6SMaxime Méré }
1041fb11a4f6SMaxime Méré
1042fb11a4f6SMaxime Méré /* No callback necessary */
1043fb11a4f6SMaxime Méré tx_in->callback_param = cryp;
1044fb11a4f6SMaxime Méré tx_in->callback = NULL;
1045fb11a4f6SMaxime Méré
1046fb11a4f6SMaxime Méré tx_out = dmaengine_prep_slave_sg(cryp->dma_lch_out, cryp->out_sg, cryp->out_sg_len,
1047fb11a4f6SMaxime Méré DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1048fb11a4f6SMaxime Méré if (!tx_out) {
1049fb11a4f6SMaxime Méré dev_err(cryp->dev, "OUT prep_slave_sg() failed\n");
1050fb11a4f6SMaxime Méré return -EINVAL;
1051fb11a4f6SMaxime Méré }
1052fb11a4f6SMaxime Méré
1053fb11a4f6SMaxime Méré reinit_completion(&cryp->dma_completion);
1054fb11a4f6SMaxime Méré tx_out->callback = stm32_cryp_dma_callback;
1055fb11a4f6SMaxime Méré tx_out->callback_param = cryp;
1056fb11a4f6SMaxime Méré
1057fb11a4f6SMaxime Méré /* Advance scatterwalk to not DMA'ed data */
1058fb11a4f6SMaxime Méré align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize);
1059fb11a4f6SMaxime Méré scatterwalk_copychunks(NULL, &cryp->in_walk, align_size, 2);
1060fb11a4f6SMaxime Méré cryp->payload_in -= align_size;
1061fb11a4f6SMaxime Méré
1062fb11a4f6SMaxime Méré ret = dma_submit_error(dmaengine_submit(tx_in));
1063fb11a4f6SMaxime Méré if (ret < 0) {
1064fb11a4f6SMaxime Méré dev_err(cryp->dev, "DMA in submit failed\n");
1065fb11a4f6SMaxime Méré return ret;
1066fb11a4f6SMaxime Méré }
1067fb11a4f6SMaxime Méré dma_async_issue_pending(cryp->dma_lch_in);
1068fb11a4f6SMaxime Méré
1069fb11a4f6SMaxime Méré /* Advance scatterwalk to not DMA'ed data */
1070fb11a4f6SMaxime Méré scatterwalk_copychunks(NULL, &cryp->out_walk, align_size, 2);
1071fb11a4f6SMaxime Méré cryp->payload_out -= align_size;
1072fb11a4f6SMaxime Méré ret = dma_submit_error(dmaengine_submit(tx_out));
1073fb11a4f6SMaxime Méré if (ret < 0) {
1074fb11a4f6SMaxime Méré dev_err(cryp->dev, "DMA out submit failed\n");
1075fb11a4f6SMaxime Méré return ret;
1076fb11a4f6SMaxime Méré }
1077fb11a4f6SMaxime Méré dma_async_issue_pending(cryp->dma_lch_out);
1078fb11a4f6SMaxime Méré
1079fb11a4f6SMaxime Méré reg = stm32_cryp_read(cryp, cryp->caps->dmacr);
1080fb11a4f6SMaxime Méré stm32_cryp_write(cryp, cryp->caps->dmacr, reg | DMACR_DOEN | DMACR_DIEN);
1081fb11a4f6SMaxime Méré
1082fb11a4f6SMaxime Méré if (!wait_for_completion_timeout(&cryp->dma_completion, msecs_to_jiffies(1000))) {
1083fb11a4f6SMaxime Méré dev_err(cryp->dev, "DMA out timed out\n");
1084fb11a4f6SMaxime Méré dmaengine_terminate_sync(cryp->dma_lch_out);
1085fb11a4f6SMaxime Méré return -ETIMEDOUT;
1086fb11a4f6SMaxime Méré }
1087fb11a4f6SMaxime Méré
1088fb11a4f6SMaxime Méré return 0;
1089fb11a4f6SMaxime Méré }
1090fb11a4f6SMaxime Méré
stm32_cryp_it_start(struct stm32_cryp * cryp)1091fb11a4f6SMaxime Méré static int stm32_cryp_it_start(struct stm32_cryp *cryp)
10929e054ec2SFabien DESSENNE {
10939e054ec2SFabien DESSENNE /* Enable interrupt and let the IRQ handler do everything */
10940b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, IMSCR_IN | IMSCR_OUT);
10959e054ec2SFabien DESSENNE
10969e054ec2SFabien DESSENNE return 0;
10979e054ec2SFabien DESSENNE }
10989e054ec2SFabien DESSENNE
1099dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq);
1100dc7bcef5SCorentin LABBE
stm32_cryp_init_tfm(struct crypto_skcipher * tfm)110147ece481SArd Biesheuvel static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm)
11029e054ec2SFabien DESSENNE {
110347ece481SArd Biesheuvel crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx));
11049e054ec2SFabien DESSENNE
11059e054ec2SFabien DESSENNE return 0;
11069e054ec2SFabien DESSENNE }
11079e054ec2SFabien DESSENNE
11089d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq);
11099d3b5030SFabien DESSENNE
stm32_cryp_aes_aead_init(struct crypto_aead * tfm)11109d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm)
11119d3b5030SFabien DESSENNE {
11127b0795d9SOvidiu Panait crypto_aead_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx));
11139d3b5030SFabien DESSENNE
11149d3b5030SFabien DESSENNE return 0;
11159d3b5030SFabien DESSENNE }
11169d3b5030SFabien DESSENNE
stm32_cryp_crypt(struct skcipher_request * req,unsigned long mode)111747ece481SArd Biesheuvel static int stm32_cryp_crypt(struct skcipher_request *req, unsigned long mode)
11189e054ec2SFabien DESSENNE {
111947ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
112047ece481SArd Biesheuvel crypto_skcipher_reqtfm(req));
112147ece481SArd Biesheuvel struct stm32_cryp_reqctx *rctx = skcipher_request_ctx(req);
11229e054ec2SFabien DESSENNE struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
11239e054ec2SFabien DESSENNE
11249e054ec2SFabien DESSENNE if (!cryp)
11259e054ec2SFabien DESSENNE return -ENODEV;
11269e054ec2SFabien DESSENNE
11279e054ec2SFabien DESSENNE rctx->mode = mode;
11289e054ec2SFabien DESSENNE
112947ece481SArd Biesheuvel return crypto_transfer_skcipher_request_to_engine(cryp->engine, req);
11309e054ec2SFabien DESSENNE }
11319e054ec2SFabien DESSENNE
stm32_cryp_aead_crypt(struct aead_request * req,unsigned long mode)11329d3b5030SFabien DESSENNE static int stm32_cryp_aead_crypt(struct aead_request *req, unsigned long mode)
11339d3b5030SFabien DESSENNE {
11349d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
11359d3b5030SFabien DESSENNE struct stm32_cryp_reqctx *rctx = aead_request_ctx(req);
11369d3b5030SFabien DESSENNE struct stm32_cryp *cryp = stm32_cryp_find_dev(ctx);
11379d3b5030SFabien DESSENNE
11389d3b5030SFabien DESSENNE if (!cryp)
11399d3b5030SFabien DESSENNE return -ENODEV;
11409d3b5030SFabien DESSENNE
11419d3b5030SFabien DESSENNE rctx->mode = mode;
11429d3b5030SFabien DESSENNE
11439d3b5030SFabien DESSENNE return crypto_transfer_aead_request_to_engine(cryp->engine, req);
11449d3b5030SFabien DESSENNE }
11459d3b5030SFabien DESSENNE
stm32_cryp_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)114647ece481SArd Biesheuvel static int stm32_cryp_setkey(struct crypto_skcipher *tfm, const u8 *key,
11479e054ec2SFabien DESSENNE unsigned int keylen)
11489e054ec2SFabien DESSENNE {
114947ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm);
11509e054ec2SFabien DESSENNE
11519e054ec2SFabien DESSENNE memcpy(ctx->key, key, keylen);
11529e054ec2SFabien DESSENNE ctx->keylen = keylen;
11539e054ec2SFabien DESSENNE
11549e054ec2SFabien DESSENNE return 0;
11559e054ec2SFabien DESSENNE }
11569e054ec2SFabien DESSENNE
stm32_cryp_aes_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)115747ece481SArd Biesheuvel static int stm32_cryp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
11589e054ec2SFabien DESSENNE unsigned int keylen)
11599e054ec2SFabien DESSENNE {
11609e054ec2SFabien DESSENNE if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
11619e054ec2SFabien DESSENNE keylen != AES_KEYSIZE_256)
11629e054ec2SFabien DESSENNE return -EINVAL;
11639e054ec2SFabien DESSENNE else
11649e054ec2SFabien DESSENNE return stm32_cryp_setkey(tfm, key, keylen);
11659e054ec2SFabien DESSENNE }
11669e054ec2SFabien DESSENNE
stm32_cryp_des_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)116747ece481SArd Biesheuvel static int stm32_cryp_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
11689e054ec2SFabien DESSENNE unsigned int keylen)
11699e054ec2SFabien DESSENNE {
117047ece481SArd Biesheuvel return verify_skcipher_des_key(tfm, key) ?:
1171b5d0ba83SArd Biesheuvel stm32_cryp_setkey(tfm, key, keylen);
11729e054ec2SFabien DESSENNE }
11739e054ec2SFabien DESSENNE
stm32_cryp_tdes_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)117447ece481SArd Biesheuvel static int stm32_cryp_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key,
11759e054ec2SFabien DESSENNE unsigned int keylen)
11769e054ec2SFabien DESSENNE {
117747ece481SArd Biesheuvel return verify_skcipher_des3_key(tfm, key) ?:
1178b5d0ba83SArd Biesheuvel stm32_cryp_setkey(tfm, key, keylen);
11799e054ec2SFabien DESSENNE }
11809e054ec2SFabien DESSENNE
stm32_cryp_aes_aead_setkey(struct crypto_aead * tfm,const u8 * key,unsigned int keylen)11819d3b5030SFabien DESSENNE static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key,
11829d3b5030SFabien DESSENNE unsigned int keylen)
11839d3b5030SFabien DESSENNE {
11849d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm);
11859d3b5030SFabien DESSENNE
11869d3b5030SFabien DESSENNE if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
11879d3b5030SFabien DESSENNE keylen != AES_KEYSIZE_256)
11889d3b5030SFabien DESSENNE return -EINVAL;
11899d3b5030SFabien DESSENNE
11909d3b5030SFabien DESSENNE memcpy(ctx->key, key, keylen);
11919d3b5030SFabien DESSENNE ctx->keylen = keylen;
11929d3b5030SFabien DESSENNE
11939d3b5030SFabien DESSENNE return 0;
11949d3b5030SFabien DESSENNE }
11959d3b5030SFabien DESSENNE
stm32_cryp_aes_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)11969d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm,
11979d3b5030SFabien DESSENNE unsigned int authsize)
11989d3b5030SFabien DESSENNE {
119939e6e699SNicolas Toromanoff switch (authsize) {
120039e6e699SNicolas Toromanoff case 4:
120139e6e699SNicolas Toromanoff case 8:
120239e6e699SNicolas Toromanoff case 12:
120339e6e699SNicolas Toromanoff case 13:
120439e6e699SNicolas Toromanoff case 14:
120539e6e699SNicolas Toromanoff case 15:
120639e6e699SNicolas Toromanoff case 16:
120739e6e699SNicolas Toromanoff break;
120839e6e699SNicolas Toromanoff default:
120939e6e699SNicolas Toromanoff return -EINVAL;
121039e6e699SNicolas Toromanoff }
121139e6e699SNicolas Toromanoff
121239e6e699SNicolas Toromanoff return 0;
12139d3b5030SFabien DESSENNE }
12149d3b5030SFabien DESSENNE
stm32_cryp_aes_ccm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)12159d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm,
12169d3b5030SFabien DESSENNE unsigned int authsize)
12179d3b5030SFabien DESSENNE {
12189d3b5030SFabien DESSENNE switch (authsize) {
12199d3b5030SFabien DESSENNE case 4:
12209d3b5030SFabien DESSENNE case 6:
12219d3b5030SFabien DESSENNE case 8:
12229d3b5030SFabien DESSENNE case 10:
12239d3b5030SFabien DESSENNE case 12:
12249d3b5030SFabien DESSENNE case 14:
12259d3b5030SFabien DESSENNE case 16:
12269d3b5030SFabien DESSENNE break;
12279d3b5030SFabien DESSENNE default:
12289d3b5030SFabien DESSENNE return -EINVAL;
12299d3b5030SFabien DESSENNE }
12309d3b5030SFabien DESSENNE
12319d3b5030SFabien DESSENNE return 0;
12329d3b5030SFabien DESSENNE }
12339d3b5030SFabien DESSENNE
stm32_cryp_aes_ecb_encrypt(struct skcipher_request * req)123447ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req)
12359e054ec2SFabien DESSENNE {
123639e6e699SNicolas Toromanoff if (req->cryptlen % AES_BLOCK_SIZE)
123739e6e699SNicolas Toromanoff return -EINVAL;
123839e6e699SNicolas Toromanoff
123939e6e699SNicolas Toromanoff if (req->cryptlen == 0)
124039e6e699SNicolas Toromanoff return 0;
124139e6e699SNicolas Toromanoff
12429e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT);
12439e054ec2SFabien DESSENNE }
12449e054ec2SFabien DESSENNE
stm32_cryp_aes_ecb_decrypt(struct skcipher_request * req)124547ece481SArd Biesheuvel static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req)
12469e054ec2SFabien DESSENNE {
124739e6e699SNicolas Toromanoff if (req->cryptlen % AES_BLOCK_SIZE)
124839e6e699SNicolas Toromanoff return -EINVAL;
124939e6e699SNicolas Toromanoff
125039e6e699SNicolas Toromanoff if (req->cryptlen == 0)
125139e6e699SNicolas Toromanoff return 0;
125239e6e699SNicolas Toromanoff
12539e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_ECB);
12549e054ec2SFabien DESSENNE }
12559e054ec2SFabien DESSENNE
stm32_cryp_aes_cbc_encrypt(struct skcipher_request * req)125647ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req)
12579e054ec2SFabien DESSENNE {
125839e6e699SNicolas Toromanoff if (req->cryptlen % AES_BLOCK_SIZE)
125939e6e699SNicolas Toromanoff return -EINVAL;
126039e6e699SNicolas Toromanoff
126139e6e699SNicolas Toromanoff if (req->cryptlen == 0)
126239e6e699SNicolas Toromanoff return 0;
126339e6e699SNicolas Toromanoff
12649e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT);
12659e054ec2SFabien DESSENNE }
12669e054ec2SFabien DESSENNE
stm32_cryp_aes_cbc_decrypt(struct skcipher_request * req)126747ece481SArd Biesheuvel static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req)
12689e054ec2SFabien DESSENNE {
126939e6e699SNicolas Toromanoff if (req->cryptlen % AES_BLOCK_SIZE)
127039e6e699SNicolas Toromanoff return -EINVAL;
127139e6e699SNicolas Toromanoff
127239e6e699SNicolas Toromanoff if (req->cryptlen == 0)
127339e6e699SNicolas Toromanoff return 0;
127439e6e699SNicolas Toromanoff
12759e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CBC);
12769e054ec2SFabien DESSENNE }
12779e054ec2SFabien DESSENNE
stm32_cryp_aes_ctr_encrypt(struct skcipher_request * req)127847ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req)
12799e054ec2SFabien DESSENNE {
128039e6e699SNicolas Toromanoff if (req->cryptlen == 0)
128139e6e699SNicolas Toromanoff return 0;
128239e6e699SNicolas Toromanoff
12839e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT);
12849e054ec2SFabien DESSENNE }
12859e054ec2SFabien DESSENNE
stm32_cryp_aes_ctr_decrypt(struct skcipher_request * req)128647ece481SArd Biesheuvel static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req)
12879e054ec2SFabien DESSENNE {
128839e6e699SNicolas Toromanoff if (req->cryptlen == 0)
128939e6e699SNicolas Toromanoff return 0;
129039e6e699SNicolas Toromanoff
12919e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_AES | FLG_CTR);
12929e054ec2SFabien DESSENNE }
12939e054ec2SFabien DESSENNE
stm32_cryp_aes_gcm_encrypt(struct aead_request * req)12949d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_encrypt(struct aead_request *req)
12959d3b5030SFabien DESSENNE {
12969d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM | FLG_ENCRYPT);
12979d3b5030SFabien DESSENNE }
12989d3b5030SFabien DESSENNE
stm32_cryp_aes_gcm_decrypt(struct aead_request * req)12999d3b5030SFabien DESSENNE static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req)
13009d3b5030SFabien DESSENNE {
13019d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM);
13029d3b5030SFabien DESSENNE }
13039d3b5030SFabien DESSENNE
crypto_ccm_check_iv(const u8 * iv)130439e6e699SNicolas Toromanoff static inline int crypto_ccm_check_iv(const u8 *iv)
130539e6e699SNicolas Toromanoff {
130639e6e699SNicolas Toromanoff /* 2 <= L <= 8, so 1 <= L' <= 7. */
130739e6e699SNicolas Toromanoff if (iv[0] < 1 || iv[0] > 7)
130839e6e699SNicolas Toromanoff return -EINVAL;
130939e6e699SNicolas Toromanoff
131039e6e699SNicolas Toromanoff return 0;
131139e6e699SNicolas Toromanoff }
131239e6e699SNicolas Toromanoff
stm32_cryp_aes_ccm_encrypt(struct aead_request * req)13139d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req)
13149d3b5030SFabien DESSENNE {
131539e6e699SNicolas Toromanoff int err;
131639e6e699SNicolas Toromanoff
131739e6e699SNicolas Toromanoff err = crypto_ccm_check_iv(req->iv);
131839e6e699SNicolas Toromanoff if (err)
131939e6e699SNicolas Toromanoff return err;
132039e6e699SNicolas Toromanoff
13219d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT);
13229d3b5030SFabien DESSENNE }
13239d3b5030SFabien DESSENNE
stm32_cryp_aes_ccm_decrypt(struct aead_request * req)13249d3b5030SFabien DESSENNE static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req)
13259d3b5030SFabien DESSENNE {
132639e6e699SNicolas Toromanoff int err;
132739e6e699SNicolas Toromanoff
132839e6e699SNicolas Toromanoff err = crypto_ccm_check_iv(req->iv);
132939e6e699SNicolas Toromanoff if (err)
133039e6e699SNicolas Toromanoff return err;
133139e6e699SNicolas Toromanoff
13329d3b5030SFabien DESSENNE return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM);
13339d3b5030SFabien DESSENNE }
13349d3b5030SFabien DESSENNE
stm32_cryp_des_ecb_encrypt(struct skcipher_request * req)133547ece481SArd Biesheuvel static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req)
13369e054ec2SFabien DESSENNE {
133739e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
133839e6e699SNicolas Toromanoff return -EINVAL;
133939e6e699SNicolas Toromanoff
134039e6e699SNicolas Toromanoff if (req->cryptlen == 0)
134139e6e699SNicolas Toromanoff return 0;
134239e6e699SNicolas Toromanoff
13439e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT);
13449e054ec2SFabien DESSENNE }
13459e054ec2SFabien DESSENNE
stm32_cryp_des_ecb_decrypt(struct skcipher_request * req)134647ece481SArd Biesheuvel static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req)
13479e054ec2SFabien DESSENNE {
134839e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
134939e6e699SNicolas Toromanoff return -EINVAL;
135039e6e699SNicolas Toromanoff
135139e6e699SNicolas Toromanoff if (req->cryptlen == 0)
135239e6e699SNicolas Toromanoff return 0;
135339e6e699SNicolas Toromanoff
13549e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_ECB);
13559e054ec2SFabien DESSENNE }
13569e054ec2SFabien DESSENNE
stm32_cryp_des_cbc_encrypt(struct skcipher_request * req)135747ece481SArd Biesheuvel static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req)
13589e054ec2SFabien DESSENNE {
135939e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
136039e6e699SNicolas Toromanoff return -EINVAL;
136139e6e699SNicolas Toromanoff
136239e6e699SNicolas Toromanoff if (req->cryptlen == 0)
136339e6e699SNicolas Toromanoff return 0;
136439e6e699SNicolas Toromanoff
13659e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT);
13669e054ec2SFabien DESSENNE }
13679e054ec2SFabien DESSENNE
stm32_cryp_des_cbc_decrypt(struct skcipher_request * req)136847ece481SArd Biesheuvel static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req)
13699e054ec2SFabien DESSENNE {
137039e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
137139e6e699SNicolas Toromanoff return -EINVAL;
137239e6e699SNicolas Toromanoff
137339e6e699SNicolas Toromanoff if (req->cryptlen == 0)
137439e6e699SNicolas Toromanoff return 0;
137539e6e699SNicolas Toromanoff
13769e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_DES | FLG_CBC);
13779e054ec2SFabien DESSENNE }
13789e054ec2SFabien DESSENNE
stm32_cryp_tdes_ecb_encrypt(struct skcipher_request * req)137947ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req)
13809e054ec2SFabien DESSENNE {
138139e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
138239e6e699SNicolas Toromanoff return -EINVAL;
138339e6e699SNicolas Toromanoff
138439e6e699SNicolas Toromanoff if (req->cryptlen == 0)
138539e6e699SNicolas Toromanoff return 0;
138639e6e699SNicolas Toromanoff
13879e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT);
13889e054ec2SFabien DESSENNE }
13899e054ec2SFabien DESSENNE
stm32_cryp_tdes_ecb_decrypt(struct skcipher_request * req)139047ece481SArd Biesheuvel static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req)
13919e054ec2SFabien DESSENNE {
139239e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
139339e6e699SNicolas Toromanoff return -EINVAL;
139439e6e699SNicolas Toromanoff
139539e6e699SNicolas Toromanoff if (req->cryptlen == 0)
139639e6e699SNicolas Toromanoff return 0;
139739e6e699SNicolas Toromanoff
13989e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB);
13999e054ec2SFabien DESSENNE }
14009e054ec2SFabien DESSENNE
stm32_cryp_tdes_cbc_encrypt(struct skcipher_request * req)140147ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req)
14029e054ec2SFabien DESSENNE {
140339e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
140439e6e699SNicolas Toromanoff return -EINVAL;
140539e6e699SNicolas Toromanoff
140639e6e699SNicolas Toromanoff if (req->cryptlen == 0)
140739e6e699SNicolas Toromanoff return 0;
140839e6e699SNicolas Toromanoff
14099e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT);
14109e054ec2SFabien DESSENNE }
14119e054ec2SFabien DESSENNE
stm32_cryp_tdes_cbc_decrypt(struct skcipher_request * req)141247ece481SArd Biesheuvel static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req)
14139e054ec2SFabien DESSENNE {
141439e6e699SNicolas Toromanoff if (req->cryptlen % DES_BLOCK_SIZE)
141539e6e699SNicolas Toromanoff return -EINVAL;
141639e6e699SNicolas Toromanoff
141739e6e699SNicolas Toromanoff if (req->cryptlen == 0)
141839e6e699SNicolas Toromanoff return 0;
141939e6e699SNicolas Toromanoff
14209e054ec2SFabien DESSENNE return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC);
14219e054ec2SFabien DESSENNE }
14229e054ec2SFabien DESSENNE
stm32_cryp_dma_check_sg(struct scatterlist * test_sg,size_t len,size_t block_size)1423fb11a4f6SMaxime Méré static enum stm32_dma_mode stm32_cryp_dma_check_sg(struct scatterlist *test_sg, size_t len,
1424fb11a4f6SMaxime Méré size_t block_size)
1425fb11a4f6SMaxime Méré {
1426fb11a4f6SMaxime Méré struct scatterlist *sg;
1427fb11a4f6SMaxime Méré int i;
1428fb11a4f6SMaxime Méré
1429fb11a4f6SMaxime Méré if (len <= 16)
1430fb11a4f6SMaxime Méré return NO_DMA; /* Faster */
1431fb11a4f6SMaxime Méré
1432fb11a4f6SMaxime Méré for_each_sg(test_sg, sg, sg_nents(test_sg), i) {
1433fb11a4f6SMaxime Méré if (!IS_ALIGNED(sg->length, block_size) && !sg_is_last(sg))
1434fb11a4f6SMaxime Méré return NO_DMA;
1435fb11a4f6SMaxime Méré
1436fb11a4f6SMaxime Méré if (sg->offset % sizeof(u32))
1437fb11a4f6SMaxime Méré return NO_DMA;
1438fb11a4f6SMaxime Méré
1439fb11a4f6SMaxime Méré if (sg_is_last(sg) && !IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
1440fb11a4f6SMaxime Méré return DMA_NEED_SG_TRUNC;
1441fb11a4f6SMaxime Méré }
1442fb11a4f6SMaxime Méré
1443fb11a4f6SMaxime Méré return DMA_PLAIN_SG;
1444fb11a4f6SMaxime Méré }
1445fb11a4f6SMaxime Méré
stm32_cryp_dma_check(struct stm32_cryp * cryp,struct scatterlist * in_sg,struct scatterlist * out_sg)1446fb11a4f6SMaxime Méré static enum stm32_dma_mode stm32_cryp_dma_check(struct stm32_cryp *cryp, struct scatterlist *in_sg,
1447fb11a4f6SMaxime Méré struct scatterlist *out_sg)
1448fb11a4f6SMaxime Méré {
1449fb11a4f6SMaxime Méré enum stm32_dma_mode ret = DMA_PLAIN_SG;
1450fb11a4f6SMaxime Méré
1451fb11a4f6SMaxime Méré if (!is_aes(cryp))
1452fb11a4f6SMaxime Méré return NO_DMA;
1453fb11a4f6SMaxime Méré
1454fb11a4f6SMaxime Méré if (!cryp->dma_lch_in || !cryp->dma_lch_out)
1455fb11a4f6SMaxime Méré return NO_DMA;
1456fb11a4f6SMaxime Méré
1457fb11a4f6SMaxime Méré ret = stm32_cryp_dma_check_sg(in_sg, cryp->payload_in, AES_BLOCK_SIZE);
1458fb11a4f6SMaxime Méré if (ret == NO_DMA)
1459fb11a4f6SMaxime Méré return ret;
1460fb11a4f6SMaxime Méré
1461fb11a4f6SMaxime Méré ret = stm32_cryp_dma_check_sg(out_sg, cryp->payload_out, AES_BLOCK_SIZE);
1462fb11a4f6SMaxime Méré if (ret == NO_DMA)
1463fb11a4f6SMaxime Méré return ret;
1464fb11a4f6SMaxime Méré
1465fb11a4f6SMaxime Méré /* Check CTR counter overflow */
1466fb11a4f6SMaxime Méré if (is_aes(cryp) && is_ctr(cryp)) {
1467fb11a4f6SMaxime Méré u32 c;
1468fb11a4f6SMaxime Méré __be32 iv3;
1469fb11a4f6SMaxime Méré
1470fb11a4f6SMaxime Méré memcpy(&iv3, &cryp->req->iv[3 * sizeof(u32)], sizeof(iv3));
1471fb11a4f6SMaxime Méré c = be32_to_cpu(iv3);
1472fb11a4f6SMaxime Méré if ((c + cryp->payload_in) < cryp->payload_in)
1473fb11a4f6SMaxime Méré return NO_DMA;
1474fb11a4f6SMaxime Méré }
1475fb11a4f6SMaxime Méré
1476fb11a4f6SMaxime Méré /* Workaround */
1477fb11a4f6SMaxime Méré if (is_aes(cryp) && is_ctr(cryp) && ret == DMA_NEED_SG_TRUNC)
1478fb11a4f6SMaxime Méré return NO_DMA;
1479fb11a4f6SMaxime Méré
1480fb11a4f6SMaxime Méré return ret;
1481fb11a4f6SMaxime Méré }
1482fb11a4f6SMaxime Méré
stm32_cryp_truncate_sg(struct scatterlist ** new_sg,size_t * new_sg_len,struct scatterlist * sg,off_t skip,size_t size)1483fb11a4f6SMaxime Méré static int stm32_cryp_truncate_sg(struct scatterlist **new_sg, size_t *new_sg_len,
1484fb11a4f6SMaxime Méré struct scatterlist *sg, off_t skip, size_t size)
1485fb11a4f6SMaxime Méré {
1486fb11a4f6SMaxime Méré struct scatterlist *cur;
1487fb11a4f6SMaxime Méré int alloc_sg_len;
1488fb11a4f6SMaxime Méré
1489fb11a4f6SMaxime Méré *new_sg_len = 0;
1490fb11a4f6SMaxime Méré
1491fb11a4f6SMaxime Méré if (!sg || !size) {
1492fb11a4f6SMaxime Méré *new_sg = NULL;
1493fb11a4f6SMaxime Méré return 0;
1494fb11a4f6SMaxime Méré }
1495fb11a4f6SMaxime Méré
1496fb11a4f6SMaxime Méré alloc_sg_len = sg_nents_for_len(sg, skip + size);
1497fb11a4f6SMaxime Méré if (alloc_sg_len < 0)
1498fb11a4f6SMaxime Méré return alloc_sg_len;
1499fb11a4f6SMaxime Méré
1500fb11a4f6SMaxime Méré /* We allocate to much sg entry, but it is easier */
1501fb11a4f6SMaxime Méré *new_sg = kmalloc_array((size_t)alloc_sg_len, sizeof(struct scatterlist), GFP_KERNEL);
1502fb11a4f6SMaxime Méré if (!*new_sg)
1503fb11a4f6SMaxime Méré return -ENOMEM;
1504fb11a4f6SMaxime Méré
1505fb11a4f6SMaxime Méré sg_init_table(*new_sg, (unsigned int)alloc_sg_len);
1506fb11a4f6SMaxime Méré
1507fb11a4f6SMaxime Méré cur = *new_sg;
1508fb11a4f6SMaxime Méré while (sg && size) {
1509fb11a4f6SMaxime Méré unsigned int len = sg->length;
1510fb11a4f6SMaxime Méré unsigned int offset = sg->offset;
1511fb11a4f6SMaxime Méré
1512fb11a4f6SMaxime Méré if (skip > len) {
1513fb11a4f6SMaxime Méré skip -= len;
1514fb11a4f6SMaxime Méré sg = sg_next(sg);
1515fb11a4f6SMaxime Méré continue;
1516fb11a4f6SMaxime Méré }
1517fb11a4f6SMaxime Méré
1518fb11a4f6SMaxime Méré if (skip) {
1519fb11a4f6SMaxime Méré len -= skip;
1520fb11a4f6SMaxime Méré offset += skip;
1521fb11a4f6SMaxime Méré skip = 0;
1522fb11a4f6SMaxime Méré }
1523fb11a4f6SMaxime Méré
1524fb11a4f6SMaxime Méré if (size < len)
1525fb11a4f6SMaxime Méré len = size;
1526fb11a4f6SMaxime Méré
1527fb11a4f6SMaxime Méré if (len > 0) {
1528fb11a4f6SMaxime Méré (*new_sg_len)++;
1529fb11a4f6SMaxime Méré size -= len;
1530fb11a4f6SMaxime Méré sg_set_page(cur, sg_page(sg), len, offset);
1531fb11a4f6SMaxime Méré if (size == 0)
1532fb11a4f6SMaxime Méré sg_mark_end(cur);
1533fb11a4f6SMaxime Méré cur = sg_next(cur);
1534fb11a4f6SMaxime Méré }
1535fb11a4f6SMaxime Méré
1536fb11a4f6SMaxime Méré sg = sg_next(sg);
1537fb11a4f6SMaxime Méré }
1538fb11a4f6SMaxime Méré
1539fb11a4f6SMaxime Méré return 0;
1540fb11a4f6SMaxime Méré }
1541fb11a4f6SMaxime Méré
stm32_cryp_cipher_prepare(struct stm32_cryp * cryp,struct scatterlist * in_sg,struct scatterlist * out_sg)1542fb11a4f6SMaxime Méré static int stm32_cryp_cipher_prepare(struct stm32_cryp *cryp, struct scatterlist *in_sg,
1543fb11a4f6SMaxime Méré struct scatterlist *out_sg)
1544fb11a4f6SMaxime Méré {
1545fb11a4f6SMaxime Méré size_t align_size;
1546fb11a4f6SMaxime Méré int ret;
1547fb11a4f6SMaxime Méré
1548fb11a4f6SMaxime Méré cryp->dma_mode = stm32_cryp_dma_check(cryp, in_sg, out_sg);
1549fb11a4f6SMaxime Méré
1550fb11a4f6SMaxime Méré scatterwalk_start(&cryp->in_walk, in_sg);
1551fb11a4f6SMaxime Méré scatterwalk_start(&cryp->out_walk, out_sg);
1552fb11a4f6SMaxime Méré
1553fb11a4f6SMaxime Méré if (cryp->dma_mode == NO_DMA) {
1554fb11a4f6SMaxime Méré cryp->flags &= ~FLG_IN_OUT_DMA;
1555fb11a4f6SMaxime Méré
1556fb11a4f6SMaxime Méré if (is_ctr(cryp))
1557fb11a4f6SMaxime Méré memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr));
1558fb11a4f6SMaxime Méré
1559fb11a4f6SMaxime Méré } else if (cryp->dma_mode == DMA_NEED_SG_TRUNC) {
1560fb11a4f6SMaxime Méré
1561fb11a4f6SMaxime Méré cryp->flags |= FLG_IN_OUT_DMA;
1562fb11a4f6SMaxime Méré
1563fb11a4f6SMaxime Méré align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize);
1564fb11a4f6SMaxime Méré ret = stm32_cryp_truncate_sg(&cryp->in_sg, &cryp->in_sg_len, in_sg, 0, align_size);
1565fb11a4f6SMaxime Méré if (ret)
1566fb11a4f6SMaxime Méré return ret;
1567fb11a4f6SMaxime Méré
1568fb11a4f6SMaxime Méré ret = stm32_cryp_truncate_sg(&cryp->out_sg, &cryp->out_sg_len, out_sg, 0,
1569fb11a4f6SMaxime Méré align_size);
1570fb11a4f6SMaxime Méré if (ret) {
1571fb11a4f6SMaxime Méré kfree(cryp->in_sg);
1572fb11a4f6SMaxime Méré return ret;
1573fb11a4f6SMaxime Méré }
1574fb11a4f6SMaxime Méré } else {
1575fb11a4f6SMaxime Méré cryp->flags |= FLG_IN_OUT_DMA;
1576fb11a4f6SMaxime Méré
1577fb11a4f6SMaxime Méré cryp->in_sg = in_sg;
1578fb11a4f6SMaxime Méré cryp->out_sg = out_sg;
1579fb11a4f6SMaxime Méré
1580fb11a4f6SMaxime Méré ret = sg_nents_for_len(cryp->in_sg, cryp->payload_in);
1581fb11a4f6SMaxime Méré if (ret < 0)
1582fb11a4f6SMaxime Méré return ret;
1583fb11a4f6SMaxime Méré cryp->in_sg_len = (size_t)ret;
1584fb11a4f6SMaxime Méré
1585fb11a4f6SMaxime Méré ret = sg_nents_for_len(out_sg, cryp->payload_out);
1586fb11a4f6SMaxime Méré if (ret < 0)
1587fb11a4f6SMaxime Méré return ret;
1588fb11a4f6SMaxime Méré cryp->out_sg_len = (size_t)ret;
1589fb11a4f6SMaxime Méré }
1590fb11a4f6SMaxime Méré
1591fb11a4f6SMaxime Méré return 0;
1592fb11a4f6SMaxime Méré }
1593fb11a4f6SMaxime Méré
stm32_cryp_aead_prepare(struct stm32_cryp * cryp,struct scatterlist * in_sg,struct scatterlist * out_sg)1594fb11a4f6SMaxime Méré static int stm32_cryp_aead_prepare(struct stm32_cryp *cryp, struct scatterlist *in_sg,
1595fb11a4f6SMaxime Méré struct scatterlist *out_sg)
1596fb11a4f6SMaxime Méré {
1597fb11a4f6SMaxime Méré size_t align_size;
1598fb11a4f6SMaxime Méré off_t skip;
1599fb11a4f6SMaxime Méré int ret, ret2;
1600fb11a4f6SMaxime Méré
1601fb11a4f6SMaxime Méré cryp->header_sg = NULL;
1602fb11a4f6SMaxime Méré cryp->in_sg = NULL;
1603fb11a4f6SMaxime Méré cryp->out_sg = NULL;
1604fb11a4f6SMaxime Méré
1605fb11a4f6SMaxime Méré if (!cryp->dma_lch_in || !cryp->dma_lch_out) {
1606fb11a4f6SMaxime Méré cryp->dma_mode = NO_DMA;
1607fb11a4f6SMaxime Méré cryp->flags &= ~(FLG_IN_OUT_DMA | FLG_HEADER_DMA);
1608fb11a4f6SMaxime Méré
1609fb11a4f6SMaxime Méré return 0;
1610fb11a4f6SMaxime Méré }
1611fb11a4f6SMaxime Méré
1612fb11a4f6SMaxime Méré /* CCM hw_init may have advanced in header */
1613fb11a4f6SMaxime Méré skip = cryp->areq->assoclen - cryp->header_in;
1614fb11a4f6SMaxime Méré
1615fb11a4f6SMaxime Méré align_size = ALIGN_DOWN(cryp->header_in, cryp->hw_blocksize);
1616fb11a4f6SMaxime Méré ret = stm32_cryp_truncate_sg(&cryp->header_sg, &cryp->header_sg_len, in_sg, skip,
1617fb11a4f6SMaxime Méré align_size);
1618fb11a4f6SMaxime Méré if (ret)
1619fb11a4f6SMaxime Méré return ret;
1620fb11a4f6SMaxime Méré
1621fb11a4f6SMaxime Méré ret = stm32_cryp_dma_check_sg(cryp->header_sg, align_size, AES_BLOCK_SIZE);
1622fb11a4f6SMaxime Méré if (ret == NO_DMA) {
1623fb11a4f6SMaxime Méré /* We cannot DMA the header */
1624fb11a4f6SMaxime Méré kfree(cryp->header_sg);
1625fb11a4f6SMaxime Méré cryp->header_sg = NULL;
1626fb11a4f6SMaxime Méré
1627fb11a4f6SMaxime Méré cryp->flags &= ~FLG_HEADER_DMA;
1628fb11a4f6SMaxime Méré } else {
1629fb11a4f6SMaxime Méré cryp->flags |= FLG_HEADER_DMA;
1630fb11a4f6SMaxime Méré }
1631fb11a4f6SMaxime Méré
1632fb11a4f6SMaxime Méré /* Now skip all header to be at payload start */
1633fb11a4f6SMaxime Méré skip = cryp->areq->assoclen;
1634fb11a4f6SMaxime Méré align_size = ALIGN_DOWN(cryp->payload_in, cryp->hw_blocksize);
1635fb11a4f6SMaxime Méré ret = stm32_cryp_truncate_sg(&cryp->in_sg, &cryp->in_sg_len, in_sg, skip, align_size);
1636fb11a4f6SMaxime Méré if (ret) {
1637fb11a4f6SMaxime Méré kfree(cryp->header_sg);
1638fb11a4f6SMaxime Méré return ret;
1639fb11a4f6SMaxime Méré }
1640fb11a4f6SMaxime Méré
1641fb11a4f6SMaxime Méré /* For out buffer align_size is same as in buffer */
1642fb11a4f6SMaxime Méré ret = stm32_cryp_truncate_sg(&cryp->out_sg, &cryp->out_sg_len, out_sg, skip, align_size);
1643fb11a4f6SMaxime Méré if (ret) {
1644fb11a4f6SMaxime Méré kfree(cryp->header_sg);
1645fb11a4f6SMaxime Méré kfree(cryp->in_sg);
1646fb11a4f6SMaxime Méré return ret;
1647fb11a4f6SMaxime Méré }
1648fb11a4f6SMaxime Méré
1649fb11a4f6SMaxime Méré ret = stm32_cryp_dma_check_sg(cryp->in_sg, align_size, AES_BLOCK_SIZE);
1650fb11a4f6SMaxime Méré ret2 = stm32_cryp_dma_check_sg(cryp->out_sg, align_size, AES_BLOCK_SIZE);
1651fb11a4f6SMaxime Méré if (ret == NO_DMA || ret2 == NO_DMA) {
1652fb11a4f6SMaxime Méré kfree(cryp->in_sg);
1653fb11a4f6SMaxime Méré cryp->in_sg = NULL;
1654fb11a4f6SMaxime Méré
1655fb11a4f6SMaxime Méré kfree(cryp->out_sg);
1656fb11a4f6SMaxime Méré cryp->out_sg = NULL;
1657fb11a4f6SMaxime Méré
1658fb11a4f6SMaxime Méré cryp->flags &= ~FLG_IN_OUT_DMA;
1659fb11a4f6SMaxime Méré } else {
1660fb11a4f6SMaxime Méré cryp->flags |= FLG_IN_OUT_DMA;
1661fb11a4f6SMaxime Méré }
1662fb11a4f6SMaxime Méré
1663fb11a4f6SMaxime Méré return 0;
1664fb11a4f6SMaxime Méré }
1665fb11a4f6SMaxime Méré
stm32_cryp_prepare_req(struct skcipher_request * req,struct aead_request * areq)166647ece481SArd Biesheuvel static int stm32_cryp_prepare_req(struct skcipher_request *req,
16679d3b5030SFabien DESSENNE struct aead_request *areq)
16689e054ec2SFabien DESSENNE {
16699e054ec2SFabien DESSENNE struct stm32_cryp_ctx *ctx;
16709e054ec2SFabien DESSENNE struct stm32_cryp *cryp;
16719e054ec2SFabien DESSENNE struct stm32_cryp_reqctx *rctx;
1672fb11a4f6SMaxime Méré struct scatterlist *in_sg, *out_sg;
16739e054ec2SFabien DESSENNE int ret;
16749e054ec2SFabien DESSENNE
16759d3b5030SFabien DESSENNE if (!req && !areq)
16769e054ec2SFabien DESSENNE return -EINVAL;
16779e054ec2SFabien DESSENNE
167847ece481SArd Biesheuvel ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) :
16799d3b5030SFabien DESSENNE crypto_aead_ctx(crypto_aead_reqtfm(areq));
16809e054ec2SFabien DESSENNE
16819e054ec2SFabien DESSENNE cryp = ctx->cryp;
16829e054ec2SFabien DESSENNE
168347ece481SArd Biesheuvel rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq);
16849e054ec2SFabien DESSENNE rctx->mode &= FLG_MODE_MASK;
16859e054ec2SFabien DESSENNE
16869e054ec2SFabien DESSENNE cryp->flags = (cryp->flags & ~FLG_MODE_MASK) | rctx->mode;
16879e054ec2SFabien DESSENNE cryp->hw_blocksize = is_aes(cryp) ? AES_BLOCK_SIZE : DES_BLOCK_SIZE;
16889e054ec2SFabien DESSENNE cryp->ctx = ctx;
16899e054ec2SFabien DESSENNE
16909d3b5030SFabien DESSENNE if (req) {
16919e054ec2SFabien DESSENNE cryp->req = req;
169229aed438SLionel Debieve cryp->areq = NULL;
16934b898d5cSNicolas Toromanoff cryp->header_in = 0;
16944b898d5cSNicolas Toromanoff cryp->payload_in = req->cryptlen;
16954b898d5cSNicolas Toromanoff cryp->payload_out = req->cryptlen;
16964b898d5cSNicolas Toromanoff cryp->authsize = 0;
1697fb11a4f6SMaxime Méré
1698fb11a4f6SMaxime Méré in_sg = req->src;
1699fb11a4f6SMaxime Méré out_sg = req->dst;
1700fb11a4f6SMaxime Méré
1701fb11a4f6SMaxime Méré ret = stm32_cryp_cipher_prepare(cryp, in_sg, out_sg);
1702fb11a4f6SMaxime Méré if (ret)
1703fb11a4f6SMaxime Méré return ret;
1704fb11a4f6SMaxime Méré
1705fb11a4f6SMaxime Méré ret = stm32_cryp_hw_init(cryp);
17069d3b5030SFabien DESSENNE } else {
17079d3b5030SFabien DESSENNE /*
17089d3b5030SFabien DESSENNE * Length of input and output data:
17099d3b5030SFabien DESSENNE * Encryption case:
17109d3b5030SFabien DESSENNE * INPUT = AssocData || PlainText
17119d3b5030SFabien DESSENNE * <- assoclen -> <- cryptlen ->
17129d3b5030SFabien DESSENNE *
17139d3b5030SFabien DESSENNE * OUTPUT = AssocData || CipherText || AuthTag
17144b898d5cSNicolas Toromanoff * <- assoclen -> <-- cryptlen --> <- authsize ->
17159d3b5030SFabien DESSENNE *
17169d3b5030SFabien DESSENNE * Decryption case:
17174b898d5cSNicolas Toromanoff * INPUT = AssocData || CipherTex || AuthTag
17184b898d5cSNicolas Toromanoff * <- assoclen ---> <---------- cryptlen ---------->
17199d3b5030SFabien DESSENNE *
17209d3b5030SFabien DESSENNE * OUTPUT = AssocData || PlainText
17214b898d5cSNicolas Toromanoff * <- assoclen -> <- cryptlen - authsize ->
17229d3b5030SFabien DESSENNE */
17239d3b5030SFabien DESSENNE cryp->areq = areq;
172429aed438SLionel Debieve cryp->req = NULL;
17259d3b5030SFabien DESSENNE cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq));
17264b898d5cSNicolas Toromanoff if (is_encrypt(cryp)) {
17274b898d5cSNicolas Toromanoff cryp->payload_in = areq->cryptlen;
17284b898d5cSNicolas Toromanoff cryp->header_in = areq->assoclen;
17294b898d5cSNicolas Toromanoff cryp->payload_out = areq->cryptlen;
17304b898d5cSNicolas Toromanoff } else {
17314b898d5cSNicolas Toromanoff cryp->payload_in = areq->cryptlen - cryp->authsize;
17324b898d5cSNicolas Toromanoff cryp->header_in = areq->assoclen;
17334b898d5cSNicolas Toromanoff cryp->payload_out = cryp->payload_in;
17344b898d5cSNicolas Toromanoff }
17359e054ec2SFabien DESSENNE
1736fb11a4f6SMaxime Méré in_sg = areq->src;
1737fb11a4f6SMaxime Méré out_sg = areq->dst;
1738fb11a4f6SMaxime Méré
17394b898d5cSNicolas Toromanoff scatterwalk_start(&cryp->in_walk, in_sg);
1740fb11a4f6SMaxime Méré scatterwalk_start(&cryp->out_walk, out_sg);
17419d3b5030SFabien DESSENNE /* In output, jump after assoc data */
17424b898d5cSNicolas Toromanoff scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->areq->assoclen, 2);
17434b898d5cSNicolas Toromanoff
17449e054ec2SFabien DESSENNE ret = stm32_cryp_hw_init(cryp);
1745fb11a4f6SMaxime Méré if (ret)
1746fb11a4f6SMaxime Méré return ret;
1747fb11a4f6SMaxime Méré
1748fb11a4f6SMaxime Méré ret = stm32_cryp_aead_prepare(cryp, in_sg, out_sg);
1749fb11a4f6SMaxime Méré }
1750fb11a4f6SMaxime Méré
17519e054ec2SFabien DESSENNE return ret;
17529e054ec2SFabien DESSENNE }
17539e054ec2SFabien DESSENNE
stm32_cryp_cipher_one_req(struct crypto_engine * engine,void * areq)1754dc7bcef5SCorentin LABBE static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq)
17559e054ec2SFabien DESSENNE {
175647ece481SArd Biesheuvel struct skcipher_request *req = container_of(areq,
175747ece481SArd Biesheuvel struct skcipher_request,
1758dc7bcef5SCorentin LABBE base);
175947ece481SArd Biesheuvel struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(
176047ece481SArd Biesheuvel crypto_skcipher_reqtfm(req));
17619e054ec2SFabien DESSENNE struct stm32_cryp *cryp = ctx->cryp;
1762fb11a4f6SMaxime Méré int ret;
17639e054ec2SFabien DESSENNE
17649e054ec2SFabien DESSENNE if (!cryp)
17659e054ec2SFabien DESSENNE return -ENODEV;
17669e054ec2SFabien DESSENNE
1767fb11a4f6SMaxime Méré ret = stm32_cryp_prepare_req(req, NULL);
1768fb11a4f6SMaxime Méré if (ret)
1769fb11a4f6SMaxime Méré return ret;
1770fb11a4f6SMaxime Méré
1771fb11a4f6SMaxime Méré if (cryp->flags & FLG_IN_OUT_DMA)
1772fb11a4f6SMaxime Méré ret = stm32_cryp_dma_start(cryp);
1773fb11a4f6SMaxime Méré else
1774fb11a4f6SMaxime Méré ret = stm32_cryp_it_start(cryp);
1775fb11a4f6SMaxime Méré
1776fb11a4f6SMaxime Méré if (ret == -ETIMEDOUT)
1777fb11a4f6SMaxime Méré stm32_cryp_finish_req(cryp, ret);
1778fb11a4f6SMaxime Méré
1779fb11a4f6SMaxime Méré return ret;
17809d3b5030SFabien DESSENNE }
17819d3b5030SFabien DESSENNE
stm32_cryp_aead_one_req(struct crypto_engine * engine,void * areq)17829d3b5030SFabien DESSENNE static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq)
17839d3b5030SFabien DESSENNE {
17849d3b5030SFabien DESSENNE struct aead_request *req = container_of(areq, struct aead_request,
17859d3b5030SFabien DESSENNE base);
17869d3b5030SFabien DESSENNE struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
17879d3b5030SFabien DESSENNE struct stm32_cryp *cryp = ctx->cryp;
17886912b79dSHerbert Xu int err;
17899d3b5030SFabien DESSENNE
17909d3b5030SFabien DESSENNE if (!cryp)
17919d3b5030SFabien DESSENNE return -ENODEV;
17929d3b5030SFabien DESSENNE
17936912b79dSHerbert Xu err = stm32_cryp_prepare_req(NULL, req);
17946912b79dSHerbert Xu if (err)
17956912b79dSHerbert Xu return err;
17966912b79dSHerbert Xu
1797fb11a4f6SMaxime Méré if (!stm32_cryp_get_input_text_len(cryp) && !cryp->header_in &&
1798fb11a4f6SMaxime Méré !(cryp->flags & FLG_HEADER_DMA)) {
17999d3b5030SFabien DESSENNE /* No input data to process: get tag and finish */
18009d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0);
18019d3b5030SFabien DESSENNE return 0;
18029d3b5030SFabien DESSENNE }
18039d3b5030SFabien DESSENNE
1804fb11a4f6SMaxime Méré if (cryp->flags & FLG_HEADER_DMA)
1805fb11a4f6SMaxime Méré return stm32_cryp_header_dma_start(cryp);
1806fb11a4f6SMaxime Méré
1807fb11a4f6SMaxime Méré if (!cryp->header_in && cryp->flags & FLG_IN_OUT_DMA)
1808fb11a4f6SMaxime Méré return stm32_cryp_dma_start(cryp);
1809fb11a4f6SMaxime Méré
1810fb11a4f6SMaxime Méré return stm32_cryp_it_start(cryp);
18119d3b5030SFabien DESSENNE }
18129d3b5030SFabien DESSENNE
stm32_cryp_read_auth_tag(struct stm32_cryp * cryp)18139d3b5030SFabien DESSENNE static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp)
18149d3b5030SFabien DESSENNE {
18154b898d5cSNicolas Toromanoff u32 cfg, size_bit;
18164b898d5cSNicolas Toromanoff unsigned int i;
18179d3b5030SFabien DESSENNE int ret = 0;
18189d3b5030SFabien DESSENNE
18199d3b5030SFabien DESSENNE /* Update Config */
18200b496efbSLinus Walleij cfg = stm32_cryp_read(cryp, cryp->caps->cr);
18219d3b5030SFabien DESSENNE
18229d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK;
18239d3b5030SFabien DESSENNE cfg |= CR_PH_FINAL;
18249d3b5030SFabien DESSENNE cfg &= ~CR_DEC_NOT_ENC;
18259d3b5030SFabien DESSENNE cfg |= CR_CRYPEN;
18269d3b5030SFabien DESSENNE
18270b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
18289d3b5030SFabien DESSENNE
18299d3b5030SFabien DESSENNE if (is_gcm(cryp)) {
18309d3b5030SFabien DESSENNE /* GCM: write aad and payload size (in bits) */
18319d3b5030SFabien DESSENNE size_bit = cryp->areq->assoclen * 8;
18329d3b5030SFabien DESSENNE if (cryp->caps->swap_final)
1833bbb28326SHerbert Xu size_bit = (__force u32)cpu_to_be32(size_bit);
18349d3b5030SFabien DESSENNE
18350b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, 0);
18360b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, size_bit);
18379d3b5030SFabien DESSENNE
18389d3b5030SFabien DESSENNE size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen :
18394b898d5cSNicolas Toromanoff cryp->areq->cryptlen - cryp->authsize;
18409d3b5030SFabien DESSENNE size_bit *= 8;
18419d3b5030SFabien DESSENNE if (cryp->caps->swap_final)
1842bbb28326SHerbert Xu size_bit = (__force u32)cpu_to_be32(size_bit);
18439d3b5030SFabien DESSENNE
18440b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, 0);
18450b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, size_bit);
18469d3b5030SFabien DESSENNE } else {
18479d3b5030SFabien DESSENNE /* CCM: write CTR0 */
18484b898d5cSNicolas Toromanoff u32 iv32[AES_BLOCK_32];
18494b898d5cSNicolas Toromanoff u8 *iv = (u8 *)iv32;
18504b898d5cSNicolas Toromanoff __be32 *biv = (__be32 *)iv32;
18519d3b5030SFabien DESSENNE
18529d3b5030SFabien DESSENNE memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE);
18539d3b5030SFabien DESSENNE memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1);
18549d3b5030SFabien DESSENNE
18559d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++) {
1856bbb28326SHerbert Xu u32 xiv = iv32[i];
1857bbb28326SHerbert Xu
18589d3b5030SFabien DESSENNE if (!cryp->caps->padding_wa)
1859bbb28326SHerbert Xu xiv = be32_to_cpu(biv[i]);
18600b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, xiv);
18619d3b5030SFabien DESSENNE }
18629d3b5030SFabien DESSENNE }
18639d3b5030SFabien DESSENNE
18649d3b5030SFabien DESSENNE /* Wait for output data */
18659d3b5030SFabien DESSENNE ret = stm32_cryp_wait_output(cryp);
18669d3b5030SFabien DESSENNE if (ret) {
18679d3b5030SFabien DESSENNE dev_err(cryp->dev, "Timeout (read tag)\n");
18689d3b5030SFabien DESSENNE return ret;
18699d3b5030SFabien DESSENNE }
18709d3b5030SFabien DESSENNE
18719d3b5030SFabien DESSENNE if (is_encrypt(cryp)) {
18724b898d5cSNicolas Toromanoff u32 out_tag[AES_BLOCK_32];
18734b898d5cSNicolas Toromanoff
18749d3b5030SFabien DESSENNE /* Get and write tag */
1875319ad16dSLinus Walleij readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
18764b898d5cSNicolas Toromanoff scatterwalk_copychunks(out_tag, &cryp->out_walk, cryp->authsize, 1);
18779d3b5030SFabien DESSENNE } else {
18789d3b5030SFabien DESSENNE /* Get and check tag */
18799d3b5030SFabien DESSENNE u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32];
18809d3b5030SFabien DESSENNE
18814b898d5cSNicolas Toromanoff scatterwalk_copychunks(in_tag, &cryp->in_walk, cryp->authsize, 0);
1882319ad16dSLinus Walleij readsl(cryp->regs + cryp->caps->dout, out_tag, AES_BLOCK_32);
18839d3b5030SFabien DESSENNE
18849d3b5030SFabien DESSENNE if (crypto_memneq(in_tag, out_tag, cryp->authsize))
18859d3b5030SFabien DESSENNE ret = -EBADMSG;
18869d3b5030SFabien DESSENNE }
18879d3b5030SFabien DESSENNE
18889d3b5030SFabien DESSENNE /* Disable cryp */
18899d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN;
18900b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
18919d3b5030SFabien DESSENNE
18929d3b5030SFabien DESSENNE return ret;
18939d3b5030SFabien DESSENNE }
18949d3b5030SFabien DESSENNE
stm32_cryp_check_ctr_counter(struct stm32_cryp * cryp)18959e054ec2SFabien DESSENNE static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp)
18969e054ec2SFabien DESSENNE {
18979e054ec2SFabien DESSENNE u32 cr;
18989e054ec2SFabien DESSENNE
189941c76690SNicolas Toromanoff if (unlikely(cryp->last_ctr[3] == cpu_to_be32(0xFFFFFFFF))) {
190041c76690SNicolas Toromanoff /*
190141c76690SNicolas Toromanoff * In this case, we need to increment manually the ctr counter,
190241c76690SNicolas Toromanoff * as HW doesn't handle the U32 carry.
190341c76690SNicolas Toromanoff */
190441c76690SNicolas Toromanoff crypto_inc((u8 *)cryp->last_ctr, sizeof(cryp->last_ctr));
19059e054ec2SFabien DESSENNE
19060b496efbSLinus Walleij cr = stm32_cryp_read(cryp, cryp->caps->cr);
19070b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cr & ~CR_CRYPEN);
19089e054ec2SFabien DESSENNE
190941c76690SNicolas Toromanoff stm32_cryp_hw_write_iv(cryp, cryp->last_ctr);
19109e054ec2SFabien DESSENNE
19110b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cr);
19129e054ec2SFabien DESSENNE }
19139e054ec2SFabien DESSENNE
191441c76690SNicolas Toromanoff /* The IV registers are BE */
19150b496efbSLinus Walleij cryp->last_ctr[0] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0l));
19160b496efbSLinus Walleij cryp->last_ctr[1] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv0r));
19170b496efbSLinus Walleij cryp->last_ctr[2] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1l));
19180b496efbSLinus Walleij cryp->last_ctr[3] = cpu_to_be32(stm32_cryp_read(cryp, cryp->caps->iv1r));
19199e054ec2SFabien DESSENNE }
19209e054ec2SFabien DESSENNE
stm32_cryp_irq_read_data(struct stm32_cryp * cryp)19214b898d5cSNicolas Toromanoff static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp)
19229e054ec2SFabien DESSENNE {
19234b898d5cSNicolas Toromanoff u32 block[AES_BLOCK_32];
19249d3b5030SFabien DESSENNE
1925319ad16dSLinus Walleij readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
19264b898d5cSNicolas Toromanoff scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
19274b898d5cSNicolas Toromanoff cryp->payload_out), 1);
19284b898d5cSNicolas Toromanoff cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
19294b898d5cSNicolas Toromanoff cryp->payload_out);
19309e054ec2SFabien DESSENNE }
19319e054ec2SFabien DESSENNE
stm32_cryp_irq_write_block(struct stm32_cryp * cryp)19329e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
19339e054ec2SFabien DESSENNE {
19344b898d5cSNicolas Toromanoff u32 block[AES_BLOCK_32] = {0};
19359d3b5030SFabien DESSENNE
19364b898d5cSNicolas Toromanoff scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, cryp->hw_blocksize,
19374b898d5cSNicolas Toromanoff cryp->payload_in), 0);
1938319ad16dSLinus Walleij writesl(cryp->regs + cryp->caps->din, block, cryp->hw_blocksize / sizeof(u32));
19394b898d5cSNicolas Toromanoff cryp->payload_in -= min_t(size_t, cryp->hw_blocksize, cryp->payload_in);
19409e054ec2SFabien DESSENNE }
19419e054ec2SFabien DESSENNE
stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp * cryp)19429d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp)
19439d3b5030SFabien DESSENNE {
19449d3b5030SFabien DESSENNE int err;
19454b898d5cSNicolas Toromanoff u32 cfg, block[AES_BLOCK_32] = {0};
19469d3b5030SFabien DESSENNE unsigned int i;
19479d3b5030SFabien DESSENNE
19489d3b5030SFabien DESSENNE /* 'Special workaround' procedure described in the datasheet */
19499d3b5030SFabien DESSENNE
19509d3b5030SFabien DESSENNE /* a) disable ip */
19510b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, 0);
19520b496efbSLinus Walleij cfg = stm32_cryp_read(cryp, cryp->caps->cr);
19539d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN;
19540b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
19559d3b5030SFabien DESSENNE
19569d3b5030SFabien DESSENNE /* b) Update IV1R */
19570b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv1r, cryp->gcm_ctr - 2);
19589d3b5030SFabien DESSENNE
19599d3b5030SFabien DESSENNE /* c) change mode to CTR */
19609d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK;
19619d3b5030SFabien DESSENNE cfg |= CR_AES_CTR;
19620b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
19639d3b5030SFabien DESSENNE
19649d3b5030SFabien DESSENNE /* a) enable IP */
19659d3b5030SFabien DESSENNE cfg |= CR_CRYPEN;
19660b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
19679d3b5030SFabien DESSENNE
19689d3b5030SFabien DESSENNE /* b) pad and write the last block */
19699d3b5030SFabien DESSENNE stm32_cryp_irq_write_block(cryp);
19704b898d5cSNicolas Toromanoff /* wait end of process */
19719d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp);
19729d3b5030SFabien DESSENNE if (err) {
19734b898d5cSNicolas Toromanoff dev_err(cryp->dev, "Timeout (write gcm last data)\n");
19749d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err);
19759d3b5030SFabien DESSENNE }
19769d3b5030SFabien DESSENNE
19779d3b5030SFabien DESSENNE /* c) get and store encrypted data */
19784b898d5cSNicolas Toromanoff /*
19794b898d5cSNicolas Toromanoff * Same code as stm32_cryp_irq_read_data(), but we want to store
19804b898d5cSNicolas Toromanoff * block value
19814b898d5cSNicolas Toromanoff */
1982319ad16dSLinus Walleij readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
19834b898d5cSNicolas Toromanoff
19844b898d5cSNicolas Toromanoff scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
19854b898d5cSNicolas Toromanoff cryp->payload_out), 1);
19864b898d5cSNicolas Toromanoff cryp->payload_out -= min_t(size_t, cryp->hw_blocksize,
19874b898d5cSNicolas Toromanoff cryp->payload_out);
19889d3b5030SFabien DESSENNE
19899d3b5030SFabien DESSENNE /* d) change mode back to AES GCM */
19909d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK;
19919d3b5030SFabien DESSENNE cfg |= CR_AES_GCM;
19920b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
19939d3b5030SFabien DESSENNE
19949d3b5030SFabien DESSENNE /* e) change phase to Final */
19959d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK;
19969d3b5030SFabien DESSENNE cfg |= CR_PH_FINAL;
19970b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
19989d3b5030SFabien DESSENNE
19999d3b5030SFabien DESSENNE /* f) write padded data */
2000319ad16dSLinus Walleij writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
20019d3b5030SFabien DESSENNE
20029d3b5030SFabien DESSENNE /* g) Empty fifo out */
20039d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp);
20049d3b5030SFabien DESSENNE if (err) {
20054b898d5cSNicolas Toromanoff dev_err(cryp->dev, "Timeout (write gcm padded data)\n");
20069d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err);
20079d3b5030SFabien DESSENNE }
20089d3b5030SFabien DESSENNE
20099d3b5030SFabien DESSENNE for (i = 0; i < AES_BLOCK_32; i++)
20100b496efbSLinus Walleij stm32_cryp_read(cryp, cryp->caps->dout);
20119d3b5030SFabien DESSENNE
20129d3b5030SFabien DESSENNE /* h) run the he normal Final phase */
20139d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, 0);
20149d3b5030SFabien DESSENNE }
20159d3b5030SFabien DESSENNE
stm32_cryp_irq_set_npblb(struct stm32_cryp * cryp)20169d3b5030SFabien DESSENNE static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp)
20179d3b5030SFabien DESSENNE {
20184b898d5cSNicolas Toromanoff u32 cfg;
20199d3b5030SFabien DESSENNE
20209d3b5030SFabien DESSENNE /* disable ip, set NPBLB and reneable ip */
20210b496efbSLinus Walleij cfg = stm32_cryp_read(cryp, cryp->caps->cr);
20229d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN;
20230b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20249d3b5030SFabien DESSENNE
20254b898d5cSNicolas Toromanoff cfg |= (cryp->hw_blocksize - cryp->payload_in) << CR_NBPBL_SHIFT;
20269d3b5030SFabien DESSENNE cfg |= CR_CRYPEN;
20270b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20289d3b5030SFabien DESSENNE }
20299d3b5030SFabien DESSENNE
stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp * cryp)20309d3b5030SFabien DESSENNE static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp)
20319d3b5030SFabien DESSENNE {
20329d3b5030SFabien DESSENNE int err = 0;
20339d3b5030SFabien DESSENNE u32 cfg, iv1tmp;
20344b898d5cSNicolas Toromanoff u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32];
20354b898d5cSNicolas Toromanoff u32 block[AES_BLOCK_32] = {0};
20369d3b5030SFabien DESSENNE unsigned int i;
20379d3b5030SFabien DESSENNE
20389d3b5030SFabien DESSENNE /* 'Special workaround' procedure described in the datasheet */
20399d3b5030SFabien DESSENNE
20409d3b5030SFabien DESSENNE /* a) disable ip */
20410b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, 0);
20429d3b5030SFabien DESSENNE
20430b496efbSLinus Walleij cfg = stm32_cryp_read(cryp, cryp->caps->cr);
20449d3b5030SFabien DESSENNE cfg &= ~CR_CRYPEN;
20450b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20469d3b5030SFabien DESSENNE
20479d3b5030SFabien DESSENNE /* b) get IV1 from CRYP_CSGCMCCM7 */
20489d3b5030SFabien DESSENNE iv1tmp = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + 7 * 4);
20499d3b5030SFabien DESSENNE
20509d3b5030SFabien DESSENNE /* c) Load CRYP_CSGCMCCMxR */
20519d3b5030SFabien DESSENNE for (i = 0; i < ARRAY_SIZE(cstmp1); i++)
20529d3b5030SFabien DESSENNE cstmp1[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
20539d3b5030SFabien DESSENNE
20549d3b5030SFabien DESSENNE /* d) Write IV1R */
20550b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->iv1r, iv1tmp);
20569d3b5030SFabien DESSENNE
20579d3b5030SFabien DESSENNE /* e) change mode to CTR */
20589d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK;
20599d3b5030SFabien DESSENNE cfg |= CR_AES_CTR;
20600b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20619d3b5030SFabien DESSENNE
20629d3b5030SFabien DESSENNE /* a) enable IP */
20639d3b5030SFabien DESSENNE cfg |= CR_CRYPEN;
20640b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20659d3b5030SFabien DESSENNE
20669d3b5030SFabien DESSENNE /* b) pad and write the last block */
20679d3b5030SFabien DESSENNE stm32_cryp_irq_write_block(cryp);
20684b898d5cSNicolas Toromanoff /* wait end of process */
20699d3b5030SFabien DESSENNE err = stm32_cryp_wait_output(cryp);
20709d3b5030SFabien DESSENNE if (err) {
2071be7f5ef9SColin Ian King dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
20729d3b5030SFabien DESSENNE return stm32_cryp_finish_req(cryp, err);
20739d3b5030SFabien DESSENNE }
20749d3b5030SFabien DESSENNE
20759d3b5030SFabien DESSENNE /* c) get and store decrypted data */
20764b898d5cSNicolas Toromanoff /*
20774b898d5cSNicolas Toromanoff * Same code as stm32_cryp_irq_read_data(), but we want to store
20784b898d5cSNicolas Toromanoff * block value
20794b898d5cSNicolas Toromanoff */
2080319ad16dSLinus Walleij readsl(cryp->regs + cryp->caps->dout, block, cryp->hw_blocksize / sizeof(u32));
20819d3b5030SFabien DESSENNE
20824b898d5cSNicolas Toromanoff scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize,
20834b898d5cSNicolas Toromanoff cryp->payload_out), 1);
20844b898d5cSNicolas Toromanoff cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, cryp->payload_out);
20859d3b5030SFabien DESSENNE
20869d3b5030SFabien DESSENNE /* d) Load again CRYP_CSGCMCCMxR */
20879d3b5030SFabien DESSENNE for (i = 0; i < ARRAY_SIZE(cstmp2); i++)
20889d3b5030SFabien DESSENNE cstmp2[i] = stm32_cryp_read(cryp, CRYP_CSGCMCCM0R + i * 4);
20899d3b5030SFabien DESSENNE
20909d3b5030SFabien DESSENNE /* e) change mode back to AES CCM */
20919d3b5030SFabien DESSENNE cfg &= ~CR_ALGO_MASK;
20929d3b5030SFabien DESSENNE cfg |= CR_AES_CCM;
20930b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20949d3b5030SFabien DESSENNE
20959d3b5030SFabien DESSENNE /* f) change phase to header */
20969d3b5030SFabien DESSENNE cfg &= ~CR_PH_MASK;
20979d3b5030SFabien DESSENNE cfg |= CR_PH_HEADER;
20980b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->cr, cfg);
20999d3b5030SFabien DESSENNE
21009d3b5030SFabien DESSENNE /* g) XOR and write padded data */
21014b898d5cSNicolas Toromanoff for (i = 0; i < ARRAY_SIZE(block); i++) {
21024b898d5cSNicolas Toromanoff block[i] ^= cstmp1[i];
21034b898d5cSNicolas Toromanoff block[i] ^= cstmp2[i];
21040b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->din, block[i]);
21059d3b5030SFabien DESSENNE }
21069d3b5030SFabien DESSENNE
21079d3b5030SFabien DESSENNE /* h) wait for completion */
21089d3b5030SFabien DESSENNE err = stm32_cryp_wait_busy(cryp);
21099d3b5030SFabien DESSENNE if (err)
2110be7f5ef9SColin Ian King dev_err(cryp->dev, "Timeout (write ccm padded data)\n");
21119d3b5030SFabien DESSENNE
21129d3b5030SFabien DESSENNE /* i) run the he normal Final phase */
21139d3b5030SFabien DESSENNE stm32_cryp_finish_req(cryp, err);
21149d3b5030SFabien DESSENNE }
21159d3b5030SFabien DESSENNE
stm32_cryp_irq_write_data(struct stm32_cryp * cryp)21169e054ec2SFabien DESSENNE static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp)
21179e054ec2SFabien DESSENNE {
21184b898d5cSNicolas Toromanoff if (unlikely(!cryp->payload_in)) {
21199e054ec2SFabien DESSENNE dev_warn(cryp->dev, "No more data to process\n");
21209e054ec2SFabien DESSENNE return;
21219e054ec2SFabien DESSENNE }
21229e054ec2SFabien DESSENNE
21234b898d5cSNicolas Toromanoff if (unlikely(cryp->payload_in < AES_BLOCK_SIZE &&
21249d3b5030SFabien DESSENNE (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) &&
21259d3b5030SFabien DESSENNE is_encrypt(cryp))) {
21269d3b5030SFabien DESSENNE /* Padding for AES GCM encryption */
21274b898d5cSNicolas Toromanoff if (cryp->caps->padding_wa) {
21289d3b5030SFabien DESSENNE /* Special case 1 */
21294b898d5cSNicolas Toromanoff stm32_cryp_irq_write_gcm_padded_data(cryp);
21304b898d5cSNicolas Toromanoff return;
21314b898d5cSNicolas Toromanoff }
21329d3b5030SFabien DESSENNE
21339d3b5030SFabien DESSENNE /* Setting padding bytes (NBBLB) */
21349d3b5030SFabien DESSENNE stm32_cryp_irq_set_npblb(cryp);
21359d3b5030SFabien DESSENNE }
21369d3b5030SFabien DESSENNE
21374b898d5cSNicolas Toromanoff if (unlikely((cryp->payload_in < AES_BLOCK_SIZE) &&
21389d3b5030SFabien DESSENNE (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) &&
21399d3b5030SFabien DESSENNE is_decrypt(cryp))) {
21409d3b5030SFabien DESSENNE /* Padding for AES CCM decryption */
21414b898d5cSNicolas Toromanoff if (cryp->caps->padding_wa) {
21429d3b5030SFabien DESSENNE /* Special case 2 */
21434b898d5cSNicolas Toromanoff stm32_cryp_irq_write_ccm_padded_data(cryp);
21444b898d5cSNicolas Toromanoff return;
21454b898d5cSNicolas Toromanoff }
21469d3b5030SFabien DESSENNE
21479d3b5030SFabien DESSENNE /* Setting padding bytes (NBBLB) */
21489d3b5030SFabien DESSENNE stm32_cryp_irq_set_npblb(cryp);
21499d3b5030SFabien DESSENNE }
21509d3b5030SFabien DESSENNE
21519e054ec2SFabien DESSENNE if (is_aes(cryp) && is_ctr(cryp))
21529e054ec2SFabien DESSENNE stm32_cryp_check_ctr_counter(cryp);
21539e054ec2SFabien DESSENNE
21549e054ec2SFabien DESSENNE stm32_cryp_irq_write_block(cryp);
21559e054ec2SFabien DESSENNE }
21569e054ec2SFabien DESSENNE
stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp * cryp)21574b898d5cSNicolas Toromanoff static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp)
21589d3b5030SFabien DESSENNE {
21594b898d5cSNicolas Toromanoff u32 block[AES_BLOCK_32] = {0};
21604b898d5cSNicolas Toromanoff size_t written;
21619d3b5030SFabien DESSENNE
21624b898d5cSNicolas Toromanoff written = min_t(size_t, AES_BLOCK_SIZE, cryp->header_in);
21639d3b5030SFabien DESSENNE
21644b898d5cSNicolas Toromanoff scatterwalk_copychunks(block, &cryp->in_walk, written, 0);
2165319ad16dSLinus Walleij
2166319ad16dSLinus Walleij writesl(cryp->regs + cryp->caps->din, block, AES_BLOCK_32);
21679d3b5030SFabien DESSENNE
21684b898d5cSNicolas Toromanoff cryp->header_in -= written;
21699d3b5030SFabien DESSENNE
21704b898d5cSNicolas Toromanoff stm32_crypt_gcmccm_end_header(cryp);
21719d3b5030SFabien DESSENNE }
21729d3b5030SFabien DESSENNE
stm32_cryp_irq_thread(int irq,void * arg)21739e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg)
21749e054ec2SFabien DESSENNE {
21759e054ec2SFabien DESSENNE struct stm32_cryp *cryp = arg;
21769d3b5030SFabien DESSENNE u32 ph;
21770b496efbSLinus Walleij u32 it_mask = stm32_cryp_read(cryp, cryp->caps->imsc);
21789e054ec2SFabien DESSENNE
21799e054ec2SFabien DESSENNE if (cryp->irq_status & MISR_OUT)
21809e054ec2SFabien DESSENNE /* Output FIFO IRQ: read data */
21814b898d5cSNicolas Toromanoff stm32_cryp_irq_read_data(cryp);
21829e054ec2SFabien DESSENNE
21839e054ec2SFabien DESSENNE if (cryp->irq_status & MISR_IN) {
21844b898d5cSNicolas Toromanoff if (is_gcm(cryp) || is_ccm(cryp)) {
21850b496efbSLinus Walleij ph = stm32_cryp_read(cryp, cryp->caps->cr) & CR_PH_MASK;
21869d3b5030SFabien DESSENNE if (unlikely(ph == CR_PH_HEADER))
21879d3b5030SFabien DESSENNE /* Write Header */
21884b898d5cSNicolas Toromanoff stm32_cryp_irq_write_gcmccm_header(cryp);
21899d3b5030SFabien DESSENNE else
21909e054ec2SFabien DESSENNE /* Input FIFO IRQ: write data */
21919e054ec2SFabien DESSENNE stm32_cryp_irq_write_data(cryp);
21924b898d5cSNicolas Toromanoff if (is_gcm(cryp))
21939d3b5030SFabien DESSENNE cryp->gcm_ctr++;
21949d3b5030SFabien DESSENNE } else {
21959d3b5030SFabien DESSENNE /* Input FIFO IRQ: write data */
21969d3b5030SFabien DESSENNE stm32_cryp_irq_write_data(cryp);
21979d3b5030SFabien DESSENNE }
21989e054ec2SFabien DESSENNE }
21999e054ec2SFabien DESSENNE
22004b898d5cSNicolas Toromanoff /* Mask useless interrupts */
22014b898d5cSNicolas Toromanoff if (!cryp->payload_in && !cryp->header_in)
22024b898d5cSNicolas Toromanoff it_mask &= ~IMSCR_IN;
22034b898d5cSNicolas Toromanoff if (!cryp->payload_out)
22044b898d5cSNicolas Toromanoff it_mask &= ~IMSCR_OUT;
22050b496efbSLinus Walleij stm32_cryp_write(cryp, cryp->caps->imsc, it_mask);
22064b898d5cSNicolas Toromanoff
2207*56ddb9aaSMaxime Méré if (!cryp->payload_in && !cryp->header_in && !cryp->payload_out) {
2208*56ddb9aaSMaxime Méré local_bh_disable();
22094b898d5cSNicolas Toromanoff stm32_cryp_finish_req(cryp, 0);
2210*56ddb9aaSMaxime Méré local_bh_enable();
2211*56ddb9aaSMaxime Méré }
22124b898d5cSNicolas Toromanoff
22139e054ec2SFabien DESSENNE return IRQ_HANDLED;
22149e054ec2SFabien DESSENNE }
22159e054ec2SFabien DESSENNE
stm32_cryp_irq(int irq,void * arg)22169e054ec2SFabien DESSENNE static irqreturn_t stm32_cryp_irq(int irq, void *arg)
22179e054ec2SFabien DESSENNE {
22189e054ec2SFabien DESSENNE struct stm32_cryp *cryp = arg;
22199e054ec2SFabien DESSENNE
22200b496efbSLinus Walleij cryp->irq_status = stm32_cryp_read(cryp, cryp->caps->mis);
22219e054ec2SFabien DESSENNE
22229e054ec2SFabien DESSENNE return IRQ_WAKE_THREAD;
22239e054ec2SFabien DESSENNE }
22249e054ec2SFabien DESSENNE
stm32_cryp_dma_init(struct stm32_cryp * cryp)2225fb11a4f6SMaxime Méré static int stm32_cryp_dma_init(struct stm32_cryp *cryp)
2226fb11a4f6SMaxime Méré {
2227fb11a4f6SMaxime Méré struct dma_slave_config dma_conf;
2228fb11a4f6SMaxime Méré struct dma_chan *chan;
2229fb11a4f6SMaxime Méré int ret;
2230fb11a4f6SMaxime Méré
2231fb11a4f6SMaxime Méré memset(&dma_conf, 0, sizeof(dma_conf));
2232fb11a4f6SMaxime Méré
2233fb11a4f6SMaxime Méré dma_conf.direction = DMA_MEM_TO_DEV;
2234fb11a4f6SMaxime Méré dma_conf.dst_addr = cryp->phys_base + cryp->caps->din;
2235fb11a4f6SMaxime Méré dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2236fb11a4f6SMaxime Méré dma_conf.dst_maxburst = CRYP_DMA_BURST_REG;
2237fb11a4f6SMaxime Méré dma_conf.device_fc = false;
2238fb11a4f6SMaxime Méré
2239fb11a4f6SMaxime Méré chan = dma_request_chan(cryp->dev, "in");
2240fb11a4f6SMaxime Méré if (IS_ERR(chan))
2241fb11a4f6SMaxime Méré return PTR_ERR(chan);
2242fb11a4f6SMaxime Méré
2243fb11a4f6SMaxime Méré cryp->dma_lch_in = chan;
2244fb11a4f6SMaxime Méré ret = dmaengine_slave_config(cryp->dma_lch_in, &dma_conf);
2245fb11a4f6SMaxime Méré if (ret) {
2246fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_in);
2247fb11a4f6SMaxime Méré cryp->dma_lch_in = NULL;
2248fb11a4f6SMaxime Méré dev_err(cryp->dev, "Couldn't configure DMA in slave.\n");
2249fb11a4f6SMaxime Méré return ret;
2250fb11a4f6SMaxime Méré }
2251fb11a4f6SMaxime Méré
2252fb11a4f6SMaxime Méré memset(&dma_conf, 0, sizeof(dma_conf));
2253fb11a4f6SMaxime Méré
2254fb11a4f6SMaxime Méré dma_conf.direction = DMA_DEV_TO_MEM;
2255fb11a4f6SMaxime Méré dma_conf.src_addr = cryp->phys_base + cryp->caps->dout;
2256fb11a4f6SMaxime Méré dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2257fb11a4f6SMaxime Méré dma_conf.src_maxburst = CRYP_DMA_BURST_REG;
2258fb11a4f6SMaxime Méré dma_conf.device_fc = false;
2259fb11a4f6SMaxime Méré
2260fb11a4f6SMaxime Méré chan = dma_request_chan(cryp->dev, "out");
2261fb11a4f6SMaxime Méré if (IS_ERR(chan)) {
2262fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_in);
2263fb11a4f6SMaxime Méré cryp->dma_lch_in = NULL;
2264fb11a4f6SMaxime Méré return PTR_ERR(chan);
2265fb11a4f6SMaxime Méré }
2266fb11a4f6SMaxime Méré
2267fb11a4f6SMaxime Méré cryp->dma_lch_out = chan;
2268fb11a4f6SMaxime Méré
2269fb11a4f6SMaxime Méré ret = dmaengine_slave_config(cryp->dma_lch_out, &dma_conf);
2270fb11a4f6SMaxime Méré if (ret) {
2271fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_out);
2272fb11a4f6SMaxime Méré cryp->dma_lch_out = NULL;
2273fb11a4f6SMaxime Méré dev_err(cryp->dev, "Couldn't configure DMA out slave.\n");
2274fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_in);
2275fb11a4f6SMaxime Méré cryp->dma_lch_in = NULL;
2276fb11a4f6SMaxime Méré return ret;
2277fb11a4f6SMaxime Méré }
2278fb11a4f6SMaxime Méré
2279fb11a4f6SMaxime Méré init_completion(&cryp->dma_completion);
2280fb11a4f6SMaxime Méré
2281fb11a4f6SMaxime Méré return 0;
2282fb11a4f6SMaxime Méré }
2283fb11a4f6SMaxime Méré
2284d5e6b48fSHerbert Xu static struct skcipher_engine_alg crypto_algs[] = {
22859e054ec2SFabien DESSENNE {
2286d5e6b48fSHerbert Xu .base = {
228747ece481SArd Biesheuvel .base.cra_name = "ecb(aes)",
228847ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-aes",
22896364352eSMaxime Méré .base.cra_priority = 300,
229040277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
229147ece481SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
229247ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
22934b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
229447ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
229547ece481SArd Biesheuvel
229647ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
22979e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE,
22989e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE,
22999e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey,
23009e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_ecb_encrypt,
23019e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_ecb_decrypt,
23029e054ec2SFabien DESSENNE },
2303d5e6b48fSHerbert Xu .op = {
2304d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2305d5e6b48fSHerbert Xu },
2306d5e6b48fSHerbert Xu },
23079e054ec2SFabien DESSENNE {
2308d5e6b48fSHerbert Xu .base = {
230947ece481SArd Biesheuvel .base.cra_name = "cbc(aes)",
231047ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-aes",
23116364352eSMaxime Méré .base.cra_priority = 300,
231240277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
231347ece481SArd Biesheuvel .base.cra_blocksize = AES_BLOCK_SIZE,
231447ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
23154b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
231647ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
231747ece481SArd Biesheuvel
231847ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
23199e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE,
23209e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE,
23219e054ec2SFabien DESSENNE .ivsize = AES_BLOCK_SIZE,
23229e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey,
23239e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_cbc_encrypt,
23249e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_cbc_decrypt,
23259e054ec2SFabien DESSENNE },
2326d5e6b48fSHerbert Xu .op = {
2327d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2328d5e6b48fSHerbert Xu },
2329d5e6b48fSHerbert Xu },
23309e054ec2SFabien DESSENNE {
2331d5e6b48fSHerbert Xu .base = {
233247ece481SArd Biesheuvel .base.cra_name = "ctr(aes)",
233347ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ctr-aes",
23346364352eSMaxime Méré .base.cra_priority = 300,
233540277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
233647ece481SArd Biesheuvel .base.cra_blocksize = 1,
233747ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
23384b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
233947ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
234047ece481SArd Biesheuvel
234147ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
23429e054ec2SFabien DESSENNE .min_keysize = AES_MIN_KEY_SIZE,
23439e054ec2SFabien DESSENNE .max_keysize = AES_MAX_KEY_SIZE,
23449e054ec2SFabien DESSENNE .ivsize = AES_BLOCK_SIZE,
23459e054ec2SFabien DESSENNE .setkey = stm32_cryp_aes_setkey,
23469e054ec2SFabien DESSENNE .encrypt = stm32_cryp_aes_ctr_encrypt,
23479e054ec2SFabien DESSENNE .decrypt = stm32_cryp_aes_ctr_decrypt,
23489e054ec2SFabien DESSENNE },
2349d5e6b48fSHerbert Xu .op = {
2350d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2351d5e6b48fSHerbert Xu },
2352d5e6b48fSHerbert Xu },
23539e054ec2SFabien DESSENNE {
2354d5e6b48fSHerbert Xu .base = {
235547ece481SArd Biesheuvel .base.cra_name = "ecb(des)",
235647ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-des",
23576364352eSMaxime Méré .base.cra_priority = 300,
235840277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
235947ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE,
236047ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
23614b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
236247ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
236347ece481SArd Biesheuvel
236447ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
23659e054ec2SFabien DESSENNE .min_keysize = DES_BLOCK_SIZE,
23669e054ec2SFabien DESSENNE .max_keysize = DES_BLOCK_SIZE,
23679e054ec2SFabien DESSENNE .setkey = stm32_cryp_des_setkey,
23689e054ec2SFabien DESSENNE .encrypt = stm32_cryp_des_ecb_encrypt,
23699e054ec2SFabien DESSENNE .decrypt = stm32_cryp_des_ecb_decrypt,
23709e054ec2SFabien DESSENNE },
2371d5e6b48fSHerbert Xu .op = {
2372d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2373d5e6b48fSHerbert Xu },
2374d5e6b48fSHerbert Xu },
23759e054ec2SFabien DESSENNE {
2376d5e6b48fSHerbert Xu .base = {
237747ece481SArd Biesheuvel .base.cra_name = "cbc(des)",
237847ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-des",
23796364352eSMaxime Méré .base.cra_priority = 300,
238040277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
238147ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE,
238247ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
23834b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
238447ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
238547ece481SArd Biesheuvel
238647ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
23879e054ec2SFabien DESSENNE .min_keysize = DES_BLOCK_SIZE,
23889e054ec2SFabien DESSENNE .max_keysize = DES_BLOCK_SIZE,
23899e054ec2SFabien DESSENNE .ivsize = DES_BLOCK_SIZE,
23909e054ec2SFabien DESSENNE .setkey = stm32_cryp_des_setkey,
23919e054ec2SFabien DESSENNE .encrypt = stm32_cryp_des_cbc_encrypt,
23929e054ec2SFabien DESSENNE .decrypt = stm32_cryp_des_cbc_decrypt,
23939e054ec2SFabien DESSENNE },
2394d5e6b48fSHerbert Xu .op = {
2395d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2396d5e6b48fSHerbert Xu },
2397d5e6b48fSHerbert Xu },
23989e054ec2SFabien DESSENNE {
2399d5e6b48fSHerbert Xu .base = {
240047ece481SArd Biesheuvel .base.cra_name = "ecb(des3_ede)",
240147ece481SArd Biesheuvel .base.cra_driver_name = "stm32-ecb-des3",
24026364352eSMaxime Méré .base.cra_priority = 300,
240340277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
240447ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE,
240547ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
24064b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
240747ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
240847ece481SArd Biesheuvel
240947ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
24109e054ec2SFabien DESSENNE .min_keysize = 3 * DES_BLOCK_SIZE,
24119e054ec2SFabien DESSENNE .max_keysize = 3 * DES_BLOCK_SIZE,
24129e054ec2SFabien DESSENNE .setkey = stm32_cryp_tdes_setkey,
24139e054ec2SFabien DESSENNE .encrypt = stm32_cryp_tdes_ecb_encrypt,
24149e054ec2SFabien DESSENNE .decrypt = stm32_cryp_tdes_ecb_decrypt,
24159e054ec2SFabien DESSENNE },
2416d5e6b48fSHerbert Xu .op = {
2417d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2418d5e6b48fSHerbert Xu },
2419d5e6b48fSHerbert Xu },
24209e054ec2SFabien DESSENNE {
2421d5e6b48fSHerbert Xu .base = {
242247ece481SArd Biesheuvel .base.cra_name = "cbc(des3_ede)",
242347ece481SArd Biesheuvel .base.cra_driver_name = "stm32-cbc-des3",
24246364352eSMaxime Méré .base.cra_priority = 300,
242540277252SMaxime Méré .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
242647ece481SArd Biesheuvel .base.cra_blocksize = DES_BLOCK_SIZE,
242747ece481SArd Biesheuvel .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx),
24284b898d5cSNicolas Toromanoff .base.cra_alignmask = 0,
242947ece481SArd Biesheuvel .base.cra_module = THIS_MODULE,
243047ece481SArd Biesheuvel
243147ece481SArd Biesheuvel .init = stm32_cryp_init_tfm,
24329e054ec2SFabien DESSENNE .min_keysize = 3 * DES_BLOCK_SIZE,
24339e054ec2SFabien DESSENNE .max_keysize = 3 * DES_BLOCK_SIZE,
24349e054ec2SFabien DESSENNE .ivsize = DES_BLOCK_SIZE,
24359e054ec2SFabien DESSENNE .setkey = stm32_cryp_tdes_setkey,
24369e054ec2SFabien DESSENNE .encrypt = stm32_cryp_tdes_cbc_encrypt,
24379e054ec2SFabien DESSENNE .decrypt = stm32_cryp_tdes_cbc_decrypt,
24389e054ec2SFabien DESSENNE },
2439d5e6b48fSHerbert Xu .op = {
2440d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_cipher_one_req,
2441d5e6b48fSHerbert Xu },
2442d5e6b48fSHerbert Xu },
24439e054ec2SFabien DESSENNE };
24449e054ec2SFabien DESSENNE
2445d5e6b48fSHerbert Xu static struct aead_engine_alg aead_algs[] = {
24469d3b5030SFabien DESSENNE {
2447d5e6b48fSHerbert Xu .base.setkey = stm32_cryp_aes_aead_setkey,
2448d5e6b48fSHerbert Xu .base.setauthsize = stm32_cryp_aes_gcm_setauthsize,
2449d5e6b48fSHerbert Xu .base.encrypt = stm32_cryp_aes_gcm_encrypt,
2450d5e6b48fSHerbert Xu .base.decrypt = stm32_cryp_aes_gcm_decrypt,
2451d5e6b48fSHerbert Xu .base.init = stm32_cryp_aes_aead_init,
2452d5e6b48fSHerbert Xu .base.ivsize = 12,
2453d5e6b48fSHerbert Xu .base.maxauthsize = AES_BLOCK_SIZE,
24549d3b5030SFabien DESSENNE
2455d5e6b48fSHerbert Xu .base.base = {
24569d3b5030SFabien DESSENNE .cra_name = "gcm(aes)",
24579d3b5030SFabien DESSENNE .cra_driver_name = "stm32-gcm-aes",
24586364352eSMaxime Méré .cra_priority = 300,
245940277252SMaxime Méré .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
24609d3b5030SFabien DESSENNE .cra_blocksize = 1,
24619d3b5030SFabien DESSENNE .cra_ctxsize = sizeof(struct stm32_cryp_ctx),
24624b898d5cSNicolas Toromanoff .cra_alignmask = 0,
24639d3b5030SFabien DESSENNE .cra_module = THIS_MODULE,
24649d3b5030SFabien DESSENNE },
2465d5e6b48fSHerbert Xu .op = {
2466d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_aead_one_req,
2467d5e6b48fSHerbert Xu },
24689d3b5030SFabien DESSENNE },
24699d3b5030SFabien DESSENNE {
2470d5e6b48fSHerbert Xu .base.setkey = stm32_cryp_aes_aead_setkey,
2471d5e6b48fSHerbert Xu .base.setauthsize = stm32_cryp_aes_ccm_setauthsize,
2472d5e6b48fSHerbert Xu .base.encrypt = stm32_cryp_aes_ccm_encrypt,
2473d5e6b48fSHerbert Xu .base.decrypt = stm32_cryp_aes_ccm_decrypt,
2474d5e6b48fSHerbert Xu .base.init = stm32_cryp_aes_aead_init,
2475d5e6b48fSHerbert Xu .base.ivsize = AES_BLOCK_SIZE,
2476d5e6b48fSHerbert Xu .base.maxauthsize = AES_BLOCK_SIZE,
24779d3b5030SFabien DESSENNE
2478d5e6b48fSHerbert Xu .base.base = {
24799d3b5030SFabien DESSENNE .cra_name = "ccm(aes)",
24809d3b5030SFabien DESSENNE .cra_driver_name = "stm32-ccm-aes",
24816364352eSMaxime Méré .cra_priority = 300,
248240277252SMaxime Méré .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY,
24839d3b5030SFabien DESSENNE .cra_blocksize = 1,
24849d3b5030SFabien DESSENNE .cra_ctxsize = sizeof(struct stm32_cryp_ctx),
24854b898d5cSNicolas Toromanoff .cra_alignmask = 0,
24869d3b5030SFabien DESSENNE .cra_module = THIS_MODULE,
24879d3b5030SFabien DESSENNE },
2488d5e6b48fSHerbert Xu .op = {
2489d5e6b48fSHerbert Xu .do_one_request = stm32_cryp_aead_one_req,
2490d5e6b48fSHerbert Xu },
24919d3b5030SFabien DESSENNE },
24929d3b5030SFabien DESSENNE };
24939d3b5030SFabien DESSENNE
24940b496efbSLinus Walleij static const struct stm32_cryp_caps ux500_data = {
24950b496efbSLinus Walleij .aeads_support = false,
24960b496efbSLinus Walleij .linear_aes_key = true,
24970b496efbSLinus Walleij .kp_mode = false,
24980b496efbSLinus Walleij .iv_protection = true,
24999d3b5030SFabien DESSENNE .swap_final = true,
25009d3b5030SFabien DESSENNE .padding_wa = true,
25010b496efbSLinus Walleij .cr = UX500_CRYP_CR,
25020b496efbSLinus Walleij .sr = UX500_CRYP_SR,
25030b496efbSLinus Walleij .din = UX500_CRYP_DIN,
25040b496efbSLinus Walleij .dout = UX500_CRYP_DOUT,
2505fb11a4f6SMaxime Méré .dmacr = UX500_CRYP_DMACR,
25060b496efbSLinus Walleij .imsc = UX500_CRYP_IMSC,
25070b496efbSLinus Walleij .mis = UX500_CRYP_MIS,
25080b496efbSLinus Walleij .k1l = UX500_CRYP_K1L,
25090b496efbSLinus Walleij .k1r = UX500_CRYP_K1R,
25100b496efbSLinus Walleij .k3r = UX500_CRYP_K3R,
25110b496efbSLinus Walleij .iv0l = UX500_CRYP_IV0L,
25120b496efbSLinus Walleij .iv0r = UX500_CRYP_IV0R,
25130b496efbSLinus Walleij .iv1l = UX500_CRYP_IV1L,
25140b496efbSLinus Walleij .iv1r = UX500_CRYP_IV1R,
25150b496efbSLinus Walleij };
25160b496efbSLinus Walleij
25170b496efbSLinus Walleij static const struct stm32_cryp_caps f7_data = {
25180b496efbSLinus Walleij .aeads_support = true,
25190b496efbSLinus Walleij .linear_aes_key = false,
25200b496efbSLinus Walleij .kp_mode = true,
25210b496efbSLinus Walleij .iv_protection = false,
25220b496efbSLinus Walleij .swap_final = true,
25230b496efbSLinus Walleij .padding_wa = true,
25240b496efbSLinus Walleij .cr = CRYP_CR,
25250b496efbSLinus Walleij .sr = CRYP_SR,
25260b496efbSLinus Walleij .din = CRYP_DIN,
25270b496efbSLinus Walleij .dout = CRYP_DOUT,
2528fb11a4f6SMaxime Méré .dmacr = CRYP_DMACR,
25290b496efbSLinus Walleij .imsc = CRYP_IMSCR,
25300b496efbSLinus Walleij .mis = CRYP_MISR,
25310b496efbSLinus Walleij .k1l = CRYP_K1LR,
25320b496efbSLinus Walleij .k1r = CRYP_K1RR,
25330b496efbSLinus Walleij .k3r = CRYP_K3RR,
25340b496efbSLinus Walleij .iv0l = CRYP_IV0LR,
25350b496efbSLinus Walleij .iv0r = CRYP_IV0RR,
25360b496efbSLinus Walleij .iv1l = CRYP_IV1LR,
25370b496efbSLinus Walleij .iv1r = CRYP_IV1RR,
25389d3b5030SFabien DESSENNE };
25399d3b5030SFabien DESSENNE
2540a43a3484SFabien DESSENNE static const struct stm32_cryp_caps mp1_data = {
25410b496efbSLinus Walleij .aeads_support = true,
25420b496efbSLinus Walleij .linear_aes_key = false,
25430b496efbSLinus Walleij .kp_mode = true,
25440b496efbSLinus Walleij .iv_protection = false,
2545a43a3484SFabien DESSENNE .swap_final = false,
2546a43a3484SFabien DESSENNE .padding_wa = false,
25470b496efbSLinus Walleij .cr = CRYP_CR,
25480b496efbSLinus Walleij .sr = CRYP_SR,
25490b496efbSLinus Walleij .din = CRYP_DIN,
25500b496efbSLinus Walleij .dout = CRYP_DOUT,
2551fb11a4f6SMaxime Méré .dmacr = CRYP_DMACR,
25520b496efbSLinus Walleij .imsc = CRYP_IMSCR,
25530b496efbSLinus Walleij .mis = CRYP_MISR,
25540b496efbSLinus Walleij .k1l = CRYP_K1LR,
25550b496efbSLinus Walleij .k1r = CRYP_K1RR,
25560b496efbSLinus Walleij .k3r = CRYP_K3RR,
25570b496efbSLinus Walleij .iv0l = CRYP_IV0LR,
25580b496efbSLinus Walleij .iv0r = CRYP_IV0RR,
25590b496efbSLinus Walleij .iv1l = CRYP_IV1LR,
25600b496efbSLinus Walleij .iv1r = CRYP_IV1RR,
2561a43a3484SFabien DESSENNE };
2562a43a3484SFabien DESSENNE
25639e054ec2SFabien DESSENNE static const struct of_device_id stm32_dt_ids[] = {
25640b496efbSLinus Walleij { .compatible = "stericsson,ux500-cryp", .data = &ux500_data},
25659d3b5030SFabien DESSENNE { .compatible = "st,stm32f756-cryp", .data = &f7_data},
2566a43a3484SFabien DESSENNE { .compatible = "st,stm32mp1-cryp", .data = &mp1_data},
25679e054ec2SFabien DESSENNE {},
25689e054ec2SFabien DESSENNE };
2569761a6982SCorentin LABBE MODULE_DEVICE_TABLE(of, stm32_dt_ids);
25709e054ec2SFabien DESSENNE
stm32_cryp_probe(struct platform_device * pdev)25719e054ec2SFabien DESSENNE static int stm32_cryp_probe(struct platform_device *pdev)
25729e054ec2SFabien DESSENNE {
25739e054ec2SFabien DESSENNE struct device *dev = &pdev->dev;
25749e054ec2SFabien DESSENNE struct stm32_cryp *cryp;
25759e054ec2SFabien DESSENNE struct reset_control *rst;
25769e054ec2SFabien DESSENNE int irq, ret;
25779e054ec2SFabien DESSENNE
25789e054ec2SFabien DESSENNE cryp = devm_kzalloc(dev, sizeof(*cryp), GFP_KERNEL);
25799e054ec2SFabien DESSENNE if (!cryp)
25809e054ec2SFabien DESSENNE return -ENOMEM;
25819e054ec2SFabien DESSENNE
25829d3b5030SFabien DESSENNE cryp->caps = of_device_get_match_data(dev);
25839d3b5030SFabien DESSENNE if (!cryp->caps)
25849d3b5030SFabien DESSENNE return -ENODEV;
25859d3b5030SFabien DESSENNE
25869e054ec2SFabien DESSENNE cryp->dev = dev;
25879e054ec2SFabien DESSENNE
2588473b4d99SYueHaibing cryp->regs = devm_platform_ioremap_resource(pdev, 0);
258960bcf265Sweiyongjun \(A\) if (IS_ERR(cryp->regs))
25909e054ec2SFabien DESSENNE return PTR_ERR(cryp->regs);
25919e054ec2SFabien DESSENNE
2592fb11a4f6SMaxime Méré cryp->phys_base = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start;
2593fb11a4f6SMaxime Méré
25949e054ec2SFabien DESSENNE irq = platform_get_irq(pdev, 0);
2595514838e9SStephen Boyd if (irq < 0)
25969e054ec2SFabien DESSENNE return irq;
25979e054ec2SFabien DESSENNE
25989e054ec2SFabien DESSENNE ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq,
25999e054ec2SFabien DESSENNE stm32_cryp_irq_thread, IRQF_ONESHOT,
26009e054ec2SFabien DESSENNE dev_name(dev), cryp);
26019e054ec2SFabien DESSENNE if (ret) {
26029e054ec2SFabien DESSENNE dev_err(dev, "Cannot grab IRQ\n");
26039e054ec2SFabien DESSENNE return ret;
26049e054ec2SFabien DESSENNE }
26059e054ec2SFabien DESSENNE
26069e054ec2SFabien DESSENNE cryp->clk = devm_clk_get(dev, NULL);
26079e054ec2SFabien DESSENNE if (IS_ERR(cryp->clk)) {
2608029812aeSEtienne Carriere dev_err_probe(dev, PTR_ERR(cryp->clk), "Could not get clock\n");
2609029812aeSEtienne Carriere
26109e054ec2SFabien DESSENNE return PTR_ERR(cryp->clk);
26119e054ec2SFabien DESSENNE }
26129e054ec2SFabien DESSENNE
26139e054ec2SFabien DESSENNE ret = clk_prepare_enable(cryp->clk);
26149e054ec2SFabien DESSENNE if (ret) {
26159e054ec2SFabien DESSENNE dev_err(cryp->dev, "Failed to enable clock\n");
26169e054ec2SFabien DESSENNE return ret;
26179e054ec2SFabien DESSENNE }
26189e054ec2SFabien DESSENNE
261965f9aa36Slionel.debieve@st.com pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY);
262065f9aa36Slionel.debieve@st.com pm_runtime_use_autosuspend(dev);
262165f9aa36Slionel.debieve@st.com
262265f9aa36Slionel.debieve@st.com pm_runtime_get_noresume(dev);
262365f9aa36Slionel.debieve@st.com pm_runtime_set_active(dev);
262465f9aa36Slionel.debieve@st.com pm_runtime_enable(dev);
262565f9aa36Slionel.debieve@st.com
26269e054ec2SFabien DESSENNE rst = devm_reset_control_get(dev, NULL);
26270a2f9f57SEtienne Carriere if (IS_ERR(rst)) {
26280a2f9f57SEtienne Carriere ret = PTR_ERR(rst);
26290a2f9f57SEtienne Carriere if (ret == -EPROBE_DEFER)
26300a2f9f57SEtienne Carriere goto err_rst;
26310a2f9f57SEtienne Carriere } else {
26329e054ec2SFabien DESSENNE reset_control_assert(rst);
26339e054ec2SFabien DESSENNE udelay(2);
26349e054ec2SFabien DESSENNE reset_control_deassert(rst);
26359e054ec2SFabien DESSENNE }
26369e054ec2SFabien DESSENNE
26379e054ec2SFabien DESSENNE platform_set_drvdata(pdev, cryp);
26389e054ec2SFabien DESSENNE
2639fb11a4f6SMaxime Méré ret = stm32_cryp_dma_init(cryp);
2640fb11a4f6SMaxime Méré switch (ret) {
2641fb11a4f6SMaxime Méré case 0:
2642fb11a4f6SMaxime Méré break;
2643fb11a4f6SMaxime Méré case -ENODEV:
2644fb11a4f6SMaxime Méré dev_dbg(dev, "DMA mode not available\n");
2645fb11a4f6SMaxime Méré break;
2646fb11a4f6SMaxime Méré default:
2647fb11a4f6SMaxime Méré goto err_dma;
2648fb11a4f6SMaxime Méré }
2649fb11a4f6SMaxime Méré
26509e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock);
26519e054ec2SFabien DESSENNE list_add(&cryp->list, &cryp_list.dev_list);
26529e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock);
26539e054ec2SFabien DESSENNE
26549e054ec2SFabien DESSENNE /* Initialize crypto engine */
26559e054ec2SFabien DESSENNE cryp->engine = crypto_engine_alloc_init(dev, 1);
26569e054ec2SFabien DESSENNE if (!cryp->engine) {
26579e054ec2SFabien DESSENNE dev_err(dev, "Could not init crypto engine\n");
26589e054ec2SFabien DESSENNE ret = -ENOMEM;
26599e054ec2SFabien DESSENNE goto err_engine1;
26609e054ec2SFabien DESSENNE }
26619e054ec2SFabien DESSENNE
26629e054ec2SFabien DESSENNE ret = crypto_engine_start(cryp->engine);
26639e054ec2SFabien DESSENNE if (ret) {
26649e054ec2SFabien DESSENNE dev_err(dev, "Could not start crypto engine\n");
26659e054ec2SFabien DESSENNE goto err_engine2;
26669e054ec2SFabien DESSENNE }
26679e054ec2SFabien DESSENNE
2668d5e6b48fSHerbert Xu ret = crypto_engine_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
26699e054ec2SFabien DESSENNE if (ret) {
26709e054ec2SFabien DESSENNE dev_err(dev, "Could not register algs\n");
26719e054ec2SFabien DESSENNE goto err_algs;
26729e054ec2SFabien DESSENNE }
26739e054ec2SFabien DESSENNE
26740b496efbSLinus Walleij if (cryp->caps->aeads_support) {
2675d5e6b48fSHerbert Xu ret = crypto_engine_register_aeads(aead_algs, ARRAY_SIZE(aead_algs));
26769d3b5030SFabien DESSENNE if (ret)
26779d3b5030SFabien DESSENNE goto err_aead_algs;
26780b496efbSLinus Walleij }
26799d3b5030SFabien DESSENNE
26809e054ec2SFabien DESSENNE dev_info(dev, "Initialized\n");
26819e054ec2SFabien DESSENNE
268265f9aa36Slionel.debieve@st.com pm_runtime_put_sync(dev);
268365f9aa36Slionel.debieve@st.com
26849e054ec2SFabien DESSENNE return 0;
26859e054ec2SFabien DESSENNE
26869d3b5030SFabien DESSENNE err_aead_algs:
2687d5e6b48fSHerbert Xu crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
26889e054ec2SFabien DESSENNE err_algs:
26899e054ec2SFabien DESSENNE err_engine2:
26909e054ec2SFabien DESSENNE crypto_engine_exit(cryp->engine);
26919e054ec2SFabien DESSENNE err_engine1:
26929e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock);
26939e054ec2SFabien DESSENNE list_del(&cryp->list);
26949e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock);
2695fb11a4f6SMaxime Méré
2696fb11a4f6SMaxime Méré if (cryp->dma_lch_in)
2697fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_in);
2698fb11a4f6SMaxime Méré if (cryp->dma_lch_out)
2699fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_out);
2700fb11a4f6SMaxime Méré err_dma:
27010a2f9f57SEtienne Carriere err_rst:
270265f9aa36Slionel.debieve@st.com pm_runtime_disable(dev);
270365f9aa36Slionel.debieve@st.com pm_runtime_put_noidle(dev);
270465f9aa36Slionel.debieve@st.com
27059e054ec2SFabien DESSENNE clk_disable_unprepare(cryp->clk);
27069e054ec2SFabien DESSENNE
27079e054ec2SFabien DESSENNE return ret;
27089e054ec2SFabien DESSENNE }
27099e054ec2SFabien DESSENNE
stm32_cryp_remove(struct platform_device * pdev)271088b01c8aSUwe Kleine-König static void stm32_cryp_remove(struct platform_device *pdev)
27119e054ec2SFabien DESSENNE {
27129e054ec2SFabien DESSENNE struct stm32_cryp *cryp = platform_get_drvdata(pdev);
271365f9aa36Slionel.debieve@st.com int ret;
27149e054ec2SFabien DESSENNE
271588b01c8aSUwe Kleine-König ret = pm_runtime_get_sync(cryp->dev);
271665f9aa36Slionel.debieve@st.com
27170b496efbSLinus Walleij if (cryp->caps->aeads_support)
2718d5e6b48fSHerbert Xu crypto_engine_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs));
2719d5e6b48fSHerbert Xu crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs));
27209e054ec2SFabien DESSENNE
27219e054ec2SFabien DESSENNE crypto_engine_exit(cryp->engine);
27229e054ec2SFabien DESSENNE
27239e054ec2SFabien DESSENNE spin_lock(&cryp_list.lock);
27249e054ec2SFabien DESSENNE list_del(&cryp->list);
27259e054ec2SFabien DESSENNE spin_unlock(&cryp_list.lock);
27269e054ec2SFabien DESSENNE
2727fb11a4f6SMaxime Méré if (cryp->dma_lch_in)
2728fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_in);
2729fb11a4f6SMaxime Méré
2730fb11a4f6SMaxime Méré if (cryp->dma_lch_out)
2731fb11a4f6SMaxime Méré dma_release_channel(cryp->dma_lch_out);
2732fb11a4f6SMaxime Méré
273365f9aa36Slionel.debieve@st.com pm_runtime_disable(cryp->dev);
273465f9aa36Slionel.debieve@st.com pm_runtime_put_noidle(cryp->dev);
273565f9aa36Slionel.debieve@st.com
273688b01c8aSUwe Kleine-König if (ret >= 0)
27379e054ec2SFabien DESSENNE clk_disable_unprepare(cryp->clk);
27389e054ec2SFabien DESSENNE }
27399e054ec2SFabien DESSENNE
274065f9aa36Slionel.debieve@st.com #ifdef CONFIG_PM
stm32_cryp_runtime_suspend(struct device * dev)274165f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_suspend(struct device *dev)
274265f9aa36Slionel.debieve@st.com {
274365f9aa36Slionel.debieve@st.com struct stm32_cryp *cryp = dev_get_drvdata(dev);
274465f9aa36Slionel.debieve@st.com
274565f9aa36Slionel.debieve@st.com clk_disable_unprepare(cryp->clk);
274665f9aa36Slionel.debieve@st.com
274765f9aa36Slionel.debieve@st.com return 0;
274865f9aa36Slionel.debieve@st.com }
274965f9aa36Slionel.debieve@st.com
stm32_cryp_runtime_resume(struct device * dev)275065f9aa36Slionel.debieve@st.com static int stm32_cryp_runtime_resume(struct device *dev)
275165f9aa36Slionel.debieve@st.com {
275265f9aa36Slionel.debieve@st.com struct stm32_cryp *cryp = dev_get_drvdata(dev);
275365f9aa36Slionel.debieve@st.com int ret;
275465f9aa36Slionel.debieve@st.com
275565f9aa36Slionel.debieve@st.com ret = clk_prepare_enable(cryp->clk);
275665f9aa36Slionel.debieve@st.com if (ret) {
275765f9aa36Slionel.debieve@st.com dev_err(cryp->dev, "Failed to prepare_enable clock\n");
275865f9aa36Slionel.debieve@st.com return ret;
275965f9aa36Slionel.debieve@st.com }
276065f9aa36Slionel.debieve@st.com
276165f9aa36Slionel.debieve@st.com return 0;
276265f9aa36Slionel.debieve@st.com }
276365f9aa36Slionel.debieve@st.com #endif
276465f9aa36Slionel.debieve@st.com
276565f9aa36Slionel.debieve@st.com static const struct dev_pm_ops stm32_cryp_pm_ops = {
276665f9aa36Slionel.debieve@st.com SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
276765f9aa36Slionel.debieve@st.com pm_runtime_force_resume)
276865f9aa36Slionel.debieve@st.com SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend,
276965f9aa36Slionel.debieve@st.com stm32_cryp_runtime_resume, NULL)
277065f9aa36Slionel.debieve@st.com };
277165f9aa36Slionel.debieve@st.com
27729e054ec2SFabien DESSENNE static struct platform_driver stm32_cryp_driver = {
27739e054ec2SFabien DESSENNE .probe = stm32_cryp_probe,
277488b01c8aSUwe Kleine-König .remove_new = stm32_cryp_remove,
27759e054ec2SFabien DESSENNE .driver = {
27769e054ec2SFabien DESSENNE .name = DRIVER_NAME,
277765f9aa36Slionel.debieve@st.com .pm = &stm32_cryp_pm_ops,
27789e054ec2SFabien DESSENNE .of_match_table = stm32_dt_ids,
27799e054ec2SFabien DESSENNE },
27809e054ec2SFabien DESSENNE };
27819e054ec2SFabien DESSENNE
27829e054ec2SFabien DESSENNE module_platform_driver(stm32_cryp_driver);
27839e054ec2SFabien DESSENNE
27849e054ec2SFabien DESSENNE MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
27859e054ec2SFabien DESSENNE MODULE_DESCRIPTION("STMicrolectronics STM32 CRYP hardware driver");
27869e054ec2SFabien DESSENNE MODULE_LICENSE("GPL");
2787