Skip to content

Commit

Permalink
drivers: entropy: add maxq10xx
Browse files Browse the repository at this point in the history
add maxq10xx entropy device.

Signed-off-by: Fin Maaß <[email protected]>
  • Loading branch information
maass-hamburg committed Jan 10, 2025
1 parent 6487761 commit 25990c8
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/entropy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_GECKO_SE entropy_gecko_se.c)
zephyr_library_sources_ifdef(CONFIG_ENTROPY_PSA_CRYPTO_RNG entropy_psa_crypto.c)
zephyr_library_sources_ifdef(CONFIG_ENTROPY_NPCX_DRBG entropy_npcx_drbg.c)
zephyr_library_sources_ifdef(CONFIG_ENTROPY_MAX32_TRNG entropy_max32.c)
zephyr_library_sources_ifdef(CONFIG_ENTROPY_MAXQ10XX_RNG entropy_maxq10xx.c)
zephyr_library_sources_ifdef(CONFIG_ENTROPY_RENESAS_RA entropy_renesas_ra.c)

zephyr_library_link_libraries_ifdef(CONFIG_BUILD_WITH_TFM tfm_api)
1 change: 1 addition & 0 deletions drivers/entropy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ source "drivers/entropy/Kconfig.bt_hci"
source "drivers/entropy/Kconfig.psa_crypto"
source "drivers/entropy/Kconfig.npcx"
source "drivers/entropy/Kconfig.max32"
source "drivers/entropy/Kconfig.maxq10xx"
source "drivers/entropy/Kconfig.renesas_ra"

config ENTROPY_HAS_DRIVER
Expand Down
33 changes: 33 additions & 0 deletions drivers/entropy/Kconfig.maxq10xx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# MAXQ10XX entropy generator driver configuration

# Copyright (c) 2025 Vogl Electronic GmbH
# SPDX-License-Identifier: Apache-2.0

config ENTROPY_MAXQ10XX_RNG
bool "MAXQ10xx entropy number generator driver"
default y
depends on DT_HAS_ADI_MAXQ10XX_TRNG_ENABLED
select ENTROPY_HAS_DRIVER
select SPI
select CRC
help
This option enables the entropy number generator driver for the
MAXQ10xx crypto chips.

# Don't use use the MAXQ10XX RNG as a random source since it can be quite slow.
# Instead, use the software implemented xoshiro RNG.
choice RNG_GENERATOR_CHOICE
default XOSHIRO_RANDOM_GENERATOR if ENTROPY_MAXQ10XX_RNG
endchoice

if ENTROPY_MAXQ10XX_RNG

config ENTROPY_MAXQ10XX_RNG_INIT_PRIORITY
int "MAXQ10xx entropy init priority"
default 51
help
Device driver initialization priority.
Device is connected to SPI bus, it has to
be initialized after SPI driver.

endif # ENTROPY_MAXQ10XX_RNG
233 changes: 233 additions & 0 deletions drivers/entropy/entropy_maxq10xx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2024 Vogl Electronic GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT adi_maxq10xx_trng

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/entropy.h>
#include <zephyr/sys/crc.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(entropy_maxq10xx, CONFIG_ENTROPY_LOG_LEVEL);

#define MAXQ10XX_CMD_HEADER 0xAA
#define MAXQ10XX_CMD_GET_RANDOM 0xC9
#define MAXQ10XX_CMD_GET_RANDOM_INPUT_DATA 0x02
#define MAXQ10XX_CMD_READ_READY 0x55

#define MAXQ10XX_CRC16_POLYNOMIAL 0xA001
#define MAXQ10XX_CRC16_INITIAL_VALUE 0x0000

#define MAXQ10XX_WAIT_TIME K_MSEC(1)

struct entropy_maxq10xx_config {
struct spi_dt_spec spi;
};

struct entropy_maxq10xx_data {
struct k_sem sem_lock;
};

static int entropy_maxq10xx_send_cmd(const struct device *dev, uint16_t length)
{
const struct entropy_maxq10xx_config *config = dev->config;

uint8_t buffer_tx[9];
uint16_t crc;
int ret;

buffer_tx[0] = MAXQ10XX_CMD_HEADER;
buffer_tx[1] = 0x00;
buffer_tx[2] = MAXQ10XX_CMD_GET_RANDOM;
buffer_tx[3] = 0x00;
buffer_tx[4] = MAXQ10XX_CMD_GET_RANDOM_INPUT_DATA;

sys_put_be16(length, &buffer_tx[5]);

crc = crc16_reflect(MAXQ10XX_CRC16_POLYNOMIAL, MAXQ10XX_CRC16_INITIAL_VALUE, buffer_tx, 7);

sys_put_le16(crc, &buffer_tx[7]);

const struct spi_buf tx_buf[] = {{
.buf = buffer_tx,
.len = ARRAY_SIZE(buffer_tx),
}};
const struct spi_buf_set tx = {
.buffers = tx_buf,
.count = ARRAY_SIZE(tx_buf),
};

LOG_HEXDUMP_DBG(buffer_tx, sizeof(buffer_tx), "TX buffer");

ret = spi_write_dt(&config->spi, &tx);

return ret;
}

