Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: entropy: add maxq10xx #83797

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 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
Loading