Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
/drivers/ps2/ @albertofloyd @franciscomunoz @scottwcpg
/drivers/kscan/ @albertofloyd @franciscomunoz @scottwcpg
/drivers/ethernet/ @jukkar @tbursztyka @pfalcon
/drivers/entropy/*sam0* @benpicco
/drivers/flash/ @nashif @nvlsianpu
/drivers/flash/*native_posix* @vanwinkeljan @aescolar
/drivers/flash/*nrf* @nvlsianpu
Expand Down
1 change: 1 addition & 0 deletions drivers/entropy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_MCUX_RNGA entropy_mcux_rnga
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_SAM0_RNG entropy_sam0.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)
1 change: 1 addition & 0 deletions drivers/entropy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ source "drivers/entropy/Kconfig.stm32"
source "drivers/entropy/Kconfig.esp32"
source "drivers/entropy/Kconfig.nrf5"
source "drivers/entropy/Kconfig.sam"
source "drivers/entropy/Kconfig.sam0"
source "drivers/entropy/Kconfig.native_posix"

config ENTROPY_HAS_DRIVER
Expand Down
13 changes: 13 additions & 0 deletions drivers/entropy/Kconfig.sam0
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Kconfig.sam - Atmel SAM0 TRNG configuration
#
# Copyright (c) 2019 Benjamin Valentin
#
# SPDX-License-Identifier: Apache-2.0

config ENTROPY_SAM0_RNG
bool "Atmel SAM0 MCU Family True Random Number Generator (TRNG) Driver"
depends on SOC_FAMILY_SAM0
select ENTROPY_HAS_DRIVER
select HAS_DTS_ENTROPY
help
Enable True Random Number Generator (TRNG) driver for Atmel SAM0 MCUs.
159 changes: 159 additions & 0 deletions drivers/entropy/entropy_sam0.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2019 ML!PA Consulting GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <device.h>
#include <drivers/entropy.h>
#include <errno.h>
#include <init.h>
#include <soc.h>
#include <string.h>

struct trng_sam0_dev_cfg {
Trng *regs;
};

#define DEV_CFG(dev) \
((const struct trng_sam0_dev_cfg *const)(dev)->config->config_info)

static int entropy_sam0_wait_ready(Trng *const trng, u32_t flags)
{
/* 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->INTFLAG.bit.DATARDY) {
if (timeout-- == 0) {
return -ETIMEDOUT;
}

if ((flags & ENTROPY_BUSYWAIT) == 0U) {
/* This internal function is used by both get_entropy,
* and get_entropy_isr APIs. The later may call this
* function with the ENTROPY_BUSYWAIT flag set. In
* that case make no assumption that the kernel is
* initialized when the function is called; so, just
* do busy-wait for the random data to be ready.
*/
k_yield();
}
}

return 0;
}

static int entropy_sam0_get_entropy_internal(struct device *dev, u8_t *buffer,
u16_t length, u32_t flags)
{
Trng *const trng = DEV_CFG(dev)->regs;

while (length > 0) {
size_t to_copy;
u32_t value;
int res;

res = entropy_sam0_wait_ready(trng, flags);
if (res < 0) {
return res;
}

value = TRNG->DATA.reg;
to_copy = MIN(length, sizeof(value));

memcpy(buffer, &value, to_copy);
buffer += to_copy;
length -= to_copy;
}

return 0;
}

static int entropy_sam0_get_entropy(struct device *dev, u8_t *buffer,
u16_t length)
{
return entropy_sam0_get_entropy_internal(dev, buffer, length, 0);
}

static int entropy_sam0_get_entropy_isr(struct device *dev, u8_t *buffer,
u16_t length, u32_t flags)
{
u16_t cnt = length;


if ((flags & ENTROPY_BUSYWAIT) == 0U) {

/* No busy wait; return whatever data is available. */

Trng *const trng = DEV_CFG(dev)->regs;

do {
size_t to_copy;
u32_t value;

if (!(trng->INTFLAG.bit.DATARDY)) {

/* Data not ready */
break;
}

value = TRNG->DATA.reg;
to_copy = MIN(length, sizeof(value));

memcpy(buffer, &value, to_copy);
buffer += to_copy;
length -= to_copy;

} while (length > 0);

return cnt - length;

} else {
/* Allowed to busy-wait */
int ret =
entropy_sam0_get_entropy_internal(dev,
buffer, length, flags);

if (ret == 0) {
/* Data retrieved successfully. */
return cnt;
}

return ret;
}
}

static int entropy_sam0_init(struct device *dev)
{
Trng *const trng = DEV_CFG(dev)->regs;

/* Enable the MCLK */
MCLK->APBCMASK.bit.TRNG_ = 1;

/* Enable the TRNG */
trng->CTRLA.bit.ENABLE = 1;

return 0;
}

static const struct entropy_driver_api entropy_sam0_api = {
.get_entropy = entropy_sam0_get_entropy,
.get_entropy_isr = entropy_sam0_get_entropy_isr
};

static const struct trng_sam0_dev_cfg trng_sam0_cfg = {
.regs = (Trng *)DT_ATMEL_SAM0_TRNG_0_BASE_ADDRESS,
};

DEVICE_AND_API_INIT(entropy_sam0, CONFIG_ENTROPY_NAME,
entropy_sam0_init, NULL, &trng_sam0_cfg,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&entropy_sam0_api);
21 changes: 21 additions & 0 deletions dts/bindings/rng/atmel,sam0-trng.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (c) 2019 ML!PA Consulting GmbH
# SPDX-License-Identifier: Apache-2.0

title: Atmel SAM0 TRNG (True Random Number Generator)

description: >
This binding gives a base representation of the Atmel SAM0 RNG

compatible: "atmel,sam0-trng"

include: base.yaml

properties:
reg:
required: true

interrupts:
required: true

label:
required: true