drivers: counter: added ctimer driver for lpcexpresso55s69
Added shim driver for the CTIMERs for the lpcexpresso55s69 board. Fixes: #22705 Signed-off-by: Toby Firth <tobyjfirth@gmail.com>
This commit is contained in:
parent
7355204f41
commit
893bfc0fc1
21 changed files with 474 additions and 7 deletions
|
@ -82,6 +82,8 @@ features:
|
||||||
+-----------+------------+-------------------------------------+
|
+-----------+------------+-------------------------------------+
|
||||||
| USB | on-chip | USB device |
|
| USB | on-chip | USB device |
|
||||||
+-----------+------------+-------------------------------------+
|
+-----------+------------+-------------------------------------+
|
||||||
|
| COUNTER | on-chip | counter |
|
||||||
|
+-----------+------------+-------------------------------------+
|
||||||
|
|
||||||
Targets available
|
Targets available
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -109,3 +109,23 @@
|
||||||
zephyr_udc0: &usbhs {
|
zephyr_udc0: &usbhs {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&ctimer0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer3 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer4 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ supported:
|
||||||
- arduino_i2c
|
- arduino_i2c
|
||||||
- arduino_serial
|
- arduino_serial
|
||||||
- arduino_spi
|
- arduino_spi
|
||||||
|
- counter
|
||||||
- gpio
|
- gpio
|
||||||
- i2c
|
- i2c
|
||||||
- spi
|
- spi
|
||||||
|
|
|
@ -107,3 +107,23 @@
|
||||||
zephyr_udc0: &usbhs {
|
zephyr_udc0: &usbhs {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&ctimer0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer3 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&ctimer4 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
|
@ -17,6 +17,7 @@ toolchain:
|
||||||
supported:
|
supported:
|
||||||
- adc
|
- adc
|
||||||
- arduino_spi
|
- arduino_spi
|
||||||
|
- counter
|
||||||
- dma
|
- dma
|
||||||
- gpio
|
- gpio
|
||||||
- spi
|
- spi
|
||||||
|
|
|
@ -34,7 +34,8 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate(
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_I2C_MCUX_FLEXCOMM) || \
|
#if defined(CONFIG_I2C_MCUX_FLEXCOMM) || \
|
||||||
defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
|
defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
|
||||||
defined(CONFIG_UART_MCUX_FLEXCOMM)
|
defined(CONFIG_UART_MCUX_FLEXCOMM) || \
|
||||||
|
defined(CONFIG_COUNTER_MCUX_CTIMER)
|
||||||
|
|
||||||
uint32_t clock_name = (uint32_t) sub_system;
|
uint32_t clock_name = (uint32_t) sub_system;
|
||||||
|
|
||||||
|
@ -79,6 +80,23 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate(
|
||||||
case MCUX_USDHC2_CLK:
|
case MCUX_USDHC2_CLK:
|
||||||
*rate = CLOCK_GetSdioClkFreq(1);
|
*rate = CLOCK_GetSdioClkFreq(1);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_COUNTER_MCUX_CTIMER)
|
||||||
|
case (MCUX_CTIMER0_CLK + MCUX_CTIMER_CLK_OFFSET):
|
||||||
|
*rate = CLOCK_GetCTimerClkFreq(0);
|
||||||
|
break;
|
||||||
|
case (MCUX_CTIMER1_CLK + MCUX_CTIMER_CLK_OFFSET):
|
||||||
|
*rate = CLOCK_GetCTimerClkFreq(1);
|
||||||
|
break;
|
||||||
|
case (MCUX_CTIMER2_CLK + MCUX_CTIMER_CLK_OFFSET):
|
||||||
|
*rate = CLOCK_GetCTimerClkFreq(2);
|
||||||
|
break;
|
||||||
|
case (MCUX_CTIMER3_CLK + MCUX_CTIMER_CLK_OFFSET):
|
||||||
|
*rate = CLOCK_GetCTimerClkFreq(3);
|
||||||
|
break;
|
||||||
|
case (MCUX_CTIMER4_CLK + MCUX_CTIMER_CLK_OFFSET):
|
||||||
|
*rate = CLOCK_GetCTimerClkFreq(4);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,6 +6,7 @@ zephyr_library_sources_ifdef(CONFIG_TIMER_TMR_CMSDK_APB timer_tmr_cmsdk_
|
||||||
zephyr_library_sources_ifdef(CONFIG_TIMER_DTMR_CMSDK_APB timer_dtmr_cmsdk_apb.c)
|
zephyr_library_sources_ifdef(CONFIG_TIMER_DTMR_CMSDK_APB timer_dtmr_cmsdk_apb.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_RTCC counter_gecko_rtcc.c)
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_RTCC counter_gecko_rtcc.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_IMX_EPIT counter_imx_epit.c)
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_IMX_EPIT counter_imx_epit.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_CTIMER counter_mcux_ctimer.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_RTC counter_mcux_rtc.c)
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_RTC counter_mcux_rtc.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_LPC_RTC counter_mcux_lpc_rtc.c)
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_LPC_RTC counter_mcux_lpc_rtc.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_NRF_TIMER counter_nrfx_timer.c)
|
zephyr_library_sources_ifdef(CONFIG_COUNTER_NRF_TIMER counter_nrfx_timer.c)
|
||||||
|
|
|
@ -54,4 +54,6 @@ source "drivers/counter/Kconfig.esp32"
|
||||||
|
|
||||||
source "drivers/counter/Kconfig.mcp7940n"
|
source "drivers/counter/Kconfig.mcp7940n"
|
||||||
|
|
||||||
|
source "drivers/counter/Kconfig.mcux_ctimer"
|
||||||
|
|
||||||
endif # COUNTER
|
endif # COUNTER
|
||||||
|
|
10
drivers/counter/Kconfig.mcux_ctimer
Normal file
10
drivers/counter/Kconfig.mcux_ctimer
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# MCUXpresso SDK CTIMER
|
||||||
|
|
||||||
|
# Copyright (c) 2021 Toby firth
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config COUNTER_MCUX_CTIMER
|
||||||
|
bool "MCUX CTIMER driver"
|
||||||
|
depends on HAS_MCUX_CTIMER
|
||||||
|
help
|
||||||
|
Enable support for MCUX CTIMER driver.
|
251
drivers/counter/counter_mcux_ctimer.c
Normal file
251
drivers/counter/counter_mcux_ctimer.c
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Toby Firth.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#define DT_DRV_COMPAT nxp_lpc_ctimer
|
||||||
|
|
||||||
|
#include <drivers/counter.h>
|
||||||
|
#include <fsl_ctimer.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <drivers/clock_control.h>
|
||||||
|
#include <dt-bindings/clock/mcux_lpc_syscon_clock.h>
|
||||||
|
LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define NUM_CHANNELS 4
|
||||||
|
|
||||||
|
struct mcux_lpc_ctimer_channel_data {
|
||||||
|
counter_alarm_callback_t alarm_callback;
|
||||||
|
void *alarm_user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mcux_lpc_ctimer_data {
|
||||||
|
struct mcux_lpc_ctimer_channel_data channels[NUM_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mcux_lpc_ctimer_config {
|
||||||
|
struct counter_config_info info;
|
||||||
|
CTIMER_Type *base;
|
||||||
|
const struct device *clock_dev;
|
||||||
|
clock_control_subsys_t clock_subsys;
|
||||||
|
ctimer_timer_mode_t mode;
|
||||||
|
ctimer_capture_channel_t input;
|
||||||
|
uint32_t prescale;
|
||||||
|
void (*irq_config_func)(const struct device *dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_start(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
|
||||||
|
CTIMER_StartTimer(config->base);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_stop(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
|
||||||
|
CTIMER_StopTimer(config->base);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t mcux_lpc_ctimer_read(CTIMER_Type *base)
|
||||||
|
{
|
||||||
|
return CTIMER_GetTimerCountValue(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
*ticks = mcux_lpc_ctimer_read(config->base);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
|
||||||
|
const struct counter_alarm_cfg *alarm_cfg)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||||
|
|
||||||
|
uint32_t ticks = alarm_cfg->ticks;
|
||||||
|
uint32_t current = mcux_lpc_ctimer_read(config->base);
|
||||||
|
|
||||||
|
if (data->channels[chan_id].alarm_callback != NULL) {
|
||||||
|
LOG_ERR("channel already in use");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
|
||||||
|
ticks += current;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->channels[chan_id].alarm_callback = alarm_cfg->callback;
|
||||||
|
data->channels[chan_id].alarm_user_data = alarm_cfg->user_data;
|
||||||
|
|
||||||
|
ctimer_match_config_t match_config = { .matchValue = ticks,
|
||||||
|
.enableCounterReset = false,
|
||||||
|
.enableCounterStop = false,
|
||||||
|
.outControl = kCTIMER_Output_NoAction,
|
||||||
|
.outPinInitState = false,
|
||||||
|
.enableInterrupt = true };
|
||||||
|
|
||||||
|
CTIMER_SetupMatch(config->base, chan_id, &match_config);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_cancel_alarm(const struct device *dev, uint8_t chan_id)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||||
|
|
||||||
|
CTIMER_DisableInterrupts(config->base, (1 << chan_id));
|
||||||
|
|
||||||
|
data->channels[chan_id].alarm_callback = NULL;
|
||||||
|
data->channels[chan_id].alarm_user_data = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
|
||||||
|
const struct counter_top_cfg *cfg)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
ARG_UNUSED(cfg);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t mcux_lpc_ctimer_get_pending_int(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
|
||||||
|
return (CTIMER_GetStatusFlags(config->base) & 0xF) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
|
||||||
|
return config->info.max_top_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mcux_lpc_ctimer_isr(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||||
|
|
||||||
|
uint32_t interrupt_stat = CTIMER_GetStatusFlags(config->base);
|
||||||
|
|
||||||
|
CTIMER_ClearStatusFlags(config->base, interrupt_stat);
|
||||||
|
|
||||||
|
uint32_t ticks = mcux_lpc_ctimer_read(config->base);
|
||||||
|
|
||||||
|
for (uint8_t chan = 0; chan < NUM_CHANNELS; chan++) {
|
||||||
|
uint8_t channel_mask = 0x01 << chan;
|
||||||
|
|
||||||
|
if (((interrupt_stat & channel_mask) != 0) &&
|
||||||
|
(data->channels[chan].alarm_callback != NULL)) {
|
||||||
|
counter_alarm_callback_t alarm_callback =
|
||||||
|
data->channels[chan].alarm_callback;
|
||||||
|
void *alarm_user_data = data->channels[chan].alarm_user_data;
|
||||||
|
|
||||||
|
data->channels[chan].alarm_callback = NULL;
|
||||||
|
data->channels[chan].alarm_user_data = NULL;
|
||||||
|
alarm_callback(dev, chan, ticks, alarm_user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_lpc_ctimer_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The frequency of the timer is not known at compile time so we need to
|
||||||
|
* modify the timer's config in the init function at runtime when the
|
||||||
|
* frequency is known.
|
||||||
|
*/
|
||||||
|
struct mcux_lpc_ctimer_config *config = (struct mcux_lpc_ctimer_config *)dev->config;
|
||||||
|
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||||
|
|
||||||
|
ctimer_config_t ctimer_config;
|
||||||
|
|
||||||
|
uint32_t clk_freq = 0;
|
||||||
|
|
||||||
|
if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
|
||||||
|
&clk_freq)) {
|
||||||
|
LOG_ERR("unable to get clock frequency");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prescale increments when the prescale counter is 0 so if prescale is 1
|
||||||
|
* the counter is incremented every 2 cycles of the clock so will actually
|
||||||
|
* divide by 2 hence the addition of 1 to the value here.
|
||||||
|
*/
|
||||||
|
uint32_t freq = clk_freq / (config->prescale + 1);
|
||||||
|
|
||||||
|
config->info.freq = freq;
|
||||||
|
|
||||||
|
for (uint8_t chan = 0; chan < NUM_CHANNELS; chan++) {
|
||||||
|
data->channels[chan].alarm_callback = NULL;
|
||||||
|
data->channels[chan].alarm_user_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTIMER_GetDefaultConfig(&ctimer_config);
|
||||||
|
|
||||||
|
ctimer_config.mode = config->mode;
|
||||||
|
ctimer_config.input = config->input;
|
||||||
|
ctimer_config.prescale = config->prescale;
|
||||||
|
|
||||||
|
CTIMER_Init(config->base, &ctimer_config);
|
||||||
|
|
||||||
|
config->irq_config_func(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct counter_driver_api mcux_ctimer_driver_api = {
|
||||||
|
.start = mcux_lpc_ctimer_start,
|
||||||
|
.stop = mcux_lpc_ctimer_stop,
|
||||||
|
.get_value = mcux_lpc_ctimer_get_value,
|
||||||
|
.set_alarm = mcux_lpc_ctimer_set_alarm,
|
||||||
|
.cancel_alarm = mcux_lpc_ctimer_cancel_alarm,
|
||||||
|
.set_top_value = mcux_lpc_ctimer_set_top_value,
|
||||||
|
.get_pending_int = mcux_lpc_ctimer_get_pending_int,
|
||||||
|
.get_top_value = mcux_lpc_ctimer_get_top_value,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CTIMER_CLOCK_SOURCE(id) TO_CTIMER_CLOCK_SOURCE(id, DT_INST_PROP(id, clk_source))
|
||||||
|
#define TO_CTIMER_CLOCK_SOURCE(id, val) MUX_A(CM_CTIMERCLKSEL##id, val)
|
||||||
|
|
||||||
|
#define COUNTER_LPC_CTIMER_DEVICE(id) \
|
||||||
|
static void mcux_lpc_ctimer_irq_config_##id(const struct device *dev); \
|
||||||
|
static struct mcux_lpc_ctimer_config mcux_lpc_ctimer_config_##id = { \
|
||||||
|
.info = { \
|
||||||
|
.max_top_value = UINT32_MAX, \
|
||||||
|
.freq = 1, \
|
||||||
|
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
|
||||||
|
.channels = NUM_CHANNELS, \
|
||||||
|
},\
|
||||||
|
.base = (CTIMER_Type *)DT_INST_REG_ADDR(id), \
|
||||||
|
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
|
||||||
|
.clock_subsys = \
|
||||||
|
(clock_control_subsys_t)(DT_INST_CLOCKS_CELL(id, name) + MCUX_CTIMER_CLK_OFFSET),\
|
||||||
|
.mode = DT_INST_PROP(id, mode), \
|
||||||
|
.input = DT_INST_PROP(id, input), \
|
||||||
|
.prescale = DT_INST_PROP(id, prescale), \
|
||||||
|
.irq_config_func = mcux_lpc_ctimer_irq_config_##id, \
|
||||||
|
}; \
|
||||||
|
static struct mcux_lpc_ctimer_data mcux_lpc_ctimer_data_##id; \
|
||||||
|
DEVICE_DT_INST_DEFINE(id, &mcux_lpc_ctimer_init, NULL, &mcux_lpc_ctimer_data_##id, \
|
||||||
|
&mcux_lpc_ctimer_config_##id, POST_KERNEL, \
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &mcux_ctimer_driver_api); \
|
||||||
|
static void mcux_lpc_ctimer_irq_config_##id(const struct device *dev) \
|
||||||
|
{ \
|
||||||
|
IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), mcux_lpc_ctimer_isr, \
|
||||||
|
DEVICE_DT_INST_GET(id), 0); \
|
||||||
|
irq_enable(DT_INST_IRQN(id)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(COUNTER_LPC_CTIMER_DEVICE)
|
|
@ -310,6 +310,71 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "USBHS_0";
|
label = "USBHS_0";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ctimer0: ctimer@8000 {
|
||||||
|
compatible = "nxp,lpc-ctimer";
|
||||||
|
reg = <0x8000 0x1000>;
|
||||||
|
interrupts = <10 0>;
|
||||||
|
status = "disabled";
|
||||||
|
clk-source = <3>;
|
||||||
|
clocks = <&syscon MCUX_CTIMER0_CLK>;
|
||||||
|
mode = <0>;
|
||||||
|
input = <0>;
|
||||||
|
prescale = <0>;
|
||||||
|
label = "CTIMER_0";
|
||||||
|
};
|
||||||
|
|
||||||
|
ctimer1: ctimer@9000 {
|
||||||
|
compatible = "nxp,lpc-ctimer";
|
||||||
|
reg = <0x9000 0x1000>;
|
||||||
|
interrupts = <11 0>;
|
||||||
|
status = "disabled";
|
||||||
|
clk-source = <3>;
|
||||||
|
clocks = <&syscon MCUX_CTIMER1_CLK>;
|
||||||
|
mode = <0>;
|
||||||
|
input = <0>;
|
||||||
|
prescale = <0>;
|
||||||
|
label = "CTIMER_1";
|
||||||
|
};
|
||||||
|
|
||||||
|
ctimer2: ctimer@28000 {
|
||||||
|
compatible = "nxp,lpc-ctimer";
|
||||||
|
reg = <0x28000 0x1000>;
|
||||||
|
interrupts = <36 0>;
|
||||||
|
status = "disabled";
|
||||||
|
clk-source = <3>;
|
||||||
|
clocks = <&syscon MCUX_CTIMER2_CLK>;
|
||||||
|
mode = <0>;
|
||||||
|
input = <0>;
|
||||||
|
prescale = <0>;
|
||||||
|
label = "CTIMER_2";
|
||||||
|
};
|
||||||
|
|
||||||
|
ctimer3: ctimer@29000 {
|
||||||
|
compatible = "nxp,lpc-ctimer";
|
||||||
|
reg = <0x29000 0x1000>;
|
||||||
|
interrupts = <13 0>;
|
||||||
|
status = "disabled";
|
||||||
|
clk-source = <3>;
|
||||||
|
clocks = <&syscon MCUX_CTIMER3_CLK>;
|
||||||
|
mode = <0>;
|
||||||
|
input = <0>;
|
||||||
|
prescale = <0>;
|
||||||
|
label = "CTIMER_3";
|
||||||
|
};
|
||||||
|
|
||||||
|
ctimer4: ctimer@2A000 {
|
||||||
|
compatible = "nxp,lpc-ctimer";
|
||||||
|
reg = <0x2A000 0x1000>;
|
||||||
|
interrupts = <37 0>;
|
||||||
|
status = "disabled";
|
||||||
|
clk-source = <3>;
|
||||||
|
clocks = <&syscon MCUX_CTIMER4_CLK>;
|
||||||
|
mode = <0>;
|
||||||
|
input = <0>;
|
||||||
|
prescale = <0>;
|
||||||
|
label = "CTIMER_4";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&nvic {
|
&nvic {
|
||||||
|
|
38
dts/bindings/timer/nxp,lpc-ctimer.yaml
Normal file
38
dts/bindings/timer/nxp,lpc-ctimer.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# Copyright (c) 2021 Toby Firth
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: NXP MCUX Standard Timer/Counter
|
||||||
|
|
||||||
|
compatible: "nxp,lpc-ctimer"
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
label:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
clk-source:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: clock to use
|
||||||
|
|
||||||
|
mode:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: timer mode
|
||||||
|
|
||||||
|
input:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: input channel
|
||||||
|
|
||||||
|
prescale:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: prescale value
|
|
@ -19,4 +19,13 @@
|
||||||
#define MCUX_USDHC1_CLK 9
|
#define MCUX_USDHC1_CLK 9
|
||||||
#define MCUX_USDHC2_CLK 10
|
#define MCUX_USDHC2_CLK 10
|
||||||
|
|
||||||
|
#define MCUX_CTIMER_CLK_OFFSET 11
|
||||||
|
|
||||||
|
#define MCUX_CTIMER0_CLK 0
|
||||||
|
#define MCUX_CTIMER1_CLK 1
|
||||||
|
#define MCUX_CTIMER2_CLK 2
|
||||||
|
#define MCUX_CTIMER3_CLK 3
|
||||||
|
#define MCUX_CTIMER4_CLK 4
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */
|
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */
|
||||||
|
|
|
@ -288,4 +288,9 @@ config HAS_MCUX_RCM
|
||||||
Set if the Reset Control Module (RCM) module is present in
|
Set if the Reset Control Module (RCM) module is present in
|
||||||
the SoC.
|
the SoC.
|
||||||
|
|
||||||
|
config HAS_MCUX_CTIMER
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Set if the CTIMER module is present in the SoC.
|
||||||
|
|
||||||
endif # HAS_MCUX
|
endif # HAS_MCUX
|
||||||
|
|
|
@ -31,6 +31,8 @@ struct counter_alarm_cfg alarm_cfg;
|
||||||
#define TIMER DT_LABEL(DT_INST(0, xlnx_xps_timer_1_00_a))
|
#define TIMER DT_LABEL(DT_INST(0, xlnx_xps_timer_1_00_a))
|
||||||
#elif defined(CONFIG_COUNTER_ESP32)
|
#elif defined(CONFIG_COUNTER_ESP32)
|
||||||
#define TIMER DT_LABEL(DT_NODELABEL(timer0))
|
#define TIMER DT_LABEL(DT_NODELABEL(timer0))
|
||||||
|
#elif defined(CONFIG_COUNTER_MCUX_CTIMER)
|
||||||
|
#define TIMER DT_LABEL(DT_NODELABEL(ctimer0))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void test_counter_interrupt_fn(const struct device *counter_dev,
|
static void test_counter_interrupt_fn(const struct device *counter_dev,
|
||||||
|
|
|
@ -45,4 +45,8 @@ choice USB_MCUX_CONTROLLER_TYPE
|
||||||
default USB_DC_NXP_LPCIP3511
|
default USB_DC_NXP_LPCIP3511
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config COUNTER_MCUX_CTIMER
|
||||||
|
default y
|
||||||
|
depends on COUNTER
|
||||||
|
|
||||||
endif # SOC_LPC55S69_CPU0
|
endif # SOC_LPC55S69_CPU0
|
||||||
|
|
|
@ -43,6 +43,7 @@ config SOC_LPC55S69_CPU0
|
||||||
select HAS_MCUX_LPC_DMA
|
select HAS_MCUX_LPC_DMA
|
||||||
select HAS_MCUX_USB_LPCIP3511
|
select HAS_MCUX_USB_LPCIP3511
|
||||||
select USB_DEDICATED_MEMORY if USB_DEVICE_DRIVER
|
select USB_DEDICATED_MEMORY if USB_DEVICE_DRIVER
|
||||||
|
select HAS_MCUX_CTIMER
|
||||||
|
|
||||||
config SOC_LPC55S69_CPU1
|
config SOC_LPC55S69_CPU1
|
||||||
bool "SOC_LPC55S69 M33 [CPU 1]"
|
bool "SOC_LPC55S69 M33 [CPU 1]"
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
#include "usb_dc_mcux.h"
|
#include "usb_dc_mcux.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CTIMER_CLOCK_SOURCE(node_id) \
|
||||||
|
TO_CTIMER_CLOCK_SOURCE(DT_CLOCKS_CELL(node_id, name), DT_PROP(node_id, clk_source))
|
||||||
|
#define TO_CTIMER_CLOCK_SOURCE(inst, val) TO_CLOCK_ATTACH_ID(inst, val)
|
||||||
|
#define TO_CLOCK_ATTACH_ID(inst, val) MUX_A(CM_CTIMERCLKSEL##inst, val)
|
||||||
|
#define CTIMER_CLOCK_SETUP(node_id) CLOCK_AttachClk(CTIMER_CLOCK_SOURCE(node_id));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Initialize the system clock
|
* @brief Initialize the system clock
|
||||||
|
@ -124,6 +130,8 @@ static ALWAYS_INLINE void clock_init(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP)
|
||||||
|
|
||||||
#endif /* CONFIG_SOC_LPC55S69_CPU0 */
|
#endif /* CONFIG_SOC_LPC55S69_CPU0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ static const char * const devices[] = {
|
||||||
LABELS_FOR_DT_COMPAT(microchip_xec_timer)
|
LABELS_FOR_DT_COMPAT(microchip_xec_timer)
|
||||||
LABELS_FOR_DT_COMPAT(nxp_imx_epit)
|
LABELS_FOR_DT_COMPAT(nxp_imx_epit)
|
||||||
LABELS_FOR_DT_COMPAT(nxp_imx_gpt)
|
LABELS_FOR_DT_COMPAT(nxp_imx_gpt)
|
||||||
|
#ifdef CONFIG_COUNTER_MCUX_CTIMER
|
||||||
|
LABELS_FOR_DT_COMPAT(nxp_lpc_ctimer)
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_COUNTER_MCUX_RTC
|
#ifdef CONFIG_COUNTER_MCUX_RTC
|
||||||
LABELS_FOR_DT_COMPAT(nxp_kinetis_rtc)
|
LABELS_FOR_DT_COMPAT(nxp_kinetis_rtc)
|
||||||
#endif
|
#endif
|
||||||
|
@ -534,9 +537,10 @@ void test_multiple_alarms_instance(const char *dev_name)
|
||||||
err = counter_start(dev);
|
err = counter_start(dev);
|
||||||
zassert_equal(0, err, "%s: Counter failed to start", dev_name);
|
zassert_equal(0, err, "%s: Counter failed to start", dev_name);
|
||||||
|
|
||||||
|
if (set_top_value_capable(dev_name)) {
|
||||||
err = counter_set_top_value(dev, &top_cfg);
|
err = counter_set_top_value(dev, &top_cfg);
|
||||||
zassert_equal(0, err,
|
zassert_equal(0, err, "%s: Counter failed to set top value", dev_name);
|
||||||
"%s: Counter failed to set top value", dev_name);
|
}
|
||||||
|
|
||||||
k_busy_wait(3*(uint32_t)counter_ticks_to_us(dev, alarm_cfg.ticks));
|
k_busy_wait(3*(uint32_t)counter_ticks_to_us(dev, alarm_cfg.ticks));
|
||||||
|
|
||||||
|
@ -546,7 +550,12 @@ void test_multiple_alarms_instance(const char *dev_name)
|
||||||
err = counter_set_channel_alarm(dev, 1, &alarm_cfg2);
|
err = counter_set_channel_alarm(dev, 1, &alarm_cfg2);
|
||||||
zassert_equal(0, err, "%s: Counter set alarm failed", dev_name);
|
zassert_equal(0, err, "%s: Counter set alarm failed", dev_name);
|
||||||
|
|
||||||
|
#ifdef CONFIG_COUNTER_MCUX_CTIMER
|
||||||
|
k_busy_wait((uint32_t)counter_ticks_to_us(dev, 0xFFFFFFFF));
|
||||||
|
#else
|
||||||
k_busy_wait(1.2 * counter_ticks_to_us(dev, ticks * 2U));
|
k_busy_wait(1.2 * counter_ticks_to_us(dev, ticks * 2U));
|
||||||
|
#endif
|
||||||
|
|
||||||
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ?
|
||||||
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
alarm_cnt : k_sem_count_get(&alarm_cnt_sem);
|
||||||
zassert_equal(2, cnt,
|
zassert_equal(2, cnt,
|
||||||
|
|
|
@ -4,7 +4,7 @@ tests:
|
||||||
depends_on: counter
|
depends_on: counter
|
||||||
min_ram: 16
|
min_ram: 16
|
||||||
platform_exclude: nucleo_f302r8
|
platform_exclude: nucleo_f302r8
|
||||||
timeout: 400
|
timeout: 600
|
||||||
drivers.counter_nrf_zli:
|
drivers.counter_nrf_zli:
|
||||||
tags: drivers
|
tags: drivers
|
||||||
depends_on: counter
|
depends_on: counter
|
||||||
|
|
2
west.yml
2
west.yml
|
@ -88,7 +88,7 @@ manifest:
|
||||||
groups:
|
groups:
|
||||||
- hal
|
- hal
|
||||||
- name: hal_nxp
|
- name: hal_nxp
|
||||||
revision: ef99b119e4b41fa4610454b7b48bf9012ea7ae61
|
revision: 6287a073922a42685cc0b63b97d35b49b66b7a8f
|
||||||
path: modules/hal/nxp
|
path: modules/hal/nxp
|
||||||
groups:
|
groups:
|
||||||
- hal
|
- hal
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue