From 16994088fd1f1086f80fdb8fee5dc2c8ba3c951c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 4 Nov 2018 00:13:01 +0100 Subject: [PATCH] drivers: entropy: add Atmel SAM entropy generator driver Tested on the Atmel SAM E70 Xplained board. Signed-off-by: Aurelien Jarno --- drivers/entropy/CMakeLists.txt | 1 + drivers/entropy/Kconfig | 1 + drivers/entropy/Kconfig.sam | 14 +++ drivers/entropy/entropy_sam.c | 95 +++++++++++++++++++ dts/arm/atmel/same70.dtsi | 9 ++ dts/bindings/rng/atmel,sam-trng.yaml | 45 +++++++++ .../atmel_sam/same70/Kconfig.defconfig.series | 5 + soc/arm/atmel_sam/same70/dts_fixup.h | 7 ++ 8 files changed, 177 insertions(+) create mode 100644 drivers/entropy/Kconfig.sam create mode 100644 drivers/entropy/entropy_sam.c create mode 100644 dts/bindings/rng/atmel,sam-trng.yaml diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index cba00551b14..5e1a321a758 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_ESP32_RNG entropy_esp32.c) zephyr_library_sources_ifdef(CONFIG_ENTROPY_MCUX_RNGA entropy_mcux_rnga.c) zephyr_library_sources_ifdef(CONFIG_ENTROPY_MCUX_TRNG entropy_mcux_trng.c) zephyr_library_sources_ifdef(CONFIG_ENTROPY_NRF5_RNG entropy_nrf5.c) +zephyr_library_sources_ifdef(CONFIG_ENTROPY_SAM_RNG entropy_sam.c) zephyr_library_sources_ifdef(CONFIG_ENTROPY_STM32_RNG entropy_stm32.c) zephyr_library_sources_ifdef(CONFIG_FAKE_ENTROPY_NATIVE_POSIX fake_entropy_native_posix.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE entropy_handlers.c) diff --git a/drivers/entropy/Kconfig b/drivers/entropy/Kconfig index 79ae7f8c965..ca0803f7249 100644 --- a/drivers/entropy/Kconfig +++ b/drivers/entropy/Kconfig @@ -17,6 +17,7 @@ source "drivers/entropy/Kconfig.mcux" source "drivers/entropy/Kconfig.stm32" source "drivers/entropy/Kconfig.esp32" source "drivers/entropy/Kconfig.nrf5" +source "drivers/entropy/Kconfig.sam" source "drivers/entropy/Kconfig.native_posix" config ENTROPY_HAS_DRIVER diff --git a/drivers/entropy/Kconfig.sam b/drivers/entropy/Kconfig.sam new file mode 100644 index 00000000000..8639af7e853 --- /dev/null +++ b/drivers/entropy/Kconfig.sam @@ -0,0 +1,14 @@ +# Kconfig.sam - Atmel SAM TRNG configuration +# +# Copyright (c) 2018 Aurelien Jarno +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ENTROPY_SAM_RNG + bool "Atmel SAM MCU Family True Random Number Generator (TRNG) Driver" + depends on SOC_FAMILY_SAM + depends on ENTROPY_GENERATOR + select ENTROPY_HAS_DRIVER + select HAS_DTS_ENTROPY + help + Enable True Random Number Generator (TRNG) driver for Atmel SAM MCUs. diff --git a/drivers/entropy/entropy_sam.c b/drivers/entropy/entropy_sam.c new file mode 100644 index 00000000000..2da922e6788 --- /dev/null +++ b/drivers/entropy/entropy_sam.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018 Aurelien Jarno + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +struct trng_sam_dev_cfg { + Trng *regs; +}; + +#define DEV_CFG(dev) \ + ((const struct trng_sam_dev_cfg *const)(dev)->config->config_info) + +static int entropy_sam_wait_ready(Trng *const trng) +{ + /* According to the reference manual, the generator provides + * one 32-bit random value every 84 peripheral clock cycles. + * MCK may not be smaller than HCLK/4, so it should not take + * more than 336 HCLK ticks. Assuming the CPU can do 1 + * instruction per HCLK the number of times to loop before + * the TRNG is ready is less than 1000. And that is when + * assuming the loop only takes 1 instruction. So looping a + * million times should be more than enough. + */ + int timeout = 1000000; + + while (!(trng->TRNG_ISR & TRNG_ISR_DATRDY)) { + if (timeout-- == 0) { + return -ETIMEDOUT; + } + + k_yield(); + } + + return 0; +} + +static int entropy_sam_get_entropy(struct device *dev, u8_t *buffer, + u16_t length) +{ + Trng *const trng = DEV_CFG(dev)->regs; + + while (length > 0) { + size_t to_copy; + u32_t value; + int res; + + res = entropy_sam_wait_ready(trng); + if (res < 0) { + return res; + } + + value = trng->TRNG_ODATA; + to_copy = min(length, sizeof(value)); + + memcpy(buffer, &value, to_copy); + buffer += to_copy; + length -= to_copy; + } + + return 0; +} + +static int entropy_sam_init(struct device *dev) +{ + Trng *const trng = DEV_CFG(dev)->regs; + + /* Enable the user interface clock */ + soc_pmc_peripheral_enable(DT_ENTROPY_SAM_TRNG_PERIPHERAL_ID); + + /* Enable the TRNG */ + trng->TRNG_CR = TRNG_CR_KEY_PASSWD | TRNG_CR_ENABLE; + + return 0; +} + +static const struct entropy_driver_api entropy_sam_api = { + .get_entropy = entropy_sam_get_entropy +}; + +static const struct trng_sam_dev_cfg trng_sam_cfg = { + .regs = (Trng *)DT_ENTROPY_SAM_TRNG_BASE_ADDRESS, +}; + +DEVICE_AND_API_INIT(entropy_sam, CONFIG_ENTROPY_NAME, + entropy_sam_init, NULL, &trng_sam_cfg, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &entropy_sam_api); diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index 3d540d19746..d4e11c7a845 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -252,6 +252,15 @@ status = "disabled"; label = "USBHS"; }; + + trng: random@40070000 { + compatible = "atmel,sam-trng"; + reg = <0x40070000 0x4000>; + interrupts = <57 0>; + peripheral-id = <57>; + status = "ok"; + label = "TRNG"; + }; }; }; diff --git a/dts/bindings/rng/atmel,sam-trng.yaml b/dts/bindings/rng/atmel,sam-trng.yaml new file mode 100644 index 00000000000..db5d1e2a986 --- /dev/null +++ b/dts/bindings/rng/atmel,sam-trng.yaml @@ -0,0 +1,45 @@ +# +# Copyright (c) 2018, Aurelien Jarno +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Atmel SAM TRNG (True Random Number Generator) +version: 0.1 + +description: > + This binding gives a base representation of the Atmel SAM RNG + +properties: + compatible: + type: string + category: required + description: compatible strings + constraint: "atmel,sam-trng" + generation: define + + reg: + type: int + description: mmio register space + generation: define + category: required + + interrupts: + type: compound + category: required + description: required interrupts + generation: define + + peripheral-id: + type: int + description: peripheral ID + generation: define + category: required + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for API name) + generation: define + +... diff --git a/soc/arm/atmel_sam/same70/Kconfig.defconfig.series b/soc/arm/atmel_sam/same70/Kconfig.defconfig.series index 5637ecdd20d..c163ba1eafc 100644 --- a/soc/arm/atmel_sam/same70/Kconfig.defconfig.series +++ b/soc/arm/atmel_sam/same70/Kconfig.defconfig.series @@ -73,4 +73,9 @@ config USB_DC_SAM default y endif # USB +if ENTROPY_GENERATOR +config ENTROPY_SAM_RNG + default y +endif # ENTROPY_GENERATOR + endif # SOC_SERIES_SAME70 diff --git a/soc/arm/atmel_sam/same70/dts_fixup.h b/soc/arm/atmel_sam/same70/dts_fixup.h index ad0813bc1dc..086116bc108 100644 --- a/soc/arm/atmel_sam/same70/dts_fixup.h +++ b/soc/arm/atmel_sam/same70/dts_fixup.h @@ -128,4 +128,11 @@ #define DT_USBHS_PERIPHERAL_ID DT_ATMEL_SAM_USBHS_40038000_PERIPHERAL_ID #define DT_USBHS_RAM_BASE_ADDRESS DT_ATMEL_SAM_USBHS_40038000_RAM_0 +#define DT_ENTROPY_SAM_TRNG_BASE_ADDRESS DT_ATMEL_SAM_TRNG_40070000_BASE_ADDRESS +#define DT_ENTROPY_SAM_TRNG_IRQ DT_ATMEL_SAM_TRNG_40070000_IRQ_0 +#define DT_ENTROPY_SAM_TRNG_IRQ_PRI DT_ATMEL_SAM_TRNG_40070000_IRQ_0_PRIORITY +#define DT_ENTROPY_SAM_TRNG_PERIPHERAL_ID DT_ATMEL_SAM_TRNG_40070000_PERIPHERAL_ID +#define DT_ENTROPY_SAM_TRNG_NAME DT_ATMEL_SAM_TRNG_40070000_LABEL +#define CONFIG_ENTROPY_NAME DT_ATMEL_SAM_TRNG_40070000_LABEL + /* End of SoC Level DTS fixup file */