Browse Source
Add driver for the TRNG entropy source on the TI CC13xx / CC26xx series SoCs. Signed-off-by: Brett Witherspoon <spoonb@cdspooner.com>pull/16139/head
8 changed files with 278 additions and 0 deletions
@ -0,0 +1,51 @@
@@ -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 |
@ -0,0 +1,170 @@
@@ -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); |
@ -0,0 +1,39 @@
@@ -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 |
||||
|
||||
... |
Loading…
Reference in new issue