drivers: entropy: add maxq10xx
add maxq10xx entropy device. Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_SILABS_SIWX91X entropy_silabs_siwx9
|
||||
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_sources_ifdef(CONFIG_ENTROPY_SY1XX_TRNG entropy_sy1xx_trng.c)
|
||||
|
||||
|
||||
@@ -40,6 +40,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"
|
||||
source "drivers/entropy/Kconfig.sy1xx"
|
||||
|
||||
|
||||
20
drivers/entropy/Kconfig.maxq10xx
Normal file
20
drivers/entropy/Kconfig.maxq10xx
Normal file
@@ -0,0 +1,20 @@
|
||||
# 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 MFD
|
||||
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 PRNG.
|
||||
choice RNG_GENERATOR_CHOICE
|
||||
default XOSHIRO_RANDOM_GENERATOR if ENTROPY_MAXQ10XX_RNG
|
||||
endchoice
|
||||
224
drivers/entropy/entropy_maxq10xx.c
Normal file
224
drivers/entropy/entropy_maxq10xx.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2025 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/drivers/mfd/mfd_maxq10xx.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;
|
||||
const struct device *parent;
|
||||
};
|
||||
|
||||
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] != 0 || execution_status[1] != 0) {
|
||||
LOG_ERR("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)
|
||||
{
|
||||
const struct entropy_maxq10xx_config *config = dev->config;
|
||||
struct k_sem *sem_lock = mfd_maxq10xx_get_lock(config->parent);
|
||||
|
||||
int ret;
|
||||
|
||||
if (!spi_is_ready_dt(&config->spi)) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
k_sem_take(sem_lock, K_FOREVER);
|
||||
|
||||
ret = entropy_maxq10xx_send_cmd(dev, length);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to send command: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = entropy_maxq10xx_wait(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to wait for ready: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = entropy_maxq10xx_read(dev, buffer, length);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read data: %d", ret);
|
||||
}
|
||||
exit:
|
||||
k_sem_give(sem_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_API(entropy, entropy_maxq10xx_api) = {
|
||||
.get_entropy = entropy_maxq10xx_get_entropy
|
||||
};
|
||||
|
||||
#define DEFINE_MAXQ10XX_ENTROPY(_num) \
|
||||
static const struct entropy_maxq10xx_config entropy_maxq10xx_config##_num = { \
|
||||
.spi = SPI_DT_SPEC_GET(DT_INST_PARENT(_num), SPI_WORD_SET(8), 0), \
|
||||
.parent = DEVICE_DT_GET(DT_INST_PARENT(_num)), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(_num, NULL, NULL, NULL, \
|
||||
&entropy_maxq10xx_config##_num, POST_KERNEL, \
|
||||
CONFIG_MFD_MAXQ10XX_INIT_PRIORITY, &entropy_maxq10xx_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DEFINE_MAXQ10XX_ENTROPY);
|
||||
@@ -14,6 +14,7 @@ zephyr_library_sources_ifdef(CONFIG_MFD_AD559X mfd_ad559x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_I2C mfd_ad559x_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_SPI mfd_ad559x_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_MAX31790 mfd_max31790.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_MAXQ10XX mfd_maxq10xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_MFD_TLE9104 mfd_tle9104.c)
|
||||
|
||||
@@ -27,6 +27,7 @@ source "drivers/mfd/Kconfig.ds3231"
|
||||
source "drivers/mfd/Kconfig.max20335"
|
||||
source "drivers/mfd/Kconfig.max22017"
|
||||
source "drivers/mfd/Kconfig.max31790"
|
||||
source "drivers/mfd/Kconfig.maxq10xx"
|
||||
source "drivers/mfd/Kconfig.nct38xx"
|
||||
source "drivers/mfd/Kconfig.npm1300"
|
||||
source "drivers/mfd/Kconfig.npm2100"
|
||||
|
||||
24
drivers/mfd/Kconfig.maxq10xx
Normal file
24
drivers/mfd/Kconfig.maxq10xx
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2025 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config MFD_MAXQ10XX
|
||||
bool "MAXQ10xx mfd driver"
|
||||
default y
|
||||
depends on DT_HAS_ADI_MAXQ10XX_ENABLED
|
||||
# using select SPI at this point introduces a cyclic dependency
|
||||
depends on SPI
|
||||
help
|
||||
This option enables the mfd driver for the
|
||||
MAXQ10xx crypto chips.
|
||||
|
||||
if MFD_MAXQ10XX
|
||||
|
||||
config MFD_MAXQ10XX_INIT_PRIORITY
|
||||
int "MAXQ10xx init priority"
|
||||
default 51
|
||||
help
|
||||
Device driver initialization priority.
|
||||
Device is connected to SPI bus, it has to
|
||||
be initialized after SPI driver.
|
||||
|
||||
endif # MFD_MAXQ10XX
|
||||
57
drivers/mfd/mfd_maxq10xx.c
Normal file
57
drivers/mfd/mfd_maxq10xx.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vogl Electronic GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_maxq10xx
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/drivers/mfd/mfd_maxq10xx.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(mfd_maxq10xx, CONFIG_MFD_LOG_LEVEL);
|
||||
|
||||
struct mfd_maxq10xx_config {
|
||||
struct spi_dt_spec spi;
|
||||
};
|
||||
|
||||
struct mfd_maxq10xx_data {
|
||||
struct k_sem sem_lock;
|
||||
};
|
||||
|
||||
struct k_sem *mfd_maxq10xx_get_lock(const struct device *dev)
|
||||
{
|
||||
struct mfd_maxq10xx_data *data = dev->data;
|
||||
|
||||
return &data->sem_lock;
|
||||
}
|
||||
|
||||
static int mfd_maxq10xx_init(const struct device *dev)
|
||||
{
|
||||
const struct mfd_maxq10xx_config *config = dev->config;
|
||||
|
||||
if (!spi_is_ready_dt(&config->spi)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BUILD_ASSERT(CONFIG_SPI_INIT_PRIORITY < CONFIG_MFD_MAXQ10XX_INIT_PRIORITY,
|
||||
"SPI driver must be initialized before maxq10xx mfd driver");
|
||||
|
||||
#define DEFINE_MAXQ10XX_MFD(_num) \
|
||||
static const struct mfd_maxq10xx_config mfd_maxq10xx_config##_num = { \
|
||||
.spi = SPI_DT_SPEC_INST_GET(_num, SPI_WORD_SET(8), 0), \
|
||||
}; \
|
||||
static struct mfd_maxq10xx_data mfd_maxq10xx_data##_num = { \
|
||||
.sem_lock = Z_SEM_INITIALIZER(mfd_maxq10xx_data##_num.sem_lock, 1, 1), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(_num, mfd_maxq10xx_init, NULL, &mfd_maxq10xx_data##_num, \
|
||||
&mfd_maxq10xx_config##_num, POST_KERNEL, \
|
||||
CONFIG_MFD_MAXQ10XX_INIT_PRIORITY, NULL);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DEFINE_MAXQ10XX_MFD);
|
||||
8
dts/bindings/mfd/adi,maxq10xx.yaml
Normal file
8
dts/bindings/mfd/adi,maxq10xx.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2025 Vogl Electronic GmbH
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: ADI MAXQ10XX
|
||||
|
||||
compatible: "adi,maxq10xx"
|
||||
|
||||
include: spi-device.yaml
|
||||
8
dts/bindings/rng/adi,maxq10xx-trng.yaml
Normal file
8
dts/bindings/rng/adi,maxq10xx-trng.yaml
Normal file
@@ -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: base.yaml
|
||||
31
include/zephyr/drivers/mfd/mfd_maxq10xx.h
Normal file
31
include/zephyr/drivers/mfd/mfd_maxq10xx.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vogl Electronic GmbH
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_MAXQ10XX_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_MFD_MAXQ10XX_H_
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the semaphore reference for a MAXQ1xx instance. Callers
|
||||
* should pass the return value to k_sem_take/k_sem_give
|
||||
*
|
||||
* @param[in] dev Pointer to device struct of the driver instance
|
||||
*
|
||||
* @return Address of the semaphore
|
||||
*/
|
||||
struct k_sem *mfd_maxq10xx_get_lock(const struct device *dev);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_MAXQ10XX_H_ */
|
||||
Reference in New Issue
Block a user