Browse Source
Add the nxp,rtxxx-dsp-ctrl driver. Responsibility of this driver is to load code executed by Xtensa-family cores on NXP i.MX RTxxx microcontrollers and to control their run. Signed-off-by: Vit Stanicek <vit.stanicek@nxp.com>pull/90277/head
8 changed files with 265 additions and 0 deletions
@ -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 |
||||||
|
) |
@ -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. |
@ -0,0 +1,118 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2025 NXP |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#define DT_DRV_COMPAT nxp_rtxxx_dsp_ctrl |
||||||
|
|
||||||
|
#include <zephyr/drivers/misc/nxp_rtxxx_dsp_ctrl/nxp_rtxxx_dsp_ctrl.h> |
||||||
|
#include <zephyr/dt-bindings/misc/nxp_rtxxx_dsp_ctrl.h> |
||||||
|
|
||||||
|
#include <fsl_device_registers.h> |
||||||
|
#include <fsl_dsp.h> |
||||||
|
#include <fsl_clock.h> |
||||||
|
|
||||||
|
#include <errno.h> |
||||||
|
#include <zephyr/init.h> |
||||||
|
#include <zephyr/device.h> |
||||||
|
#include <zephyr/devicetree.h> |
||||||
|
|
||||||
|
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); |
@ -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_*) |
@ -0,0 +1,79 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2025 NXP |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <zephyr/device.h> |
||||||
|
#include <zephyr/dt-bindings/misc/nxp_rtxxx_dsp_ctrl.h> |
||||||
|
|
||||||
|
#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 |
@ -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 |
Loading…
Reference in new issue