diff --git a/drivers/misc/CMakeLists.txt b/drivers/misc/CMakeLists.txt index 4b1e29a4901..54ed29d9349 100644 --- a/drivers/misc/CMakeLists.txt +++ b/drivers/misc/CMakeLists.txt @@ -11,4 +11,6 @@ add_subdirectory_ifdef(CONFIG_DEVMUX devmux) add_subdirectory_ifdef(CONFIG_NORDIC_VPR_LAUNCHER nordic_vpr_launcher) add_subdirectory_ifdef(CONFIG_MCUX_FLEXIO mcux_flexio) add_subdirectory_ifdef(CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT renesas_ra_external_interrupt) +add_subdirectory_ifdef(CONFIG_NXP_RTXXX_DSP_CTRL nxp_rtxxx_dsp_ctrl) + add_subdirectory(coresight) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e80b1650ccd..5668434c43e 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -16,5 +16,6 @@ source "drivers/misc/nordic_vpr_launcher/Kconfig" source "drivers/misc/mcux_flexio/Kconfig" source "drivers/misc/coresight/Kconfig" source "drivers/misc/renesas_ra_external_interrupt/Kconfig" +source "drivers/misc/nxp_rtxxx_dsp_ctrl/Kconfig" endmenu diff --git a/drivers/misc/nxp_rtxxx_dsp_ctrl/CMakeLists.txt b/drivers/misc/nxp_rtxxx_dsp_ctrl/CMakeLists.txt new file mode 100644 index 00000000000..9b4e1a1ef43 --- /dev/null +++ b/drivers/misc/nxp_rtxxx_dsp_ctrl/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.h) + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_NXP_RTXXX_DSP_CTRL + nxp_rtxxx_dsp_ctrl.c +) diff --git a/drivers/misc/nxp_rtxxx_dsp_ctrl/Kconfig b/drivers/misc/nxp_rtxxx_dsp_ctrl/Kconfig new file mode 100644 index 00000000000..5eb7ee980d9 --- /dev/null +++ b/drivers/misc/nxp_rtxxx_dsp_ctrl/Kconfig @@ -0,0 +1,9 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +config NXP_RTXXX_DSP_CTRL + bool "NXP i.MX RTxxx DSP control" + depends on DT_HAS_NXP_RTXXX_DSP_CTRL_ENABLED + default y + help + Enables a DSP control driver for NXP i.MX RTxxx devices. diff --git a/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.c b/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.c new file mode 100644 index 00000000000..0ab59540bb3 --- /dev/null +++ b/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.c @@ -0,0 +1,118 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_rtxxx_dsp_ctrl + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +struct nxp_rtxxx_dsp_ctrl_region { + void *base; + int32_t length; +}; + +struct nxp_rtxxx_dsp_ctrl_config { + SYSCTL0_Type *sysctl; + struct nxp_rtxxx_dsp_ctrl_region regions[NXP_RTXXX_DSP_REGION_MAX]; +}; + +static void dsp_ctrl_enable(const struct device *dev) +{ + SYSCTL0_Type *sysctl = ((struct nxp_rtxxx_dsp_ctrl_config *)dev->config)->sysctl; + + sysctl->DSPSTALL = 0; +} + +static void dsp_ctrl_disable(const struct device *dev) +{ + SYSCTL0_Type *sysctl = ((struct nxp_rtxxx_dsp_ctrl_config *)dev->config)->sysctl; + + sysctl->DSPSTALL = 1; +} + +static int dsp_ctrl_load_section(const struct device *dev, const void *base, size_t length, + enum nxp_rtxxx_dsp_ctrl_section_type section) +{ + if (section >= NXP_RTXXX_DSP_REGION_MAX) { + return -EINVAL; + } + + const struct nxp_rtxxx_dsp_ctrl_config *cfg = + (const struct nxp_rtxxx_dsp_ctrl_config *)dev->config; + + if (cfg->regions[section].base == NULL) { + return -EINVAL; + } + + if (length > cfg->regions[section].length) { + return -ENOMEM; + } + + /* + * Custom memcpy implementation is needed because the DSP TCMs can be accessed + * only by 32 bits. + */ + const uint32_t *src = (const uint32_t *)base; + uint32_t *dst = cfg->regions[section].base; + + for (size_t remaining = length; remaining > 0; remaining -= sizeof(uint32_t)) { + *dst++ = *src++; + + if (remaining < sizeof(uint32_t)) { + break; + } + } + + return 0; +} + +static int nxp_rtxxx_dsp_ctrl_init(const struct device *dev) +{ + /* + * Initialize clocks associated with the DSP. + * Taken from DSP examples for the MIMXRT685-EVK in the MCUXpresso SDK. + */ + CLOCK_InitSysPfd(kCLOCK_Pfd1, 16); + CLOCK_AttachClk(kDSP_PLL_to_DSP_MAIN_CLK); + CLOCK_SetClkDiv(kCLOCK_DivDspCpuClk, 1); + CLOCK_SetClkDiv(kCLOCK_DivDspRamClk, 2); + + DSP_Init(); + + return 0; +} + +static struct nxp_rtxxx_dsp_ctrl_api nxp_rtxxx_dsp_ctrl_api = { + .load_section = dsp_ctrl_load_section, + .enable = dsp_ctrl_enable, + .disable = dsp_ctrl_disable +}; + +#define NXP_RTXXX_DSP_SECTION(child_node_id, n) \ + [DT_PROP(child_node_id, type)] = { \ + .base = (void *)DT_REG_ADDR(child_node_id), \ + .length = DT_REG_SIZE(child_node_id) \ + }, + +#define NXP_RTXXX_DSP_CTRL(n) \ + static const struct nxp_rtxxx_dsp_ctrl_config nxp_rtxxx_dsp_ctrl_##n##_config = { \ + .sysctl = (SYSCTL0_Type *)DT_REG_ADDR(DT_INST_PHANDLE(n, sysctl)), \ + .regions = {DT_INST_FOREACH_CHILD_VARGS(n, NXP_RTXXX_DSP_SECTION, n)}}; \ + \ + DEVICE_DT_INST_DEFINE(n, nxp_rtxxx_dsp_ctrl_init, NULL, NULL, \ + &nxp_rtxxx_dsp_ctrl_##n##_config, PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &nxp_rtxxx_dsp_ctrl_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_RTXXX_DSP_CTRL); diff --git a/dts/bindings/misc/nxp,rtxxx-dsp-ctrl.yaml b/dts/bindings/misc/nxp,rtxxx-dsp-ctrl.yaml new file mode 100644 index 00000000000..7df709ebe11 --- /dev/null +++ b/dts/bindings/misc/nxp,rtxxx-dsp-ctrl.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +include: [base.yaml] + +compatible: "nxp,rtxxx-dsp-ctrl" +description: NXP i.MX RTxxx DSP control driver + +properties: + "#address-cells": + const: 1 + "#size-cells": + const: 1 + sysctl: + required: true + type: phandle + description: phandle to a SYSCTL node + +child-binding: + description: Memory region definition + + properties: + reg: + required: true + type: array + description: Base address and length of a memory region + + type: + required: true + type: int + description: Memory region type (NXP_RTXXX_DSP_REGION_*) diff --git a/include/zephyr/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.h b/include/zephyr/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.h new file mode 100644 index 00000000000..79b32476d60 --- /dev/null +++ b/include/zephyr/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.h @@ -0,0 +1,79 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifndef __NXP_RTXXX_DSP_CTRL_H__ +#define __NXP_RTXXX_DSP_CTRL_H__ + +/** + * @brief Describes an image section type selection. + */ +enum nxp_rtxxx_dsp_ctrl_section_type { + NXP_RTXXX_DSP_CTRL_SECTION_RESET = NXP_RTXXX_DSP_REGION_RESET, + NXP_RTXXX_DSP_CTRL_SECTION_TEXT = NXP_RTXXX_DSP_REGION_TEXT, + NXP_RTXXX_DSP_CTRL_SECTION_DATA = NXP_RTXXX_DSP_REGION_DATA +}; + +typedef int (*nxp_rtxxx_dsp_ctrl_api_load_section)( + const struct device *, + const void *, + size_t, + enum nxp_rtxxx_dsp_ctrl_section_type +); +typedef void (*nxp_rtxxx_dsp_ctrl_api_enable)(const struct device *dev); +typedef void (*nxp_rtxxx_dsp_ctrl_api_disable)(const struct device *dev); + +struct nxp_rtxxx_dsp_ctrl_api { + nxp_rtxxx_dsp_ctrl_api_load_section load_section; + nxp_rtxxx_dsp_ctrl_api_enable enable; + nxp_rtxxx_dsp_ctrl_api_disable disable; +}; + +/** + * @brief Loads a specified image representing a specified section to a particular region in the + * DSP's memory. + * + * @param dev DSP device + * @param base Base pointer of the image to load + * @param length Length of the image + * @param section Section type which specified image represents + * @return int 0 on success, -EINVAL for invalid parameters, -ENOMEM for image bigger than the + * target region + */ +static inline int nxp_rtxxx_dsp_ctrl_load_section( + const struct device *dev, + const void *base, + size_t length, + enum nxp_rtxxx_dsp_ctrl_section_type section +) +{ + return ((struct nxp_rtxxx_dsp_ctrl_api *)dev->api) + ->load_section(dev, base, length, section); +} + +/** + * @brief Starts (unstalls) the DSP. + * + * @param dev DSP device + */ +static inline void nxp_rtxxx_dsp_ctrl_enable(const struct device *dev) +{ + ((struct nxp_rtxxx_dsp_ctrl_api *)dev->api)->enable(dev); +} + +/** + * @brief Stops (stalls) the DSP. + * + * @param dev DSP device + */ +static inline void nxp_rtxxx_dsp_ctrl_disable(const struct device *dev) +{ + ((struct nxp_rtxxx_dsp_ctrl_api *)dev->api)->disable(dev); +} + +#endif diff --git a/include/zephyr/dt-bindings/misc/nxp_rtxxx_dsp_ctrl.h b/include/zephyr/dt-bindings/misc/nxp_rtxxx_dsp_ctrl.h new file mode 100644 index 00000000000..b8f8a77c955 --- /dev/null +++ b/include/zephyr/dt-bindings/misc/nxp_rtxxx_dsp_ctrl.h @@ -0,0 +1,15 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __NXP_RTXXX_DSP_CTRL_DT_CONST_H__ +#define __NXP_RTXXX_DSP_CTRL_DT_CONST_H__ + +#define NXP_RTXXX_DSP_REGION_RESET 0 +#define NXP_RTXXX_DSP_REGION_TEXT 1 +#define NXP_RTXXX_DSP_REGION_DATA 2 +#define NXP_RTXXX_DSP_REGION_MAX 3 + +#endif