From 77e0c6087923574579abe1a04538bb4982e33d55 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Tue, 19 Sep 2023 17:27:53 +0200 Subject: rng: stm32: rename STM32 RNG driver Rename the RNG driver as it is usable by other STM32 platforms than the STM32MP1x ones. Rename CONFIG_RNG_STM32MP1 to CONFIG_RNG_STM32 Signed-off-by: Gatien Chevallier Reviewed-by: Grzegorz Szymaszek Reviewed-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/rng/stm32_rng.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 drivers/rng/stm32_rng.c (limited to 'drivers/rng/stm32_rng.c') diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c new file mode 100644 index 00000000000..89da78c6c8b --- /dev/null +++ b/drivers/rng/stm32_rng.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019, Linaro Limited + */ + +#define LOG_CATEGORY UCLASS_RNG + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RNG_CR 0x00 +#define RNG_CR_RNGEN BIT(2) +#define RNG_CR_CED BIT(5) +#define RNG_CR_CONDRST BIT(30) + +#define RNG_SR 0x04 +#define RNG_SR_SEIS BIT(6) +#define RNG_SR_CEIS BIT(5) +#define RNG_SR_SECS BIT(2) +#define RNG_SR_DRDY BIT(0) + +#define RNG_DR 0x08 + +struct stm32_rng_data { + bool has_cond_reset; +}; + +struct stm32_rng_plat { + fdt_addr_t base; + struct clk clk; + struct reset_ctl rst; + const struct stm32_rng_data *data; +}; + +static int stm32_rng_read(struct udevice *dev, void *data, size_t len) +{ + int retval, i; + u32 sr, count, reg; + size_t increment; + struct stm32_rng_plat *pdata = dev_get_plat(dev); + + while (len > 0) { + retval = readl_poll_timeout(pdata->base + RNG_SR, sr, + sr & RNG_SR_DRDY, 10000); + if (retval) + return retval; + + if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) { + /* As per SoC TRM */ + clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS); + for (i = 0; i < 12; i++) + readl(pdata->base + RNG_DR); + if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) { + log_err("RNG Noise"); + return -EIO; + } + /* start again */ + continue; + } + + /* + * Once the DRDY bit is set, the RNG_DR register can + * be read four consecutive times. + */ + count = 4; + while (len && count) { + reg = readl(pdata->base + RNG_DR); + memcpy(data, ®, min(len, sizeof(u32))); + increment = min(len, sizeof(u32)); + data += increment; + len -= increment; + count--; + } + } + + return 0; +} + +static int stm32_rng_init(struct stm32_rng_plat *pdata) +{ + int err; + u32 cr, sr; + + err = clk_enable(&pdata->clk); + if (err) + return err; + + cr = readl(pdata->base + RNG_CR); + + /* Disable CED */ + cr |= RNG_CR_CED; + if (pdata->data->has_cond_reset) { + cr |= RNG_CR_CONDRST; + writel(cr, pdata->base + RNG_CR); + cr &= ~RNG_CR_CONDRST; + writel(cr, pdata->base + RNG_CR); + err = readl_poll_timeout(pdata->base + RNG_CR, cr, + (!(cr & RNG_CR_CONDRST)), 10000); + if (err) + return err; + } + + /* clear error indicators */ + writel(0, pdata->base + RNG_SR); + + cr |= RNG_CR_RNGEN; + writel(cr, pdata->base + RNG_CR); + + err = readl_poll_timeout(pdata->base + RNG_SR, sr, + sr & RNG_SR_DRDY, 10000); + return err; +} + +static int stm32_rng_cleanup(struct stm32_rng_plat *pdata) +{ + writel(0, pdata->base + RNG_CR); + + return clk_disable(&pdata->clk); +} + +static int stm32_rng_probe(struct udevice *dev) +{ + struct stm32_rng_plat *pdata = dev_get_plat(dev); + + pdata->data = (struct stm32_rng_data *)dev_get_driver_data(dev); + + reset_assert(&pdata->rst); + udelay(20); + reset_deassert(&pdata->rst); + + return stm32_rng_init(pdata); +} + +static int stm32_rng_remove(struct udevice *dev) +{ + struct stm32_rng_plat *pdata = dev_get_plat(dev); + + return stm32_rng_cleanup(pdata); +} + +static int stm32_rng_of_to_plat(struct udevice *dev) +{ + struct stm32_rng_plat *pdata = dev_get_plat(dev); + int err; + + pdata->base = dev_read_addr(dev); + if (!pdata->base) + return -ENOMEM; + + err = clk_get_by_index(dev, 0, &pdata->clk); + if (err) + return err; + + err = reset_get_by_index(dev, 0, &pdata->rst); + if (err) + return err; + + return 0; +} + +static const struct dm_rng_ops stm32_rng_ops = { + .read = stm32_rng_read, +}; + +static const struct stm32_rng_data stm32mp13_rng_data = { + .has_cond_reset = true, +}; + +static const struct stm32_rng_data stm32_rng_data = { + .has_cond_reset = false, +}; + +static const struct udevice_id stm32_rng_match[] = { + {.compatible = "st,stm32mp13-rng", .data = (ulong)&stm32mp13_rng_data}, + {.compatible = "st,stm32-rng", .data = (ulong)&stm32_rng_data}, + {}, +}; + +U_BOOT_DRIVER(stm32_rng) = { + .name = "stm32-rng", + .id = UCLASS_RNG, + .of_match = stm32_rng_match, + .ops = &stm32_rng_ops, + .probe = stm32_rng_probe, + .remove = stm32_rng_remove, + .plat_auto = sizeof(struct stm32_rng_plat), + .of_to_plat = stm32_rng_of_to_plat, +}; -- cgit v1.2.3 From 2d2574b4055f86f2fac57c6322e6487f15524baf Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Tue, 19 Sep 2023 17:27:55 +0200 Subject: rng: stm32: Implement configurable RNG clock error detection RNG clock error detection is now enabled if the "clock-error-detect" property is set in the device tree. Signed-off-by: Gatien Chevallier Reviewed-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/rng/stm32_rng.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/rng/stm32_rng.c') diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c index 89da78c6c8b..ada5d922141 100644 --- a/drivers/rng/stm32_rng.c +++ b/drivers/rng/stm32_rng.c @@ -40,6 +40,7 @@ struct stm32_rng_plat { struct clk clk; struct reset_ctl rst; const struct stm32_rng_data *data; + bool ced; }; static int stm32_rng_read(struct udevice *dev, void *data, size_t len) @@ -97,25 +98,34 @@ static int stm32_rng_init(struct stm32_rng_plat *pdata) cr = readl(pdata->base + RNG_CR); - /* Disable CED */ - cr |= RNG_CR_CED; if (pdata->data->has_cond_reset) { cr |= RNG_CR_CONDRST; + if (pdata->ced) + cr &= ~RNG_CR_CED; + else + cr |= RNG_CR_CED; writel(cr, pdata->base + RNG_CR); cr &= ~RNG_CR_CONDRST; + cr |= RNG_CR_RNGEN; writel(cr, pdata->base + RNG_CR); err = readl_poll_timeout(pdata->base + RNG_CR, cr, (!(cr & RNG_CR_CONDRST)), 10000); if (err) return err; + } else { + if (pdata->ced) + cr &= ~RNG_CR_CED; + else + cr |= RNG_CR_CED; + + cr |= RNG_CR_RNGEN; + + writel(cr, pdata->base + RNG_CR); } /* clear error indicators */ writel(0, pdata->base + RNG_SR); - cr |= RNG_CR_RNGEN; - writel(cr, pdata->base + RNG_CR); - err = readl_poll_timeout(pdata->base + RNG_SR, sr, sr & RNG_SR_DRDY, 10000); return err; @@ -165,6 +175,8 @@ static int stm32_rng_of_to_plat(struct udevice *dev) if (err) return err; + pdata->ced = dev_read_bool(dev, "clock-error-detect"); + return 0; } -- cgit v1.2.3 From 01af3636230656cdcba7a1c625c17a5c32a3fb69 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Tue, 19 Sep 2023 17:27:56 +0200 Subject: rng: stm32: add RNG clock frequency restraint In order to ensure a good RNG quality and compatibility with certified RNG configuration, add RNG clock frequency restraint. Signed-off-by: Gatien Chevallier Reviewed-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/rng/stm32_rng.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'drivers/rng/stm32_rng.c') diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c index ada5d922141..f943acd7d22 100644 --- a/drivers/rng/stm32_rng.c +++ b/drivers/rng/stm32_rng.c @@ -18,10 +18,11 @@ #include #include -#define RNG_CR 0x00 -#define RNG_CR_RNGEN BIT(2) -#define RNG_CR_CED BIT(5) -#define RNG_CR_CONDRST BIT(30) +#define RNG_CR 0x00 +#define RNG_CR_RNGEN BIT(2) +#define RNG_CR_CED BIT(5) +#define RNG_CR_CLKDIV_SHIFT 16 +#define RNG_CR_CONDRST BIT(30) #define RNG_SR 0x04 #define RNG_SR_SEIS BIT(6) @@ -31,7 +32,15 @@ #define RNG_DR 0x08 +/* + * struct stm32_rng_data - RNG compat data + * + * @max_clock_rate: Max RNG clock frequency, in Hertz + * @has_cond_reset: True if conditionnal reset is supported + * + */ struct stm32_rng_data { + uint max_clock_rate; bool has_cond_reset; }; @@ -87,6 +96,26 @@ static int stm32_rng_read(struct udevice *dev, void *data, size_t len) return 0; } +static uint stm32_rng_clock_freq_restrain(struct stm32_rng_plat *pdata) +{ + ulong clock_rate = 0; + uint clock_div = 0; + + clock_rate = clk_get_rate(&pdata->clk); + + /* + * Get the exponent to apply on the CLKDIV field in RNG_CR register. + * No need to handle the case when clock-div > 0xF as it is physically + * impossible. + */ + while ((clock_rate >> clock_div) > pdata->data->max_clock_rate) + clock_div++; + + log_debug("RNG clk rate : %lu\n", clk_get_rate(&pdata->clk) >> clock_div); + + return clock_div; +} + static int stm32_rng_init(struct stm32_rng_plat *pdata) { int err; @@ -99,7 +128,9 @@ static int stm32_rng_init(struct stm32_rng_plat *pdata) cr = readl(pdata->base + RNG_CR); if (pdata->data->has_cond_reset) { - cr |= RNG_CR_CONDRST; + uint clock_div = stm32_rng_clock_freq_restrain(pdata); + + cr |= RNG_CR_CONDRST | (clock_div << RNG_CR_CLKDIV_SHIFT); if (pdata->ced) cr &= ~RNG_CR_CED; else @@ -186,10 +217,12 @@ static const struct dm_rng_ops stm32_rng_ops = { static const struct stm32_rng_data stm32mp13_rng_data = { .has_cond_reset = true, + .max_clock_rate = 48000000, }; static const struct stm32_rng_data stm32_rng_data = { .has_cond_reset = false, + .max_clock_rate = 3000000, }; static const struct udevice_id stm32_rng_match[] = { -- cgit v1.2.3 From 6032292534e0f47012edd76cd88b2c952856f928 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Tue, 19 Sep 2023 17:27:57 +0200 Subject: rng: stm32: add error concealment sequence Seed errors can occur when using the hardware RNG. Implement the sequences to handle them. This avoids irrecoverable RNG state. Try to conceal seed errors when possible. If, despite the error concealing tries, a seed error is still present, then return an error. A clock error does not compromise the hardware block and data can still be read from RNG_DR. Just warn that the RNG clock is too slow and clear RNG_SR. Signed-off-by: Gatien Chevallier Reviewed-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/rng/stm32_rng.c | 163 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 140 insertions(+), 23 deletions(-) (limited to 'drivers/rng/stm32_rng.c') diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c index f943acd7d22..b1a790b217f 100644 --- a/drivers/rng/stm32_rng.c +++ b/drivers/rng/stm32_rng.c @@ -32,6 +32,8 @@ #define RNG_DR 0x08 +#define RNG_NB_RECOVER_TRIES 3 + /* * struct stm32_rng_data - RNG compat data * @@ -52,45 +54,160 @@ struct stm32_rng_plat { bool ced; }; +/* + * Extracts from the STM32 RNG specification when RNG supports CONDRST. + * + * When a noise source (or seed) error occurs, the RNG stops generating + * random numbers and sets to “1” both SEIS and SECS bits to indicate + * that a seed error occurred. (...) + * + * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield + * description for details). This step is needed only if SECS is set. + * Indeed, when SEIS is set and SECS is cleared it means RNG performed + * the reset automatically (auto-reset). + * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST + * to be cleared in the RNG_CR register, then confirm that SEIS is + * cleared in the RNG_SR register. Otherwise just clear SEIS bit in + * the RNG_SR register. + * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be + * cleared by RNG. The random number generation is now back to normal. + */ +static int stm32_rng_conceal_seed_error_cond_reset(struct stm32_rng_plat *pdata) +{ + u32 sr = readl_relaxed(pdata->base + RNG_SR); + u32 cr = readl_relaxed(pdata->base + RNG_CR); + int err; + + if (sr & RNG_SR_SECS) { + /* Conceal by resetting the subsystem (step 1.) */ + writel_relaxed(cr | RNG_CR_CONDRST, pdata->base + RNG_CR); + writel_relaxed(cr & ~RNG_CR_CONDRST, pdata->base + RNG_CR); + } else { + /* RNG auto-reset (step 2.) */ + writel_relaxed(sr & ~RNG_SR_SEIS, pdata->base + RNG_SR); + return 0; + } + + err = readl_relaxed_poll_timeout(pdata->base + RNG_SR, sr, !(sr & RNG_CR_CONDRST), 100000); + if (err) { + log_err("%s: timeout %x\n", __func__, sr); + return err; + } + + /* Check SEIS is cleared (step 2.) */ + if (readl_relaxed(pdata->base + RNG_SR) & RNG_SR_SEIS) + return -EINVAL; + + err = readl_relaxed_poll_timeout(pdata->base + RNG_SR, sr, !(sr & RNG_SR_SECS), 100000); + if (err) { + log_err("%s: timeout %x\n", __func__, sr); + return err; + } + + return 0; +} + +/* + * Extracts from the STM32 RNG specification, when CONDRST is not supported + * + * When a noise source (or seed) error occurs, the RNG stops generating + * random numbers and sets to “1” both SEIS and SECS bits to indicate + * that a seed error occurred. (...) + * + * The following sequence shall be used to fully recover from a seed + * error after the RNG initialization: + * 1. Clear the SEIS bit by writing it to “0”. + * 2. Read out 12 words from the RNG_DR register, and discard each of + * them in order to clean the pipeline. + * 3. Confirm that SEIS is still cleared. Random number generation is + * back to normal. + */ +static int stm32_rng_conceal_seed_error_sw_reset(struct stm32_rng_plat *pdata) +{ + uint i = 0; + u32 sr = readl_relaxed(pdata->base + RNG_SR); + + writel_relaxed(sr & ~RNG_SR_SEIS, pdata->base + RNG_SR); + + for (i = 12; i != 0; i--) + (void)readl_relaxed(pdata->base + RNG_DR); + + if (readl_relaxed(pdata->base + RNG_SR) & RNG_SR_SEIS) + return -EINVAL; + + return 0; +} + +static int stm32_rng_conceal_seed_error(struct stm32_rng_plat *pdata) +{ + log_debug("Concealing RNG seed error\n"); + + if (pdata->data->has_cond_reset) + return stm32_rng_conceal_seed_error_cond_reset(pdata); + else + return stm32_rng_conceal_seed_error_sw_reset(pdata); +}; + static int stm32_rng_read(struct udevice *dev, void *data, size_t len) { - int retval, i; - u32 sr, count, reg; + int retval; + u32 sr, reg; size_t increment; struct stm32_rng_plat *pdata = dev_get_plat(dev); + uint tries = 0; while (len > 0) { retval = readl_poll_timeout(pdata->base + RNG_SR, sr, - sr & RNG_SR_DRDY, 10000); - if (retval) + sr, 10000); + if (retval) { + log_err("%s: Timeout RNG no data", __func__); return retval; + } - if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) { - /* As per SoC TRM */ - clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS); - for (i = 0; i < 12; i++) - readl(pdata->base + RNG_DR); - if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) { - log_err("RNG Noise"); - return -EIO; + if (sr != RNG_SR_DRDY) { + if (sr & RNG_SR_SEIS) { + retval = stm32_rng_conceal_seed_error(pdata); + tries++; + if (retval || tries > RNG_NB_RECOVER_TRIES) { + log_err("%s: Couldn't recover from seed error", __func__); + return -ENOTRECOVERABLE; + } + + /* Start again */ + continue; + } + + if (sr & RNG_SR_CEIS) { + log_info("RNG clock too slow"); + writel_relaxed(0, pdata->base + RNG_SR); } - /* start again */ - continue; } /* * Once the DRDY bit is set, the RNG_DR register can - * be read four consecutive times. + * be read up to four consecutive times. */ - count = 4; - while (len && count) { - reg = readl(pdata->base + RNG_DR); - memcpy(data, ®, min(len, sizeof(u32))); - increment = min(len, sizeof(u32)); - data += increment; - len -= increment; - count--; + reg = readl(pdata->base + RNG_DR); + /* Late seed error case: DR being 0 is an error status */ + if (!reg) { + retval = stm32_rng_conceal_seed_error(pdata); + tries++; + + if (retval || tries > RNG_NB_RECOVER_TRIES) { + log_err("%s: Couldn't recover from seed error", __func__); + return -ENOTRECOVERABLE; + } + + /* Start again */ + continue; } + + increment = min(len, sizeof(u32)); + memcpy(data, ®, increment); + data += increment; + len -= increment; + + tries = 0; } return 0; -- cgit v1.2.3 From e077d7f61309d83fa94c55b17bfccc255b4467fb Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Tue, 19 Sep 2023 17:27:58 +0200 Subject: rng: stm32: Implement custom RNG configuration support STM32 RNG configuration should best fit the requirements of the platform. Therefore, put a platform-specific RNG configuration field in the platform data. Default RNG configuration for STM32MP13 is the NIST certified configuration [1]. While there, fix and the RNG init sequence to support all RNG versions. [1] https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/53 Signed-off-by: Gatien Chevallier Reviewed-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/rng/stm32_rng.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'drivers/rng/stm32_rng.c') diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c index b1a790b217f..c397b4d95cd 100644 --- a/drivers/rng/stm32_rng.c +++ b/drivers/rng/stm32_rng.c @@ -21,8 +21,15 @@ #define RNG_CR 0x00 #define RNG_CR_RNGEN BIT(2) #define RNG_CR_CED BIT(5) +#define RNG_CR_CONFIG1 GENMASK(11, 8) +#define RNG_CR_NISTC BIT(12) +#define RNG_CR_CONFIG2 GENMASK(15, 13) #define RNG_CR_CLKDIV_SHIFT 16 +#define RNG_CR_CLKDIV GENMASK(19, 16) +#define RNG_CR_CONFIG3 GENMASK(25, 20) #define RNG_CR_CONDRST BIT(30) +#define RNG_CR_ENTROPY_SRC_MASK (RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3) +#define RNG_CR_CONFIG_MASK (RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | RNG_CR_CLKDIV) #define RNG_SR 0x04 #define RNG_SR_SEIS BIT(6) @@ -32,17 +39,28 @@ #define RNG_DR 0x08 +#define RNG_NSCR 0x0C +#define RNG_NSCR_MASK GENMASK(17, 0) + +#define RNG_HTCR 0x10 + #define RNG_NB_RECOVER_TRIES 3 /* * struct stm32_rng_data - RNG compat data * * @max_clock_rate: Max RNG clock frequency, in Hertz + * @cr: Entropy source configuration + * @nscr: Noice sources control configuration + * @htcr: Health tests configuration * @has_cond_reset: True if conditionnal reset is supported * */ struct stm32_rng_data { uint max_clock_rate; + u32 cr; + u32 nscr; + u32 htcr; bool has_cond_reset; }; @@ -244,28 +262,48 @@ static int stm32_rng_init(struct stm32_rng_plat *pdata) cr = readl(pdata->base + RNG_CR); - if (pdata->data->has_cond_reset) { + /* + * Keep default RNG configuration if none was specified, that is when conf.cr is set to 0. + */ + if (pdata->data->has_cond_reset && pdata->data->cr) { uint clock_div = stm32_rng_clock_freq_restrain(pdata); - cr |= RNG_CR_CONDRST | (clock_div << RNG_CR_CLKDIV_SHIFT); + cr &= ~RNG_CR_CONFIG_MASK; + cr |= RNG_CR_CONDRST | (pdata->data->cr & RNG_CR_ENTROPY_SRC_MASK) | + (clock_div << RNG_CR_CLKDIV_SHIFT); if (pdata->ced) cr &= ~RNG_CR_CED; else cr |= RNG_CR_CED; writel(cr, pdata->base + RNG_CR); + + /* Health tests and noise control registers */ + writel_relaxed(pdata->data->htcr, pdata->base + RNG_HTCR); + writel_relaxed(pdata->data->nscr & RNG_NSCR_MASK, pdata->base + RNG_NSCR); + cr &= ~RNG_CR_CONDRST; cr |= RNG_CR_RNGEN; writel(cr, pdata->base + RNG_CR); err = readl_poll_timeout(pdata->base + RNG_CR, cr, (!(cr & RNG_CR_CONDRST)), 10000); - if (err) + if (err) { + log_err("%s: Timeout!", __func__); return err; + } } else { + if (pdata->data->has_cond_reset) + cr |= RNG_CR_CONDRST; + if (pdata->ced) cr &= ~RNG_CR_CED; else cr |= RNG_CR_CED; + writel(cr, pdata->base + RNG_CR); + + if (pdata->data->has_cond_reset) + cr &= ~RNG_CR_CONDRST; + cr |= RNG_CR_RNGEN; writel(cr, pdata->base + RNG_CR); @@ -276,6 +314,9 @@ static int stm32_rng_init(struct stm32_rng_plat *pdata) err = readl_poll_timeout(pdata->base + RNG_SR, sr, sr & RNG_SR_DRDY, 10000); + if (err) + log_err("%s: Timeout!", __func__); + return err; } @@ -335,11 +376,18 @@ static const struct dm_rng_ops stm32_rng_ops = { static const struct stm32_rng_data stm32mp13_rng_data = { .has_cond_reset = true, .max_clock_rate = 48000000, + .htcr = 0x969D, + .nscr = 0x2B5BB, + .cr = 0xF00D00, }; static const struct stm32_rng_data stm32_rng_data = { .has_cond_reset = false, .max_clock_rate = 3000000, + /* Not supported */ + .htcr = 0, + .nscr = 0, + .cr = 0, }; static const struct udevice_id stm32_rng_match[] = { -- cgit v1.2.3