Re: [PATCH v5] crypto : stm32 - Add STM32F4 CRC32 support
Hi Cosar, Sorry for the delay to feedback. This implementation is in the good way. But it should be better to use platform data and use array with type of algs instead of duplicating the algo description for each platform. If we add a new platform, with another type of crc, we will again duplicate the section. This is how I did it in stm32-hash.c. BR, Lionel On 08/03/2017 03:46 PM, Cosar Dindar wrote: > This patch adds CRC (CRC32 Crypto) support for STM32F4 series. > > As an hardware limitation polynomial and key setting are not supported. > They are fixed as 0x4C11DB7 (poly) and 0x (key). > CRC32C Castagnoli algorithm is not used. > > Signed-off-by: Cosar Dindar > --- > Changes in v5: >- shash_alg struct definitons are defined seperately according to > the platform type. > Changes in v4: >- Edited patch summary. > Changes in v3: >- Rearranged patch order to fix build test error. > Changes in v2: >- Patchset created instead of one patch. > > drivers/crypto/stm32/stm32_crc32.c | 101 > - > 1 file changed, 89 insertions(+), 12 deletions(-) > > diff --git a/drivers/crypto/stm32/stm32_crc32.c > b/drivers/crypto/stm32/stm32_crc32.c > index ec83b1e..39b28b8 100644 > --- a/drivers/crypto/stm32/stm32_crc32.c > +++ b/drivers/crypto/stm32/stm32_crc32.c > @@ -1,12 +1,14 @@ > /* >* Copyright (C) STMicroelectronics SA 2017 >* Author: Fabien Dessenne > + * Author: Cosar Dindar >* License terms: GNU General Public License (GPL), version 2 >*/ > > #include > #include > #include > +#include > #include > > #include > @@ -37,8 +39,12 @@ struct stm32_crc { > struct device*dev; > void __iomem *regs; > struct clk *clk; > + struct shash_alg *algs; > u8 pending_data[sizeof(u32)]; > size_t nb_pending_bytes; > + bool key_support; > + bool poly_support; > + bool reverse_support; > }; > > struct stm32_crc_list { > @@ -106,13 +112,31 @@ static int stm32_crc_init(struct shash_desc *desc) > } > spin_unlock_bh(&crc_list.lock); > > - /* Reset, set key, poly and configure in bit reverse mode */ > - writel(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); > - writel(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); > - writel(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); > + /* set key */ > + if (ctx->crc->key_support) { > + writel(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); > + } else if (mctx->key != CRC_INIT_DEFAULT) { > + dev_err(ctx->crc->dev, "Unsupported key value! Should be: > 0x%x\n", > + CRC_INIT_DEFAULT); > + return -EINVAL; > + } > + > + /* set poly */ > + if (ctx->crc->poly_support) > + writel(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); > + > + /* reset and configure in bit reverse mode if supported */ > + if (ctx->crc->reverse_support) > + writel(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); > + else > + writel(CRC_CR_RESET, ctx->crc->regs + CRC_CR); > + > + /* store partial result */ > + if (!ctx->crc->reverse_support) > + ctx->partial = bitrev32(readl(crc->regs + CRC_DR)); > + else > + ctx->partial = readl(ctx->crc->regs + CRC_DR); > > - /* Store partial result */ > - ctx->partial = readl(ctx->crc->regs + CRC_DR); > ctx->crc->nb_pending_bytes = 0; > > return 0; > @@ -135,7 +159,12 @@ static int stm32_crc_update(struct shash_desc *desc, > const u8 *d8, > > if (crc->nb_pending_bytes == sizeof(u32)) { > /* Process completed pending data */ > - writel(*(u32 *)crc->pending_data, crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + writel(bitrev32(*(u32 *)crc->pending_data), > +crc->regs + CRC_DR); > + else > + writel(*(u32 *)crc->pending_data, > +crc->regs + CRC_DR); > crc->nb_pending_bytes = 0; > } > } > @@ -143,10 +172,16 @@ static int stm32_crc_update(struct shash_desc *desc, > const u8 *d8, > d32 = (u32 *)d8; > for (i = 0; i < length >> 2; i++) > /* Process 32 bits data */ > - writel(*(d32++), crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + writel(bitrev32(*(d32++)), crc->regs + CRC_DR); > + else > + writel(*(d32++), crc->regs + CRC_DR); > > /* Store partial result */ > - ctx->partial = readl(crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + ctx->partial = bitrev32(readl(crc->regs + CRC_DR)); > + else > +
[PATCH 1/1] crypto: stm32/hash - Remove uninitialized symbol
Remove err symbol as this is not used in the thread context and the variable is not initialized. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index b585ce5..b34ee85 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -1067,7 +1067,6 @@ static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm) static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) { struct stm32_hash_dev *hdev = dev_id; - int err; if (HASH_FLAGS_CPU & hdev->flags) { if (HASH_FLAGS_OUTPUT_READY & hdev->flags) { @@ -1084,8 +1083,8 @@ static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; finish: - /*Finish current request */ - stm32_hash_finish_req(hdev->req, err); + /* Finish current request */ + stm32_hash_finish_req(hdev->req, 0); return IRQ_HANDLED; } -- 2.7.4
Re: [PATCH 1/2] crypto: stm32 - Fix uninitialized data usage
Hi Arnd, I've already push this fix for review last month, waiting the ack. " From: Lionel Debieve To: Herbert Xu , "David S . Miller" , Maxime Coquelin , Alexandre Torgue , , , CC: Benjamin Gaignard , Fabien Dessenne , Ludovic Barre Subject: [PATCH 1/1] crypto: stm32/hash - Remove uninitialized symbol Date: Fri, 18 Aug 2017 15:54:01 +0200 " Sorry if you receive this mail twice, I didn't see any mail in the mailing list, maybe server issue. I'm reviewing your second part patch. BR, Lionel > On 09/12/2017 11:35 AM, Arnd Bergmann wrote: >> The error handling in stm32_hash_irq_thread passes >> uninitialized data into stm32_hash_finish_req, as gcc >> points out: >> drivers/crypto/stm32/stm32-hash.c: In function 'stm32_hash_irq_thread': >> drivers/crypto/stm32/stm32-hash.c:1088:2: error: 'err' may be used >> uninitialized in this function [-Werror=maybe-uninitialized] >> I could not tell what data should be passed there instead, >> so this changes the code to always pass zero, making it >> well-defined, though possibly still wrong. Please check. >> Signed-off-by: Arnd Bergmann >> --- >>drivers/crypto/stm32/stm32-hash.c | 3 +-- >>1 file changed, 1 insertion(+), 2 deletions(-) >> diff --git a/drivers/crypto/stm32/stm32-hash.c >> b/drivers/crypto/stm32/stm32-hash.c >> index b585ce54a802..3c23a23e9ee5 100644 >> --- a/drivers/crypto/stm32/stm32-hash.c >> +++ b/drivers/crypto/stm32/stm32-hash.c >> @@ -1067,7 +1067,6 @@ static int stm32_hash_cra_sha256_init(struct >> crypto_tfm *tfm) >>static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) >>{ >>struct stm32_hash_dev *hdev = dev_id; >> -int err; >> >>if (HASH_FLAGS_CPU & hdev->flags) { >>if (HASH_FLAGS_OUTPUT_READY & hdev->flags) { >> @@ -1085,7 +1084,7 @@ static irqreturn_t stm32_hash_irq_thread(int irq, void >> *dev_id) >> >>finish: >>/*Finish current request */ >> -stm32_hash_finish_req(hdev->req, err); >> +stm32_hash_finish_req(hdev->req, 0); >> >>return IRQ_HANDLED; >>} >
[PATCH 1/1] crypto: stm32/hash - Fix return issue in update
When update data reached the threshold for data processing, we must inform that processing is on going. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index c462be7..4ca4a26 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -895,7 +895,6 @@ static int stm32_hash_enqueue(struct ahash_request *req, unsigned int op) static int stm32_hash_update(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); - int ret; if (!req->nbytes || !(rctx->flags & HASH_FLAGS_CPU)) return 0; @@ -909,12 +908,7 @@ static int stm32_hash_update(struct ahash_request *req) return 0; } - ret = stm32_hash_enqueue(req, HASH_OP_UPDATE); - - if (rctx->flags & HASH_FLAGS_FINUP) - return ret; - - return 0; + return stm32_hash_enqueue(req, HASH_OP_UPDATE); } static int stm32_hash_final(struct ahash_request *req) -- 2.7.4
[PATCH 0/3] STM32 CRC update
This set of patches update the STM32 CRC driver. It contains two corrections and one global Kconfig rework. First correction is about the relaxed usage in scope of arm platform usage, second about a unbind driver issue. Last patch is about a Kconfig rework that make configuration generic for STM32 crypto algos, HASH and CRYP are pushed accordingly. Lionel Debieve (3): crypto: stm32 - CRC use relaxed function crypto: stm32 - solve crc issue during unbind crypto: stm32 - Rename module to use generic crypto drivers/crypto/Makefile| 2 +- drivers/crypto/stm32/Kconfig | 6 +++--- drivers/crypto/stm32/Makefile | 3 +-- drivers/crypto/stm32/stm32_crc32.c | 17 + 4 files changed, 14 insertions(+), 14 deletions(-) -- 2.7.4
[PATCH 3/3] crypto: stm32 - Rename module to use generic crypto
The complete stm32 module is rename as crypto in order to use generic naming Signed-off-by: Lionel Debieve Reviewed-by: Fabien Dessenne --- drivers/crypto/Makefile | 2 +- drivers/crypto/stm32/Kconfig | 6 +++--- drivers/crypto/stm32/Makefile | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 463f335..d4d69cec 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o -obj-$(CONFIG_CRYPTO_DEV_STM32) += stm32/ +obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/ obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig index 09b4ec8..7dd14f8 100644 --- a/drivers/crypto/stm32/Kconfig +++ b/drivers/crypto/stm32/Kconfig @@ -1,7 +1,7 @@ -config CRYPTO_DEV_STM32 - tristate "Support for STM32 crypto accelerators" +config CRC_DEV_STM32 + tristate "Support for STM32 crc accelerators" depends on ARCH_STM32 select CRYPTO_HASH help This enables support for the CRC32 hw accelerator which can be found - on STMicroelectronis STM32 SOC. + on STMicroelectronics STM32 SOC. diff --git a/drivers/crypto/stm32/Makefile b/drivers/crypto/stm32/Makefile index 73b4c6e..4db2f28 100644 --- a/drivers/crypto/stm32/Makefile +++ b/drivers/crypto/stm32/Makefile @@ -1,2 +1 @@ -obj-$(CONFIG_CRYPTO_DEV_STM32) += stm32_cryp.o -stm32_cryp-objs := stm32_crc32.o +obj-$(CONFIG_CRC_DEV_STM32) += stm32_crc32.o -- 2.7.4
[PATCH 1/3] crypto: stm32 - CRC use relaxed function
In case of arm soc support, readl and writel will be optimized using relaxed functions Signed-off-by: Lionel Debieve Reviewed-by: Fabien Dessenne --- drivers/crypto/stm32/stm32_crc32.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/stm32/stm32_crc32.c b/drivers/crypto/stm32/stm32_crc32.c index ec83b1e..04d2f4b 100644 --- a/drivers/crypto/stm32/stm32_crc32.c +++ b/drivers/crypto/stm32/stm32_crc32.c @@ -107,12 +107,12 @@ static int stm32_crc_init(struct shash_desc *desc) spin_unlock_bh(&crc_list.lock); /* Reset, set key, poly and configure in bit reverse mode */ - writel(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); - writel(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); - writel(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); + writel_relaxed(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); + writel_relaxed(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); + writel_relaxed(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); /* Store partial result */ - ctx->partial = readl(ctx->crc->regs + CRC_DR); + ctx->partial = readl_relaxed(ctx->crc->regs + CRC_DR); ctx->crc->nb_pending_bytes = 0; return 0; @@ -135,7 +135,8 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, if (crc->nb_pending_bytes == sizeof(u32)) { /* Process completed pending data */ - writel(*(u32 *)crc->pending_data, crc->regs + CRC_DR); + writel_relaxed(*(u32 *)crc->pending_data, + crc->regs + CRC_DR); crc->nb_pending_bytes = 0; } } @@ -143,10 +144,10 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, d32 = (u32 *)d8; for (i = 0; i < length >> 2; i++) /* Process 32 bits data */ - writel(*(d32++), crc->regs + CRC_DR); + writel_relaxed(*(d32++), crc->regs + CRC_DR); /* Store partial result */ - ctx->partial = readl(crc->regs + CRC_DR); + ctx->partial = readl_relaxed(crc->regs + CRC_DR); /* Check for pending data (non 32 bits) */ length &= 3; -- 2.7.4
[PATCH 2/3] crypto: stm32 - solve crc issue during unbind
Use the correct unregister_shashes function to to remove the registered algo Signed-off-by: Lionel Debieve Reviewed-by: Fabien Dessenne --- drivers/crypto/stm32/stm32_crc32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/stm32/stm32_crc32.c b/drivers/crypto/stm32/stm32_crc32.c index 04d2f4b..090582b 100644 --- a/drivers/crypto/stm32/stm32_crc32.c +++ b/drivers/crypto/stm32/stm32_crc32.c @@ -296,7 +296,7 @@ static int stm32_crc_remove(struct platform_device *pdev) list_del(&crc->list); spin_unlock(&crc_list.lock); - crypto_unregister_shash(algs); + crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); clk_disable_unprepare(crc->clk); -- 2.7.4
[PATCH 1/2] dt-bindings: Document STM32 HASH bindings
This adds documentation of device tree bindings for the STM32 HASH controller. Signed-off-by: Lionel Debieve --- .../devicetree/bindings/crypto/st,stm32-hash.txt | 30 ++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/crypto/st,stm32-hash.txt diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-hash.txt b/Documentation/devicetree/bindings/crypto/st,stm32-hash.txt new file mode 100644 index 000..04fc246 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/st,stm32-hash.txt @@ -0,0 +1,30 @@ +* STMicroelectronics STM32 HASH + +Required properties: +- compatible: Should contain entries for this and backward compatible + HASH versions: + - "st,stm32f456-hash" for stm32 F456. + - "st,stm32f756-hash" for stm32 F756. +- reg: The address and length of the peripheral registers space +- interrupts: the interrupt specifier for the HASH +- clocks: The input clock of the HASH instance + +Optional properties: +- resets: The input reset of the HASH instance +- dmas: DMA specifiers for the HASH. See the DMA client binding, +Documentation/devicetree/bindings/dma/dma.txt +- dma-names: DMA request name. Should be "in" if a dma is present. +- dma-maxburst: Set number of maximum dma burst supported + +Example: + +hash1: hash@50060400 { + compatible = "st,stm32f756-hash"; + reg = <0x50060400 0x400>; + interrupts = <80>; + clocks = <&rcc 0 STM32F7_AHB2_CLOCK(HASH)>; + resets = <&rcc STM32F7_AHB2_RESET(HASH)>; + dmas = <&dma2 7 2 0x400 0x0>; + dma-names = "in"; + dma-maxburst = <0>; +}; -- 2.7.4
[PATCH 0/2] STM32 HASH crypto driver
This set of patches adds a new crypto driver for STMicroelectronics stm32 HW. This drivers uses the crypto API and provides with HW-enabled md5, sha1, sha224, sha256 hash based algorithms. It makes use of the crypto engine to support ahash requests. This driver was successfully tested with tcrypt / testmgr. Note: Since two other set of patches (update of STM32 CRC32 and addition of STM32 CRYP) are being proposed, it may happen that there are some minor conflicts in 'Kconfig' and 'Makefile'. In that case, I will fix the issue in due course. Lionel Debieve (2): dt-bindings: Document STM32 HASH bindings crypto: stm32 - Support for STM32 HASH module .../devicetree/bindings/crypto/st,stm32-hash.txt | 30 + drivers/crypto/stm32/Kconfig | 13 + drivers/crypto/stm32/Makefile |1 + drivers/crypto/stm32/stm32-hash.c | 1576 4 files changed, 1620 insertions(+) create mode 100644 Documentation/devicetree/bindings/crypto/st,stm32-hash.txt create mode 100644 drivers/crypto/stm32/stm32-hash.c -- 2.7.4
[PATCH 2/2] crypto: stm32 - Support for STM32 HASH module
This module register a HASH module that support multiples algorithms: MD5, SHA1, SHA224, SHA256. It includes the support of HMAC hardware processing corresponding to the supported algorithms. DMA or IRQ mode are used depending on data length. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/Kconfig | 13 + drivers/crypto/stm32/Makefile |1 + drivers/crypto/stm32/stm32-hash.c | 1576 + 3 files changed, 1590 insertions(+) create mode 100644 drivers/crypto/stm32/stm32-hash.c diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig index 7dd14f8..602332e 100644 --- a/drivers/crypto/stm32/Kconfig +++ b/drivers/crypto/stm32/Kconfig @@ -5,3 +5,16 @@ config CRC_DEV_STM32 help This enables support for the CRC32 hw accelerator which can be found on STMicroelectronics STM32 SOC. + +config HASH_DEV_STM32 + tristate "Support for STM32 hash accelerators" + depends on ARCH_STM32 + depends on HAS_DMA + select CRYPTO_HASH + select CRYPTO_MD5 + select CRYPTO_SHA1 + select CRYPTO_SHA256 + select CRYPTO_ENGINE + help + This enables support for the HASH hw accelerator which can be found + on STMicroelectronics STM32 SOC. diff --git a/drivers/crypto/stm32/Makefile b/drivers/crypto/stm32/Makefile index 4db2f28..73cd56c 100644 --- a/drivers/crypto/stm32/Makefile +++ b/drivers/crypto/stm32/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_CRC_DEV_STM32) += stm32_crc32.o +obj-$(CONFIG_HASH_DEV_STM32) += stm32-hash.o \ No newline at end of file diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c new file mode 100644 index 000..7bba90c --- /dev/null +++ b/drivers/crypto/stm32/stm32-hash.c @@ -0,0 +1,1576 @@ +/* + * This file is part of STM32 Crypto driver for Linux. + * + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Lionel DEBIEVE for STMicroelectronics. + * + * License terms: GPL V2.0. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define HASH_CR0x00 +#define HASH_DIN 0x04 +#define HASH_STR 0x08 +#define HASH_IMR 0x20 +#define HASH_SR0x24 +#define HASH_CSR(x)(0x0F8 + ((x) * 0x04)) +#define HASH_HREG(x) (0x310 + ((x) * 0x04)) +#define HASH_HWCFGR0x3F0 +#define HASH_VER 0x3F4 +#define HASH_ID0x3F8 + +/* Control Register */ +#define HASH_CR_INIT BIT(2) +#define HASH_CR_DMAE BIT(3) +#define HASH_CR_DATATYPE_POS 4 +#define HASH_CR_MODE BIT(6) +#define HASH_CR_MDMAT BIT(13) +#define HASH_CR_DMAA BIT(14) +#define HASH_CR_LKEY BIT(16) + +#define HASH_CR_ALGO_SHA1 0x0 +#define HASH_CR_ALGO_MD5 0x80 +#define HASH_CR_ALGO_SHA2240x4 +#define HASH_CR_ALGO_SHA2560x40080 + +/* Interrupt */ +#define HASH_DINIE BIT(0) +#define HASH_DCIE BIT(1) + +/* Interrupt Mask */ +#define HASH_MASK_CALC_COMPLETION BIT(0) +#define HASH_MASK_DATA_INPUT BIT(1) + +/* Context swap register */ +#define HASH_CSR_REGISTER_NUMBER 53 + +/* Status Flags */ +#define HASH_SR_DATA_INPUT_READY BIT(0) +#define HASH_SR_OUTPUT_READY BIT(1) +#define HASH_SR_DMA_ACTIVE BIT(2) +#define HASH_SR_BUSY BIT(3) + +/* STR Register */ +#define HASH_STR_NBLW_MASK GENMASK(4, 0) +#define HASH_STR_DCAL BIT(8) + +#define HASH_FLAGS_INITBIT(0) +#define HASH_FLAGS_OUTPUT_READYBIT(1) +#define HASH_FLAGS_CPU BIT(2) +#define HASH_FLAGS_DMA_READY BIT(3) +#define HASH_FLAGS_DMA_ACTIVE BIT(4) +#define HASH_FLAGS_HMAC_INIT BIT(5) +#define HASH_FLAGS_HMAC_FINAL BIT(6) +#define HASH_FLAGS_HMAC_KEYBIT(7) + +#define HASH_FLAGS_FINAL BIT(15) +#define
Re: [RESEND,PATCH v4 3/3] crypto : stm32 - Add STM32F4 CRC32 support
Hi Cosar, - ret = crypto_register_shashes(algs, ARRAY_SIZE(algs)); + /* For F4 series only CRC32 algorithm will be used */ + if (of_device_is_compatible(crc->dev->of_node, "st,stm32f4-crc")) + algs_size = 1; + else + algs_size = ARRAY_SIZE(algs); + + ret = crypto_register_shashes(algs, algs_size); Should it be better to have a dedicated array per platform data instead? Could be new platform update? BR, Lionel On 07/17/2017 10:27 AM, Cosar Dindar wrote: > This patch adds CRC (CRC32 Crypto) support for STM32F4 series. > > As an hardware limitation polynomial and key setting are not supported. > They are fixed as 0x4C11DB7 (poly) and 0x (key). > CRC32C Castagnoli algorithm is not used. > > Signed-off-by: Cosar Dindar > Reviewed-by: Fabien Dessenne > --- > drivers/crypto/stm32/stm32_crc32.c | 68 > -- > 1 file changed, 58 insertions(+), 10 deletions(-) > > diff --git a/drivers/crypto/stm32/stm32_crc32.c > b/drivers/crypto/stm32/stm32_crc32.c > index ec83b1e..12fbd98 100644 > --- a/drivers/crypto/stm32/stm32_crc32.c > +++ b/drivers/crypto/stm32/stm32_crc32.c > @@ -7,6 +7,7 @@ > #include > #include > #include > +#include > #include > > #include > @@ -39,6 +40,9 @@ struct stm32_crc { > struct clk *clk; > u8 pending_data[sizeof(u32)]; > size_t nb_pending_bytes; > + bool key_support; > + bool poly_support; > + bool reverse_support; > }; > > struct stm32_crc_list { > @@ -106,13 +110,31 @@ static int stm32_crc_init(struct shash_desc *desc) > } > spin_unlock_bh(&crc_list.lock); > > - /* Reset, set key, poly and configure in bit reverse mode */ > - writel(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); > - writel(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); > - writel(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); > + /* set key */ > + if (ctx->crc->key_support) { > + writel(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); > + } else if (mctx->key != CRC_INIT_DEFAULT) { > + dev_err(ctx->crc->dev, "Unsupported key value! Should be: > 0x%x\n", > + CRC_INIT_DEFAULT); > + return -EINVAL; > + } > + > + /* set poly */ > + if (ctx->crc->poly_support) > + writel(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); > + > + /* reset and configure in bit reverse mode if supported */ > + if (ctx->crc->reverse_support) > + writel(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR); > + else > + writel(CRC_CR_RESET, ctx->crc->regs + CRC_CR); > + > + /* store partial result */ > + if (!ctx->crc->reverse_support) > + ctx->partial = bitrev32(readl(crc->regs + CRC_DR)); > + else > + ctx->partial = readl(ctx->crc->regs + CRC_DR); > > - /* Store partial result */ > - ctx->partial = readl(ctx->crc->regs + CRC_DR); > ctx->crc->nb_pending_bytes = 0; > > return 0; > @@ -135,7 +157,12 @@ static int stm32_crc_update(struct shash_desc *desc, > const u8 *d8, > > if (crc->nb_pending_bytes == sizeof(u32)) { > /* Process completed pending data */ > - writel(*(u32 *)crc->pending_data, crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + writel(bitrev32(*(u32 *)crc->pending_data), > +crc->regs + CRC_DR); > + else > + writel(*(u32 *)crc->pending_data, > +crc->regs + CRC_DR); > crc->nb_pending_bytes = 0; > } > } > @@ -143,10 +170,16 @@ static int stm32_crc_update(struct shash_desc *desc, > const u8 *d8, > d32 = (u32 *)d8; > for (i = 0; i < length >> 2; i++) > /* Process 32 bits data */ > - writel(*(d32++), crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + writel(bitrev32(*(d32++)), crc->regs + CRC_DR); > + else > + writel(*(d32++), crc->regs + CRC_DR); > > /* Store partial result */ > - ctx->partial = readl(crc->regs + CRC_DR); > + if (!ctx->crc->reverse_support) > + ctx->partial = bitrev32(readl(crc->regs + CRC_DR)); > + else > + ctx->partial = readl(crc->regs + CRC_DR); > > /* Check for pending data (non 32 bits) */ > length &= 3; > @@ -243,6 +276,7 @@ static int stm32_crc_probe(struct platform_device *pdev) > struct stm32_crc *crc; > struct resource *res; > int ret; > + int algs_size; > > crc = devm_kzalloc(dev, sizeof(*crc), GFP_KERNEL); > if (!crc) > @@ -269,13 +303,26 @@ static int stm32_crc_probe(stru
[PATCH 3/3] crypto: stm32/hash: rework padding length
From: Lionel Debieve Due to another patch, the dma fails when padding is needed as the given length is not correct. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index d8444aeb6609..80b9ec76bbb5 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -626,7 +626,7 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) writesl(hdev->io_base + HASH_DIN, buffer, DIV_ROUND_UP(ncp, sizeof(u32))); } - stm32_hash_set_nblw(hdev, DIV_ROUND_UP(ncp, sizeof(u32))); + stm32_hash_set_nblw(hdev, ncp); reg = stm32_hash_read(hdev, HASH_STR); reg |= HASH_STR_DCAL; stm32_hash_write(hdev, HASH_STR, reg); -- 2.15.1
[PATCH 0/3] crypto: stm32/hash: Correction to improve robustness
From: Lionel Debieve Hi, This patch serie will improve global robustness for stm32-hash driver. Patch #1 is fixing dma-burst issue when configuration is not set. Patch #2 solves issue that occurs when irq append during final req processing. Patch #3 is fixing an issue that have been introduced while managing padding but breaking the padding length calculation by hardware to generate correct hash. Regards, Lionel Debieve (3): crypto: stm32/hash: avoid error if maxburst not defined crypto: stm32/hash: fix performance issues crypto: stm32/hash: rework padding length drivers/crypto/stm32/stm32-hash.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) -- 2.15.1
[PATCH 1/3] crypto: stm32/hash: avoid error if maxburst not defined
From: Lionel Debieve dma-maxburst is an optional value and must not return error in case of dma not used (or max-burst not defined). Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index 4ca4a264a833..73cdc3b4dca8 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -1404,18 +1404,19 @@ MODULE_DEVICE_TABLE(of, stm32_hash_of_match); static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, struct device *dev) { - int err; - hdev->pdata = of_device_get_match_data(dev); if (!hdev->pdata) { dev_err(dev, "no compatible OF match\n"); return -EINVAL; } - err = of_property_read_u32(dev->of_node, "dma-maxburst", - &hdev->dma_maxburst); + if (of_property_read_u32(dev->of_node, "dma-maxburst", +&hdev->dma_maxburst)) { + dev_info(dev, "dma-maxburst not specified, using 0\n"); + hdev->dma_maxburst = 0; + } - return err; + return 0; } static int stm32_hash_probe(struct platform_device *pdev) -- 2.15.1
[PATCH 2/3] crypto: stm32/hash: fix performance issues
From: Lionel Debieve Fixing bugs link to stress tests. Bad results are detected during testmgr selftests executing in a faster environment. bufcnt value may be resetted and false IT are sometimes detected. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index 73cdc3b4dca8..d8444aeb6609 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -743,13 +743,15 @@ static int stm32_hash_final_req(struct stm32_hash_dev *hdev) struct ahash_request *req = hdev->req; struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); int err; + int buflen = rctx->bufcnt; + + rctx->bufcnt = 0; if (!(rctx->flags & HASH_FLAGS_CPU)) err = stm32_hash_dma_send(hdev); else - err = stm32_hash_xmit_cpu(hdev, rctx->buffer, rctx->bufcnt, 1); + err = stm32_hash_xmit_cpu(hdev, rctx->buffer, buflen, 1); - rctx->bufcnt = 0; return err; } @@ -1096,6 +1098,8 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) reg &= ~HASH_SR_OUTPUT_READY; stm32_hash_write(hdev, HASH_SR, reg); hdev->flags |= HASH_FLAGS_OUTPUT_READY; + /* Disable IT*/ + stm32_hash_write(hdev, HASH_IMR, 0); return IRQ_WAKE_THREAD; } -- 2.15.1
[PATCH 3/5] hwrng: stm32 - allow disable clock error detection
Add a new property that allow to disable the clock error detection which is required when the clock source selected is out of specification (which is not mandatory). Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 83c695938a2d..709a8d061be3 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -26,6 +26,7 @@ #define RNG_CR 0x00 #define RNG_CR_RNGEN BIT(2) +#define RNG_CR_CED BIT(5) #define RNG_SR 0x04 #define RNG_SR_SEIS BIT(6) @@ -48,6 +49,7 @@ struct stm32_rng_private { void __iomem *base; struct clk *clk; struct reset_control *rst; + bool ced; }; static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) @@ -101,7 +103,11 @@ static int stm32_rng_init(struct hwrng *rng) if (err) return err; - writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR); + if (priv->ced) + writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR); + else + writel_relaxed(RNG_CR_RNGEN | RNG_CR_CED, + priv->base + RNG_CR); /* clear error indicators */ writel_relaxed(0, priv->base + RNG_SR); @@ -149,6 +155,8 @@ static int stm32_rng_probe(struct platform_device *ofdev) reset_control_deassert(priv->rst); } + priv->ced = of_property_read_bool(np, "clock-error-detect"); + dev_set_drvdata(dev, priv); priv->rng.name = dev_driver_string(dev), -- 2.15.1
[PATCH 2/5] dt-bindings: rng: add reset node for stm32
Adding optional resets property for rng. Signed-off-by: Lionel Debieve --- Documentation/devicetree/bindings/rng/st,stm32-rng.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt index 47f04176f93b..cb7ca78135ff 100644 --- a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt +++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt @@ -11,6 +11,9 @@ Required properties: - interrupts : The designated IRQ line for the RNG - clocks : The clock needed to enable the RNG +Optional properties: +- resets : The reset to properly start RNG + Example: rng: rng@50060800 { -- 2.15.1
[PATCH 0/5] hwrng: stm32 - Improvement for stm32-rng
This set of patches add extended functionalities for stm32 rng driver. Patch #1 includes a reset during probe to avoid any error status which can occur during bootup process and keep safe rng integrity. Patch #3 adds a new property to manage the clock error detection feature which can be disabled on specific target. Patch #5 rework the timeout calculation for read value that was previously defined based on loop operation and is now based on timer. Lionel Debieve (5): hwrng: stm32 - add reset during probe dt-bindings: rng: add reset node for stm32 hwrng: stm32 - allow disable clock error detection dt-bindings: rng: add clock detection error for stm32 hwrng: stm32 - rework read timeout calculation .../devicetree/bindings/rng/st,stm32-rng.txt | 4 ++ drivers/char/hw_random/stm32-rng.c | 44 ++ 2 files changed, 32 insertions(+), 16 deletions(-) -- 2.15.1
[PATCH 4/5] dt-bindings: rng: add clock detection error for stm32
Add optional property to enable the clock detection error on rng block. It is used to allow slow clock source which give correct entropy for rng. Signed-off-by: Lionel Debieve --- Documentation/devicetree/bindings/rng/st,stm32-rng.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt index cb7ca78135ff..1dfa7d51e006 100644 --- a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt +++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt @@ -13,6 +13,7 @@ Required properties: Optional properties: - resets : The reset to properly start RNG +- clock-error-detect : Enable the clock detection management Example: -- 2.15.1
[PATCH 1/5] hwrng: stm32 - add reset during probe
Avoid issue when probing the RNG without reset if bad status has been detected previously Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 63d84e6f1891..83c695938a2d 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define RNG_CR 0x00 @@ -46,6 +47,7 @@ struct stm32_rng_private { struct hwrng rng; void __iomem *base; struct clk *clk; + struct reset_control *rst; }; static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) @@ -140,6 +142,13 @@ static int stm32_rng_probe(struct platform_device *ofdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); + priv->rst = devm_reset_control_get(&ofdev->dev, NULL); + if (!IS_ERR(priv->rst)) { + reset_control_assert(priv->rst); + udelay(2); + reset_control_deassert(priv->rst); + } + dev_set_drvdata(dev, priv); priv->rng.name = dev_driver_string(dev), -- 2.15.1
[PATCH Resend 1/5] hwrng: stm32 - add reset during probe
Avoid issue when probing the RNG without reset if bad status has been detected previously Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 63d84e6f1891..83c695938a2d 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define RNG_CR 0x00 @@ -46,6 +47,7 @@ struct stm32_rng_private { struct hwrng rng; void __iomem *base; struct clk *clk; + struct reset_control *rst; }; static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) @@ -140,6 +142,13 @@ static int stm32_rng_probe(struct platform_device *ofdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); + priv->rst = devm_reset_control_get(&ofdev->dev, NULL); + if (!IS_ERR(priv->rst)) { + reset_control_assert(priv->rst); + udelay(2); + reset_control_deassert(priv->rst); + } + dev_set_drvdata(dev, priv); priv->rng.name = dev_driver_string(dev), -- 2.15.1
[PATCH Resend 0/5] hwrng: stm32 - Improvement for stm32-rng
This set of patches add extended functionalities for stm32 rng driver. Patch #1 includes a reset during probe to avoid any error status which can occur during bootup process and keep safe rng integrity. Patch #3 adds a new property to manage the clock error detection feature which can be disabled on specific target. Patch #5 rework the timeout calculation for read value that was previously defined based on loop operation and is now based on timer. Lionel Debieve (5): hwrng: stm32 - add reset during probe dt-bindings: rng: add reset node for stm32 hwrng: stm32 - allow disable clock error detection dt-bindings: rng: add clock detection error for stm32 hwrng: stm32 - rework read timeout calculation .../devicetree/bindings/rng/st,stm32-rng.txt | 4 ++ drivers/char/hw_random/stm32-rng.c | 44 ++ 2 files changed, 32 insertions(+), 16 deletions(-) -- 2.15.1
[PATCH Resend 4/5] dt-bindings: rng: add clock detection error for stm32
Add optional property to enable the clock detection error on rng block. It is used to allow slow clock source which give correct entropy for rng. Signed-off-by: Lionel Debieve --- Documentation/devicetree/bindings/rng/st,stm32-rng.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt index cb7ca78135ff..1dfa7d51e006 100644 --- a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt +++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt @@ -13,6 +13,7 @@ Required properties: Optional properties: - resets : The reset to properly start RNG +- clock-error-detect : Enable the clock detection management Example: -- 2.15.1
[PATCH Resend 3/5] hwrng: stm32 - allow disable clock error detection
Add a new property that allow to disable the clock error detection which is required when the clock source selected is out of specification (which is not mandatory). Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 83c695938a2d..709a8d061be3 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -26,6 +26,7 @@ #define RNG_CR 0x00 #define RNG_CR_RNGEN BIT(2) +#define RNG_CR_CED BIT(5) #define RNG_SR 0x04 #define RNG_SR_SEIS BIT(6) @@ -48,6 +49,7 @@ struct stm32_rng_private { void __iomem *base; struct clk *clk; struct reset_control *rst; + bool ced; }; static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) @@ -101,7 +103,11 @@ static int stm32_rng_init(struct hwrng *rng) if (err) return err; - writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR); + if (priv->ced) + writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR); + else + writel_relaxed(RNG_CR_RNGEN | RNG_CR_CED, + priv->base + RNG_CR); /* clear error indicators */ writel_relaxed(0, priv->base + RNG_SR); @@ -149,6 +155,8 @@ static int stm32_rng_probe(struct platform_device *ofdev) reset_control_deassert(priv->rst); } + priv->ced = of_property_read_bool(np, "clock-error-detect"); + dev_set_drvdata(dev, priv); priv->rng.name = dev_driver_string(dev), -- 2.15.1
[PATCH Resend 2/5] dt-bindings: rng: add reset node for stm32
Adding optional resets property for rng. Signed-off-by: Lionel Debieve --- Documentation/devicetree/bindings/rng/st,stm32-rng.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt index 47f04176f93b..cb7ca78135ff 100644 --- a/Documentation/devicetree/bindings/rng/st,stm32-rng.txt +++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.txt @@ -11,6 +11,9 @@ Required properties: - interrupts : The designated IRQ line for the RNG - clocks : The clock needed to enable the RNG +Optional properties: +- resets : The reset to properly start RNG + Example: rng: rng@50060800 { -- 2.15.1
[PATCH Resend 5/5] hwrng: stm32 - rework read timeout calculation
Increase timeout delay to support longer timing linked to rng initialization. Measurement is based on timer instead of instructions per iteration which is not powerful on all targets. Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 709a8d061be3..0d2328da3b76 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -35,15 +36,6 @@ #define RNG_DR 0x08 -/* - * It takes 40 cycles @ 48MHz to generate each random number (e.g. <1us). - * At the time of writing STM32 parts max out at ~200MHz meaning a timeout - * of 500 leaves us a very comfortable margin for error. The loop to which - * the timeout applies takes at least 4 instructions per iteration so the - * timeout is enough to take us up to multi-GHz parts! - */ -#define RNG_TIMEOUT 500 - struct stm32_rng_private { struct hwrng rng; void __iomem *base; @@ -63,13 +55,16 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) while (max > sizeof(u32)) { sr = readl_relaxed(priv->base + RNG_SR); + /* Manage timeout which is based on timer and take */ + /* care of initial delay time when enabling rng */ if (!sr && wait) { - unsigned int timeout = RNG_TIMEOUT; - - do { - cpu_relax(); - sr = readl_relaxed(priv->base + RNG_SR); - } while (!sr && --timeout); + retval = readl_relaxed_poll_timeout_atomic(priv->base + + RNG_SR, + sr, sr, + 10, 5); + if (retval) + dev_err((struct device *)priv->rng.priv, + "%s: timeout %x!\n", __func__, sr); } /* If error detected or data not ready... */ -- 2.15.1
[PATCH 2/2] hwrng: stm32-rng - fix pm_suspend issue
When suspend is called after pm_runtime_suspend, same callback is used and access to rng register is freezing system. By calling the pm_runtime_force_suspend, it first checks that runtime has been already done. Signed-off-by: Lionel Debieve --- drivers/char/hw_random/stm32-rng.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 0d2328da3b76..042860d97b15 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -187,8 +187,13 @@ static int stm32_rng_runtime_resume(struct device *dev) } #endif -static UNIVERSAL_DEV_PM_OPS(stm32_rng_pm_ops, stm32_rng_runtime_suspend, - stm32_rng_runtime_resume, NULL); +static const struct dev_pm_ops stm32_rng_pm_ops = { + SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend, + stm32_rng_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + static const struct of_device_id stm32_rng_match[] = { { -- 2.15.1
[PATCH 0/2] Fix stm32-rng for default state and suspend
This series are fixing the default build state for stm32-rng that activate the driver with arm multi_v7_defconfig. Second patch is fixing the power suspend/resume behavior which was not working. Lionel Debieve (2): hwrng: stm32 - define default state for rng driver hwrng: stm32-rng: Fix pm_suspend issue drivers/char/hw_random/Kconfig | 1 + drivers/char/hw_random/stm32-rng.c | 9 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) -- 2.15.1
[PATCH 1/2] hwrng: stm32 - define default state for rng driver
Define default state for stm32_rng driver. It will be default selected with multi_v7_defconfig Signed-off-by: Lionel Debieve --- drivers/char/hw_random/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index d53541e96bee..c34b257d852d 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -347,6 +347,7 @@ config HW_RANDOM_STM32 tristate "STMicroelectronics STM32 random number generator" depends on HW_RANDOM && (ARCH_STM32 || COMPILE_TEST) depends on HAS_IOMEM + default HW_RANDOM help This driver provides kernel-side support for the Random Number Generator hardware found on STM32 microcontrollers. -- 2.15.1
[Bug] STM32 crc driver failed on selftest 1
Hi All, I'm looking further to debug an issue regarding CRC32 selftests. I'm currently blocked on an issue about the second test vector implemented on CRC32: static const struct hash_testvec crc32_tv_template[] = { { .plaintext = "abcdefg", .psize = 7, .digest = "\xd8\xb5\x46\xac", }, I'm currently trying to understand the issue, but using others tools (computer or Online CRC calculation), I'm not able to find any way to get the expected output? This new vector was introduced for few version but I'm wondering who was able to verify it. Should it be written by byte? Word? Half word? Thanks for help. BR, Lionel
Re: [PATCH 21/24] crypto: stm32 - Forbid 2-key 3DES in FIPS mode
Hi Herbert, On 4/11/19 10:51 AM, Herbert Xu wrote: > This patch forbids the use of 2-key 3DES (K1 == K3) in FIPS mode. > > Signed-off-by: Herbert Xu > --- > > drivers/crypto/stm32/stm32-cryp.c | 15 +++ > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/drivers/crypto/stm32/stm32-cryp.c > b/drivers/crypto/stm32/stm32-cryp.c > index 23b0b7bd64c7..5785f3e235ce 100644 > --- a/drivers/crypto/stm32/stm32-cryp.c > +++ b/drivers/crypto/stm32/stm32-cryp.c > @@ -762,10 +762,17 @@ static int stm32_cryp_des_setkey(struct > crypto_ablkcipher *tfm, const u8 *key, > static int stm32_cryp_tdes_setkey(struct crypto_ablkcipher *tfm, const u8 > *key, > unsigned int keylen) > { > - if (keylen != (3 * DES_KEY_SIZE)) > - return -EINVAL; > - else > - return stm32_cryp_setkey(tfm, key, keylen); > + u32 flags; > + int err; > + > + flags = crypto_ablkcipher_get_flags(tfm); > + err = __des3_verify_key(&flags, key); > + if (unlikely(err)) { > + crypto_ablkcipher_set_flags(tfm, flags); > + return err; > + } > + > + return stm32_cryp_setkey(tfm, key, keylen); > } > > static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 > *key, > I was currently going to send patches around des and tdes key verification. Is there any plan to do the same factorization on des key check? Regarding this patch, ok for me. - Lionel Acked-by: Lionel Debieve Tested-by: Lionel Debieve
Re: [PATCH 21/24] crypto: stm32 - Forbid 2-key 3DES in FIPS mode
On 4/13/19 3:50 PM, Herbert Xu wrote: > On Fri, Apr 12, 2019 at 01:36:44PM +0000, Lionel DEBIEVE wrote: >> I was currently going to send patches around des and tdes key verification. >> Is there any plan >> to do the same factorization on des key check? > If you have the time please do because I think some single DES > drivers are missing the weak key check. The existing des_ekey > function should be sufficient for the check. ok, will try to do it in the same way you've done it for 3des using existing des_ekey function. Trying to push it this week for all impacted drivers. - Lionel > >> Acked-by: Lionel Debieve >> Tested-by: Lionel Debieve > Thanks, >
[PATCH 1/1] crypto: stm32/crc32 - rename driver file
Use the same naming convention for all stm32 crypto drivers. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/Makefile | 2 +- drivers/crypto/stm32/{stm32_crc32.c => stm32-crc32.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/crypto/stm32/{stm32_crc32.c => stm32-crc32.c} (100%) diff --git a/drivers/crypto/stm32/Makefile b/drivers/crypto/stm32/Makefile index ce77e38c77e0..518e0e0b11a9 100644 --- a/drivers/crypto/stm32/Makefile +++ b/drivers/crypto/stm32/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_CRYPTO_DEV_STM32_CRC) += stm32_crc32.o +obj-$(CONFIG_CRYPTO_DEV_STM32_CRC) += stm32-crc32.o obj-$(CONFIG_CRYPTO_DEV_STM32_HASH) += stm32-hash.o obj-$(CONFIG_CRYPTO_DEV_STM32_CRYP) += stm32-cryp.o diff --git a/drivers/crypto/stm32/stm32_crc32.c b/drivers/crypto/stm32/stm32-crc32.c similarity index 100% rename from drivers/crypto/stm32/stm32_crc32.c rename to drivers/crypto/stm32/stm32-crc32.c -- 2.17.1
[PATCH 0/2] crypto: stm32/hash: Fix bug in hmac mode
This series fixes issues discovered while using libkcapi library. Some more tests show wrong key management in hmac mode. It is fixes by these patches and prevent a potential issue in case of interrupt while processing in dma mode. Lionel Debieve (2): crypto: stm32/hash: Fix hmac issue more than 256 bytes crypto: stm32/hash: remove interruptible condition for dma drivers/crypto/stm32/stm32-hash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) -- 2.17.1
[PATCH 1/2] crypto: stm32/hash: Fix hmac issue more than 256 bytes
Correct condition for the second hmac loop. Key must be only set in the first loop. Initial condition was wrong, HMAC_KEY flag was not properly checked. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index 29519d1c403f..c37d1a336f98 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -349,7 +349,7 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, return -ETIMEDOUT; if ((hdev->flags & HASH_FLAGS_HMAC) && - (hdev->flags & ~HASH_FLAGS_HMAC_KEY)) { + (!(hdev->flags & HASH_FLAGS_HMAC_KEY))) { hdev->flags |= HASH_FLAGS_HMAC_KEY; stm32_hash_write_key(hdev); if (stm32_hash_wait_busy(hdev)) -- 2.17.1
[PATCH 2/2] crypto: stm32/hash: remove interruptible condition for dma
When DMA is used, waiting for completion must not be interruptible as it can generate an error that is not handle by the driver. There is no need to put the completion interruptible in this driver. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index c37d1a336f98..23061f2bc74b 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -447,8 +447,8 @@ static int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev, dma_async_issue_pending(hdev->dma_lch); - if (!wait_for_completion_interruptible_timeout(&hdev->dma_completion, - msecs_to_jiffies(100))) + if (!wait_for_completion_timeout(&hdev->dma_completion, +msecs_to_jiffies(100))) err = -ETIMEDOUT; if (dma_async_is_tx_complete(hdev->dma_lch, cookie, -- 2.17.1
[PATCH 2/3] crypto: stm32/hash - Add power management support
Adding pm and pm_runtime support to STM32 HASH. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-hash.c | 71 +++ 1 file changed, 71 insertions(+) diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index cdc96f1..d1d7233 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,8 @@ enum stm32_hash_data_format { #define HASH_QUEUE_LENGTH 16 #define HASH_DMA_THRESHOLD 50 +#define HASH_AUTOSUSPEND_DELAY 50 + struct stm32_hash_ctx { struct crypto_engine_ctx enginectx; struct stm32_hash_dev *hdev; @@ -814,12 +817,17 @@ static void stm32_hash_finish_req(struct ahash_request *req, int err) rctx->flags |= HASH_FLAGS_ERRORS; } + pm_runtime_mark_last_busy(hdev->dev); + pm_runtime_put_autosuspend(hdev->dev); + crypto_finalize_hash_request(hdev->engine, req, err); } static int stm32_hash_hw_init(struct stm32_hash_dev *hdev, struct stm32_hash_request_ctx *rctx) { + pm_runtime_get_sync(hdev->dev); + if (!(HASH_FLAGS_INIT & hdev->flags)) { stm32_hash_write(hdev, HASH_CR, HASH_CR_INIT); stm32_hash_write(hdev, HASH_STR, 0); @@ -967,6 +975,8 @@ static int stm32_hash_export(struct ahash_request *req, void *out) u32 *preg; unsigned int i; + pm_runtime_get_sync(hdev->dev); + while (!(stm32_hash_read(hdev, HASH_SR) & HASH_SR_DATA_INPUT_READY)) cpu_relax(); @@ -982,6 +992,9 @@ static int stm32_hash_export(struct ahash_request *req, void *out) for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); + pm_runtime_mark_last_busy(hdev->dev); + pm_runtime_put_autosuspend(hdev->dev); + memcpy(out, rctx, sizeof(*rctx)); return 0; @@ -1000,6 +1013,8 @@ static int stm32_hash_import(struct ahash_request *req, const void *in) preg = rctx->hw_context; + pm_runtime_get_sync(hdev->dev); + stm32_hash_write(hdev, HASH_IMR, *preg++); stm32_hash_write(hdev, HASH_STR, *preg++); stm32_hash_write(hdev, HASH_CR, *preg); @@ -1009,6 +1024,9 @@ static int stm32_hash_import(struct ahash_request *req, const void *in) for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) stm32_hash_write(hdev, HASH_CSR(i), *preg++); + pm_runtime_mark_last_busy(hdev->dev); + pm_runtime_put_autosuspend(hdev->dev); + kfree(rctx->hw_context); return 0; @@ -1482,6 +1500,13 @@ static int stm32_hash_probe(struct platform_device *pdev) return ret; } + pm_runtime_set_autosuspend_delay(dev, HASH_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + hdev->rst = devm_reset_control_get(&pdev->dev, NULL); if (!IS_ERR(hdev->rst)) { reset_control_assert(hdev->rst); @@ -1522,6 +1547,8 @@ static int stm32_hash_probe(struct platform_device *pdev) dev_info(dev, "Init HASH done HW ver %x DMA mode %u\n", stm32_hash_read(hdev, HASH_VER), hdev->dma_mode); + pm_runtime_put_sync(dev); + return 0; err_algs: @@ -1535,6 +1562,9 @@ static int stm32_hash_probe(struct platform_device *pdev) if (hdev->dma_lch) dma_release_channel(hdev->dma_lch); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + clk_disable_unprepare(hdev->clk); return ret; @@ -1543,11 +1573,16 @@ static int stm32_hash_probe(struct platform_device *pdev) static int stm32_hash_remove(struct platform_device *pdev) { static struct stm32_hash_dev *hdev; + int ret; hdev = platform_get_drvdata(pdev); if (!hdev) return -ENODEV; + ret = pm_runtime_get_sync(hdev->dev); + if (ret < 0) + return ret; + stm32_hash_unregister_algs(hdev); crypto_engine_exit(hdev->engine); @@ -1559,16 +1594,52 @@ static int stm32_hash_remove(struct platform_device *pdev) if (hdev->dma_lch) dma_release_channel(hdev->dma_lch); + pm_runtime_disable(hdev->dev); + pm_runtime_put_noidle(hdev->dev); + clk_disable_unprepare(hdev->clk); return 0; } +#ifdef CONFIG_PM +static int stm32_hash_runtime_suspend(struct device *dev) +{ + struct stm32_hash_dev *hdev = dev_get_drvdata(dev); + + clk_disable_unprepare(hdev->clk); + + return 0; +} + +static int stm32_hash_runtime
[PATCH 1/3] crypto: stm32/cryp - Add power management support
Adding pm and pm_runtime support to STM32 CRYP. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32-cryp.c | 62 +++ 1 file changed, 62 insertions(+) diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index c5d3efc..23b0b7b 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ #define GCM_CTR_INIT2 #define _walked_in (cryp->in_walk.offset - cryp->in_sg->offset) #define _walked_out (cryp->out_walk.offset - cryp->out_sg->offset) +#define CRYP_AUTOSUSPEND_DELAY 50 struct stm32_cryp_caps { boolswap_final; @@ -519,6 +521,8 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) int ret; u32 cfg, hw_mode; + pm_runtime_get_sync(cryp->dev); + /* Disable interrupt */ stm32_cryp_write(cryp, CRYP_IMSCR, 0); @@ -638,6 +642,9 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) free_pages((unsigned long)buf_out, pages); } + pm_runtime_mark_last_busy(cryp->dev); + pm_runtime_put_autosuspend(cryp->dev); + if (is_gcm(cryp) || is_ccm(cryp)) { crypto_finalize_aead_request(cryp->engine, cryp->areq, err); cryp->areq = NULL; @@ -1969,6 +1976,13 @@ static int stm32_cryp_probe(struct platform_device *pdev) return ret; } + pm_runtime_set_autosuspend_delay(dev, CRYP_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + rst = devm_reset_control_get(dev, NULL); if (!IS_ERR(rst)) { reset_control_assert(rst); @@ -2008,6 +2022,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) dev_info(dev, "Initialized\n"); + pm_runtime_put_sync(dev); + return 0; err_aead_algs: @@ -2020,6 +2036,11 @@ static int stm32_cryp_probe(struct platform_device *pdev) list_del(&cryp->list); spin_unlock(&cryp_list.lock); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + clk_disable_unprepare(cryp->clk); return ret; @@ -2028,10 +2049,15 @@ static int stm32_cryp_probe(struct platform_device *pdev) static int stm32_cryp_remove(struct platform_device *pdev) { struct stm32_cryp *cryp = platform_get_drvdata(pdev); + int ret; if (!cryp) return -ENODEV; + ret = pm_runtime_get_sync(cryp->dev); + if (ret < 0) + return ret; + crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); crypto_unregister_algs(crypto_algs, ARRAY_SIZE(crypto_algs)); @@ -2041,16 +2067,52 @@ static int stm32_cryp_remove(struct platform_device *pdev) list_del(&cryp->list); spin_unlock(&cryp_list.lock); + pm_runtime_disable(cryp->dev); + pm_runtime_put_noidle(cryp->dev); + + clk_disable_unprepare(cryp->clk); + + return 0; +} + +#ifdef CONFIG_PM +static int stm32_cryp_runtime_suspend(struct device *dev) +{ + struct stm32_cryp *cryp = dev_get_drvdata(dev); + clk_disable_unprepare(cryp->clk); return 0; } +static int stm32_cryp_runtime_resume(struct device *dev) +{ + struct stm32_cryp *cryp = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(cryp->clk); + if (ret) { + dev_err(cryp->dev, "Failed to prepare_enable clock\n"); + return ret; + } + + return 0; +} +#endif + +static const struct dev_pm_ops stm32_cryp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(stm32_cryp_runtime_suspend, + stm32_cryp_runtime_resume, NULL) +}; + static struct platform_driver stm32_cryp_driver = { .probe = stm32_cryp_probe, .remove = stm32_cryp_remove, .driver = { .name = DRIVER_NAME, + .pm = &stm32_cryp_pm_ops, .of_match_table = stm32_dt_ids, }, }; -- 2.7.4
[PATCH 0/3] crypto: stm32 - Add power mamagement support
This set of patches add pm and pm_runtime feature to stm32 crypto drivers. Lionel Debieve (3): crypto: stm32/cryp - Add power management support crypto: stm32/hash - Add power management support crypto: stm32/crc - Add power management support drivers/crypto/stm32/stm32-cryp.c | 62 + drivers/crypto/stm32/stm32-hash.c | 71 ++ drivers/crypto/stm32/stm32_crc32.c | 62 + 3 files changed, 195 insertions(+) -- 2.7.4
[PATCH 3/3] crypto: stm32/crc - Add power management support
Adding pm and pm_runtime support to STM32 CRC. Signed-off-by: Lionel Debieve --- drivers/crypto/stm32/stm32_crc32.c | 62 ++ 1 file changed, 62 insertions(+) diff --git a/drivers/crypto/stm32/stm32_crc32.c b/drivers/crypto/stm32/stm32_crc32.c index 8f09b84..04ba5e1 100644 --- a/drivers/crypto/stm32/stm32_crc32.c +++ b/drivers/crypto/stm32/stm32_crc32.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -32,6 +33,8 @@ #define POLY_CRC32 0xEDB88320 #define POLY_CRC32C 0x82F63B78 +#define CRC_AUTOSUSPEND_DELAY 50 + struct stm32_crc { struct list_head list; struct device*dev; @@ -106,6 +109,8 @@ static int stm32_crc_init(struct shash_desc *desc) } spin_unlock_bh(&crc_list.lock); + pm_runtime_get_sync(ctx->crc->dev); + /* Reset, set key, poly and configure in bit reverse mode */ writel_relaxed(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT); writel_relaxed(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL); @@ -115,6 +120,9 @@ static int stm32_crc_init(struct shash_desc *desc) ctx->partial = readl_relaxed(ctx->crc->regs + CRC_DR); ctx->crc->nb_pending_bytes = 0; + pm_runtime_mark_last_busy(ctx->crc->dev); + pm_runtime_put_autosuspend(ctx->crc->dev); + return 0; } @@ -126,6 +134,8 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, u32 *d32; unsigned int i; + pm_runtime_get_sync(crc->dev); + if (unlikely(crc->nb_pending_bytes)) { while (crc->nb_pending_bytes != sizeof(u32) && length) { /* Fill in pending data */ @@ -149,6 +159,9 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, /* Store partial result */ ctx->partial = readl_relaxed(crc->regs + CRC_DR); + pm_runtime_mark_last_busy(crc->dev); + pm_runtime_put_autosuspend(crc->dev); + /* Check for pending data (non 32 bits) */ length &= 3; if (likely(!length)) @@ -272,6 +285,13 @@ static int stm32_crc_probe(struct platform_device *pdev) return ret; } + pm_runtime_set_autosuspend_delay(dev, CRC_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + platform_set_drvdata(pdev, crc); spin_lock(&crc_list.lock); @@ -287,12 +307,18 @@ static int stm32_crc_probe(struct platform_device *pdev) dev_info(dev, "Initialized\n"); + pm_runtime_put_sync(dev); + return 0; } static int stm32_crc_remove(struct platform_device *pdev) { struct stm32_crc *crc = platform_get_drvdata(pdev); + int ret = pm_runtime_get_sync(crc->dev); + + if (ret < 0) + return ret; spin_lock(&crc_list.lock); list_del(&crc->list); @@ -300,11 +326,46 @@ static int stm32_crc_remove(struct platform_device *pdev) crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); + pm_runtime_disable(crc->dev); + pm_runtime_put_noidle(crc->dev); + clk_disable_unprepare(crc->clk); return 0; } +#ifdef CONFIG_PM +static int stm32_crc_runtime_suspend(struct device *dev) +{ + struct stm32_crc *crc = dev_get_drvdata(dev); + + clk_disable_unprepare(crc->clk); + + return 0; +} + +static int stm32_crc_runtime_resume(struct device *dev) +{ + struct stm32_crc *crc = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(crc->clk); + if (ret) { + dev_err(crc->dev, "Failed to prepare_enable clock\n"); + return ret; + } + + return 0; +} +#endif + +static const struct dev_pm_ops stm32_crc_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend, + stm32_crc_runtime_resume, NULL) +}; + static const struct of_device_id stm32_dt_ids[] = { { .compatible = "st,stm32f7-crc", }, {}, @@ -316,6 +377,7 @@ static struct platform_driver stm32_crc_driver = { .remove = stm32_crc_remove, .driver = { .name = DRIVER_NAME, + .pm = &stm32_crc_pm_ops, .of_match_table = stm32_dt_ids, }, }; -- 2.7.4