Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] drivers: audio: dmic_nrfx: Add support for nRF54H20 #2280

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions drivers/audio/dmic_nrfx_pdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#include <zephyr/drivers/pinctrl.h>
#include <soc.h>
#include <dmm.h>
#include <nrfx_pdm.h>

#include <zephyr/logging/log.h>
Expand Down Expand Up @@ -36,6 +37,7 @@
PCLK32M_HFXO,
ACLK
} clk_src;
void *mem_reg;
};

static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data, void *buffer)
Expand All @@ -47,6 +49,7 @@
static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
{
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
int ret;
bool stop = false;

Expand All @@ -59,6 +62,14 @@
LOG_ERR("Failed to allocate buffer: %d", ret);
stop = true;
} else {
ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer,
drv_data->block_size,
(void *)drv_data->mem_slab->buffer);

Check notice on line 67 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:67 - ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer, - drv_data->block_size, + ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer, drv_data->block_size,

Check notice on line 67 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:67 - ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer, - drv_data->block_size, + ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer, drv_data->block_size,
if (ret) {
LOG_ERR("Failed to prepare buffer: %d", ret);
stop = true;
goto stop_pdm;
}
err = nrfx_pdm_buffer_set(drv_data->pdm, buffer, drv_data->block_size / 2);
if (err != NRFX_SUCCESS) {
LOG_ERR("Failed to set buffer: 0x%08x", err);
Expand All @@ -69,6 +80,14 @@

if (drv_data->stopping) {
if (evt->buffer_released) {
ret = dmm_buffer_in_release(drv_cfg->mem_reg, evt->buffer_released,
drv_data->block_size,
(void *)drv_data->mem_slab->buffer);
if (ret) {
LOG_ERR("Failed to release buffer: %d", ret);
stop = true;
goto stop_pdm;
}
free_buffer(drv_data, evt->buffer_released);
}

Expand All @@ -85,13 +104,19 @@
if (ret < 0) {
LOG_ERR("No room in RX queue");
stop = true;

ret = dmm_buffer_in_release(drv_cfg->mem_reg, evt->buffer_released,
drv_data->block_size,
(void *)drv_data->mem_slab->buffer);
if (ret) {
LOG_ERR("Failed to release buffer: %d", ret);
goto stop_pdm;
}
free_buffer(drv_data, evt->buffer_released);
} else {
LOG_DBG("Queued buffer %p", evt->buffer_released);
}
}

stop_pdm:
if (stop) {
drv_data->stopping = true;
nrfx_pdm_stop(drv_data->pdm);
Expand Down Expand Up @@ -168,7 +193,7 @@
better_found = true;
}
#else
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) {
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X) || IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX)) {
const uint32_t src_freq =
(NRF_PDM_HAS_MCLKCONFIG && drv_cfg->clk_src == ACLK)
/* The DMIC_NRFX_PDM_DEVICE() macro contains build
Expand All @@ -180,10 +205,15 @@
* not defined (this expression will be eventually
* optimized away then).
*/
/* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK.
* Assume that master clock source frequency is 8 MHz. Remove once
* correct formula is found.
*/
? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency,
0)
: 32*1000*1000UL;
: COND_CODE_1(IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX),
(8*1000*1000UL), (32*1000*1000UL));
uint32_t req_freq = req_rate * ratio;

Check notice on line 216 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:216 - /* The DMIC_NRFX_PDM_DEVICE() macro contains build - * assertions that make sure that the ACLK clock - * source is only used when it is available and only - * with the "hfclkaudio-frequency" property defined, - * but the default value of 0 here needs to be used - * to prevent compilation errors when the property is - * not defined (this expression will be eventually - * optimized away then). - */ - /* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK. - * Assume that master clock source frequency is 8 MHz. Remove once - * correct formula is found. - */ - ? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, - 0) - : COND_CODE_1(IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX), - (8*1000*1000UL), (32*1000*1000UL)); + /* The DMIC_NRFX_PDM_DEVICE() macro contains build + * assertions that make sure that the ACLK clock + * source is only used when it is available and only + * with the "hfclkaudio-frequency" property defined, + * but the default value of 0 here needs to be used + * to prevent compilation errors when the property is + * not defined (this expression will be eventually + * optimized away then). + */ + /* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK. + * Assume that master clock source frequency is 8 MHz. Remove once + * correct formula is found. + */ + ? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0) + : COND_CODE_1(IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX), + (8 * 1000 * 1000UL), (32 * 1000 * 1000UL));

