drivers: firmware: scmi: add nxp specific processing

An option is added to allow vendor specific processing at
scmi_shmem_write_message() and scmi_shmem_read_message().
Additionally code has been added specific to NXP which has
some extended validation features.

Signed-off-by: Andre Heinemans <andre.heinemans@nxp.com>
This commit is contained in:
Andre Heinemans 2025-02-19 11:16:21 +01:00 committed by Carles Cufí
commit da3d029b14
9 changed files with 115 additions and 9 deletions

View file

@ -17,6 +17,7 @@ CONFIG_CONSOLE=y
CONFIG_MBOX=y
CONFIG_MBOX_INIT_PRIORITY=0
CONFIG_ARM_SCMI=y
CONFIG_ARM_SCMI_NXP_VENDOR_EXTENSIONS=y
# kernel-related configurations
CONFIG_XIP=n

View file

@ -13,3 +13,4 @@ CONFIG_XIP=y
CONFIG_MBOX=y
CONFIG_MBOX_INIT_PRIORITY=0
CONFIG_ARM_SCMI=y
CONFIG_ARM_SCMI_NXP_VENDOR_EXTENSIONS=y

View file

@ -11,3 +11,5 @@ zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_SHMEM shmem.c)
zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_CLK_HELPERS clk.c)
zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_PINCTRL_HELPERS pinctrl.c)
zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_POWER_DOMAIN_HELPERS power.c)
add_subdirectory_ifdef(CONFIG_ARM_SCMI nxp)

View file

@ -64,4 +64,6 @@ config ARM_SCMI_TRANSPORT_INIT_PRIORITY
help
SCMI transport driver device initialization priority.
source "drivers/firmware/scmi/nxp/Kconfig"
endif # ARM_SCMI

View file

@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_NXP_VENDOR_EXTENSIONS shmem.c)

View file

@ -0,0 +1,8 @@
# Copyright 2025 NXP
# SPDX-License-Identifier: Apache-2.0
config ARM_SCMI_NXP_VENDOR_EXTENSIONS
bool "Allow NXP specific SCMI features"
select CRC
help
When enabled, additional SCMI features specific to NXP will be available

View file

@ -0,0 +1,50 @@
/*
* Copyright 2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/firmware/scmi/shmem.h>
#include <zephyr/sys/crc.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(arm_scmi_shmem_nxp);
#define SMT_CRC_NONE 0U
#define SMT_CRC_XOR 1U /* Unsupported */
#define SMT_CRC_J1850 2U /* Unsupported */
#define SMT_CRC_CRC32 3U
int scmi_shmem_vendor_read_message(const struct scmi_shmem_layout *layout)
{
uint32_t validation_type = layout->res1[0];
if (validation_type == SMT_CRC_CRC32) {
if (layout->res1[1] != crc32_ieee((const uint8_t *)&layout->msg_hdr, layout->len)) {
LOG_ERR("bad message crc");
return -EBADMSG;
}
} else if (validation_type == SMT_CRC_NONE) {
/* do nothing */
} else {
LOG_ERR("unsupported validation type 0x%x", validation_type);
return -EINVAL;
}
return 0;
}
int scmi_shmem_vendor_write_message(struct scmi_shmem_layout *layout)
{
uint32_t validation_type = layout->res1[0];
if (validation_type == SMT_CRC_CRC32) {
layout->res1[1] = crc32_ieee((const uint8_t *)&layout->msg_hdr, layout->len);
} else if (validation_type == SMT_CRC_NONE) {
/* do nothing */
} else {
LOG_ERR("unsupported validation type 0x%x", validation_type);
return -EINVAL;
}
return 0;
}

View file

@ -26,15 +26,6 @@ struct scmi_shmem_data {
mm_reg_t regmap;
};
struct scmi_shmem_layout {
volatile uint32_t res0;
volatile uint32_t chan_status;
volatile uint32_t res1[2];
volatile uint32_t chan_flags;
volatile uint32_t len;
volatile uint32_t msg_hdr;
};
int scmi_shmem_get_channel_status(const struct device *dev, uint32_t *status)
{
struct scmi_shmem_data *data;
@ -57,6 +48,16 @@ static void scmi_shmem_memcpy(mm_reg_t dst, mm_reg_t src, uint32_t bytes)
}
}
__weak int scmi_shmem_vendor_read_message(const struct scmi_shmem_layout *layout)
{
return 0;
}
__weak int scmi_shmem_vendor_write_message(struct scmi_shmem_layout *layout)
{
return 0;
}
int scmi_shmem_read_message(const struct device *shmem, struct scmi_message *msg)
{
struct scmi_shmem_layout *layout;
@ -96,6 +97,11 @@ int scmi_shmem_read_message(const struct device *shmem, struct scmi_message *msg
return -EINVAL;
}
if (scmi_shmem_vendor_read_message(layout) < 0) {
LOG_ERR("vendor specific validation failed");
return -EINVAL;
}
if (msg->content) {
scmi_shmem_memcpy(POINTER_TO_UINT(msg->content),
data->regmap + sizeof(*layout), msg->len);
@ -139,6 +145,10 @@ int scmi_shmem_write_message(const struct device *shmem, struct scmi_message *ms
POINTER_TO_UINT(msg->content), msg->len);
}
if (scmi_shmem_vendor_write_message(layout) < 0) {
return -EINVAL;
}
/* done, mark channel as busy and proceed */
layout->chan_status &= ~SCMI_SHMEM_CHAN_STATUS_BUSY_BIT;

View file

@ -19,6 +19,15 @@
#define SCMI_SHMEM_CHAN_STATUS_BUSY_BIT BIT(0)
#define SCMI_SHMEM_CHAN_FLAG_IRQ_BIT BIT(0)
struct scmi_shmem_layout {
volatile uint32_t res0;
volatile uint32_t chan_status;
volatile uint32_t res1[2];
volatile uint32_t chan_flags;
volatile uint32_t len;
volatile uint32_t msg_hdr;
};
struct scmi_message;
/**
@ -64,4 +73,24 @@ void scmi_shmem_update_flags(const struct device *shmem,
*/
uint32_t scmi_shmem_channel_status(const struct device *shmem);
/**
* @brief Process vendor specific features when writing message
*
* @param layout layout of the message
*
* @retval 0 if successful
* @retval negative errno if failure
*/
int scmi_shmem_vendor_write_message(struct scmi_shmem_layout *layout);
/**
* @brief Process vendor specific features when reading message
*
* @param layout layout of the message
*
* @retval 0 if successful
* @retval negative errno if failure
*/
int scmi_shmem_vendor_read_message(const struct scmi_shmem_layout *layout);
#endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_SHMEM_H_ */