static int entropy_maxq10xx_wait(const struct device *dev)
{
const struct entropy_maxq10xx_config *config = dev->config;
uint8_t buffer_rx[1];
int ret;

const struct spi_buf rx_buf[] = {{
.buf = buffer_rx,
.len = ARRAY_SIZE(buffer_rx),
}};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = ARRAY_SIZE(rx_buf),
};

while (1) {
ret = spi_read_dt(&config->spi, &rx);
if ((ret < 0) || (buffer_rx[0] == MAXQ10XX_CMD_READ_READY)) {
break;
}

k_sleep(MAXQ10XX_WAIT_TIME);
};

return ret;
}

static int entropy_maxq10xx_read(const struct device *dev, uint8_t *buffer, uint16_t length)
{
const struct entropy_maxq10xx_config *config = dev->config;
uint8_t execution_status[2];
uint8_t length_data[2];
uint8_t crc[2];
uint16_t crc_calc;
int ret;

const struct spi_buf rx_buf[] = {
{
.buf = execution_status,
.len = ARRAY_SIZE(execution_status),
},
{
.buf = length_data,
.len = ARRAY_SIZE(length_data),
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = ARRAY_SIZE(rx_buf),
};

ret = spi_read_dt(&config->spi, &rx);
if (ret < 0) {
return ret;
}

if (execution_status[0] != 0x00 || execution_status[1] != 0x00) {
LOG_DBG("Execution status: 0x%02X 0x%02X", execution_status[0],
execution_status[1]);
return -EIO;
}

if (length != sys_get_be16(length_data)) {
LOG_ERR("Length mismatch: %d != %d", length, sys_get_be16(length_data));
return -EIO;
}

const struct spi_buf rx_data_buf[] = {
{
.buf = buffer,
.len = length,
},
{
.buf = crc,
.len = sizeof(crc),
}
};

const struct spi_buf_set rx_data = {
.buffers = rx_data_buf,
.count = ARRAY_SIZE(rx_data_buf),
};

ret = spi_read_dt(&config->spi, &rx_data);
if (ret < 0) {
return ret;
}

uint8_t header_tx[1] = {MAXQ10XX_CMD_READ_READY};

crc_calc = crc16_reflect(MAXQ10XX_CRC16_POLYNOMIAL, MAXQ10XX_CRC16_INITIAL_VALUE, header_tx,
sizeof(header_tx));
crc_calc = crc16_reflect(MAXQ10XX_CRC16_POLYNOMIAL, crc_calc, execution_status,
sizeof(execution_status));
crc_calc = crc16_reflect(MAXQ10XX_CRC16_POLYNOMIAL, crc_calc, length_data,
sizeof(length_data));
crc_calc = crc16_reflect(MAXQ10XX_CRC16_POLYNOMIAL, crc_calc, buffer, length);

if (crc_calc != sys_get_le16(crc)) {
LOG_ERR("CRC error: 0x%04X != 0x%04X", crc_calc, sys_get_le16(crc));
return -EIO;
}

return ret;
}

static int entropy_maxq10xx_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t length)
{
struct entropy_maxq10xx_data *dev_data = dev->data;

int ret;

k_sem_take(&dev_data->sem_lock, K_FOREVER);

ret = entropy_maxq10xx_send_cmd(dev, length);
if (ret < 0) {
LOG_ERR("Failed to send command");
goto exit;
}

ret = entropy_maxq10xx_wait(dev);
if (ret < 0) {
LOG_ERR("Failed to wait for ready");
goto exit;
}

ret = entropy_maxq10xx_read(dev, buffer, length);
if (ret < 0) {
LOG_ERR("Failed to read data");
}
exit:
k_sem_give(&dev_data->sem_lock);
return ret;
}

static int entropy_maxq10xx_init(const struct device *dev)
{
struct entropy_maxq10xx_data *dev_data = dev->data;

k_sem_init(&dev_data->sem_lock, 1, 1);

return 0;
}

static DEVICE_API(entropy, entropy_maxq10xx_api) = {
.get_entropy = entropy_maxq10xx_get_entropy
};

BUILD_ASSERT(CONFIG_SPI_INIT_PRIORITY < CONFIG_ENTROPY_MAXQ10XX_RNG_INIT_PRIORITY,
"SPI driver must be initialized before maxq10 entropy driver");

#define DEFINE_MAXQ10XX_ENTROPY(_num) \
static const struct entropy_maxq10xx_config entropy_maxq10xx_config##_num = { \
.spi = SPI_DT_SPEC_INST_GET(_num, SPI_WORD_SET(8), 0), \
}; \
static struct entropy_maxq10xx_data entropy_maxq10xx_data##_num; \
DEVICE_DT_INST_DEFINE(_num, entropy_maxq10xx_init, NULL, &entropy_maxq10xx_data##_num, \
&entropy_maxq10xx_config##_num, POST_KERNEL, \
CONFIG_ENTROPY_MAXQ10XX_RNG_INIT_PRIORITY, &entropy_maxq10xx_api);

DT_INST_FOREACH_STATUS_OKAY(DEFINE_MAXQ10XX_ENTROPY);
8 changes: 8 additions & 0 deletions dts/bindings/rng/adi,maxq10xx-trng.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2024 Vogl Electronic GmbH
# SPDX-License-Identifier: Apache-2.0

description: ADI MAXQ10XX RNG

compatible: "adi,maxq10xx-trng"

include: spi-device.yaml

0 comments on commit 25990c8

Please sign in to comment.