Check notice on line 216 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:216 - /* The DMIC_NRFX_PDM_DEVICE() macro contains build - * assertions that make sure that the ACLK clock - * source is only used when it is available and only - * with the "hfclkaudio-frequency" property defined, - * but the default value of 0 here needs to be used - * to prevent compilation errors when the property is - * not defined (this expression will be eventually - * optimized away then). - */ - /* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK. - * Assume that master clock source frequency is 8 MHz. Remove once - * correct formula is found. - */ - ? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, - 0) - : COND_CODE_1(IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX), - (8*1000*1000UL), (32*1000*1000UL)); + /* The DMIC_NRFX_PDM_DEVICE() macro contains build + * assertions that make sure that the ACLK clock + * source is only used when it is available and only + * with the "hfclkaudio-frequency" property defined, + * but the default value of 0 here needs to be used + * to prevent compilation errors when the property is + * not defined (this expression will be eventually + * optimized away then). + */ + /* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK. + * Assume that master clock source frequency is 8 MHz. Remove once + * correct formula is found. + */ + ? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0) + : COND_CODE_1(IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX), + (8 * 1000 * 1000UL), (32 * 1000 * 1000UL));
/* As specified in the nRF5340 PS:
*
* PDMCLKCTRL = 4096 * floor(f_pdm * 1048576 /
Expand Down Expand Up @@ -562,6 +592,7 @@
return ret;
}

#if CONFIG_CLOCK_CONTROL_NRF
static void init_clock_manager(const struct device *dev)
{
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
Expand All @@ -581,6 +612,7 @@
drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys);
__ASSERT_NO_MSG(drv_data->clk_mgr != NULL);
}
#endif

static const struct _dmic_ops dmic_ops = {
.configure = dmic_nrfx_pdm_configure,
Expand Down Expand Up @@ -609,7 +641,8 @@
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
(char *)rx_msgs##idx, sizeof(void *), \
ARRAY_SIZE(rx_msgs##idx)); \
init_clock_manager(dev); \
IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
(init_clock_manager(dev);)) \
return 0; \
} \
static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
Expand All @@ -624,6 +657,7 @@
.nrfx_def_cfg.skip_psel_cfg = true, \
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \
.clk_src = PDM_CLK_SRC(idx), \
.mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
}; \
BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
"Clock source ACLK is not available."); \
Expand All @@ -635,7 +669,7 @@
DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \
&dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \
POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
&dmic_ops);

Check notice on line 672 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:672 -#define PDM_NRFX_DEVICE(idx) \ - static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ - static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ - static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ - static int pdm_nrfx_init##idx(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \ - nrfx_isr, nrfx_pdm_##idx##_irq_handler, 0); \ - const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ - int err = pinctrl_apply_state(drv_cfg->pcfg, \ - PINCTRL_STATE_DEFAULT); \ - if (err < 0) { \ - return err; \ - } \ - dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ - k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \ - (char *)rx_msgs##idx, sizeof(void *), \ - ARRAY_SIZE(rx_msgs##idx)); \ - IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \ - (init_clock_manager(dev);)) \ - return 0; \ - } \ - static void event_handler##idx(const nrfx_pdm_evt_t *evt) \ - { \ - event_handler(DEVICE_DT_GET(PDM(idx)), evt); \ - } \ - PINCTRL_DT_DEFINE(PDM(idx)); \ - static const struct dmic_nrfx_pdm_drv_cfg dmic_nrfx_pdm_cfg##idx = { \ - .event_handler = event_handler##idx, \ - .nrfx_def_cfg = NRFX_PDM_DEFAULT_CONFIG(0, 0), \ - .nrfx_def_cfg.skip_gpio_cfg = true, \ - .nrfx_def_cfg.skip_psel_cfg = true, \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \ - .clk_src = PDM_CLK_SRC(idx), \ - .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \ - }; \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \ - "Clock source ACLK is not available."); \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \ - DT_NODE_HAS_PROP(DT_NODELABEL(clock), \ - hfclkaudio_frequency), \ - "Clock source ACLK requires the hfclkaudio-frequency " \ - "property to be defined in the nordic,nrf-clock node."); \ - DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \ - &dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \ - POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \ +#define PDM_NRFX_DEVICE(idx) \ + static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ + static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ + static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ + static int pdm_nrfx_init##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), nrfx_isr, \ + nrfx_pdm_##idx##_irq_handler, 0); \ + const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ + int err = pinctrl_apply_state(drv_cfg->pcfg, PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ + k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, (char *)rx_msgs##idx, \ + sizeof(void *), ARRAY_SIZE(rx_msgs##idx)); \ + IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, (init_clock_manager(dev);)) \ + return 0; \ + } \ + static void event_handler##idx(const nrfx_pdm_evt_t *evt)

Check notice on line 672 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:672 -#define PDM_NRFX_DEVICE(idx) \ - static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ - static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ - static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ - static int pdm_nrfx_init##idx(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \ - nrfx_isr, nrfx_pdm_##idx##_irq_handler, 0); \ - const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ - int err = pinctrl_apply_state(drv_cfg->pcfg, \ - PINCTRL_STATE_DEFAULT); \ - if (err < 0) { \ - return err; \ - } \ - dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ - k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \ - (char *)rx_msgs##idx, sizeof(void *), \ - ARRAY_SIZE(rx_msgs##idx)); \ - IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \ - (init_clock_manager(dev);)) \ - return 0; \ - } \ - static void event_handler##idx(const nrfx_pdm_evt_t *evt) \ - { \ - event_handler(DEVICE_DT_GET(PDM(idx)), evt); \ - } \ - PINCTRL_DT_DEFINE(PDM(idx)); \ - static const struct dmic_nrfx_pdm_drv_cfg dmic_nrfx_pdm_cfg##idx = { \ - .event_handler = event_handler##idx, \ - .nrfx_def_cfg = NRFX_PDM_DEFAULT_CONFIG(0, 0), \ - .nrfx_def_cfg.skip_gpio_cfg = true, \ - .nrfx_def_cfg.skip_psel_cfg = true, \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \ - .clk_src = PDM_CLK_SRC(idx), \ - .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \ - }; \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \ - "Clock source ACLK is not available."); \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \ - DT_NODE_HAS_PROP(DT_NODELABEL(clock), \ - hfclkaudio_frequency), \ - "Clock source ACLK requires the hfclkaudio-frequency " \ - "property to be defined in the nordic,nrf-clock node."); \ - DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \ - &dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \ - POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \ +#define PDM_NRFX_DEVICE(idx) \ + static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ + static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ + static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ + static int pdm_nrfx_init##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), nrfx_isr, \ + nrfx_pdm_##idx##_irq_handler, 0); \ + const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ + int err = pinctrl_apply_state(drv_cfg->pcfg, PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ + k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, (char *)rx_msgs##idx, \ + sizeof(void *), ARRAY_SIZE(rx_msgs##idx)); \ + IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, (init_clock_manager(dev);)) \ + return 0; \ + } \ + static void event_handler##idx(const nrfx_pdm_evt_t *evt)

#ifdef CONFIG_HAS_HW_NRF_PDM0
PDM_NRFX_DEVICE(0);
Expand Down
2 changes: 1 addition & 1 deletion dts/bindings/audio/nordic,nrf-pdm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Nordic PDM (Pulse Density Modulation interface)

compatible: "nordic,nrf-pdm"

include: [base.yaml, pinctrl-device.yaml]
include: ["base.yaml", "pinctrl-device.yaml", "memory-region.yaml", "nordic-clockpin.yaml"]

properties:
reg:
Expand Down
9 changes: 9 additions & 0 deletions dts/common/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,15 @@
power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>;
};

pdm0: pdm@993000 {
compatible = "nordic,nrf-pdm";
reg = <0x993000 0x1000>;
status = "disabled";
interrupts = <403 NRF_DEFAULT_IRQ_PRIORITY>;
nordic,clockpin-enable = <NRF_FUN_PDM_CLK>;
power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>;
};

qdec130: qdec@994000 {
compatible = "nordic,nrf-qdec";
reg = <0x994000 0x1000>;
Expand Down
Loading