diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_ddr_defconfig b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_ddr_defconfig index f89de52c0365..effcdb5e4d48 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_ddr_defconfig +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_ddr_defconfig @@ -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 diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_defconfig b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_defconfig index 180973c667f4..338c3ea662aa 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_defconfig +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7_defconfig @@ -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 diff --git a/drivers/firmware/scmi/CMakeLists.txt b/drivers/firmware/scmi/CMakeLists.txt index fbd52e6ed2d1..60ea86a5cb69 100644 --- a/drivers/firmware/scmi/CMakeLists.txt +++ b/drivers/firmware/scmi/CMakeLists.txt @@ -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) diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 93c1b1189636..c4beec1d2b4e 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -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 diff --git a/drivers/firmware/scmi/nxp/CMakeLists.txt b/drivers/firmware/scmi/nxp/CMakeLists.txt new file mode 100644 index 000000000000..44fa881778d5 --- /dev/null +++ b/drivers/firmware/scmi/nxp/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources_ifdef(CONFIG_ARM_SCMI_NXP_VENDOR_EXTENSIONS shmem.c) diff --git a/drivers/firmware/scmi/nxp/Kconfig b/drivers/firmware/scmi/nxp/Kconfig new file mode 100644 index 000000000000..2a20210294b3 --- /dev/null +++ b/drivers/firmware/scmi/nxp/Kconfig @@ -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 diff --git a/drivers/firmware/scmi/nxp/shmem.c b/drivers/firmware/scmi/nxp/shmem.c new file mode 100644 index 000000000000..629076a2e6de --- /dev/null +++ b/drivers/firmware/scmi/nxp/shmem.c @@ -0,0 +1,50 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +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; +} diff --git a/drivers/firmware/scmi/shmem.c b/drivers/firmware/scmi/shmem.c index 6ec645cbc309..86b1a9659d49 100644 --- a/drivers/firmware/scmi/shmem.c +++ b/drivers/firmware/scmi/shmem.c @@ -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; diff --git a/include/zephyr/drivers/firmware/scmi/shmem.h b/include/zephyr/drivers/firmware/scmi/shmem.h index a655a361e695..662bf7933735 100644 --- a/include/zephyr/drivers/firmware/scmi/shmem.h +++ b/include/zephyr/drivers/firmware/scmi/shmem.h @@ -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_ */