-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add maxq10xx entropy device. Signed-off-by: Fin Maaß <[email protected]>
- Loading branch information
1 parent
6487761
commit b9671de
Showing
5 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 lenght_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 = lenght_data, | ||
.len = ARRAY_SIZE(lenght_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(lenght_data)) { | ||
LOG_ERR("Length mismatch: %d != %d", length, sys_get_be16(lenght_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, lenght_data, | ||
sizeof(lenght_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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |