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 <spoonb@cdspooner.com>
This commit is contained in:
parent
3bcd188068
commit
2bee500f06
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
51
drivers/entropy/Kconfig.cc13xx_cc26xx
Normal file
51
drivers/entropy/Kconfig.cc13xx_cc26xx
Normal file
|
@ -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
|
170
drivers/entropy/entropy_cc13xx_cc26xx.c
Normal file
170
drivers/entropy/entropy_cc13xx_cc26xx.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Brett Witherspoon
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <device.h>
|
||||
#include <entropy.h>
|
||||
#include <irq.h>
|
||||
#include <ring_buffer.h>
|
||||
#include <sys_io.h>
|
||||
|
||||
#include <driverlib/prcm.h>
|
||||
#include <driverlib/trng.h>
|
||||
|
||||
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);
|
|
@ -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>;
|
||||
|
|
39
dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml
Normal file
39
dts/bindings/rng/ti,cc13xx-cc26xx-trng.yaml
Normal file
|
@ -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
|
||||
|
||||
...
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue