From 2bee500f062e7adaf58aaf61b38eb0c3f1efd86c Mon Sep 17 00:00:00 2001 From: Brett Witherspoon Date: Thu, 25 Apr 2019 18:07:31 -0500 Subject: [PATCH] drivers: add CC13xx / CC26xx entropy driver Add driver for the TRNG entropy source on the TI CC13xx / CC26xx series SoCs. Signed-off-by: Brett Witherspoon --- drivers/entropy/CMakeLists.txt | 1 + drivers/entropy/Kconfig | 1 + drivers/entropy/Kconfig.cc13xx_cc26xx | 51 ++++++ drivers/entropy/entropy_cc13xx_cc26xx.c | 170 ++++++++++++++++++ dts/arm/ti/cc13x2_cc26x2.dtsi | 8 + dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml | 39 ++++ .../cc13x2_cc26x2/Kconfig.defconfig.series | 7 + .../ti_simplelink/cc13x2_cc26x2/dts_fixup.h | 1 + 8 files changed, 278 insertions(+) create mode 100644 drivers/entropy/Kconfig.cc13xx_cc26xx create mode 100644 drivers/entropy/entropy_cc13xx_cc26xx.c create mode 100644 dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index 491dea058b..2b26f08977 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -2,6 +2,7 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_ENTROPY_CC13XX_CC26XX_RNG entropy_cc13xx_cc26xx.c) 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) diff --git a/drivers/entropy/Kconfig b/drivers/entropy/Kconfig index ca0803f724..24ec9b13aa 100644 --- a/drivers/entropy/Kconfig +++ b/drivers/entropy/Kconfig @@ -13,6 +13,7 @@ menuconfig ENTROPY_GENERATOR if ENTROPY_GENERATOR +source "drivers/entropy/Kconfig.cc13xx_cc26xx" source "drivers/entropy/Kconfig.mcux" source "drivers/entropy/Kconfig.stm32" source "drivers/entropy/Kconfig.esp32" diff --git a/drivers/entropy/Kconfig.cc13xx_cc26xx b/drivers/entropy/Kconfig.cc13xx_cc26xx new file mode 100644 index 0000000000..209e5a1d66 --- /dev/null +++ b/drivers/entropy/Kconfig.cc13xx_cc26xx @@ -0,0 +1,51 @@ +# Kconfig.cc13xx_cc26xx - TI CC13xx / CC26xx entropy driver configuration +# +# Copyright (c) 2019 Brett Witherspoon +# +# SPDX-License-Identifier: Apache-2.0 + +config ENTROPY_CC13XX_CC26XX_RNG + bool "TI SimpleLink CC13xx / CC26xx True Random Number Generator (TRNG)" + depends on SOC_SERIES_CC13X2_CC26X2 + select ENTROPY_HAS_DRIVER + select HAS_DTS_ENTROPY + select RING_BUFFER + help + This option enables the driver for the True Random Number Generator (TRNG) + for TI SimpleLink CC13xx / CC26xx SoCs. + +if ENTROPY_CC13XX_CC26XX_RNG + +config ENTROPY_CC13XX_CC26XX_POOL_SIZE + int "Number of bytes in the entropy pool" + default 512 + help + The size in bytes of the buffer used to store entropy generated by the + hardware. Should be a power of two for high performance. + +config ENTROPY_CC13XX_CC26XX_SAMPLES_PER_CYCLE + int "Number of samples to generate entropy" + range 256 16777216 + default 240000 + help + The number of samples used to generate entropy. The time required to + generate 64 bits of entropy is determined by the number of FROs enabled, + the sampling (system) clock frequency, and this value. + +config ENTROPY_CC13XX_CC26XX_ALARM_THRESHOLD + int "Threshold for detected repeated patterns" + range 0 255 + default 255 + help + The number of samples detected with repeating patterns before an alarm + event is triggered. The associated FRO is automatically shut down. + +config ENTROPY_CC13XX_CC26XX_SHUTDOWN_THRESHOLD + int "Threshold for the number of FROs automatically shut down" + range 0 24 + default 0 + help + The number of FROs allowed to be shutdown before the driver attempts to + take corrective action. + +endif # ENTROPY_CC13XX_CC26XX_RNG diff --git a/drivers/entropy/entropy_cc13xx_cc26xx.c b/drivers/entropy/entropy_cc13xx_cc26xx.c new file mode 100644 index 0000000000..50754de1d1 --- /dev/null +++ b/drivers/entropy/entropy_cc13xx_cc26xx.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019 Brett Witherspoon + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct entropy_cc13xx_cc26xx_data { + struct k_sem lock; + struct k_sem sync; + struct ring_buf pool; + u8_t data[CONFIG_ENTROPY_CC13XX_CC26XX_POOL_SIZE]; +}; + +DEVICE_DECLARE(entropy_cc13xx_cc26xx); + +static inline struct entropy_cc13xx_cc26xx_data * +get_dev_data(struct device *dev) +{ + return dev->driver_data; +} + +static int entropy_cc13xx_cc26xx_get_entropy(struct device *dev, u8_t *buf, + u16_t len) +{ + struct entropy_cc13xx_cc26xx_data *data = get_dev_data(dev); + u32_t cnt; + + TRNGIntEnable(TRNG_NUMBER_READY); + + while (len) { + k_sem_take(&data->lock, K_FOREVER); + cnt = ring_buf_get(&data->pool, buf, len); + k_sem_give(&data->lock); + + if (cnt) { + buf += cnt; + len -= cnt; + } else { + k_sem_take(&data->sync, K_FOREVER); + } + } + + return 0; +} + +static void entropy_cc13xx_cc26xx_isr(void *arg) +{ + struct entropy_cc13xx_cc26xx_data *data = get_dev_data(arg); + u32_t src, cnt, off; + u32_t num[2]; + + /* Interrupt service routine as described in TRM section 18.6.1.3.2 */ + src = TRNGStatusGet(); + + if (src & TRNG_NUMBER_READY) { + /* This function acknowledges the ready status */ + num[1] = TRNGNumberGet(TRNG_HI_WORD); + num[0] = TRNGNumberGet(TRNG_LOW_WORD); + + cnt = ring_buf_put(&data->pool, (u8_t *)num, sizeof(num)); + + /* When pool is full disable interrupt and stop reading numbers */ + if (cnt != sizeof(num)) { + TRNGIntDisable(TRNG_NUMBER_READY); + } + + k_sem_give(&data->sync); + } + + /* Change the shutdown FROs' oscillating frequncy in an attempt to + * prevent further locking on to the sampling clock frequncy. + */ + if (src & TRNG_FRO_SHUTDOWN) { + /* Clear shutdown */ + TRNGIntClear(TRNG_FRO_SHUTDOWN); + /* Disabled FROs */ + off = sys_read32(TRNG_BASE + TRNG_O_ALARMSTOP); + /* Clear alarms */ + sys_write32(0, TRNG_BASE + TRNG_O_ALARMMASK); + sys_write32(0, TRNG_BASE + TRNG_O_ALARMSTOP); + /* De-tune FROs */ + sys_write32(off, TRNG_BASE + TRNG_O_FRODETUNE); + /* Re-enable FROs */ + sys_write32(off, TRNG_BASE + TRNG_O_FROEN); + } +} + +static int entropy_cc13xx_cc26xx_init(struct device *dev) +{ + struct entropy_cc13xx_cc26xx_data *data = get_dev_data(dev); + + /* Power TRNG domain */ + PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH); + + /* Enable TRNG peripheral clocks */ + PRCMPeripheralRunEnable(PRCM_PERIPH_TRNG); + /* Enabled the TRNG while in sleep mode to keep the entropy pool full. After + * the pool is full the TRNG will enter idle mode when random numbers are no + * longer being read. */ + PRCMPeripheralSleepEnable(PRCM_PERIPH_TRNG); + PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_TRNG); + + + /* Load PRCM settings */ + PRCMLoadSet(); + while (!PRCMLoadGet()) { + continue; + } + + /* Peripherals should not be accessed until power domain is on. */ + while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON) { + continue; + } + + /* Initialize driver data */ + ring_buf_init(&data->pool, sizeof(data->data), data->data); + + /* Initialization as described in TRM section 18.6.1.2 */ + TRNGReset(); + while (sys_read32(TRNG_BASE + TRNG_O_SWRESET)) { + continue; + } + + /* Set samples per cycle */ + TRNGConfigure(0, CONFIG_ENTROPY_CC13XX_CC26XX_SAMPLES_PER_CYCLE, 0); + /* De-tune FROs */ + sys_write32(TRNG_FRODETUNE_FRO_MASK_M, TRNG_BASE + TRNG_O_FRODETUNE); + /* Enable FROs */ + sys_write32(TRNG_FROEN_FRO_MASK_M, TRNG_BASE + TRNG_O_FROEN); + /* Set shutdown and alarm thresholds */ + sys_write32((CONFIG_ENTROPY_CC13XX_CC26XX_SHUTDOWN_THRESHOLD << 16) | + CONFIG_ENTROPY_CC13XX_CC26XX_ALARM_THRESHOLD, + TRNG_BASE + TRNG_O_ALARMCNT); + + TRNGEnable(); + TRNGIntEnable(TRNG_NUMBER_READY | TRNG_FRO_SHUTDOWN); + + IRQ_CONNECT(DT_TI_CC13XX_CC26XX_TRNG_0_IRQ_0, + DT_TI_CC13XX_CC26XX_TRNG_0_IRQ_0_PRIORITY, + entropy_cc13xx_cc26xx_isr, + DEVICE_GET(entropy_cc13xx_cc26xx), 0); + irq_enable(DT_TI_CC13XX_CC26XX_TRNG_0_IRQ_0); + + return 0; +} + +static const struct entropy_driver_api entropy_cc13xx_cc26xx_driver_api = { + .get_entropy = entropy_cc13xx_cc26xx_get_entropy, +}; + +static struct entropy_cc13xx_cc26xx_data entropy_cc13xx_cc26xx_data = { + .lock = Z_SEM_INITIALIZER(entropy_cc13xx_cc26xx_data.lock, 1, 1), + .sync = Z_SEM_INITIALIZER(entropy_cc13xx_cc26xx_data.sync, 0, 1), +}; + +DEVICE_AND_API_INIT(entropy_cc13xx_cc26xx, DT_TI_CC13XX_CC26XX_TRNG_0_LABEL, + entropy_cc13xx_cc26xx_init, &entropy_cc13xx_cc26xx_data, + NULL, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &entropy_cc13xx_cc26xx_driver_api); diff --git a/dts/arm/ti/cc13x2_cc26x2.dtsi b/dts/arm/ti/cc13x2_cc26x2.dtsi index 83869d24c9..e601bbd664 100644 --- a/dts/arm/ti/cc13x2_cc26x2.dtsi +++ b/dts/arm/ti/cc13x2_cc26x2.dtsi @@ -52,6 +52,14 @@ #gpio-cells = <2>; }; + trng: random@40028000 { + compatible = "ti,cc13xx-cc26xx-trng"; + reg = <0x40028000 0x2000>; + interrupts = <33 0>; + status = "disabled"; + label = "TRNG"; + }; + uart0: uart@40001000 { compatible = "ti,cc13xx-cc26xx-uart"; reg = <0x40001000 0x1000>; diff --git a/dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml b/dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml new file mode 100644 index 0000000000..73c48b7435 --- /dev/null +++ b/dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml @@ -0,0 +1,39 @@ +# +# Copyright (c) 2019 Brett Witherspoon +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: TI SimpleLink CC13xx / CC26xx True Random Number Generator (TRNG) +version: 0.1 + +description: > + This is a representation of the TI SimpleLink CC13xx / CC26xx TRNG node + +properties: + compatible: + type: string + category: required + description: compatible strings + constraint: "ti,cc13xx-cc26xx-trng" + generation: define + + reg: + type: int + description: mmio register space + generation: define + category: required + + interrupts: + type: compound + category: required + description: required interrupts + generation: define + + 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/ti_simplelink/cc13x2_cc26x2/Kconfig.defconfig.series b/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.defconfig.series index bb5ab9fde5..ca84cfa8e4 100644 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.defconfig.series +++ b/soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.defconfig.series @@ -39,6 +39,13 @@ config GPIO_CC13XX_CC26XX endif # GPIO +if ENTROPY_GENERATOR + +config ENTROPY_CC13XX_CC26XX_RNG + default y + +endif # ENTROPY_GENERATOR + if SERIAL config UART_CC13XX_CC26XX diff --git a/soc/arm/ti_simplelink/cc13x2_cc26x2/dts_fixup.h b/soc/arm/ti_simplelink/cc13x2_cc26x2/dts_fixup.h index b33df58f7b..6eafb2049f 100644 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/dts_fixup.h +++ b/soc/arm/ti_simplelink/cc13x2_cc26x2/dts_fixup.h @@ -7,5 +7,6 @@ /* SoC level DTS fixup file */ #define DT_NUM_IRQ_PRIO_BITS DT_ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS +#define CONFIG_ENTROPY_NAME DT_TI_CC13XX_CC26XX_TRNG_0_LABEL /* End of SoC Level DTS fixup file */