From 9bc3ee67bea36f4eca3f99979b79ad8fc2329ce3 Mon Sep 17 00:00:00 2001 From: Maciej Sobkowski Date: Fri, 4 Aug 2023 14:47:07 +0200 Subject: [PATCH] drivers: counter: Add Ambiq counter driver This commit adds Ambiq counter driver for Apollo4p SoCs. Signed-off-by: Mateusz Sierszulski Signed-off-by: Maciej Sobkowski --- drivers/counter/CMakeLists.txt | 1 + drivers/counter/Kconfig | 2 + drivers/counter/Kconfig.ambiq | 13 ++ drivers/counter/counter_ambiq_timer.c | 190 ++++++++++++++++++++++++ dts/bindings/counter/ambiq,counter.yaml | 15 ++ modules/hal_ambiq/Kconfig | 5 + west.yml | 2 +- 7 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 drivers/counter/Kconfig.ambiq create mode 100644 drivers/counter/counter_ambiq_timer.c create mode 100644 dts/bindings/counter/ambiq,counter.yaml diff --git a/drivers/counter/CMakeLists.txt b/drivers/counter/CMakeLists.txt index 7b7c40d46f4..3eff6e79fb3 100644 --- a/drivers/counter/CMakeLists.txt +++ b/drivers/counter/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_TIMER_TMR_CMSDK_APB timer_tmr_cmsdk_apb.c) zephyr_library_sources_ifdef(CONFIG_TIMER_DTMR_CMSDK_APB timer_dtmr_cmsdk_apb.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_AMBIQ counter_ambiq_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_RTCC counter_gecko_rtcc.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_STIMER counter_gecko_stimer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_IMX_EPIT counter_imx_epit.c) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index f0060813775..6aa12a2465c 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -20,6 +20,8 @@ module = COUNTER module-str = counter source "subsys/logging/Kconfig.template.log_config" +source "drivers/counter/Kconfig.ambiq" + source "drivers/counter/Kconfig.gecko" source "drivers/counter/Kconfig.tmr_cmsdk_apb" diff --git a/drivers/counter/Kconfig.ambiq b/drivers/counter/Kconfig.ambiq new file mode 100644 index 00000000000..3c53ad65fee --- /dev/null +++ b/drivers/counter/Kconfig.ambiq @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023 Antmicro + + +config COUNTER_AMBIQ + bool "Ambiq Counter Driver" + default y + depends on DT_HAS_AMBIQ_COUNTER_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_TIMER + help + Enables the Counter driver for Ambiq devices. diff --git a/drivers/counter/counter_ambiq_timer.c b/drivers/counter/counter_ambiq_timer.c new file mode 100644 index 00000000000..94549d65685 --- /dev/null +++ b/drivers/counter/counter_ambiq_timer.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_counter + +#include +#include +#include +#include +#include +/* ambiq-sdk includes */ +#include + +LOG_MODULE_REGISTER(ambiq_counter, CONFIG_COUNTER_LOG_LEVEL); + +static void counter_ambiq_isr(void *arg); + +#define TIMER_IRQ (DT_INST_IRQN(0)) + +struct counter_ambiq_config { + struct counter_config_info counter_info; +}; + +struct counter_ambiq_data { + counter_alarm_callback_t callback; + void *user_data; +}; + +static struct k_spinlock lock; + +static int counter_ambiq_init(const struct device *dev) +{ + am_hal_timer_config_t tc; + + k_spinlock_key_t key = k_spin_lock(&lock); + + am_hal_timer_default_config_set(&tc); + tc.eInputClock = AM_HAL_TIMER_CLOCK_HFRC_DIV16; + tc.eFunction = AM_HAL_TIMER_FN_UPCOUNT; + tc.ui32PatternLimit = 0; + + am_hal_timer_config(0, &tc); + am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + + k_spin_unlock(&lock, key); + + NVIC_ClearPendingIRQ(TIMER_IRQ); + IRQ_CONNECT(TIMER_IRQ, 0, counter_ambiq_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(TIMER_IRQ); + + return 0; +} + +static int counter_ambiq_start(const struct device *dev) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + am_hal_timer_start(0); + + k_spin_unlock(&lock, key); + + return 0; +} + +static int counter_ambiq_stop(const struct device *dev) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + am_hal_timer_stop(0); + + k_spin_unlock(&lock, key); + + return 0; +} + +static int counter_ambiq_get_value(const struct device *dev, uint32_t *ticks) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + *ticks = am_hal_timer_read(0); + + k_spin_unlock(&lock, key); + + return 0; +} + +static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, + const struct counter_alarm_cfg *alarm_cfg) +{ + ARG_UNUSED(chan_id); + struct counter_ambiq_data *data = dev->data; + uint32_t now; + + counter_ambiq_get_value(dev, &now); + + k_spinlock_key_t key = k_spin_lock(&lock); + + if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { + am_hal_timer_compare1_set(0, now + alarm_cfg->ticks); + } else { + am_hal_timer_compare1_set(0, alarm_cfg->ticks); + } + + data->user_data = alarm_cfg->user_data; + data->callback = alarm_cfg->callback; + + k_spin_unlock(&lock, key); + + return 0; +} + +static int counter_ambiq_cancel_alarm(const struct device *dev, uint8_t chan_id) +{ + ARG_UNUSED(chan_id); + + k_spinlock_key_t key = k_spin_lock(&lock); + + am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + k_spin_unlock(&lock, key); + + return 0; +} + +static int counter_ambiq_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg) +{ + const struct counter_ambiq_config *config = dev->config; + + if (cfg->ticks != config->counter_info.max_top_value) { + return -ENOTSUP; + } else { + return 0; + } +} + +static uint32_t counter_ambiq_get_pending_int(const struct device *dev) +{ + return 0; +} + +static uint32_t counter_ambiq_get_top_value(const struct device *dev) +{ + const struct counter_ambiq_config *config = dev->config; + + return config->counter_info.max_top_value; +} + +static const struct counter_driver_api counter_api = { + .start = counter_ambiq_start, + .stop = counter_ambiq_stop, + .get_value = counter_ambiq_get_value, + .set_alarm = counter_ambiq_set_alarm, + .cancel_alarm = counter_ambiq_cancel_alarm, + .set_top_value = counter_ambiq_set_top_value, + .get_pending_int = counter_ambiq_get_pending_int, + .get_top_value = counter_ambiq_get_top_value, +}; + +static void counter_ambiq_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct counter_ambiq_data *data = dev->data; + uint32_t now = 0; + + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + counter_ambiq_get_value(dev, &now); + + if (data->callback) { + data->callback(dev, 0, now, data->user_data); + } +} + +#define AMBIQ_COUNTER_INIT(idx) \ + \ + static struct counter_ambiq_data counter_data_##idx; \ + \ + static const struct counter_ambiq_config counter_config_##idx = { \ + .counter_info = {.max_top_value = UINT32_MAX, \ + .freq = 6000000, \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1}, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, counter_ambiq_init, NULL, &counter_data_##idx, \ + &counter_config_##idx, PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ + &counter_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_COUNTER_INIT); diff --git a/dts/bindings/counter/ambiq,counter.yaml b/dts/bindings/counter/ambiq,counter.yaml new file mode 100644 index 00000000000..7ae915c4d21 --- /dev/null +++ b/dts/bindings/counter/ambiq,counter.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq Timer/Counter + +compatible: "ambiq,counter" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index 03f5497bfc7..9ea5b63b121 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -20,4 +20,9 @@ config AMBIQ_HAL_USE_STIMER help Use the STIMER driver from Ambiq HAL +config AMBIQ_HAL_USE_TIMER + bool + help + Use the TIMER driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/west.yml b/west.yml index 186a977f1a3..6a5fd35f783 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: c8203b6fc752e51fb3cb1e98441f392cc4493623 + revision: 5079b0096479a5630b91d38a891c2db1693faa2a path: modules/hal/ambiq groups: - hal