From 6e8bc42dbd8710b99cdba92c40a1aec1eabcb0d6 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 9 Jul 2018 15:59:24 +0800 Subject: stm32h7: Add support for TRNG STM32H7 contains a True Random Number Generator. Add support for that. We source rng_clk from HSI48 oscillator (confusingly misspelled hsi8_clk in RM), and fine-tune number of tries to make sure we wait long enough for a random number, no matter the CPU speed (64 or 400 MHz). We also add a console command to test the random number generator (disabled by default). BRANCH=none BUG=b:111190988 TEST=reboot; clock pll; rand => works. TEST=reboot; rand => works. Change-Id: I45624ff4df30b6a332226245e02e3e435b9b15bf Signed-off-by: Nicolas Boichat Reviewed-on: https://chromium-review.googlesource.com/1128785 Reviewed-by: Randall Spangler --- chip/stm32/registers.h | 12 ++++++++++++ chip/stm32/trng.c | 38 +++++++++++++++++++++++++++++++++++++- include/config.h | 1 + 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 37a49da00a..2028aa9325 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -411,6 +411,7 @@ #define STM32_PWR_BASE 0x58024800 #define STM32_RCC_BASE 0x58024400 +#define STM32_RNG_BASE 0x48021800 #define STM32_RTC_BASE 0x58004000 #define STM32_SYSCFG_BASE 0x58000400 @@ -1411,6 +1412,9 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x0D4) #define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x0D8) #define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x0DC) +#define STM32_RCC_AHB2ENR_RNGEN (1 << 6) +#define STM32_RCC_AHB2ENR_HASHEN (1 << 5) +#define STM32_RCC_AHB2ENR_CRYPTEN (1 << 4) #define STM32_RCC_AHB4ENR REG32(STM32_RCC_BASE + 0x0E0) #define STM32_RCC_AHB4ENR_GPIOMASK 0x3ff #define STM32_RCC_APB3ENR REG32(STM32_RCC_BASE + 0x0E4) @@ -1435,6 +1439,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_CR_HSIRDY (1 << 2) #define STM32_RCC_CR_CSION (1 << 7) #define STM32_RCC_CR_CSIRDY (1 << 8) +#define STM32_RCC_CR_HSI48ON (1 << 12) +#define STM32_RCC_CR_HSI48RDY (1 << 13) #define STM32_RCC_CR_PLL1ON (1 << 24) #define STM32_RCC_CR_PLL1RDY (1 << 25) #define STM32_RCC_CR_PLL2ON (1 << 26) @@ -1516,6 +1522,11 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_D2CCIP2_USART16SEL_CSI (4 << 3) #define STM32_RCC_D2CCIP2_USART16SEL_LSE (5 << 3) #define STM32_RCC_D2CCIP2_USART16SEL_MASK (7 << 3) +#define STM32_RCC_D2CCIP2_RNGSEL_HSI48 (0 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_PLL1Q (1 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_LSE (2 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_LSI (3 << 8) +#define STM32_RCC_D2CCIP2_RNGSEL_MASK (3 << 8) #define STM32_RCC_D2CCIP2_LPTIM1SEL_PCLK (0 << 28) #define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL2 (1 << 28) #define STM32_RCC_D2CCIP2_LPTIM1SEL_PLL3 (2 << 28) @@ -3049,6 +3060,7 @@ enum dmamux1_request { #define STM32_RNG_CR REG32(STM32_RNG_BASE + 0x0) #define STM32_RNG_CR_RNGEN (1<<2) #define STM32_RNG_CR_IE (1<<3) +#define STM32_RNG_CR_CED (1<<5) #define STM32_RNG_SR REG32(STM32_RNG_BASE + 0x4) #define STM32_RNG_SR_DRDY (1<<0) #define STM32_RNG_DR REG32(STM32_RNG_BASE + 0x8) diff --git a/chip/stm32/trng.c b/chip/stm32/trng.c index e19f93d688..7799c03f93 100644 --- a/chip/stm32/trng.c +++ b/chip/stm32/trng.c @@ -6,6 +6,7 @@ /* Hardware Random Number Generator */ #include "common.h" +#include "console.h" #include "panic.h" #include "registers.h" #include "task.h" @@ -14,7 +15,7 @@ uint32_t rand(void) { - int tries = 40; + int tries = 300; /* Wait for a valid random number */ while (!(STM32_RNG_SR & STM32_RNG_SR_DRDY) && --tries) ; @@ -46,6 +47,7 @@ void rand_bytes(void *buffer, size_t len) void init_trng(void) { +#ifdef CHIP_FAMILY_STM32L4 /* Enable the 48Mhz internal RC oscillator */ STM32_RCC_CRRCR |= STM32_RCC_CRRCR_HSI48ON; /* no timeout: we watchdog if the oscillator doesn't start */ @@ -55,7 +57,20 @@ void init_trng(void) /* Clock the TRNG using the HSI48 */ STM32_RCC_CCIPR = (STM32_RCC_CCIPR & ~STM32_RCC_CCIPR_CLK48SEL_MASK) | (0 << STM32_RCC_CCIPR_CLK48SEL_SHIFT); +#elif defined(CHIP_FAMILY_STM32H7) + /* Enable the 48Mhz internal RC oscillator */ + STM32_RCC_CR |= STM32_RCC_CR_HSI48ON; + /* no timeout: we watchdog if the oscillator doesn't start */ + while (!(STM32_RCC_CR & STM32_RCC_CR_HSI48RDY)) + ; + /* Clock the TRNG using the HSI48 */ + STM32_RCC_D2CCIP2R = + (STM32_RCC_D2CCIP2R & ~STM32_RCC_D2CCIP2_RNGSEL_MASK) + | STM32_RCC_D2CCIP2_RNGSEL_HSI48; +#else +#error "Please add support for CONFIG_RNG on this chip family." +#endif /* Enable the RNG logic */ STM32_RCC_AHB2ENR |= STM32_RCC_AHB2ENR_RNGEN; /* Start the random number generation */ @@ -66,5 +81,26 @@ void exit_trng(void) { STM32_RNG_CR &= ~STM32_RNG_CR_RNGEN; STM32_RCC_AHB2ENR &= ~STM32_RCC_AHB2ENR_RNGEN; +#ifdef CHIP_FAMILY_STM32L4 STM32_RCC_CRRCR &= ~STM32_RCC_CRRCR_HSI48ON; +#elif defined(CHIP_FAMILY_STM32H7) + STM32_RCC_CR &= ~STM32_RCC_CR_HSI48ON; +#endif +} + +#ifdef CONFIG_CMD_RAND +static int command_rand(int argc, char **argv) +{ + uint8_t data[32]; + + init_trng(); + rand_bytes(data, sizeof(data)); + exit_trng(); + + ccprintf("rand %.*h\n", sizeof(data), data); + + return EC_SUCCESS; } +DECLARE_CONSOLE_COMMAND(rand, command_rand, + NULL, "Output random bytes to console."); +#endif diff --git a/include/config.h b/include/config.h index bc84b4ee3f..7a0eadd75b 100644 --- a/include/config.h +++ b/include/config.h @@ -920,6 +920,7 @@ #define CONFIG_CMD_PWR_AVG #define CONFIG_CMD_POWER_AP #undef CONFIG_CMD_PPC_DUMP +#undef CONFIG_CMD_RAND #define CONFIG_CMD_REGULATOR #undef CONFIG_CMD_RTC #undef CONFIG_CMD_RTC_ALARM -- cgit v1.2.1