From eedb1a2c046c24676e75bf2b2ec813f1a5d8230c Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:27:57 -0500 Subject: [PATCH 1/7] dts: bindings: Add binding for NXP Multirate Timer Add binding for nxp,mrt and nxp,mrt-channel. MRT is NXP multirate timer, a simple timer with multiple independent channels. Signed-off-by: Declan Snyder --- dts/bindings/counter/nxp,mrt-channel.yaml | 15 ++++++++++++ dts/bindings/counter/nxp,mrt.yaml | 28 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 dts/bindings/counter/nxp,mrt-channel.yaml create mode 100644 dts/bindings/counter/nxp,mrt.yaml diff --git a/dts/bindings/counter/nxp,mrt-channel.yaml b/dts/bindings/counter/nxp,mrt-channel.yaml new file mode 100644 index 00000000000000..c3ab744fc5a878 --- /dev/null +++ b/dts/bindings/counter/nxp,mrt-channel.yaml @@ -0,0 +1,15 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP Multirate Timer Channel + + Must be a child node of an nxp,mrt compatible node. + +compatible: "nxp,mrt-channel" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/counter/nxp,mrt.yaml b/dts/bindings/counter/nxp,mrt.yaml new file mode 100644 index 00000000000000..e9e05b6c5b5b06 --- /dev/null +++ b/dts/bindings/counter/nxp,mrt.yaml @@ -0,0 +1,28 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP Multirate Timer + +compatible: "nxp,mrt" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + num-channels: + type: int + required: true + description: Number of channels on the IP version + + num-bits: + type: int + required: true + description: Timer width in bits of IP version + + clocks: + required: true From 4e1415d1022878344842ee673e5d9c4122779f84 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:30:14 -0500 Subject: [PATCH 2/7] drivers: clock_control_mcux_syscon: Add MRT subsys Add code to handle MRT subsys clock to LPC syscon driver Signed-off-by: Declan Snyder --- .../clock_control/clock_control_mcux_syscon.c | 16 +++++++++++++--- .../dt-bindings/clock/mcux_lpc_syscon_clock.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index 2349be21711bbb..3dcc073954c2fc 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -19,12 +19,19 @@ static int mcux_lpc_syscon_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system) { #if defined(CONFIG_CAN_MCUX_MCAN) - uint32_t clock_name = (uint32_t)sub_system; - - if (clock_name == MCUX_MCAN_CLK) { + if ((uint32_t)sub_system == MCUX_MCAN_CLK) { CLOCK_EnableClock(kCLOCK_Mcan); } #endif /* defined(CONFIG_CAN_MCUX_MCAN) */ +#if defined(CONFIG_COUNTER_NXP_MRT) + if ((uint32_t)sub_system == MCUX_MRT_CLK) { +#if defined(CONFIG_SOC_FAMILY_LPC) + CLOCK_EnableClock(kCLOCK_Mrt); +#elif defined(CONFIG_SOC_FAMILY_IMX) + CLOCK_EnableClock(kCLOCK_Mrt0); +#endif + } +#endif /* defined(CONFIG_COUNTER_NXP_MRT) */ return 0; } @@ -145,6 +152,9 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( break; #endif +#if defined(CONFIG_COUNTER_NXP_MRT) + case MCUX_MRT_CLK: +#endif #if defined(CONFIG_PWM_MCUX_SCTIMER) case MCUX_SCTIMER_CLK: #endif diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index 581c5b57e08f70..9f80b662c60b7a 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -51,4 +51,6 @@ #define MCUX_SCTIMER_CLK 34 +#define MCUX_MRT_CLK 40 + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ From 5b1ea6b9c556c757d885a41699441e349714fee0 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:34:09 -0500 Subject: [PATCH 3/7] drivers: counter: Add NXP MRT driver Add driver for NXP Multirate Timer Signed-off-by: Declan Snyder --- drivers/counter/CMakeLists.txt | 5 +- drivers/counter/Kconfig | 2 + drivers/counter/Kconfig.nxp_mrt | 9 + drivers/counter/counter_nxp_mrt.c | 341 ++++++++++++++++++++++++++++++ 4 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 drivers/counter/Kconfig.nxp_mrt create mode 100644 drivers/counter/counter_nxp_mrt.c diff --git a/drivers/counter/CMakeLists.txt b/drivers/counter/CMakeLists.txt index 3a59312da249b2..50a1ffad44193e 100644 --- a/drivers/counter/CMakeLists.txt +++ b/drivers/counter/CMakeLists.txt @@ -44,7 +44,8 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_INFINEON_CAT1 counter_ifx_cat1 zephyr_library_sources_ifdef(CONFIG_ACE_V1X_ART_COUNTER counter_ace_v1x_art.c) zephyr_library_sources_ifdef(CONFIG_ACE_V1X_RTC_COUNTER counter_ace_v1x_rtc.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_S32_SYS_TIMER counter_nxp_s32_sys_timer.c) -zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_GD32 counter_gd32_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_GD32 counter_gd32_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SNPS_DW counter_dw_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SHELL counter_timer_shell.c) -zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_RPI_PICO counter_rpi_pico_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_RPI_PICO counter_rpi_pico_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_MRT counter_nxp_mrt.c) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 956c5d59f642ab..16adaee75b2728 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -94,4 +94,6 @@ source "drivers/counter/Kconfig.dw" source "drivers/counter/Kconfig.rpi_pico" +source "drivers/counter/Kconfig.nxp_mrt" + endif # COUNTER diff --git a/drivers/counter/Kconfig.nxp_mrt b/drivers/counter/Kconfig.nxp_mrt new file mode 100644 index 00000000000000..a395ada36b459b --- /dev/null +++ b/drivers/counter/Kconfig.nxp_mrt @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_NXP_MRT + bool "NXP MRT driver" + default y if DT_HAS_NXP_MRT_CHANNEL_ENABLED && \ + DT_HAS_NXP_MRT_ENABLED + help + Enable driver for the NXP Multirate Timer (MRT). diff --git a/drivers/counter/counter_nxp_mrt.c b/drivers/counter/counter_nxp_mrt.c new file mode 100644 index 00000000000000..741e7b34d40c99 --- /dev/null +++ b/drivers/counter/counter_nxp_mrt.c @@ -0,0 +1,341 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * MRT (Multirate timer) is a lightweight timer with multiple independent channels, each capable + * of signalling the shared interrupt with a different period. This driver treats all the channels + * as separate devices adhering to the counter API. The parent device is responsible for the + * initialization, interrupt handling, and any other module-wide tasks. The current implementation + * of this driver prioritizes minimizing image size over speed, because it is not expected for the + * functions to be called very often, and this IP is mostly present on low memory devices. + */ + +#define DT_DRV_COMPAT nxp_mrt + +#include +#include +#include +#include +#include +#include + +#define LOG_MODULE_NAME counter_mrt +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_COUNTER_LOG_LEVEL); + +/* Device holds a pointer to pointer to data */ +#define MRT_CHANNEL_DATA(dev) \ + (*(struct nxp_mrt_channel_data *const *const)dev->data) + +/* Device config->data is an array of data pointers ordered by channel number, + * dev->data is a pointer to one of these pointers in that array, + * so the value of the dev->data - dev->config->data is the channel index + */ +#define MRT_CHANNEL_ID(dev) \ + (((struct nxp_mrt_channel_data *const *)dev->data) - \ + ((const struct nxp_mrt_config *)dev->config)->data) + +/* Specific for each channel */ +struct nxp_mrt_channel_data { + uint32_t top; + counter_top_callback_t cb; + void *user_data; +}; + +/* Shared between all channels */ +struct nxp_mrt_config { + struct counter_config_info info; + MRT_Type *base; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; + void (*irq_config_func)(const struct device *dev); + struct nxp_mrt_channel_data *const *data; + const struct device *const *channels; +}; + +static int nxp_mrt_stop(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + LOG_DBG("MRT@%p channel %d stopped", base, channel_id); + LOG_WRN("MRT channel resets upon stopping"); + + /* LOAD bit and 0 ivalue allows us to forcibly stop the timer */ + base->CHANNEL[channel_id].INTVAL = MRT_CHANNEL_INTVAL_LOAD(1); + + return 0; +} + +static int nxp_mrt_start(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + struct nxp_mrt_channel_data *data = MRT_CHANNEL_DATA(dev); + int channel_id = MRT_CHANNEL_ID(dev); + + if (data->top <= 1) { + /* Zephyr API says default should be max top value */ + LOG_INF("\"Started\" MRT@%p channel %d with default value %d", + base, channel_id, config->info.max_top_value); + data->top = config->info.max_top_value; + } + + /* Start with previously configured top value (if already running this has no effect) */ + base->CHANNEL[channel_id].INTVAL = data->top; + + LOG_DBG("MRT@%p channel %d started with top value %d", base, channel_id, data->top); + + return 0; +} + +static int nxp_mrt_get_value(const struct device *dev, uint32_t *ticks) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + *ticks = base->CHANNEL[channel_id].TIMER & MRT_CHANNEL_TIMER_VALUE_MASK; + + return 0; +} + + +static int nxp_mrt_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + struct nxp_mrt_channel_data *data = MRT_CHANNEL_DATA(dev); + int channel_id = MRT_CHANNEL_ID(dev); + /* By default in Zephyr API, the counter resets on changing top value */ + bool reset = !(cfg->flags & COUNTER_TOP_CFG_DONT_RESET); + bool active = base->CHANNEL[channel_id].STAT & MRT_CHANNEL_STAT_RUN_MASK; + uint32_t current_val = base->CHANNEL[channel_id].TIMER & MRT_CHANNEL_TIMER_VALUE_MASK; + int ret = 0; + + /* Store for use by counter_start */ + data->top = cfg->ticks; + + /* Used by ISR */ + data->cb = cfg->callback; + data->user_data = cfg->user_data; + + + /* If not yet started, wait for counter_start because setting reg value starts timer */ + if (!active) { + LOG_DBG("Set MRT@%p channel %d top value to %d", base, channel_id, data->top); + return ret; + } + + /* Otherwise if currently running, need to check for lateness */ + if (cfg->ticks < current_val) { + LOG_WRN("MRT@%p channel %d received requested top value %d which is " + "smaller than current count %d", + base, channel_id, cfg->ticks, current_val); + /* Zephyr API says return this error in case of lateness + * when COUNTER_TOP_CFG_DONT_RESET is set but can still set period + */ + ret = reset ? 0 : -ETIME; + /* If user said not to reset, they can also clarify exception for lateness */ + reset |= cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE; + } + + /* Sets the top value. If we need to reset, LOAD bit does this */ + base->CHANNEL[channel_id].INTVAL = MRT_CHANNEL_INTVAL_IVALUE(cfg->ticks) | + MRT_CHANNEL_INTVAL_LOAD(reset ? 1 : 0); + + LOG_DBG("Changed MRT@%p channel %d top value while active to %d", + base, channel_id, + base->CHANNEL[channel_id].INTVAL & MRT_CHANNEL_INTVAL_IVALUE_MASK); + + return ret; +} + +static uint32_t nxp_mrt_get_top_value(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + return base->CHANNEL[channel_id].INTVAL & MRT_CHANNEL_INTVAL_IVALUE_MASK; +} + +static uint32_t nxp_mrt_get_pending_int(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + int channel_id = MRT_CHANNEL_ID(dev); + + return base->CHANNEL[channel_id].STAT & MRT_CHANNEL_STAT_INTFLAG_MASK; +} + +static inline int nxp_mrt_set_alarm(const struct device *dev, + uint8_t chan_id, + const struct counter_alarm_cfg *alarm_cfg) +{ + ARG_UNUSED(dev); + ARG_UNUSED(chan_id); + ARG_UNUSED(alarm_cfg); + + LOG_ERR("MRT does not support alarms"); + return -ENOTSUP; +} + +static inline int nxp_mrt_cancel_alarm(const struct device *dev, uint8_t chan_id) +{ + ARG_UNUSED(dev); + ARG_UNUSED(chan_id); + + LOG_ERR("MRT does not support alarms"); + return -ENOTSUP; +} + +uint32_t nxp_mrt_get_freq(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + uint32_t freq; + + clock_control_get_rate(config->clock_dev, config->clock_subsys, &freq); + + return freq; +} + +static int nxp_mrt_init(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + + clock_control_on(config->clock_dev, config->clock_subsys); + + config->irq_config_func(dev); + + /* Enable interrupts for all the channels that have devices */ + for (int i = 0; i < num_channels; i++) { + if (config->channels[i]) { + base->CHANNEL[i].CTRL = MRT_CHANNEL_CTRL_INTEN_MASK; + } + } + + return 0; +} + +static void nxp_mrt_isr(const struct device *dev) +{ + const struct nxp_mrt_config *config = dev->config; + MRT_Type *base = config->base; + uint32_t irq_pends = base->IRQ_FLAG; + uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + + for (int i = 0; i < num_channels; i++) { + /* Channel IRQ pending flags lowest order bits in IRQ_FLAG register */ + if (!(irq_pends & (0x1 << i))) { + continue; + } + + LOG_DBG("Handling interrupt for MRT%p channel %d", base, i); + + /* W1C interrupt flag */ + base->CHANNEL[i].STAT |= MRT_CHANNEL_STAT_INTFLAG_MASK; + + /* Channel devs & pointer path to channel cbs is in shared config */ + if (config->data[i]->cb) { + config->data[i]->cb(config->channels[i], config->data[i]->user_data); + } + } +} + +struct counter_driver_api nxp_mrt_api = { + .get_value = nxp_mrt_get_value, + .start = nxp_mrt_start, + .stop = nxp_mrt_stop, + .set_top_value = nxp_mrt_set_top_value, + .get_top_value = nxp_mrt_get_top_value, + .get_pending_int = nxp_mrt_get_pending_int, + .set_alarm = nxp_mrt_set_alarm, + .cancel_alarm = nxp_mrt_cancel_alarm, + .get_freq = nxp_mrt_get_freq, +}; + +/* Creates a device for a channel (needed for counter API) */ +#define NXP_MRT_CHANNEL_DEV_INIT(node, mrt_inst) \ + DEVICE_DT_DEFINE(node, NULL, NULL, \ + (void *) \ + &nxp_mrt_##mrt_inst##_channel_datas[DT_REG_ADDR(node)], \ + &nxp_mrt_##mrt_inst##_config, \ + POST_KERNEL, CONFIG_COUNTER_INIT_PRIORITY, \ + &nxp_mrt_api); \ + +/* Creates a data struct for a channel device */ +#define NXP_MRT_CHANNEL_DATA_INIT(node) \ + static struct nxp_mrt_channel_data \ + nxp_mrt_channel_data_##node; \ + +/* Initializes an element of the channel data pointer array */ +#define NXP_MRT_CHANNEL_DATA_ARRAY_INIT(node) \ + [DT_REG_ADDR(node)] = \ + &nxp_mrt_channel_data_##node, + +/* Initializes an element of the channel device pointer array */ +#define NXP_MRT_CHANNEL_DEV_ARRAY_INIT(node) \ + [DT_REG_ADDR(node)] = DEVICE_DT_GET(node), + +#define NXP_MRT_INIT(n) \ + /* ISR is shared between all channels */ \ + static void nxp_mrt_##n##_irq_config_func(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + nxp_mrt_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + /* Initialize all the data structs for active channels */ \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, NXP_MRT_CHANNEL_DATA_INIT) \ + \ + /* Create an array of const pointers to the data structs */ \ + static struct nxp_mrt_channel_data *const nxp_mrt_##n##_channel_datas \ + [DT_INST_PROP(n, num_channels)] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, \ + NXP_MRT_CHANNEL_DATA_ARRAY_INIT) \ + }; \ + \ + /* Forward declaration */ \ + const static struct nxp_mrt_config nxp_mrt_##n##_config; \ + \ + /* Create all the channel/counter devices */ \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_VARGS(n, NXP_MRT_CHANNEL_DEV_INIT, n) \ + \ + /* This channel device array is needed by the module device ISR */ \ + const struct device *const nxp_mrt_##n##_channels \ + [DT_INST_PROP(n, num_channels)] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, \ + NXP_MRT_CHANNEL_DEV_ARRAY_INIT) \ + }; \ + \ + /* This config struct is shared by all the channels and parent device */\ + const static struct nxp_mrt_config nxp_mrt_##n##_config = { \ + .info = { \ + .max_top_value = \ + GENMASK(DT_INST_PROP(n, num_bits) - 1, 0), \ + .channels = 0, \ + }, \ + .base = (MRT_Type *)DT_INST_REG_ADDR(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) \ + DT_INST_CLOCKS_CELL(n, name), \ + .irq_config_func = nxp_mrt_##n##_irq_config_func, \ + .data = nxp_mrt_##n##_channel_datas, \ + .channels = nxp_mrt_##n##_channels, \ + }; \ + \ + /* Init parent device in order to handle ISR and init. */ \ + DEVICE_DT_INST_DEFINE(n, &nxp_mrt_init, NULL, NULL, \ + &nxp_mrt_##n##_config, \ + POST_KERNEL, \ + CONFIG_COUNTER_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(NXP_MRT_INIT) From 6436f0685377c75d25933b1edd46504046c49db1 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:34:52 -0500 Subject: [PATCH 4/7] tests: counter: Update for NXP MRT Update counter test to test NXP MRT devices Signed-off-by: Declan Snyder --- tests/drivers/counter/counter_basic_api/src/test_counter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index 462de26d03750c..f63ee5ce6c46cf 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -66,6 +66,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_MCUX_QTMR DEVS_FOR_DT_COMPAT(nxp_imx_tmr) #endif +#ifdef CONFIG_COUNTER_NXP_MRT + DEVS_FOR_DT_COMPAT(nxp_mrt_channel) +#endif #ifdef CONFIG_COUNTER_MCUX_LPC_RTC DEVS_FOR_DT_COMPAT(nxp_lpc_rtc) #endif From eedd2a71d40994cbb7fcbf31f2b86f718d285f62 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:36:15 -0500 Subject: [PATCH 5/7] soc: rt5xx: Enable NXP MRT Enable NXP MRT on RT5xx soc and MIMXRT595_EVK board Signed-off-by: Declan Snyder --- .../arm/mimxrt595_evk/mimxrt595_evk_cm33.dts | 4 +++ dts/arm/nxp/nxp_rt5xx_common.dtsi | 32 +++++++++++++++++++ soc/arm/nxp_imx/rt5xx/soc.c | 4 +++ 3 files changed, 40 insertions(+) diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts index 49dd4f424be44b..b91a45f500815c 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts @@ -478,3 +478,7 @@ zephyr_udc0: &usbhs { dmas = <&smartdma>; dma-names = "smartdma"; }; + +&mrt_channel0 { + status = "okay"; +}; diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index 9165b26441e1af..1eef1cbbd5ebdd 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -579,6 +579,38 @@ #mbox-cells = <1>; status = "disabled"; }; + + mrt: mrt@2d000 { + compatible = "nxp,mrt"; + reg = <0x2d000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&clkctl1 MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &flexspi { diff --git a/soc/arm/nxp_imx/rt5xx/soc.c b/soc/arm/nxp_imx/rt5xx/soc.c index 72684393959bad..f6af227b17cbb0 100644 --- a/soc/arm/nxp_imx/rt5xx/soc.c +++ b/soc/arm/nxp_imx/rt5xx/soc.c @@ -419,6 +419,10 @@ void __weak rt5xx_clock_init(void) CLOCK_SetClkDiv(kCLOCK_DivAdcClk, 1); #endif +#if CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; From 698adff27b52758363d53e2f37bb8f21b1375475 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:38:16 -0500 Subject: [PATCH 6/7] soc: rt6xx: Add NXP MRT Add NXP MRT to RT6xx DT definition and add peripheral reset to soc.c Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_rt6xx_common.dtsi | 32 +++++++++++++++++++++++++++++++ soc/arm/nxp_imx/rt6xx/soc.c | 4 ++++ 2 files changed, 36 insertions(+) diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 843c1739cd29ef..095e8635994386 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -459,6 +459,38 @@ #address-cells = <3>; #size-cells = <0>; }; + + mrt: mrt@2d000 { + compatible = "nxp,mrt"; + reg = <0x2d000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&clkctl1 MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &flexspi { diff --git a/soc/arm/nxp_imx/rt6xx/soc.c b/soc/arm/nxp_imx/rt6xx/soc.c index e04499b289d84c..2d4eab6854d271 100644 --- a/soc/arm/nxp_imx/rt6xx/soc.c +++ b/soc/arm/nxp_imx/rt6xx/soc.c @@ -321,6 +321,10 @@ static ALWAYS_INLINE void clock_init(void) flexspi_setup_clock(FLEXSPI, 1U, 9U); #endif +#if CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT0_RST_SHIFT_RSTn); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; From 1a459956b76f0b365b1cc310c9d285d896b1b68b Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 3 Nov 2023 10:39:36 -0500 Subject: [PATCH 7/7] soc: lpc55xxx: Support, enable, test NXP MRT Support NXP MRT on LPC55XXX SOC series, enable on lpcxpresso55s69_cpu0, add test overlay to counter basic api test Signed-off-by: Declan Snyder --- .../lpcxpresso55s69/lpcxpresso55s69_cpu0.dts | 4 +++ dts/arm/nxp/nxp_lpc55S6x_common.dtsi | 32 +++++++++++++++++++ soc/arm/nxp_lpc/lpc55xxx/soc.c | 4 +++ .../boards/lpcxpresso55s69_cpu0.overlay | 15 +++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts index 5b29efecadf2ee..14ba04fa448dea 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts @@ -204,3 +204,7 @@ i2s1: &flexcomm7 { &dma1 { status = "okay"; }; + +&mrt_channel0 { + status = "okay"; +}; diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index c7c7d238dc7862..0f953cb3a4e08f 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -412,6 +412,38 @@ prescaler = <2>; #pwm-cells = <3>; }; + + mrt: mrt@d000 { + compatible = "nxp,mrt"; + reg = <0xd000 0x100>; + interrupts = <9 0>; + num-channels = <4>; + num-bits = <24>; + clocks = <&syscon MCUX_MRT_CLK>; + #address-cells = <1>; + #size-cells = <0>; + + mrt_channel0: mrt_channel@0 { + compatible = "nxp,mrt-channel"; + reg = <0>; + status = "disabled"; + }; + mrt_channel1: mrt_channel@1 { + compatible = "nxp,mrt-channel"; + reg = <1>; + status = "disabled"; + }; + mrt_channel2: mrt_channel@2 { + compatible = "nxp,mrt-channel"; + reg = <2>; + status = "disabled"; + }; + mrt_channel3: mrt_channel@3 { + compatible = "nxp,mrt-channel"; + reg = <3>; + status = "disabled"; + }; + }; }; &nvic { diff --git a/soc/arm/nxp_lpc/lpc55xxx/soc.c b/soc/arm/nxp_lpc/lpc55xxx/soc.c index 8084be533841e5..b76f3222decfcf 100644 --- a/soc/arm/nxp_lpc/lpc55xxx/soc.c +++ b/soc/arm/nxp_lpc/lpc55xxx/soc.c @@ -347,6 +347,10 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP) #endif /* SOC platform */ #endif /* DAC */ +#ifdef CONFIG_COUNTER_NXP_MRT + RESET_PeripheralReset(kMRT_RST_SHIFT_RSTn); +#endif + } /** diff --git a/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay b/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay new file mode 100644 index 00000000000000..968741c5148924 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/lpcxpresso55s69_cpu0.overlay @@ -0,0 +1,15 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mrt_channel1 { + status = "okay"; +}; + +/* channel 2 disabled to test disabled channel not breaking things */ + +&mrt_channel3 { + status = "okay"; +};