From 664ebf3d6bd3c2f8bc0afb76350262161498fe8e Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 15 Jul 2024 10:29:44 +0200 Subject: [PATCH 01/21] [nrf fromtree] drivers: Add comparator API Add comparator API header. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 00cefa15ff5c7fa54d66a2b33db49a831780ff47) (cherry picked from commit cc1381611d9f6327f3d7605a52fa343b11fc476d) --- include/zephyr/drivers/comparator.h | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 include/zephyr/drivers/comparator.h diff --git a/include/zephyr/drivers/comparator.h b/include/zephyr/drivers/comparator.h new file mode 100644 index 00000000000..3d246fea5ff --- /dev/null +++ b/include/zephyr/drivers/comparator.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_H_ +#define ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_H_ + +/** + * @brief Comparator Interface + * @defgroup comparator_interface Comparator Interface + * @since 3.7 + * @version 0.1.0 + * @ingroup io_interfaces + * @{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Comparator trigger enumerations */ +enum comparator_trigger { + /** No trigger */ + COMPARATOR_TRIGGER_NONE = 0, + /** Trigger on rising edge of comparator output */ + COMPARATOR_TRIGGER_RISING_EDGE, + /** Trigger on falling edge of comparator output */ + COMPARATOR_TRIGGER_FALLING_EDGE, + /** Trigger on both edges of comparator output */ + COMPARATOR_TRIGGER_BOTH_EDGES +}; + +/** Comparator callback template */ +typedef void (*comparator_callback_t)(const struct device *dev, void *user_data); + +/** @cond INTERNAL_HIDDEN */ + +typedef int (*comparator_api_get_output)(const struct device *dev); +typedef int (*comparator_api_set_trigger)(const struct device *dev, + enum comparator_trigger trigger); +typedef int (*comparator_api_set_trigger_callback)(const struct device *dev, + comparator_callback_t callback, + void *user_data); +typedef int (*comparator_api_trigger_is_pending)(const struct device *dev); + +__subsystem struct comparator_driver_api { + comparator_api_get_output get_output; + comparator_api_set_trigger set_trigger; + comparator_api_set_trigger_callback set_trigger_callback; + comparator_api_trigger_is_pending trigger_is_pending; +}; + +/** @endcond */ + +/** + * @brief Get comparator's output state + * + * @param dev Comparator device + * + * @retval 1 Output state is high + * @retval 0 Output state is low + * @retval -errno code Failure + */ +__syscall int comparator_get_output(const struct device *dev); + +static inline int z_impl_comparator_get_output(const struct device *dev) +{ + const struct comparator_driver_api *api = + (const struct comparator_driver_api *)dev->api; + + return api->get_output(dev); +} + +/** + * @brief Set comparator's trigger + * + * @param dev Comparator device + * @param trigger Trigger for signal and callback + * + * @retval 0 Successful + * @retval -errno code Failure + */ +__syscall int comparator_set_trigger(const struct device *dev, + enum comparator_trigger trigger); + +static inline int z_impl_comparator_set_trigger(const struct device *dev, + enum comparator_trigger trigger) +{ + const struct comparator_driver_api *api = + (const struct comparator_driver_api *)dev->api; + + return api->set_trigger(dev, trigger); +} + +/** + * @brief Set comparator's trigger callback + * + * @param dev Comparator device + * @param callback Trigger callback + * @param user_data User data passed to callback + * + * @retval 0 Successful + * @retval -errno code Failure + * + * @note Set callback to NULL to disable callback + * @note Callback is called immediately if trigger is pending + */ +static inline int comparator_set_trigger_callback(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + const struct comparator_driver_api *api = + (const struct comparator_driver_api *)dev->api; + + return api->set_trigger_callback(dev, callback, user_data); +} + +/** + * @brief Check if comparator's trigger is pending and clear it + * + * @param dev Comparator device + * + * @retval 1 Trigger was pending + * @retval 0 Trigger was cleared + * @retval -errno code Failure + */ +__syscall int comparator_trigger_is_pending(const struct device *dev); + +static inline int z_impl_comparator_trigger_is_pending(const struct device *dev) +{ + const struct comparator_driver_api *api = + (const struct comparator_driver_api *)dev->api; + + return api->trigger_is_pending(dev); +} + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_H_ */ From 43137619a716b46500acdf38e0f37c8a4e63c726 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 15 Jul 2024 11:07:19 +0200 Subject: [PATCH 02/21] [nrf fromtree] drivers: comparator: Add initial files Add top level CMakeLists.txt entry and Kconfig options along with userspace handlers for comparator API. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 211bdd935c489391412da7bef6b1f1c061bb08b7) (cherry picked from commit 7d97fc75c24ea05a0e36cd15a079c8df0c38c85a) --- drivers/CMakeLists.txt | 1 + drivers/Kconfig | 1 + drivers/comparator/CMakeLists.txt | 8 +++++++ drivers/comparator/Kconfig | 21 +++++++++++++++++ drivers/comparator/comparator_handlers.c | 30 ++++++++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 drivers/comparator/CMakeLists.txt create mode 100644 drivers/comparator/Kconfig create mode 100644 drivers/comparator/comparator_handlers.c diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index acf20d2867c..05be8c3fd01 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -24,6 +24,7 @@ add_subdirectory_ifdef(CONFIG_CACHE_MANAGEMENT cache) add_subdirectory_ifdef(CONFIG_CAN can) add_subdirectory_ifdef(CONFIG_CHARGER charger) add_subdirectory_ifdef(CONFIG_CLOCK_CONTROL clock_control) +add_subdirectory_ifdef(CONFIG_COMPARATOR comparator) add_subdirectory_ifdef(CONFIG_CONSOLE console) add_subdirectory_ifdef(CONFIG_COREDUMP_DEVICE coredump) add_subdirectory_ifdef(CONFIG_COUNTER counter) diff --git a/drivers/Kconfig b/drivers/Kconfig index ec9e0c77b6d..db80ba39a66 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -15,6 +15,7 @@ source "drivers/cache/Kconfig" source "drivers/can/Kconfig" source "drivers/charger/Kconfig" source "drivers/clock_control/Kconfig" +source "drivers/comparator/Kconfig" source "drivers/console/Kconfig" source "drivers/coredump/Kconfig" source "drivers/counter/Kconfig" diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt new file mode 100644 index 00000000000..5f61892829d --- /dev/null +++ b/drivers/comparator/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/comparator.h) + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig new file mode 100644 index 00000000000..333fe6671a5 --- /dev/null +++ b/drivers/comparator/Kconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menuconfig COMPARATOR + bool "Comparator drivers" + help + Enable comparator driver configuration. + +if COMPARATOR + +module = COMPARATOR +module-str = comparator +source "subsys/logging/Kconfig.template.log_config" + +config COMPARATOR_INIT_PRIORITY + int "COMPARATOR init priority" + default KERNEL_INIT_PRIORITY_DEVICE + help + Comparator device driver initialization priority. + +endif # COMPARATOR diff --git a/drivers/comparator/comparator_handlers.c b/drivers/comparator/comparator_handlers.c new file mode 100644 index 00000000000..fba43a9ce8e --- /dev/null +++ b/drivers/comparator/comparator_handlers.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static inline int z_vrfy_comparator_get_output(const struct device *dev) +{ + K_OOPS(K_SYSCALL_DRIVER_COMPARATOR(dev, get_output)); + return z_impl_comparator_get_output(dev); +} +#include + +static inline int z_vrfy_comparator_set_trigger(const struct device *dev, + enum comparator_trigger trigger) +{ + K_OOPS(K_SYSCALL_DRIVER_COMPARATOR(dev, set_trigger)); + return z_impl_comparator_set_trigger(dev, trigger); +} +#include + +static inline int z_vrfy_comparator_trigger_is_pending(const struct device *dev) +{ + K_OOPS(K_SYSCALL_DRIVER_COMPARATOR(dev, trigger_is_pending)); + return z_impl_comparator_trigger_is_pending(dev); +} +#include From e15c3c3a73a27e6246c3bf2560b2e1e09c37b82f Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 13 Sep 2024 15:13:47 +0200 Subject: [PATCH 03/21] [nrf fromtree] dts: common: nordic: adjust comparator nodes Adjust comparator nodes of nrf SoCs to exclude the unused io-channel-cells property and simplify the comment describing how to configure the comparator hardware block as COMP or LPCOMP for SoCs which support this. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit ffbda1b0f84864704b2522619717896d6b22223f) (cherry picked from commit 30def4545830ad97da03707a2e62714a0426e255) --- dts/arm/nordic/nrf52810.dtsi | 1 - dts/arm/nordic/nrf52811.dtsi | 1 - dts/arm/nordic/nrf52820.dtsi | 1 - dts/arm/nordic/nrf52832.dtsi | 7 ++----- dts/arm/nordic/nrf52833.dtsi | 7 ++----- dts/arm/nordic/nrf52840.dtsi | 7 ++----- dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi | 7 ++----- dts/common/nordic/nrf54h20.dtsi | 5 ++++- dts/common/nordic/nrf54l15.dtsi | 11 +++++++++++ dts/common/nordic/nrf9280.dtsi | 5 ++++- 10 files changed, 27 insertions(+), 25 deletions(-) diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 8758a6354b8..a67d677e7a2 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -269,7 +269,6 @@ reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index b14df8b567a..41391b7eb3d 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -301,7 +301,6 @@ reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index 601a4f8c7ed..4d05bc741a0 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -313,7 +313,6 @@ reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index b722d183da8..32245608a80 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -310,16 +310,13 @@ comp: comparator@40013000 { /* - * This comparator node can be COMP or LPCOMP, - * for the user to pick: - * compatible = "nordic,nrf-comp" or - * "nordic,nrf-lpcomp". + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP */ compatible = "nordic,nrf-comp"; reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index d81a8953fda..b576401803a 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -325,16 +325,13 @@ comp: comparator@40013000 { /* - * This comparator node can be COMP or LPCOMP, - * for the user to pick: - * compatible = "nordic,nrf-comp" or - * "nordic,nrf-lpcomp". + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP */ compatible = "nordic,nrf-comp"; reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index fd7c1aeaa87..3965c4f3b11 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -312,16 +312,13 @@ comp: comparator@40013000 { /* - * This comparator node can be COMP or LPCOMP, - * for the user to pick: - * compatible = "nordic,nrf-comp" or - * "nordic,nrf-lpcomp". + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP */ compatible = "nordic,nrf-comp"; reg = <0x40013000 0x1000>; interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: swi0: egu@40014000 { diff --git a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi index 7d79b227be2..50842fb3801 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi @@ -350,16 +350,13 @@ wdt1: watchdog@19000 { comp: comparator@1a000 { /* - * This comparator node can be COMP or LPCOMP, - * for the user to pick: - * compatible = "nordic,nrf-comp" or - * "nordic,nrf-lpcomp". + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP */ compatible = "nordic,nrf-comp"; reg = <0x1a000 0x1000>; interrupts = <26 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - #io-channel-cells = <1>; }; egu0: egu@1b000 { diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index c448455c579..0c891161ab2 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -828,11 +828,14 @@ }; comp: comparator@983000 { + /* + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP + */ compatible = "nordic,nrf-comp"; reg = <0x983000 0x1000>; status = "disabled"; interrupts = <387 NRF_DEFAULT_IRQ_PRIORITY>; - #io-channel-cells = <1>; }; temp: temperature-sensor@984000 { diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index 66c5e3c2d51..d3c0c551823 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -563,6 +563,17 @@ frame-timeout-supported; }; + comp: comparator@106000 { + /* + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP + */ + compatible = "nordic,nrf-comp"; + reg = <0x106000 0x1000>; + status = "disabled"; + interrupts = <262 NRF_DEFAULT_IRQ_PRIORITY>; + }; + #ifdef USE_NON_SECURE_ADDRESS_MAP /* intentionally empty because WDT30 is hardware fixed to Secure */ #else diff --git a/dts/common/nordic/nrf9280.dtsi b/dts/common/nordic/nrf9280.dtsi index ae3ffc904d2..45b05f9262e 100644 --- a/dts/common/nordic/nrf9280.dtsi +++ b/dts/common/nordic/nrf9280.dtsi @@ -727,11 +727,14 @@ }; comp: comparator@983000 { + /* + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP + */ compatible = "nordic,nrf-comp"; reg = <0x983000 0x1000>; status = "disabled"; interrupts = <387 NRF_DEFAULT_IRQ_PRIORITY>; - #io-channel-cells = <1>; }; temp: temperature-sensor@984000 { From f7a73c5091603fd5695b9e1f3237086a8f68f2aa Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 17 Jul 2024 12:46:52 +0200 Subject: [PATCH 04/21] [nrf fromtree] drivers: comparator: Add nRF COMP device driver Add nRF COMP device driver and remove deprecated bindings from dts/bindings/sensor. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 4adc92475d951c94ab0c2267a5e6196b4df0dfb4) (cherry picked from commit cbf5449ac72eeab60b19b7c3eaa4e0010a3180a8) --- drivers/comparator/CMakeLists.txt | 1 + drivers/comparator/Kconfig | 2 + drivers/comparator/Kconfig.nrf_comp | 8 + drivers/comparator/comparator_nrf_comp.c | 764 +++++++++++++++++++ dts/bindings/comparator/nordic,nrf-comp.yaml | 128 ++++ dts/bindings/sensor/nordic,nrf-comp.yaml | 23 - include/zephyr/drivers/comparator/nrf_comp.h | 164 ++++ 7 files changed, 1067 insertions(+), 23 deletions(-) create mode 100644 drivers/comparator/Kconfig.nrf_comp create mode 100644 drivers/comparator/comparator_nrf_comp.c create mode 100644 dts/bindings/comparator/nordic,nrf-comp.yaml delete mode 100644 dts/bindings/sensor/nordic,nrf-comp.yaml create mode 100644 include/zephyr/drivers/comparator/nrf_comp.h diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index 5f61892829d..20aa301af7d 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -6,3 +6,4 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/comparator.h) zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 333fe6671a5..84ea5c74baa 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -18,4 +18,6 @@ config COMPARATOR_INIT_PRIORITY help Comparator device driver initialization priority. +rsource "Kconfig.nrf_comp" + endif # COMPARATOR diff --git a/drivers/comparator/Kconfig.nrf_comp b/drivers/comparator/Kconfig.nrf_comp new file mode 100644 index 00000000000..0e0c889f3ee --- /dev/null +++ b/drivers/comparator/Kconfig.nrf_comp @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_NRF_COMP + bool "Nordic COMP comparator driver" + default y + depends on DT_HAS_NORDIC_NRF_COMP_ENABLED + select NRFX_COMP diff --git a/drivers/comparator/comparator_nrf_comp.c b/drivers/comparator/comparator_nrf_comp.c new file mode 100644 index 00000000000..339d24f8dcd --- /dev/null +++ b/drivers/comparator/comparator_nrf_comp.c @@ -0,0 +1,764 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#define DT_DRV_COMPAT nordic_nrf_comp + +#define SHIM_NRF_COMP_DT_INST_REFSEL(inst) \ + _CONCAT(COMP_NRF_COMP_REFSEL_, DT_INST_STRING_TOKEN(inst, refsel)) + +#define SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(inst) \ + DT_INST_ENUM_HAS_VALUE(inst, refsel, AREF) + +#define SHIM_NRF_COMP_DT_INST_EXTREFSEL(inst) \ + _CONCAT(COMP_NRF_COMP_EXTREFSEL_, DT_INST_STRING_TOKEN(inst, extrefsel)) + +#define SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(inst) \ + DT_INST_ENUM_HAS_VALUE(inst, main_mode, SE) + +#define SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_DIFF(inst) \ + DT_INST_ENUM_HAS_VALUE(inst, main_mode, DIFF) + +#define SHIM_NRF_COMP_DT_INST_TH_DOWN(inst) \ + DT_INST_PROP(inst, th_down) + +#define SHIM_NRF_COMP_DT_INST_TH_UP(inst) \ + DT_INST_PROP(inst, th_up) + +#define SHIM_NRF_COMP_DT_INST_SP_MODE(inst) \ + _CONCAT(COMP_NRF_COMP_SP_MODE_, DT_INST_STRING_TOKEN(inst, sp_mode)) + +#define SHIM_NRF_COMP_DT_INST_ENABLE_HYST(inst) \ + DT_INST_PROP(inst, enable_hyst) + +#define SHIM_NRF_COMP_DT_INST_ISOURCE(inst) \ + _CONCAT(COMP_NRF_COMP_ISOURCE_, DT_INST_STRING_TOKEN(inst, isource)) + +#define SHIM_NRF_COMP_DT_INST_PSEL(inst) \ + _CONCAT(COMP_NRF_COMP_PSEL_, DT_INST_STRING_TOKEN(inst, psel)) + +#if defined(COMP_HYST_HYST_Hyst40mV) +#define NRF_COMP_HYST_ENABLED NRF_COMP_HYST_40MV +#elif defined(COMP_HYST_HYST_Hyst50mV) +#define NRF_COMP_HYST_ENABLED NRF_COMP_HYST_50MV +#endif + +#define NRF_COMP_HYST_DISABLED NRF_COMP_HYST_NO_HYST + +#if defined(NRF_COMP_HYST_ENABLED) +#define NRF_COMP_HAS_HYST 1 +#else +#define NRF_COMP_HAS_HYST 0 +#endif + +struct shim_nrf_comp_data { + uint32_t event_mask; + bool started; + atomic_t triggered; + comparator_callback_t callback; + void *user_data; +}; + +#if (NRF_COMP_HAS_AIN_AS_PIN) +static const uint32_t shim_nrf_comp_ain_map[] = { +#if defined(CONFIG_SOC_NRF54H20) || defined(CONFIG_SOC_NRF9280) + NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), +#elif defined(CONFIG_SOC_NRF54L15) + NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), +#endif +}; +#endif + +#if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0) +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_DOWN(0) < 64); +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_UP(0) < 64); +#endif + +#if NRF_COMP_HAS_AIN_AS_PIN +BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN0 == 0)); +BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN7 == 7)); +BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN0 == 0)); +BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN7 == 7)); +#else +#ifndef COMP_PSEL_PSEL_AnalogInput4 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN4); +#endif + +#ifndef COMP_PSEL_PSEL_AnalogInput5 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN5); +#endif + +#ifndef COMP_PSEL_PSEL_AnalogInput6 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN6); +#endif + +#ifndef COMP_PSEL_PSEL_AnalogInput7 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN7); +#endif +#endif + +#ifndef COMP_PSEL_PSEL_VddDiv2 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDD_DIV2); +#endif + +#ifndef COMP_PSEL_PSEL_VddhDiv5 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDDH_DIV5); +#endif + +#ifndef COMP_MODE_SP_Normal +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_SP_MODE(0) != COMP_NRF_COMP_SP_MODE_NORMAL); +#endif + +#if NRF_COMP_HAS_ISOURCE +#ifndef COMP_ISOURCE_ISOURCE_Ien2uA5 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_2UA5); +#endif + +#ifndef COMP_ISOURCE_ISOURCE_Ien5uA +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_5UA); +#endif + +#ifndef COMP_ISOURCE_ISOURCE_Ien10uA +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_10UA); +#endif +#endif + +#if SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(0) +#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference4 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN4); +#endif + +#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference5 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN5); +#endif + +#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference6 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN6); +#endif + +#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference7 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN7); +#endif +#endif + +#if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0) +#ifndef COMP_REFSEL_REFSEL_Int1V8 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_INT_1V8); +#endif + +#ifndef COMP_REFSEL_REFSEL_Int2V4 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_INT_2V4); +#endif + +#ifndef COMP_REFSEL_REFSEL_AVDDAO1V8 +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_AVDDAO1V8); +#endif + +#ifndef COMP_REFSEL_REFSEL_VDD +BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_VDD); +#endif +#endif + +#if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_DIFF(0) +#if SHIM_NRF_COMP_DT_INST_ENABLE_HYST(0) +BUILD_ASSERT(NRF_COMP_HAS_HYST); +#endif +#endif + +#if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0) +static const struct comp_nrf_comp_se_config shim_nrf_comp_config0 = { + .psel = SHIM_NRF_COMP_DT_INST_PSEL(0), + .sp_mode = SHIM_NRF_COMP_DT_INST_SP_MODE(0), + .isource = SHIM_NRF_COMP_DT_INST_ISOURCE(0), +#if SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(0) + .extrefsel = SHIM_NRF_COMP_DT_INST_EXTREFSEL(0), +#endif + .refsel = SHIM_NRF_COMP_DT_INST_REFSEL(0), + .th_down = SHIM_NRF_COMP_DT_INST_TH_DOWN(0), + .th_up = SHIM_NRF_COMP_DT_INST_TH_UP(0), +}; +#else +static const struct comp_nrf_comp_diff_config shim_nrf_comp_config0 = { + .psel = SHIM_NRF_COMP_DT_INST_PSEL(0), + .sp_mode = SHIM_NRF_COMP_DT_INST_SP_MODE(0), + .isource = SHIM_NRF_COMP_DT_INST_ISOURCE(0), + .extrefsel = SHIM_NRF_COMP_DT_INST_EXTREFSEL(0), + .enable_hyst = SHIM_NRF_COMP_DT_INST_ENABLE_HYST(0), +}; +#endif + +static struct shim_nrf_comp_data shim_nrf_comp_data0; + +#if CONFIG_PM_DEVICE +static bool shim_nrf_comp_is_resumed(void) +{ + enum pm_device_state state; + + (void)pm_device_state_get(DEVICE_DT_INST_GET(0), &state); + return state == PM_DEVICE_STATE_ACTIVE; +} +#else +static bool shim_nrf_comp_is_resumed(void) +{ + return true; +} +#endif + +static void shim_nrf_comp_start(void) +{ + if (shim_nrf_comp_data0.started) { + return; + } + + nrfx_comp_start(shim_nrf_comp_data0.event_mask, 0); + shim_nrf_comp_data0.started = true; +} + +static void shim_nrf_comp_stop(void) +{ + if (!shim_nrf_comp_data0.started) { + return; + } + + nrfx_comp_stop(); + shim_nrf_comp_data0.started = false; +} + +static int shim_nrf_comp_pm_callback(const struct device *dev, enum pm_device_action action) +{ + ARG_UNUSED(dev); + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + shim_nrf_comp_start(); + break; + +#if CONFIG_PM_DEVICE + case PM_DEVICE_ACTION_SUSPEND: + shim_nrf_comp_stop(); + break; +#endif + + default: + return -ENOTSUP; + } + + return 0; +} + +#if (NRF_COMP_HAS_AIN_AS_PIN) +static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim, + nrf_comp_input_t *nrf) +{ + if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { + return -EINVAL; + } + + *nrf = shim_nrf_comp_ain_map[(uint32_t)shim]; + return 0; +} +#else +static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim, + nrf_comp_input_t *nrf) +{ + switch (shim) { + case COMP_NRF_COMP_PSEL_AIN0: + *nrf = NRF_COMP_INPUT_0; + break; + + case COMP_NRF_COMP_PSEL_AIN1: + *nrf = NRF_COMP_INPUT_1; + break; + + case COMP_NRF_COMP_PSEL_AIN2: + *nrf = NRF_COMP_INPUT_2; + break; + + case COMP_NRF_COMP_PSEL_AIN3: + *nrf = NRF_COMP_INPUT_3; + break; + +#if defined(COMP_PSEL_PSEL_AnalogInput4) + case COMP_NRF_COMP_PSEL_AIN4: + *nrf = NRF_COMP_INPUT_4; + break; +#endif + +#if defined(COMP_PSEL_PSEL_AnalogInput5) + case COMP_NRF_COMP_PSEL_AIN5: + *nrf = NRF_COMP_INPUT_5; + break; +#endif + +#if defined(COMP_PSEL_PSEL_AnalogInput6) + case COMP_NRF_COMP_PSEL_AIN6: + *nrf = NRF_COMP_INPUT_6; + break; +#endif + +#if defined(COMP_PSEL_PSEL_AnalogInput7) + case COMP_NRF_COMP_PSEL_AIN7: + *nrf = NRF_COMP_INPUT_7; + break; +#endif + +#if defined(COMP_PSEL_PSEL_VddDiv2) + case COMP_NRF_COMP_PSEL_VDD_DIV2: + *nrf = NRF_COMP_VDD_DIV2; + break; +#endif + +#if defined(COMP_PSEL_PSEL_VddhDiv5) + case COMP_NRF_COMP_PSEL_VDDH_DIV5: + *nrf = NRF_COMP_VDDH_DIV5; + break; +#endif + + default: + return -EINVAL; + } + + return 0; +} +#endif + +static int shim_nrf_comp_sp_mode_to_nrf(enum comp_nrf_comp_sp_mode shim, + nrf_comp_sp_mode_t *nrf) +{ + switch (shim) { + case COMP_NRF_COMP_SP_MODE_LOW: + *nrf = NRF_COMP_SP_MODE_LOW; + break; + +#if defined(COMP_MODE_SP_Normal) + case COMP_NRF_COMP_SP_MODE_NORMAL: + *nrf = NRF_COMP_SP_MODE_NORMAL; + break; +#endif + + case COMP_NRF_COMP_SP_MODE_HIGH: + *nrf = NRF_COMP_SP_MODE_HIGH; + break; + + default: + return -EINVAL; + } + + return 0; +} + +#if NRF_COMP_HAS_ISOURCE +static int shim_nrf_comp_isource_to_nrf(enum comp_nrf_comp_isource shim, + nrf_isource_t *nrf) +{ + switch (shim) { + case COMP_NRF_COMP_ISOURCE_DISABLED: + *nrf = NRF_COMP_ISOURCE_OFF; + break; + +#if defined(COMP_ISOURCE_ISOURCE_Ien2uA5) + case COMP_NRF_COMP_ISOURCE_2UA5: + *nrf = NRF_COMP_ISOURCE_IEN_2UA5; + break; +#endif + +#if defined(COMP_ISOURCE_ISOURCE_Ien5uA) + case COMP_NRF_COMP_ISOURCE_5UA: + *nrf = NRF_COMP_ISOURCE_IEN_5UA; + break; +#endif + +#if defined(COMP_ISOURCE_ISOURCE_Ien10uA) + case COMP_NRF_COMP_ISOURCE_10UA: + *nrf = NRF_COMP_ISOURCE_IEN_10UA; + break; +#endif + + default: + return -EINVAL; + } + + return 0; +} +#endif + +#if (NRF_COMP_HAS_AIN_AS_PIN) +static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim, + nrf_comp_ext_ref_t *nrf) +{ + if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { + return -EINVAL; + } + + *nrf = shim_nrf_comp_ain_map[(uint32_t)shim]; + return 0; +} +#else +static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim, + nrf_comp_ext_ref_t *nrf) +{ + switch (shim) { + case COMP_NRF_COMP_EXTREFSEL_AIN0: + *nrf = NRF_COMP_EXT_REF_0; + break; + + case COMP_NRF_COMP_EXTREFSEL_AIN1: + *nrf = NRF_COMP_EXT_REF_1; + break; + + case COMP_NRF_COMP_EXTREFSEL_AIN2: + *nrf = NRF_COMP_EXT_REF_2; + break; + + case COMP_NRF_COMP_EXTREFSEL_AIN3: + *nrf = NRF_COMP_EXT_REF_3; + break; + +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference4) + case COMP_NRF_COMP_EXTREFSEL_AIN4: + *nrf = NRF_COMP_EXT_REF_4; + break; +#endif + +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference5) + case COMP_NRF_COMP_EXTREFSEL_AIN5: + *nrf = NRF_COMP_EXT_REF_5; + break; +#endif + +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference6) + case COMP_NRF_COMP_EXTREFSEL_AIN6: + *nrf = NRF_COMP_EXT_REF_6; + break; +#endif + +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference7) + case COMP_NRF_COMP_EXTREFSEL_AIN7: + *nrf = NRF_COMP_EXT_REF_7; + break; +#endif + + default: + return -EINVAL; + } + + return 0; +} +#endif + +static int shim_nrf_comp_refsel_to_nrf(enum comp_nrf_comp_refsel shim, + nrf_comp_ref_t *nrf) +{ + switch (shim) { + case COMP_NRF_COMP_REFSEL_INT_1V2: + *nrf = NRF_COMP_REF_INT_1V2; + break; + +#if defined(COMP_REFSEL_REFSEL_Int1V8) + case COMP_NRF_COMP_REFSEL_INT_1V8: + *nrf = NRF_COMP_REF_INT_1V8; + break; +#endif + +#if defined(COMP_REFSEL_REFSEL_Int2V4) + case COMP_NRF_COMP_REFSEL_INT_2V4: + *nrf = NRF_COMP_REF_INT_2V4; + break; +#endif + +#if defined(COMP_REFSEL_REFSEL_AVDDAO1V8) + case COMP_NRF_COMP_REFSEL_AVDDAO1V8: + *nrf = NRF_COMP_REF_AVDDAO1V8; + break; +#endif + +#if defined(COMP_REFSEL_REFSEL_VDD) + case COMP_NRF_COMP_REFSEL_VDD: + *nrf = NRF_COMP_REF_VDD; + break; +#endif + + case COMP_NRF_COMP_REFSEL_AREF: + *nrf = NRF_COMP_REF_AREF; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int shim_nrf_comp_se_config_to_nrf(const struct comp_nrf_comp_se_config *shim, + nrfx_comp_config_t *nrf) +{ + if (shim_nrf_comp_refsel_to_nrf(shim->refsel, &nrf->reference)) { + return -EINVAL; + } + + if (shim_nrf_comp_extrefsel_to_nrf(shim->extrefsel, &nrf->ext_ref)) { + return -EINVAL; + } + + nrf->main_mode = NRF_COMP_MAIN_MODE_SE; + + if (shim->th_down > 63 || shim->th_up > 63) { + return -EINVAL; + } + + nrf->threshold.th_down = shim->th_down; + nrf->threshold.th_up = shim->th_up; + + if (shim_nrf_comp_sp_mode_to_nrf(shim->sp_mode, &nrf->speed_mode)) { + return -EINVAL; + } + + nrf->hyst = NRF_COMP_HYST_NO_HYST; + +#if NRF_COMP_HAS_ISOURCE + if (shim_nrf_comp_isource_to_nrf(shim->isource, &nrf->isource)) { + return -EINVAL; + } +#else + if (shim->isource != COMP_NRF_COMP_ISOURCE_DISABLED) { + return -EINVAL; + } +#endif + + if (shim_nrf_comp_psel_to_nrf(shim->psel, &nrf->input)) { + return -EINVAL; + } + + nrf->interrupt_priority = 0; + return 0; +} + +static int shim_nrf_comp_diff_config_to_nrf(const struct comp_nrf_comp_diff_config *shim, + nrfx_comp_config_t *nrf) +{ + nrf->reference = NRF_COMP_REF_AREF; + + if (shim_nrf_comp_extrefsel_to_nrf(shim->extrefsel, &nrf->ext_ref)) { + return -EINVAL; + } + + nrf->main_mode = NRF_COMP_MAIN_MODE_DIFF; + nrf->threshold.th_down = 0; + nrf->threshold.th_up = 0; + + if (shim_nrf_comp_sp_mode_to_nrf(shim->sp_mode, &nrf->speed_mode)) { + return -EINVAL; + } + +#if NRF_COMP_HAS_HYST + if (shim->enable_hyst) { + nrf->hyst = NRF_COMP_HYST_ENABLED; + } else { + nrf->hyst = NRF_COMP_HYST_DISABLED; + } +#else + if (shim->enable_hyst) { + return -EINVAL; + } +#endif + +#if NRF_COMP_HAS_ISOURCE + if (shim_nrf_comp_isource_to_nrf(shim->isource, &nrf->isource)) { + return -EINVAL; + } +#else + if (shim->isource != COMP_NRF_COMP_ISOURCE_DISABLED) { + return -EINVAL; + } +#endif + + if (shim_nrf_comp_psel_to_nrf(shim->psel, &nrf->input)) { + return -EINVAL; + } + + nrf->interrupt_priority = 0; + return 0; +} + +static int shim_nrf_comp_get_output(const struct device *dev) +{ + ARG_UNUSED(dev); + + return nrfx_comp_sample(); +} + +static int shim_nrf_comp_set_trigger(const struct device *dev, + enum comparator_trigger trigger) +{ + shim_nrf_comp_stop(); + + switch (trigger) { + case COMPARATOR_TRIGGER_NONE: + shim_nrf_comp_data0.event_mask = 0; + break; + + case COMPARATOR_TRIGGER_RISING_EDGE: + shim_nrf_comp_data0.event_mask = NRF_COMP_INT_UP_MASK; + break; + + case COMPARATOR_TRIGGER_FALLING_EDGE: + shim_nrf_comp_data0.event_mask = NRF_COMP_INT_DOWN_MASK; + break; + + case COMPARATOR_TRIGGER_BOTH_EDGES: + shim_nrf_comp_data0.event_mask = NRF_COMP_INT_CROSS_MASK; + break; + } + + if (shim_nrf_comp_is_resumed()) { + shim_nrf_comp_start(); + } + + return 0; +} + +static int shim_nrf_comp_set_trigger_callback(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + shim_nrf_comp_stop(); + + shim_nrf_comp_data0.callback = callback; + shim_nrf_comp_data0.user_data = user_data; + + if (callback != NULL && atomic_test_and_clear_bit(&shim_nrf_comp_data0.triggered, 0)) { + callback(dev, user_data); + } + + if (shim_nrf_comp_is_resumed()) { + shim_nrf_comp_start(); + } + + return 0; +} + +static int shim_nrf_comp_trigger_is_pending(const struct device *dev) +{ + ARG_UNUSED(dev); + + return atomic_test_and_clear_bit(&shim_nrf_comp_data0.triggered, 0); +} + +static const struct comparator_driver_api shim_nrf_comp_api = { + .get_output = shim_nrf_comp_get_output, + .set_trigger = shim_nrf_comp_set_trigger, + .set_trigger_callback = shim_nrf_comp_set_trigger_callback, + .trigger_is_pending = shim_nrf_comp_trigger_is_pending, +}; + +static int shim_nrf_comp_reconfigure(const nrfx_comp_config_t *nrf) +{ + shim_nrf_comp_stop(); + + (void)nrfx_comp_reconfigure(nrf); + + if (shim_nrf_comp_is_resumed()) { + shim_nrf_comp_start(); + } + + return 0; +} + +int comp_nrf_comp_configure_se(const struct device *dev, + const struct comp_nrf_comp_se_config *config) +{ + nrfx_comp_config_t nrf = {}; + + ARG_UNUSED(dev); + + if (shim_nrf_comp_se_config_to_nrf(config, &nrf)) { + return -EINVAL; + } + + return shim_nrf_comp_reconfigure(&nrf); +} + +int comp_nrf_comp_configure_diff(const struct device *dev, + const struct comp_nrf_comp_diff_config *config) +{ + nrfx_comp_config_t nrf = {}; + + ARG_UNUSED(dev); + + if (shim_nrf_comp_diff_config_to_nrf(config, &nrf)) { + return -EINVAL; + } + + return shim_nrf_comp_reconfigure(&nrf); +} + +static void shim_nrf_comp_event_handler(nrf_comp_event_t event) +{ + ARG_UNUSED(event); + + if (shim_nrf_comp_data0.callback == NULL) { + atomic_set_bit(&shim_nrf_comp_data0.triggered, 0); + return; + } + + shim_nrf_comp_data0.callback(DEVICE_DT_INST_GET(0), shim_nrf_comp_data0.user_data); + atomic_clear_bit(&shim_nrf_comp_data0.triggered, 0); +} + +static int shim_nrf_comp_init(const struct device *dev) +{ + nrfx_comp_config_t nrf = {}; + + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + nrfx_isr, + nrfx_comp_irq_handler, + 0); + + irq_enable(DT_INST_IRQN(0)); + +#if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0) + (void)shim_nrf_comp_se_config_to_nrf(&shim_nrf_comp_config0, &nrf); +#else + (void)shim_nrf_comp_diff_config_to_nrf(&shim_nrf_comp_config0, &nrf); +#endif + + if (nrfx_comp_init(&nrf, shim_nrf_comp_event_handler) != NRFX_SUCCESS) { + return -ENODEV; + } + + return pm_device_driver_init(dev, shim_nrf_comp_pm_callback); +} + +PM_DEVICE_DT_INST_DEFINE(0, shim_nrf_comp_pm_callback); + +DEVICE_DT_INST_DEFINE(0, + shim_nrf_comp_init, + PM_DEVICE_DT_INST_GET(0), + NULL, + NULL, + POST_KERNEL, + CONFIG_COMPARATOR_INIT_PRIORITY, + &shim_nrf_comp_api); diff --git a/dts/bindings/comparator/nordic,nrf-comp.yaml b/dts/bindings/comparator/nordic,nrf-comp.yaml new file mode 100644 index 00000000000..a6f7f32db5f --- /dev/null +++ b/dts/bindings/comparator/nordic,nrf-comp.yaml @@ -0,0 +1,128 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nRF COMP (analog COMParator) + + This comparator has varying configurations which require varying + properties be set in the devicetree. + + The following example displays the minimum node layout: + + comp: comp@deadbeef { + compatible = "nordic,nrf-comp"; + reg = <0xdeadbeef 0x1000>; + interrupts = <0 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + Enabling the comparator node requires setting the default + configuration of the comparator. + + The following example displays enabling the comparator in + single-ended mode, selecting an internal reference: + + &comp { + status = "okay"; + main-mode = "SE"; + psel = "AIN0"; + refsel = "INT_1V2"; + sp-mode = "NORMAL"; + th-up = <36>; + th-down = <30>; + isource = "OFF"; + }; + + To select an external reference, select the "AREF" + reference and add the external reference: + + &comp { + ... + refsel = "AREF"; + extrefsel = "AIN1"; + ... + }; + + The following example displays enabling the comparator + in differential mode: + + &comp { + status = "okay"; + main-mode = "DIFF"; + psel = "AIN0"; + extrefsel = "AIN1"; + sp-mode = "NORMAL"; + hyst = "50MV"; + isource = "OFF"; + }; + +compatible: "nordic,nrf-comp" + +include: base.yaml + +properties: + main-mode: + type: string + enum: + - "SE" + - "DIFF" + + psel: + type: string + enum: + - "AIN0" + - "AIN1" + - "AIN2" + - "AIN3" + - "AIN4" + - "AIN5" + - "AIN6" + - "AIN7" + - "VDD_DIV2" + - "VDDH_DIV5" + + extrefsel: + type: string + enum: + - "AIN0" + - "AIN1" + - "AIN2" + - "AIN3" + - "AIN4" + - "AIN5" + - "AIN6" + - "AIN7" + + refsel: + type: string + enum: + - "INT_1V2" + - "INT_1V8" + - "INT_2V4" + - "AVDDAO1V8" + - "VDD" + - "AREF" + + enable-hyst: + type: boolean + + sp-mode: + type: string + enum: + - "LOW" + - "NORMAL" + - "HIGH" + + th-up: + type: int + + th-down: + type: int + + isource: + type: string + enum: + - "DISABLED" + - "2UA5" + - "5UA" + - "10UA" diff --git a/dts/bindings/sensor/nordic,nrf-comp.yaml b/dts/bindings/sensor/nordic,nrf-comp.yaml deleted file mode 100644 index cc964015ba1..00000000000 --- a/dts/bindings/sensor/nordic,nrf-comp.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2022, Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: Nordic nRF family COMP (Comparator) - -compatible: "nordic,nrf-comp" - -include: base.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - "#io-channel-cells": - type: int - const: 1 - required: true - -io-channel-cells: - - input diff --git a/include/zephyr/drivers/comparator/nrf_comp.h b/include/zephyr/drivers/comparator/nrf_comp.h new file mode 100644 index 00000000000..59e1cbbb3ce --- /dev/null +++ b/include/zephyr/drivers/comparator/nrf_comp.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_COMP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_COMP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Positive input selection */ +enum comp_nrf_comp_psel { + /** AIN0 external input */ + COMP_NRF_COMP_PSEL_AIN0, + /** AIN1 external input */ + COMP_NRF_COMP_PSEL_AIN1, + /** AIN2 external input */ + COMP_NRF_COMP_PSEL_AIN2, + /** AIN3 external input */ + COMP_NRF_COMP_PSEL_AIN3, + /** AIN4 external input */ + COMP_NRF_COMP_PSEL_AIN4, + /** AIN5 external input */ + COMP_NRF_COMP_PSEL_AIN5, + /** AIN6 external input */ + COMP_NRF_COMP_PSEL_AIN6, + /** AIN7 external input */ + COMP_NRF_COMP_PSEL_AIN7, + /** VDD / 2 */ + COMP_NRF_COMP_PSEL_VDD_DIV2, + /** VDDH / 5 */ + COMP_NRF_COMP_PSEL_VDDH_DIV5, +}; + +/** External reference selection */ +enum comp_nrf_comp_extrefsel { + /** AIN0 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN0, + /** AIN1 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN1, + /** AIN2 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN2, + /** AIN3 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN3, + /** AIN4 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN4, + /** AIN5 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN5, + /** AIN6 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN6, + /** AIN7 external input */ + COMP_NRF_COMP_EXTREFSEL_AIN7, +}; + +/** Reference selection */ +enum comp_nrf_comp_refsel { + /** Internal 1.2V reference */ + COMP_NRF_COMP_REFSEL_INT_1V2, + /** Internal 1.8V reference */ + COMP_NRF_COMP_REFSEL_INT_1V8, + /** Internal 2.4V reference */ + COMP_NRF_COMP_REFSEL_INT_2V4, + /** AVDD 1.8V reference */ + COMP_NRF_COMP_REFSEL_AVDDAO1V8, + /** VDD reference */ + COMP_NRF_COMP_REFSEL_VDD, + /** Use external analog reference */ + COMP_NRF_COMP_REFSEL_AREF, +}; + +/** Speed mode selection */ +enum comp_nrf_comp_sp_mode { + /** Low-power mode */ + COMP_NRF_COMP_SP_MODE_LOW, + /** Normal mode */ + COMP_NRF_COMP_SP_MODE_NORMAL, + /** High-speed mode */ + COMP_NRF_COMP_SP_MODE_HIGH, +}; + +/** Current source configuration */ +enum comp_nrf_comp_isource { + /** Current source disabled */ + COMP_NRF_COMP_ISOURCE_DISABLED, + /** 2.5uA current source enabled */ + COMP_NRF_COMP_ISOURCE_2UA5, + /** 5uA current source enabled */ + COMP_NRF_COMP_ISOURCE_5UA, + /** 10uA current source enabled */ + COMP_NRF_COMP_ISOURCE_10UA, +}; + +/** + * @brief Single-ended mode configuration structure + * + * @note extrefsel is only used if refsel == COMP_NRF_COMP_REFSEL_AREF + * @note Hysteresis down in volts = ((th_down + 1) / 64) * ref + * @note Hysteresis up in volts = ((th_up + 1) / 64) * ref + */ +struct comp_nrf_comp_se_config { + /** Positive input selection */ + enum comp_nrf_comp_psel psel; + /** Speed mode selection */ + enum comp_nrf_comp_sp_mode sp_mode; + /** Current source configuration */ + enum comp_nrf_comp_isource isource; + /** External reference selection */ + enum comp_nrf_comp_extrefsel extrefsel; + /** Reference selection */ + enum comp_nrf_comp_refsel refsel; + /** Hysteresis down threshold configuration */ + uint8_t th_down; + /** Hysteresis up threshold configuration */ + uint8_t th_up; +}; + +/** + * @brief Configure comparator in single-ended mode + * + * @param dev Comparator device instance + * @param config Single-ended mode configuration + * + * @retval 0 if successful + * @retval negative errno-code otherwise + */ +int comp_nrf_comp_configure_se(const struct device *dev, + const struct comp_nrf_comp_se_config *config); + +/** Differential mode configuration structure */ +struct comp_nrf_comp_diff_config { + /** Positive input selection */ + enum comp_nrf_comp_psel psel; + /** Speed mode selection */ + enum comp_nrf_comp_sp_mode sp_mode; + /** Current source configuration */ + enum comp_nrf_comp_isource isource; + /** Negative input selection */ + enum comp_nrf_comp_extrefsel extrefsel; + /** Hysteresis configuration */ + bool enable_hyst; +}; + +/** + * @brief Configure comparator in differential mode + * + * @param dev Comparator device instance + * @param config Differential mode configuration + * + * @retval 0 if successful + * @retval negative errno-code otherwise + */ +int comp_nrf_comp_configure_diff(const struct device *dev, + const struct comp_nrf_comp_diff_config *config); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_COMP_H_ */ From ce87c7997eefa8f49ab8eafa1eadc3d6043ef28e Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 4 Sep 2024 11:22:29 +0200 Subject: [PATCH 05/21] [nrf fromtree] tests: drivers: build_all: add comparator test suite Add comparator build_all test suite designed to test multiple devicetree overlays and boards for each comparator device driver. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 13af5ca0dc86dc88f0ad448be26ba556af2bcefe) (cherry picked from commit aca1d406727f7232a360263eac0ddb4549026cde) --- .../build_all/comparator/CMakeLists.txt | 8 ++++ .../comparator/nrf_comp/diff.overlay | 14 ++++++ .../build_all/comparator/nrf_comp/se.overlay | 16 +++++++ .../comparator/nrf_comp/se_aref.overlay | 17 +++++++ tests/drivers/build_all/comparator/prj.conf | 6 +++ tests/drivers/build_all/comparator/src/main.c | 10 ++++ .../build_all/comparator/testcase.yaml | 48 +++++++++++++++++++ 7 files changed, 119 insertions(+) create mode 100644 tests/drivers/build_all/comparator/CMakeLists.txt create mode 100644 tests/drivers/build_all/comparator/nrf_comp/diff.overlay create mode 100644 tests/drivers/build_all/comparator/nrf_comp/se.overlay create mode 100644 tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay create mode 100644 tests/drivers/build_all/comparator/prj.conf create mode 100644 tests/drivers/build_all/comparator/src/main.c create mode 100644 tests/drivers/build_all/comparator/testcase.yaml diff --git a/tests/drivers/build_all/comparator/CMakeLists.txt b/tests/drivers/build_all/comparator/CMakeLists.txt new file mode 100644 index 00000000000..edb50bd78e5 --- /dev/null +++ b/tests/drivers/build_all/comparator/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(build_all_comparator) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/build_all/comparator/nrf_comp/diff.overlay b/tests/drivers/build_all/comparator/nrf_comp/diff.overlay new file mode 100644 index 00000000000..8b8e9a02c2b --- /dev/null +++ b/tests/drivers/build_all/comparator/nrf_comp/diff.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "DIFF"; + psel = "AIN0"; + extrefsel = "AIN1"; + sp-mode = "HIGH"; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/build_all/comparator/nrf_comp/se.overlay b/tests/drivers/build_all/comparator/nrf_comp/se.overlay new file mode 100644 index 00000000000..e4eb56f61a9 --- /dev/null +++ b/tests/drivers/build_all/comparator/nrf_comp/se.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN0"; + refsel = "INT_1V2"; + sp-mode = "HIGH"; + th-up = <36>; + th-down = <28>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay b/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay new file mode 100644 index 00000000000..0d36a3e40b4 --- /dev/null +++ b/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN0"; + extrefsel = "AIN1"; + refsel = "AREF"; + sp-mode = "HIGH"; + th-up = <36>; + th-down = <28>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/build_all/comparator/prj.conf b/tests/drivers/build_all/comparator/prj.conf new file mode 100644 index 00000000000..9e78e0bbe53 --- /dev/null +++ b/tests/drivers/build_all/comparator/prj.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_COMPARATOR=y diff --git a/tests/drivers/build_all/comparator/src/main.c b/tests/drivers/build_all/comparator/src/main.c new file mode 100644 index 00000000000..a05ee591430 --- /dev/null +++ b/tests/drivers/build_all/comparator/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/comparator/testcase.yaml b/tests/drivers/build_all/comparator/testcase.yaml new file mode 100644 index 00000000000..9c94ef9a69e --- /dev/null +++ b/tests/drivers/build_all/comparator/testcase.yaml @@ -0,0 +1,48 @@ +common: + build_only: true + tags: + - drivers + - comparator +tests: + drivers.build_all.comparator.nrf_comp.diff: + extra_args: + - DTC_OVERLAY_FILE="nrf_comp/diff.overlay" + platform_allow: + - nrf52dk/nrf52810 + - nrf52dk/nrf52832 + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52811 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf9280pdk/nrf9280/cpuapp + drivers.build_all.comparator.nrf_comp.se_aref: + extra_args: + - DTC_OVERLAY_FILE="nrf_comp/se_aref.overlay" + platform_allow: + - nrf52dk/nrf52810 + - nrf52dk/nrf52832 + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52811 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf9280pdk/nrf9280/cpuapp + drivers.build_all.comparator.nrf_comp.se: + extra_args: + - DTC_OVERLAY_FILE="nrf_comp/se.overlay" + platform_allow: + - nrf52dk/nrf52810 + - nrf52dk/nrf52832 + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52811 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf9280pdk/nrf9280/cpuapp From 15d0039115606ff9138d10b9b6ee4c54cfcaaffe Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 2 Sep 2024 19:39:11 +0200 Subject: [PATCH 06/21] [nrf fromtree] drivers: comparator: add nRF LPCOMP device driver Add nRF LPCOMP device driver. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 04e70ab96c54a7413fd300ad599b44c8a7b8f91f) (cherry picked from commit 1e13d3f1d29baa78255b222dbc91cf828b5aa489) --- drivers/comparator/CMakeLists.txt | 1 + drivers/comparator/Kconfig | 1 + drivers/comparator/Kconfig.nrf_lpcomp | 8 + drivers/comparator/comparator_nrf_lpcomp.c | 491 ++++++++++++++++++ .../comparator/nordic,nrf-lpcomp.yaml | 83 +++ dts/bindings/sensor/nordic,nrf-lpcomp.yaml | 23 - .../zephyr/drivers/comparator/nrf_lpcomp.h | 112 ++++ 7 files changed, 696 insertions(+), 23 deletions(-) create mode 100644 drivers/comparator/Kconfig.nrf_lpcomp create mode 100644 drivers/comparator/comparator_nrf_lpcomp.c create mode 100644 dts/bindings/comparator/nordic,nrf-lpcomp.yaml delete mode 100644 dts/bindings/sensor/nordic,nrf-lpcomp.yaml create mode 100644 include/zephyr/drivers/comparator/nrf_lpcomp.h diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index 20aa301af7d..d0dc726bf58 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -7,3 +7,4 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 84ea5c74baa..819936024b9 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -19,5 +19,6 @@ config COMPARATOR_INIT_PRIORITY Comparator device driver initialization priority. rsource "Kconfig.nrf_comp" +rsource "Kconfig.nrf_lpcomp" endif # COMPARATOR diff --git a/drivers/comparator/Kconfig.nrf_lpcomp b/drivers/comparator/Kconfig.nrf_lpcomp new file mode 100644 index 00000000000..f33de46f15d --- /dev/null +++ b/drivers/comparator/Kconfig.nrf_lpcomp @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_NRF_LPCOMP + bool "Nordic LPCOMP comparator driver" + default y + depends on DT_HAS_NORDIC_NRF_LPCOMP_ENABLED + select NRFX_LPCOMP diff --git a/drivers/comparator/comparator_nrf_lpcomp.c b/drivers/comparator/comparator_nrf_lpcomp.c new file mode 100644 index 00000000000..6c6710d337d --- /dev/null +++ b/drivers/comparator/comparator_nrf_lpcomp.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include + +#define DT_DRV_COMPAT nordic_nrf_lpcomp + +#define SHIM_NRF_LPCOMP_DT_INST_REFSEL(inst) \ + _CONCAT(COMP_NRF_LPCOMP_REFSEL_, DT_INST_STRING_TOKEN(inst, refsel)) + +#define SHIM_NRF_LPCOMP_DT_INST_REFSEL_IS_AREF(inst) \ + DT_INST_ENUM_HAS_VALUE(inst, refsel, AREF) + +#define SHIM_NRF_LPCOMP_DT_INST_EXTREFSEL(inst) \ + _CONCAT(COMP_NRF_LPCOMP_EXTREFSEL_, DT_INST_STRING_TOKEN(inst, extrefsel)) + +#define SHIM_NRF_LPCOMP_DT_INST_ENABLE_HYST(inst) \ + DT_INST_PROP(inst, enable_hyst) + +#define SHIM_NRF_LPCOMP_DT_INST_PSEL(inst) \ + _CONCAT(COMP_NRF_LPCOMP_PSEL_, DT_INST_STRING_TOKEN(inst, psel)) + +struct shim_nrf_lpcomp_data { + nrfx_lpcomp_config_t config; + uint32_t event_mask; + bool started; + atomic_t triggered; + comparator_callback_t callback; + void *user_data; +}; + +#if (NRF_LPCOMP_HAS_AIN_AS_PIN) +static const uint32_t shim_nrf_lpcomp_ain_map[] = { +#if defined(CONFIG_SOC_NRF54H20) || defined(CONFIG_SOC_NRF9280) + NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), +#elif defined(CONFIG_SOC_NRF54L15) + NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), +#endif +}; +#endif + +#if (NRF_LPCOMP_HAS_AIN_AS_PIN) +BUILD_ASSERT(COMP_NRF_LPCOMP_PSEL_AIN0 == 0); +BUILD_ASSERT(COMP_NRF_LPCOMP_PSEL_AIN7 == 7); +BUILD_ASSERT(COMP_NRF_LPCOMP_EXTREFSEL_AIN0 == 0); +BUILD_ASSERT(COMP_NRF_LPCOMP_EXTREFSEL_AIN1 == 1); +#endif + +#if (LPCOMP_REFSEL_RESOLUTION == 8) +BUILD_ASSERT((SHIM_NRF_LPCOMP_DT_INST_REFSEL(0) < COMP_NRF_LPCOMP_REFSEL_VDD_1_16) || + (SHIM_NRF_LPCOMP_DT_INST_REFSEL(0) > COMP_NRF_LPCOMP_REFSEL_VDD_15_16)); +#endif + +#if SHIM_NRF_LPCOMP_DT_INST_ENABLE_HYST(0) +BUILD_ASSERT(NRF_LPCOMP_HAS_HYST); +#endif + +static struct shim_nrf_lpcomp_data shim_nrf_lpcomp_data0; + +static const struct comp_nrf_lpcomp_config shim_nrf_lpcomp_config0 = { + .psel = SHIM_NRF_LPCOMP_DT_INST_PSEL(0), +#if SHIM_NRF_LPCOMP_DT_INST_REFSEL_IS_AREF(0) + .extrefsel = SHIM_NRF_LPCOMP_DT_INST_EXTREFSEL(0), +#endif + .refsel = SHIM_NRF_LPCOMP_DT_INST_REFSEL(0), + .enable_hyst = SHIM_NRF_LPCOMP_DT_INST_ENABLE_HYST(0), +}; + +#if CONFIG_PM_DEVICE +static bool shim_nrf_lpcomp_is_resumed(void) +{ + enum pm_device_state state; + + (void)pm_device_state_get(DEVICE_DT_INST_GET(0), &state); + return state == PM_DEVICE_STATE_ACTIVE; +} +#else +static bool shim_nrf_lpcomp_is_resumed(void) +{ + return true; +} +#endif + +static void shim_nrf_lpcomp_start(void) +{ + if (shim_nrf_lpcomp_data0.started) { + return; + } + + nrfx_lpcomp_start(shim_nrf_lpcomp_data0.event_mask, 0); + shim_nrf_lpcomp_data0.started = true; +} + +static void shim_nrf_lpcomp_stop(void) +{ + if (!shim_nrf_lpcomp_data0.started) { + return; + } + + nrfx_lpcomp_stop(); + shim_nrf_lpcomp_data0.started = false; +} + +static int shim_nrf_lpcomp_pm_callback(const struct device *dev, enum pm_device_action action) +{ + ARG_UNUSED(dev); + + ARG_UNUSED(dev); + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + shim_nrf_lpcomp_start(); + break; + +#if CONFIG_PM_DEVICE + case PM_DEVICE_ACTION_SUSPEND: + shim_nrf_lpcomp_stop(); + break; +#endif + + default: + return -ENOTSUP; + } + + return 0; +} + +#if (NRF_LPCOMP_HAS_AIN_AS_PIN) +static int shim_nrf_lpcomp_psel_to_nrf(enum comp_nrf_lpcomp_psel shim, + nrf_lpcomp_input_t *nrf) +{ + if (shim >= ARRAY_SIZE(shim_nrf_lpcomp_ain_map)) { + return -EINVAL; + } + + *nrf = shim_nrf_lpcomp_ain_map[(uint32_t)shim]; + return 0; +} +#else +static int shim_nrf_lpcomp_psel_to_nrf(enum comp_nrf_lpcomp_psel shim, + nrf_lpcomp_input_t *nrf) +{ + switch (shim) { + case COMP_NRF_LPCOMP_PSEL_AIN0: + *nrf = NRF_LPCOMP_INPUT_0; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN1: + *nrf = NRF_LPCOMP_INPUT_1; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN2: + *nrf = NRF_LPCOMP_INPUT_2; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN3: + *nrf = NRF_LPCOMP_INPUT_3; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN4: + *nrf = NRF_LPCOMP_INPUT_4; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN5: + *nrf = NRF_LPCOMP_INPUT_5; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN6: + *nrf = NRF_LPCOMP_INPUT_6; + break; + + case COMP_NRF_LPCOMP_PSEL_AIN7: + *nrf = NRF_LPCOMP_INPUT_7; + break; + + default: + return -EINVAL; + } + + return 0; +} +#endif + +#if (NRF_LPCOMP_HAS_AIN_AS_PIN) +static int shim_nrf_lpcomp_extrefsel_to_nrf(enum comp_nrf_lpcomp_extrefsel shim, + nrf_lpcomp_ext_ref_t *nrf) +{ + if (shim >= ARRAY_SIZE(shim_nrf_lpcomp_ain_map)) { + return -EINVAL; + } + + *nrf = shim_nrf_lpcomp_ain_map[shim]; + return 0; +} +#else +static int shim_nrf_lpcomp_extrefsel_to_nrf(enum comp_nrf_lpcomp_extrefsel shim, + nrf_lpcomp_ext_ref_t *nrf) +{ + switch (shim) { + case COMP_NRF_LPCOMP_EXTREFSEL_AIN0: + *nrf = NRF_LPCOMP_EXT_REF_REF0; + break; + + case COMP_NRF_LPCOMP_EXTREFSEL_AIN1: + *nrf = NRF_LPCOMP_EXT_REF_REF1; + break; + + default: + return -EINVAL; + } + + return 0; +} +#endif + +static int shim_nrf_lpcomp_refsel_to_nrf(enum comp_nrf_lpcomp_refsel shim, + nrf_lpcomp_ref_t *nrf) +{ + switch (shim) { + case COMP_NRF_LPCOMP_REFSEL_VDD_1_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_1_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_2_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_2_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_3_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_3_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_4_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_4_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_5_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_5_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_6_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_6_8; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_7_8: + *nrf = NRF_LPCOMP_REF_SUPPLY_7_8; + break; + +#if (LPCOMP_REFSEL_RESOLUTION == 16) + case COMP_NRF_LPCOMP_REFSEL_VDD_1_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_1_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_3_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_3_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_5_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_5_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_7_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_7_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_9_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_9_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_11_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_11_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_13_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_13_16; + break; + + case COMP_NRF_LPCOMP_REFSEL_VDD_15_16: + *nrf = NRF_LPCOMP_REF_SUPPLY_15_16; + break; +#endif + + case COMP_NRF_LPCOMP_REFSEL_AREF: + *nrf = NRF_LPCOMP_REF_EXT_REF; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int shim_nrf_lpcomp_config_to_nrf(const struct comp_nrf_lpcomp_config *shim, + nrfx_lpcomp_config_t *nrf) +{ + if (shim_nrf_lpcomp_refsel_to_nrf(shim->refsel, &nrf->reference)) { + return -EINVAL; + } + + if (shim_nrf_lpcomp_extrefsel_to_nrf(shim->extrefsel, &nrf->ext_ref)) { + return -EINVAL; + } + +#if NRF_LPCOMP_HAS_HYST + if (shim->enable_hyst) { + nrf->hyst = NRF_LPCOMP_HYST_ENABLED; + } else { + nrf->hyst = NRF_LPCOMP_HYST_NOHYST; + } +#else + if (shim->enable_hyst) { + return -EINVAL; + } +#endif + + if (shim_nrf_lpcomp_psel_to_nrf(shim->psel, &nrf->input)) { + return -EINVAL; + } + + return 0; +} + +static void shim_nrf_lpcomp_reconfigure(void) +{ + (void)nrfx_lpcomp_reconfigure(&shim_nrf_lpcomp_data0.config); +} + +static int shim_nrf_lpcomp_get_output(const struct device *dev) +{ + ARG_UNUSED(dev); + + return nrfx_lpcomp_sample(); +} + +static int shim_nrf_lpcomp_set_trigger(const struct device *dev, + enum comparator_trigger trigger) +{ + shim_nrf_lpcomp_stop(); + + switch (trigger) { + case COMPARATOR_TRIGGER_NONE: + shim_nrf_lpcomp_data0.event_mask = 0; + shim_nrf_lpcomp_data0.config.detection = NRF_LPCOMP_DETECT_CROSS; + break; + + case COMPARATOR_TRIGGER_RISING_EDGE: + shim_nrf_lpcomp_data0.event_mask = NRF_LPCOMP_INT_UP_MASK; + shim_nrf_lpcomp_data0.config.detection = NRF_LPCOMP_DETECT_UP; + break; + + case COMPARATOR_TRIGGER_FALLING_EDGE: + shim_nrf_lpcomp_data0.event_mask = NRF_LPCOMP_INT_DOWN_MASK; + shim_nrf_lpcomp_data0.config.detection = NRF_LPCOMP_DETECT_DOWN; + break; + + case COMPARATOR_TRIGGER_BOTH_EDGES: + shim_nrf_lpcomp_data0.event_mask = NRF_LPCOMP_INT_CROSS_MASK; + shim_nrf_lpcomp_data0.config.detection = NRF_LPCOMP_DETECT_CROSS; + break; + } + + shim_nrf_lpcomp_reconfigure(); + + if (shim_nrf_lpcomp_is_resumed()) { + shim_nrf_lpcomp_start(); + } + + return 0; +} + +static int shim_nrf_lpcomp_set_trigger_callback(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + shim_nrf_lpcomp_stop(); + + shim_nrf_lpcomp_data0.callback = callback; + shim_nrf_lpcomp_data0.user_data = user_data; + + if (callback != NULL && atomic_test_and_clear_bit(&shim_nrf_lpcomp_data0.triggered, 0)) { + callback(dev, user_data); + } + + if (shim_nrf_lpcomp_is_resumed()) { + shim_nrf_lpcomp_start(); + } + + return 0; +} + +static int shim_nrf_lpcomp_trigger_is_pending(const struct device *dev) +{ + ARG_UNUSED(dev); + + return atomic_test_and_clear_bit(&shim_nrf_lpcomp_data0.triggered, 0); +} + +static const struct comparator_driver_api shim_nrf_lpcomp_api = { + .get_output = shim_nrf_lpcomp_get_output, + .set_trigger = shim_nrf_lpcomp_set_trigger, + .set_trigger_callback = shim_nrf_lpcomp_set_trigger_callback, + .trigger_is_pending = shim_nrf_lpcomp_trigger_is_pending, +}; + +int comp_nrf_lpcomp_configure(const struct device *dev, + const struct comp_nrf_lpcomp_config *config) +{ + nrfx_lpcomp_config_t nrf = {}; + + if (shim_nrf_lpcomp_config_to_nrf(config, &nrf)) { + return -EINVAL; + } + + memcpy(&shim_nrf_lpcomp_data0.config, &nrf, sizeof(shim_nrf_lpcomp_data0.config)); + + shim_nrf_lpcomp_stop(); + shim_nrf_lpcomp_reconfigure(); + if (shim_nrf_lpcomp_is_resumed()) { + shim_nrf_lpcomp_start(); + } + + return 0; +} + +static void shim_nrf_lpcomp_event_handler(nrf_lpcomp_event_t event) +{ + ARG_UNUSED(event); + + if (shim_nrf_lpcomp_data0.callback == NULL) { + atomic_set_bit(&shim_nrf_lpcomp_data0.triggered, 0); + return; + } + + shim_nrf_lpcomp_data0.callback(DEVICE_DT_INST_GET(0), shim_nrf_lpcomp_data0.user_data); + atomic_clear_bit(&shim_nrf_lpcomp_data0.triggered, 0); +} + +static int shim_nrf_lpcomp_init(const struct device *dev) +{ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + nrfx_isr, + nrfx_lpcomp_irq_handler, + 0); + + irq_enable(DT_INST_IRQN(0)); + + (void)shim_nrf_lpcomp_config_to_nrf(&shim_nrf_lpcomp_config0, + &shim_nrf_lpcomp_data0.config); + + if (nrfx_lpcomp_init(&shim_nrf_lpcomp_data0.config, + shim_nrf_lpcomp_event_handler) != NRFX_SUCCESS) { + return -ENODEV; + } + + return pm_device_driver_init(dev, shim_nrf_lpcomp_pm_callback); +} + +PM_DEVICE_DT_INST_DEFINE(0, shim_nrf_lpcomp_pm_callback); + +DEVICE_DT_INST_DEFINE(0, + shim_nrf_lpcomp_init, + PM_DEVICE_DT_INST_GET(0), + NULL, + NULL, + POST_KERNEL, + CONFIG_COMPARATOR_INIT_PRIORITY, + &shim_nrf_lpcomp_api); diff --git a/dts/bindings/comparator/nordic,nrf-lpcomp.yaml b/dts/bindings/comparator/nordic,nrf-lpcomp.yaml new file mode 100644 index 00000000000..8f9cd91a6b7 --- /dev/null +++ b/dts/bindings/comparator/nordic,nrf-lpcomp.yaml @@ -0,0 +1,83 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nRF LPCOMP (analog Low-Power COMParator) + + The following example displays the minimum node layout: + + comp: comp@deadbeef { + compatible = "nordic,nrf-lpcomp"; + reg = <0xdeadbeef 0x1000>; + interrupts = <0 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + Enabling the comparator node requires setting the default + configuration of the comparator. + + The following example displays enabling the comparator + using an internal reference: + + &comp { + status = "okay"; + psel = "AIN0"; + refsel = "VDD_4_8"; + hyst = "ENABLED"; + }; + + To select an external reference, select the "AREF" + reference and add the external reference: + + &comp { + ... + refsel = "AREF"; + extrefsel = "AIN1"; + ... + }; + +compatible: "nordic,nrf-lpcomp" + +include: base.yaml + +properties: + psel: + type: string + enum: + - "AIN0" + - "AIN1" + - "AIN2" + - "AIN3" + - "AIN4" + - "AIN5" + - "AIN6" + - "AIN7" + + extrefsel: + type: string + enum: + - "AIN0" + - "AIN1" + + refsel: + type: string + enum: + - "VDD_1_8" + - "VDD_2_8" + - "VDD_3_8" + - "VDD_4_8" + - "VDD_5_8" + - "VDD_6_8" + - "VDD_7_8" + - "VDD_1_16" + - "VDD_3_16" + - "VDD_5_16" + - "VDD_7_16" + - "VDD_9_16" + - "VDD_11_16" + - "VDD_13_16" + - "VDD_15_16" + - "AREF" + + enable-hyst: + type: boolean diff --git a/dts/bindings/sensor/nordic,nrf-lpcomp.yaml b/dts/bindings/sensor/nordic,nrf-lpcomp.yaml deleted file mode 100644 index 132b0980ac5..00000000000 --- a/dts/bindings/sensor/nordic,nrf-lpcomp.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2022, Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: Nordic nRF family LPCOMP (Low-power Comparator) - -compatible: "nordic,nrf-lpcomp" - -include: base.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - "#io-channel-cells": - type: int - const: 1 - required: true - -io-channel-cells: - - input diff --git a/include/zephyr/drivers/comparator/nrf_lpcomp.h b/include/zephyr/drivers/comparator/nrf_lpcomp.h new file mode 100644 index 00000000000..e1f2343a8de --- /dev/null +++ b/include/zephyr/drivers/comparator/nrf_lpcomp.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_LPCOMP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_LPCOMP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Positive input selection */ +enum comp_nrf_lpcomp_psel { + /** AIN0 external input */ + COMP_NRF_LPCOMP_PSEL_AIN0, + /** AIN1 external input */ + COMP_NRF_LPCOMP_PSEL_AIN1, + /** AIN2 external input */ + COMP_NRF_LPCOMP_PSEL_AIN2, + /** AIN3 external input */ + COMP_NRF_LPCOMP_PSEL_AIN3, + /** AIN4 external input */ + COMP_NRF_LPCOMP_PSEL_AIN4, + /** AIN5 external input */ + COMP_NRF_LPCOMP_PSEL_AIN5, + /** AIN6 external input */ + COMP_NRF_LPCOMP_PSEL_AIN6, + /** AIN7 external input */ + COMP_NRF_LPCOMP_PSEL_AIN7, +}; + +/** External reference selection */ +enum comp_nrf_lpcomp_extrefsel { + /** AIN0 external input */ + COMP_NRF_LPCOMP_EXTREFSEL_AIN0, + /** AIN1 external input */ + COMP_NRF_LPCOMP_EXTREFSEL_AIN1, +}; + +/** Reference selection */ +enum comp_nrf_lpcomp_refsel { + /** Use (VDD * (1/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_1_8, + /** Use (VDD * (2/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_2_8, + /** Use (VDD * (3/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_3_8, + /** Use (VDD * (4/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_4_8, + /** Use (VDD * (5/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_5_8, + /** Use (VDD * (6/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_6_8, + /** Use (VDD * (7/8)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_7_8, + /** Use (VDD * (1/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_1_16, + /** Use (VDD * (3/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_3_16, + /** Use (VDD * (5/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_5_16, + /** Use (VDD * (7/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_7_16, + /** Use (VDD * (9/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_9_16, + /** Use (VDD * (11/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_11_16, + /** Use (VDD * (13/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_13_16, + /** Use (VDD * (15/16)) as reference */ + COMP_NRF_LPCOMP_REFSEL_VDD_15_16, + /** Use external analog reference */ + COMP_NRF_LPCOMP_REFSEL_AREF, +}; + +/** + * @brief Configuration structure + * + * @note extrefsel is only used if refsel == COMP_NRF_LPCOMP_REFSEL_AREF + */ +struct comp_nrf_lpcomp_config { + /** Positive input selection */ + enum comp_nrf_lpcomp_psel psel; + /** External reference selection */ + enum comp_nrf_lpcomp_extrefsel extrefsel; + /** Reference selection */ + enum comp_nrf_lpcomp_refsel refsel; + /** Hysteresis configuration */ + bool enable_hyst; +}; + +/** + * @brief Configure comparator + * + * @param dev Comparator device instance + * @param config Configuration + * + * @retval 0 if successful + * @retval negative errno-code otherwise + */ +int comp_nrf_lpcomp_configure(const struct device *dev, + const struct comp_nrf_lpcomp_config *config); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_LPCOMP_H_ */ From 986d7d4ba5643b126a331feb071bf11f5d334a34 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 4 Sep 2024 11:52:51 +0200 Subject: [PATCH 07/21] [nrf fromtree] tests: drivers: build_all: comparator: add nrf_lpcomp Add nrf_lpcomp to build_all comparator test suite. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit a4fce338acc1cc183177f98d2e8243ed0f4493a3) (cherry picked from commit 2badeca4fdc01e73cec648909759a93aaace6b65) --- .../comparator/nrf_lpcomp/ext_ref.overlay | 12 +++++++++++ .../comparator/nrf_lpcomp/int_ref.overlay | 13 ++++++++++++ .../build_all/comparator/testcase.yaml | 20 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay create mode 100644 tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay diff --git a/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay b/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay new file mode 100644 index 00000000000..95e44fbed3d --- /dev/null +++ b/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN0"; + refsel = "VDD_4_8"; + status = "okay"; +}; diff --git a/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay b/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay new file mode 100644 index 00000000000..7aadd8b3fae --- /dev/null +++ b/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN0"; + refsel = "AREF"; + extrefsel = "AIN1"; + status = "okay"; +}; diff --git a/tests/drivers/build_all/comparator/testcase.yaml b/tests/drivers/build_all/comparator/testcase.yaml index 9c94ef9a69e..8dbc9dfb32a 100644 --- a/tests/drivers/build_all/comparator/testcase.yaml +++ b/tests/drivers/build_all/comparator/testcase.yaml @@ -46,3 +46,23 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf9280pdk/nrf9280/cpuapp + drivers.build_all.comparator.nrf_lpcomp.ext_ref: + extra_args: + - DTC_OVERLAY_FILE="nrf_lpcomp/ext_ref.overlay" + platform_allow: + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf9280pdk/nrf9280/cpuapp + drivers.build_all.comparator.nrf_lpcomp.int_ref: + extra_args: + - DTC_OVERLAY_FILE="nrf_lpcomp/int_ref.overlay" + platform_allow: + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf9280pdk/nrf9280/cpuapp From 0d5cf34d69b8bc18ec98793df8118b241efc088c Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 19 Aug 2024 13:03:10 +0200 Subject: [PATCH 08/21] [nrf fromtree] sensor: mcux_acmp: namespace driver and kconfigs The mcux_acmp will get support by the comparator subsystem. To avoid namespace clashes, namespace the driver, kconfigs and use the MCUX_ACMP config solely to select the MCUX SDK driver. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit e0363f252d09acd907c92bfc112d69ff3919587c) (cherry picked from commit 67c448a615ad40b31519ec1700df7cf5106ded9f) --- drivers/sensor/nxp/CMakeLists.txt | 2 +- drivers/sensor/nxp/mcux_acmp/Kconfig | 7 ++++--- drivers/sensor/nxp/mcux_acmp/mcux_acmp.c | 26 ++++++++++++------------ modules/hal_nxp/Kconfig | 3 ++- samples/sensor/mcux_acmp/prj.conf | 2 +- samples/sensor/mcux_acmp/sample.yaml | 2 +- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/sensor/nxp/CMakeLists.txt b/drivers/sensor/nxp/CMakeLists.txt index 73dc2cb274b..36e39e002bf 100644 --- a/drivers/sensor/nxp/CMakeLists.txt +++ b/drivers/sensor/nxp/CMakeLists.txt @@ -5,10 +5,10 @@ add_subdirectory_ifdef(CONFIG_FXAS21002 fxas21002) add_subdirectory_ifdef(CONFIG_FXLS8974 fxls8974) add_subdirectory_ifdef(CONFIG_FXOS8700 fxos8700) -add_subdirectory_ifdef(CONFIG_MCUX_ACMP mcux_acmp) add_subdirectory_ifdef(CONFIG_MCUX_LPCMP mcux_lpcmp) add_subdirectory_ifdef(CONFIG_NXP_TEMPMON nxp_tempmon) add_subdirectory_ifdef(CONFIG_QDEC_MCUX qdec_mcux) add_subdirectory_ifdef(CONFIG_QDEC_NXP_S32 qdec_nxp_s32) +add_subdirectory_ifdef(CONFIG_SENSOR_MCUX_ACMP mcux_acmp) add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nxp/mcux_acmp/Kconfig b/drivers/sensor/nxp/mcux_acmp/Kconfig index 0f976c65e21..1934e4d93f7 100644 --- a/drivers/sensor/nxp/mcux_acmp/Kconfig +++ b/drivers/sensor/nxp/mcux_acmp/Kconfig @@ -4,17 +4,18 @@ # Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 -config MCUX_ACMP +config SENSOR_MCUX_ACMP bool "NXP MCUX Analog Comparator (ACMP)" default y depends on DT_HAS_NXP_KINETIS_ACMP_ENABLED select PINCTRL + select MCUX_ACMP help Enable driver for the NXP MCUX Analog Comparator (ACMP). -config MCUX_ACMP_TRIGGER +config SENSOR_MCUX_ACMP_TRIGGER bool "Trigger support" - depends on MCUX_ACMP + depends on SENSOR_MCUX_ACMP help Enable trigger support for the NXP MCUX Analog Comparator (ACMP). diff --git a/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c b/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c index 30339f3e48d..69c01c3a5ff 100644 --- a/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c +++ b/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c @@ -45,9 +45,9 @@ struct mcux_acmp_config { CMP_Type *base; acmp_filter_config_t filter; const struct pinctrl_dev_config *pincfg; -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER void (*irq_config_func)(const struct device *dev); -#endif /* CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ bool high_speed : 1; bool unfiltered : 1; bool output : 1; @@ -61,7 +61,7 @@ struct mcux_acmp_data { #if MCUX_ACMP_HAS_DISCRETE_MODE acmp_discrete_mode_config_t discrete_config; #endif -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER const struct device *dev; sensor_trigger_handler_t rising_handler; const struct sensor_trigger *rising_trigger; @@ -69,7 +69,7 @@ struct mcux_acmp_data { const struct sensor_trigger *falling_trigger; struct k_work work; volatile uint32_t status; -#endif /* CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ bool cout; }; @@ -370,7 +370,7 @@ static int mcux_acmp_channel_get(const struct device *dev, return 0; } -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER static int mcux_acmp_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) @@ -431,7 +431,7 @@ static void mcux_acmp_isr(const struct device *dev) k_work_submit(&data->work); } -#endif /* CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ static int mcux_acmp_init(const struct device *dev) { @@ -462,7 +462,7 @@ static int mcux_acmp_init(const struct device *dev) /* Disable DAC */ ACMP_SetDACConfig(config->base, NULL); -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER data->dev = dev; k_work_init(&data->work, mcux_acmp_trigger_work_handler); @@ -470,7 +470,7 @@ static int mcux_acmp_init(const struct device *dev) ACMP_EnableInterrupts(config->base, kACMP_OutputRisingInterruptEnable | kACMP_OutputFallingInterruptEnable); -#endif /* CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ ACMP_Enable(config->base, true); @@ -480,9 +480,9 @@ static int mcux_acmp_init(const struct device *dev) static const struct sensor_driver_api mcux_acmp_driver_api = { .attr_set = mcux_acmp_attr_set, .attr_get = mcux_acmp_attr_get, -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER .trigger_set = mcux_acmp_trigger_set, -#endif /* CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ .sample_fetch = mcux_acmp_sample_fetch, .channel_get = mcux_acmp_channel_get, }; @@ -503,7 +503,7 @@ static const struct mcux_acmp_config mcux_acmp_config_##n = { \ config_func_init \ } -#ifdef CONFIG_MCUX_ACMP_TRIGGER +#ifdef CONFIG_SENSOR_MCUX_ACMP_TRIGGER #define MCUX_ACMP_CONFIG_FUNC(n) \ static void mcux_acmp_config_func_##n(const struct device *dev) \ { \ @@ -517,12 +517,12 @@ static const struct mcux_acmp_config mcux_acmp_config_##n = { \ .irq_config_func = mcux_acmp_config_func_##n #define MCUX_ACMP_INIT_CONFIG(n) \ MCUX_ACMP_DECLARE_CONFIG(n, MCUX_ACMP_CONFIG_FUNC_INIT(n)) -#else /* !CONFIG_MCUX_ACMP_TRIGGER */ +#else /* !CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ #define MCUX_ACMP_CONFIG_FUNC(n) #define MCUX_ACMP_CONFIG_FUNC_INIT #define MCUX_ACMP_INIT_CONFIG(n) \ MCUX_ACMP_DECLARE_CONFIG(n, MCUX_ACMP_CONFIG_FUNC_INIT) -#endif /* !CONFIG_MCUX_ACMP_TRIGGER */ +#endif /* !CONFIG_SENSOR_MCUX_ACMP_TRIGGER */ #define MCUX_ACMP_INIT(n) \ static struct mcux_acmp_data mcux_acmp_data_##n; \ diff --git a/modules/hal_nxp/Kconfig b/modules/hal_nxp/Kconfig index aaec4e84aba..4f055faa07d 100644 --- a/modules/hal_nxp/Kconfig +++ b/modules/hal_nxp/Kconfig @@ -4,4 +4,5 @@ # SPDX-License-Identifier: Apache-2.0 # -# file is empty and kept as a place holder if/when Kconfig is needed +config MCUX_ACMP + bool "Include ACMP driver from MCUX SDK" diff --git a/samples/sensor/mcux_acmp/prj.conf b/samples/sensor/mcux_acmp/prj.conf index 8b70c7ae30b..202fe6b8564 100644 --- a/samples/sensor/mcux_acmp/prj.conf +++ b/samples/sensor/mcux_acmp/prj.conf @@ -1,2 +1,2 @@ CONFIG_SENSOR=y -CONFIG_MCUX_ACMP_TRIGGER=y +CONFIG_SENSOR_MCUX_ACMP_TRIGGER=y diff --git a/samples/sensor/mcux_acmp/sample.yaml b/samples/sensor/mcux_acmp/sample.yaml index fa7782d896d..a00773fdbb6 100644 --- a/samples/sensor/mcux_acmp/sample.yaml +++ b/samples/sensor/mcux_acmp/sample.yaml @@ -27,4 +27,4 @@ tests: sample.sensor.mcux_acmp.no_trigger: build_only: true extra_configs: - - CONFIG_MCUX_ACMP_TRIGGER=n + - CONFIG_SENSOR_MCUX_ACMP_TRIGGER=n From 44b0343ca091c84ce3067095dd7bb61391d09864 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 18 Sep 2024 13:13:45 +0200 Subject: [PATCH 09/21] [nrf fromtree] drivers: sensor: mcux_acmp: update dts binding and adapt driver Update the devicetree binding for the nxp,kinetis-acmp comparator and move the binding to dts/bindings/comparator. The update to the binding includes: - Remove unused io-channel-cells property - Remove unused sensor-device include - Adding missing properties dac config, discrete mode config, and input configs. - Rename properties to exclude redundant vendor prefix since props in this binding are not inhereted, and as such, don't need to be namespaced. - Deprecate the old names of the renamed properties The sensor based device driver has been updated to support both the deprecated and new property names. This allows it to use both nxp,enable-sample and filter-enable-sample for example. Additionally, remove the unused io-channel-cells properties from in-tree nodes of compatible = "nxp,kinetis-acmp" Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 4e55597527a4becf61ee35d38cd8e451f488c391) (cherry picked from commit bee7df84c97cc4326b13d32c87cb2ad947c2eaed) --- drivers/sensor/nxp/mcux_acmp/mcux_acmp.c | 59 +++++- dts/arm/nxp/nxp_ke1xf.dtsi | 3 - dts/arm/nxp/nxp_ke1xz.dtsi | 1 - dts/arm/nxp/nxp_rt118x.dtsi | 4 - dts/arm/nxp/nxp_rt11xx.dtsi | 4 - dts/bindings/comparator/nxp,kinetis-acmp.yaml | 195 ++++++++++++++++++ dts/bindings/sensor/nxp,kinetis-acmp.yaml | 58 ------ 7 files changed, 246 insertions(+), 78 deletions(-) create mode 100644 dts/bindings/comparator/nxp,kinetis-acmp.yaml delete mode 100644 dts/bindings/sensor/nxp,kinetis-acmp.yaml diff --git a/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c b/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c index 69c01c3a5ff..90dde17e83c 100644 --- a/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c +++ b/drivers/sensor/nxp/mcux_acmp/mcux_acmp.c @@ -41,6 +41,49 @@ BUILD_ASSERT(kACMP_PortInputFromDAC == 0); BUILD_ASSERT(kACMP_PortInputFromMux == 1); #endif /* MCUX_ACMP_HAS_INPSEL || MCUX_ACMP_HAS_INNSEL */ +/* + * prop New property name + * depr Deprecated property name + */ +#define MCUX_ACMP_DT_INST_PROP(inst, prop, depr) \ + COND_CODE_1( \ + DT_INST_NODE_HAS_PROP(inst, prop), \ + (DT_INST_PROP(inst, prop)), \ + (DT_INST_PROP(inst, depr)) \ + ) + +/* + * prop New property name + * depr Deprecated property name + */ +#define MCUX_ACMP_DT_INST_PROP_OR(inst, prop, depr, default_value) \ + COND_CODE_1( \ + DT_INST_NODE_HAS_PROP(inst, prop) || DT_INST_NODE_HAS_PROP(inst, depr), \ + (MCUX_ACMP_DT_INST_PROP(inst, prop, depr)), \ + (default_value) \ + ) + +#define MCUX_ACMP_DT_INST_ENABLE_SAMPLE(inst) \ + MCUX_ACMP_DT_INST_PROP(inst, filter_enable_sample, nxp_enable_sample) + +#define MCUX_ACMP_DT_INST_FILTER_COUNT(inst) \ + MCUX_ACMP_DT_INST_PROP_OR(inst, filter_count, nxp_filter_count, 0) + +#define MCUX_ACMP_DT_INST_FILTER_PERIOD(inst) \ + MCUX_ACMP_DT_INST_PROP_OR(inst, filter_period, nxp_filter_period, 0) + +#define MCUX_ACMP_DT_INST_HIGH_SPEED(inst) \ + MCUX_ACMP_DT_INST_PROP(inst, enable_high_speed_mode, nxp_high_speed_mode) + +#define MCUX_ACMP_DT_INST_USE_UNFILTERED_MODE(inst) \ + MCUX_ACMP_DT_INST_PROP(inst, use_unfiltered_output, nxp_use_unfiltered_output) + +#define MCUX_ACMP_DT_INST_USE_ENABLE_PIN_OUT(inst) \ + MCUX_ACMP_DT_INST_PROP(inst, enable_pin_out, nxp_enable_output_pin) + +#define MCUX_ACMP_DT_INST_ENABLE_WINDOW_MODE(inst) \ + MCUX_ACMP_DT_INST_PROP(inst, enable_window_mode, nxp_window_mode) + struct mcux_acmp_config { CMP_Type *base; acmp_filter_config_t filter; @@ -487,18 +530,18 @@ static const struct sensor_driver_api mcux_acmp_driver_api = { .channel_get = mcux_acmp_channel_get, }; -#define MCUX_ACMP_DECLARE_CONFIG(n, config_func_init) \ +#define MCUX_ACMP_DECLARE_CONFIG(n, config_func_init) \ static const struct mcux_acmp_config mcux_acmp_config_##n = { \ .base = (CMP_Type *)DT_INST_REG_ADDR(n), \ .filter = { \ - .enableSample = DT_INST_PROP(n, nxp_enable_sample), \ - .filterCount = DT_INST_PROP_OR(n, nxp_filter_count, 0), \ - .filterPeriod = DT_INST_PROP_OR(n, nxp_filter_period, 0), \ + .enableSample = MCUX_ACMP_DT_INST_ENABLE_SAMPLE(n), \ + .filterCount = MCUX_ACMP_DT_INST_FILTER_COUNT(n), \ + .filterPeriod = MCUX_ACMP_DT_INST_FILTER_PERIOD(n), \ }, \ - .high_speed = DT_INST_PROP(n, nxp_high_speed_mode), \ - .unfiltered = DT_INST_PROP(n, nxp_use_unfiltered_output), \ - .output = DT_INST_PROP(n, nxp_enable_output_pin), \ - .window = DT_INST_PROP(n, nxp_window_mode), \ + .high_speed = MCUX_ACMP_DT_INST_HIGH_SPEED(n), \ + .unfiltered = MCUX_ACMP_DT_INST_USE_UNFILTERED_MODE(n), \ + .output = MCUX_ACMP_DT_INST_USE_ENABLE_PIN_OUT(n), \ + .window = MCUX_ACMP_DT_INST_ENABLE_WINDOW_MODE(n), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ config_func_init \ } diff --git a/dts/arm/nxp/nxp_ke1xf.dtsi b/dts/arm/nxp/nxp_ke1xf.dtsi index 6aff4315889..8c880c06daf 100644 --- a/dts/arm/nxp/nxp_ke1xf.dtsi +++ b/dts/arm/nxp/nxp_ke1xf.dtsi @@ -575,7 +575,6 @@ interrupts = <40 0>; clocks = <&scg KINETIS_SCG_BUS_CLK>; status = "disabled"; - #io-channel-cells = <2>; }; cmp1: cmp@40074000 { @@ -584,7 +583,6 @@ interrupts = <41 0>; clocks = <&scg KINETIS_SCG_BUS_CLK>; status = "disabled"; - #io-channel-cells = <2>; }; cmp2: cmp@40075000 { @@ -593,7 +591,6 @@ interrupts = <70 0>; clocks = <&scg KINETIS_SCG_BUS_CLK>; status = "disabled"; - #io-channel-cells = <2>; }; flexio1: flexio@4005a000 { diff --git a/dts/arm/nxp/nxp_ke1xz.dtsi b/dts/arm/nxp/nxp_ke1xz.dtsi index 577f0e894fe..8e34d564845 100644 --- a/dts/arm/nxp/nxp_ke1xz.dtsi +++ b/dts/arm/nxp/nxp_ke1xz.dtsi @@ -419,7 +419,6 @@ interrupts = <16 0>; clocks = <&scg KINETIS_SCG_BUS_CLK>; status = "disabled"; - #io-channel-cells = <2>; }; lpspi0: spi@4002c000 { diff --git a/dts/arm/nxp/nxp_rt118x.dtsi b/dts/arm/nxp/nxp_rt118x.dtsi index b0f7c5e078a..4bb645e8979 100644 --- a/dts/arm/nxp/nxp_rt118x.dtsi +++ b/dts/arm/nxp/nxp_rt118x.dtsi @@ -299,7 +299,6 @@ reg = <0x2dc0000 0x4000>; interrupts = <200 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp2: cmp@2dd0000 { @@ -307,7 +306,6 @@ reg = <0x2dd0000 0x4000>; interrupts = <201 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp3: cmp@2de0000 { @@ -315,7 +313,6 @@ reg = <0x2de0000 0x4000>; interrupts = <202 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp4: cmp@2df0000 { @@ -323,7 +320,6 @@ reg = <0x2df0000 0x4000>; interrupts = <203 0>; status = "disabled"; - #io-channel-cells = <2>; }; }; diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index 6e3644f58fa..5dd41ed398b 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -1011,7 +1011,6 @@ reg = <0x401a4000 0x4000>; interrupts = <157 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp2: cmp@401a8000 { @@ -1019,7 +1018,6 @@ reg = <0x401a8000 0x4000>; interrupts = <158 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp3: cmp@401ac000 { @@ -1027,7 +1025,6 @@ reg = <0x401ac000 0x4000>; interrupts = <159 0>; status = "disabled"; - #io-channel-cells = <2>; }; acmp4: cmp@401b0000 { @@ -1035,7 +1032,6 @@ reg = <0x401b0000 0x4000>; interrupts = <160 0>; status = "disabled"; - #io-channel-cells = <2>; }; anatop: anatop@40c84000 { diff --git a/dts/bindings/comparator/nxp,kinetis-acmp.yaml b/dts/bindings/comparator/nxp,kinetis-acmp.yaml new file mode 100644 index 00000000000..76ce24b5bba --- /dev/null +++ b/dts/bindings/comparator/nxp,kinetis-acmp.yaml @@ -0,0 +1,195 @@ +# Copyright (c) 2020 Vestas Wind Systems A/S +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: NXP Kinetis ACMP (Analog CoMParator) + +compatible: "nxp,kinetis-acmp" + +include: + - base.yaml + - pinctrl-device.yaml + +properties: + interrupts: + required: true + + reg: + required: true + + nxp,enable-output-pin: + type: boolean + deprecated: true + description: Deprecated. Please use enable-pin-out instead + + nxp,use-unfiltered-output: + type: boolean + deprecated: true + description: Deprecated. Please use use-unfiltered-output instead + + nxp,high-speed-mode: + type: boolean + deprecated: true + description: Deprecated. Please use enable-high-speed-mode instead + + nxp,enable-sample: + type: boolean + deprecated: true + description: Deprecated. Please use filter-enable-sample instead + + nxp,filter-count: + type: int + deprecated: true + description: Deprecated. Please use filter-count instead + + nxp,filter-period: + type: int + deprecated: true + description: Deprecated. Please use filter-period instead + + nxp,window-mode: + type: boolean + deprecated: true + description: Deprecated. Please use enable-window-mode instead + + offset-mode: + type: string + enum: + - "LEVEL0" + - "LEVEL1" + + hysteresis-mode: + type: string + enum: + - "LEVEL0" + - "LEVEL1" + - "LEVEL2" + - "LEVEL3" + + enable-high-speed-mode: + type: boolean + + invert-output: + type: boolean + + use-unfiltered-output: + type: boolean + + enable-pin-out: + type: boolean + + enable-window-mode: + type: boolean + + positive-mux-input: + type: string + enum: + - IN0 + - IN1 + - IN2 + - IN3 + - IN4 + - IN5 + - IN6 + - IN7 + + negative-mux-input: + type: string + enum: + - IN0 + - IN1 + - IN2 + - IN3 + - IN4 + - IN5 + - IN6 + - IN7 + + positive-port-input: + type: string + enum: + - DAC + - MUX + + negative-port-input: + type: string + enum: + - DAC + - MUX + + filter-enable-sample: + type: boolean + + filter-count: + type: int + description: Filter sample count (0 to 7). + + filter-period: + type: int + description: Filter sample period in bus clock cycles (0 to 255). + + dac-vref-source: + type: string + enum: + - "VIN1" + - "VIN2" + + dac-value: + type: int + + dac-enable: + type: boolean + + dac-enable-high-speed: + type: boolean + + discrete-mode-enable-positive-channel: + type: boolean + + discrete-mode-enable-negative-channel: + type: boolean + + discrete-mode-enable-resistor-divider: + type: boolean + + discrete-mode-clock-source: + type: string + enum: + - "SLOW" + - "FAST" + + discrete-mode-sample-time: + type: string + enum: + - "T1" + - "T2" + - "T4" + - "T8" + - "T16" + - "T32" + - "T64" + - "T256" + + discrete-mode-phase1-time: + type: string + enum: + - "ALT0" + - "ALT1" + - "ALT2" + - "ALT3" + - "ALT4" + - "ALT5" + - "ALT6" + - "ALT7" + + discrete-mode-phase2-time: + type: string + enum: + - "ALT0" + - "ALT1" + - "ALT2" + - "ALT3" + - "ALT4" + - "ALT5" + - "ALT6" + - "ALT7" diff --git a/dts/bindings/sensor/nxp,kinetis-acmp.yaml b/dts/bindings/sensor/nxp,kinetis-acmp.yaml deleted file mode 100644 index 9608f9305c9..00000000000 --- a/dts/bindings/sensor/nxp,kinetis-acmp.yaml +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2020 Vestas Wind Systems A/S -# SPDX-License-Identifier: Apache-2.0 - -description: NXP Kinetis Analog Comparator (ACMP) - -compatible: "nxp,kinetis-acmp" - -include: [sensor-device.yaml, pinctrl-device.yaml] - -properties: - interrupts: - required: true - - reg: - required: true - - nxp,enable-output-pin: - type: boolean - description: | - Make the comparator output (CMP0) available on a packaged pin. - - nxp,use-unfiltered-output: - type: boolean - description: | - Use the unfiltered comparator output for CMP0. - - nxp,high-speed-mode: - type: boolean - description: | - Enable high speed comparison mode. - - nxp,enable-sample: - type: boolean - description: | - Enable external sample signal as clock input. - - nxp,filter-count: - type: int - description: | - Filter sample count (0 to 7). - - nxp,filter-period: - type: int - description: | - Filter sample period in bus clock cycles (0 to 255). - - nxp,window-mode: - type: boolean - description: | - Enable windowing mode. - - "#io-channel-cells": - type: int - const: 2 - -io-channel-cells: - - positive - - negative From c5f74a1644d56331c85932cd6174e4e05b9747a8 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 22 Sep 2024 19:30:43 +0200 Subject: [PATCH 10/21] [nrf fromtree] doc: releases: migration-guide: deprecated nxp,kinetis-acmp props Add entyr mentioning the deprecation of the nxp, prefixed properties in the nxp,kinetis-acmp dts binding. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 3b08a08c7f1b9741de3bdeab103e7c4b27e6e24d) (cherry picked from commit 28879e016e1045ff9ba447eb9fe19e99e7db7519) --- doc/releases/migration-guide-4.0.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/migration-guide-4.0.rst b/doc/releases/migration-guide-4.0.rst index 3699a7fedcb..3581625f830 100644 --- a/doc/releases/migration-guide-4.0.rst +++ b/doc/releases/migration-guide-4.0.rst @@ -150,6 +150,11 @@ Sensors to support all JEDEC JC 42.4 compatible temperature sensors. It now uses the :dtcompatible:`jedec,jc-42.4-temp` compatible string instead to the ``microchip,mcp9808`` string. +* The ``nxp,`` prefixed properties in :dtcompatible:`nxp,kinetis-acmp` have been deprecated in favor + of properties without the prefix. The sensor based driver for the :dtcompatible:`nxp,kinetis-acmp` + has been updated to support both the new and deprecated property names. Uses of the deprecated + property names should be updated to the new property names. + Serial ====== From be1151870be3d4b0f575e6ea85e6689737419c1b Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 19 Aug 2024 11:53:09 +0200 Subject: [PATCH 11/21] [nrf fromtree] drivers: comparator: add mcux acmp device driver Add mcux SDK based kinetis acmp device driver implementing the comparator device driver API. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit d37f8441043b064eabe5d924e93d103a91c40b44) (cherry picked from commit 4f0b5225b967333c805fb39fdcb18c47ae57b4e1) --- drivers/comparator/CMakeLists.txt | 1 + drivers/comparator/Kconfig | 1 + drivers/comparator/Kconfig.mcux_acmp | 9 + drivers/comparator/comparator_mcux_acmp.c | 651 ++++++++++++++++++ dts/bindings/comparator/nxp,kinetis-acmp.yaml | 34 +- include/zephyr/drivers/comparator/mcux_acmp.h | 136 ++++ 6 files changed, 831 insertions(+), 1 deletion(-) create mode 100644 drivers/comparator/Kconfig.mcux_acmp create mode 100644 drivers/comparator/comparator_mcux_acmp.c create mode 100644 include/zephyr/drivers/comparator/mcux_acmp.h diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index d0dc726bf58..b5fe633a333 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -6,5 +6,6 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/comparator.h) zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_MCUX_ACMP comparator_mcux_acmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 819936024b9..871ee5d9ed6 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -18,6 +18,7 @@ config COMPARATOR_INIT_PRIORITY help Comparator device driver initialization priority. +rsource "Kconfig.mcux_acmp" rsource "Kconfig.nrf_comp" rsource "Kconfig.nrf_lpcomp" diff --git a/drivers/comparator/Kconfig.mcux_acmp b/drivers/comparator/Kconfig.mcux_acmp new file mode 100644 index 00000000000..8109cb1cdd2 --- /dev/null +++ b/drivers/comparator/Kconfig.mcux_acmp @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_MCUX_ACMP + bool "NXP MCUX ACMP comparator driver" + default y + depends on DT_HAS_NXP_KINETIS_ACMP_ENABLED + select PINCTRL + select MCUX_ACMP diff --git a/drivers/comparator/comparator_mcux_acmp.c b/drivers/comparator/comparator_mcux_acmp.c new file mode 100644 index 00000000000..4d76f105e34 --- /dev/null +++ b/drivers/comparator/comparator_mcux_acmp.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2020 Vestas Wind Systems A/S + * Copyright (c) 2022 NXP + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(nxp_kinetis_acmp, CONFIG_COMPARATOR_LOG_LEVEL); + +#define DT_DRV_COMPAT nxp_kinetis_acmp + +/* + * DAC is a register defined in the MCUX HAL. We don't need it here and it conflicts + * with the COMP_MCUX_ACMP_PORT_INPUT_DAC definition so undef it here. + */ +#ifdef DAC +#undef DAC +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT) && (FSL_FEATURE_ACMP_HAS_C0_OFFSET_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_OFFSET 1 +#else +#define COMP_MCUX_ACMP_HAS_OFFSET 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C0_HYSTCTR_BIT) && (FSL_FEATURE_ACMP_HAS_C0_HYSTCTR_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_HYSTERESIS 1 +#else +#define COMP_MCUX_ACMP_HAS_HYSTERESIS 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT) && (FSL_FEATURE_ACMP_HAS_C1_INPSEL_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_INPSEL 1 +#else +#define COMP_MCUX_ACMP_HAS_INPSEL 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C1_INNSEL_BIT) && (FSL_FEATURE_ACMP_HAS_C1_INNSEL_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_INNSEL 1 +#else +#define COMP_MCUX_ACMP_HAS_INNSEL 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C1_DACOE_BIT) && (FSL_FEATURE_ACMP_HAS_C1_DACOE_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_DAC_OUT_ENABLE 1 +#else +#define COMP_MCUX_ACMP_HAS_DAC_OUT_ENABLE 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C1_DMODE_BIT) && (FSL_FEATURE_ACMP_HAS_C1_DMODE_BIT == 1U) +#define COMP_MCUX_ACMP_HAS_DAC_WORK_MODE 1 +#else +#define COMP_MCUX_ACMP_HAS_DAC_WORK_MODE 0 +#endif + +#if defined(FSL_FEATURE_ACMP_HAS_C3_REG) && (FSL_FEATURE_ACMP_HAS_C3_REG != 0U) +#define COMP_MCUX_ACMP_HAS_DISCRETE_MODE 1 +#else +#define COMP_MCUX_ACMP_HAS_DISCRETE_MODE 0 +#endif + +#if !(defined(FSL_FEATURE_ACMP_HAS_NO_WINDOW_MODE) && (FSL_FEATURE_ACMP_HAS_NO_WINDOW_MODE == 1U)) +#define COMP_MCUX_ACMP_HAS_WINDOW_MODE 1 +#else +#define COMP_MCUX_ACMP_HAS_WINDOW_MODE 0 +#endif + +#define MCUX_ACMP_ENUM(name, value) \ + _CONCAT_4(COMP_MCUX_ACMP_, name, _, value) + +#define MCUX_ACMP_DT_INST_ENUM(inst, name, prop) \ + MCUX_ACMP_ENUM(name, DT_INST_STRING_TOKEN(inst, prop)) + +#define MCUX_ACMP_DT_INST_ENUM_OR(inst, name, prop, or) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, prop), \ + (MCUX_ACMP_DT_INST_ENUM(inst, name, prop)), \ + (MCUX_ACMP_ENUM(name, or))) + +#define MCUX_ACMP_DT_INST_OFFSET_MODE(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, OFFSET_MODE, offset_mode, LEVEL0) + +#define MCUX_ACMP_DT_INST_HYST_MODE(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, HYSTERESIS_MODE, hysteresis_mode, LEVEL0) + +#define MCUX_ACMP_DT_INST_EN_HS_MODE(inst) \ + DT_INST_PROP(inst, enable_high_speed_mode) + +#define MCUX_ACMP_DT_INST_INV_OUT(inst) \ + DT_INST_PROP(inst, invert_output) + +#define MCUX_ACMP_DT_INST_USE_UNFILTERED_OUT(inst) \ + DT_INST_PROP(inst, use_unfiltered_output) + +#define MCUX_ACMP_DT_INST_EN_PIN_OUT(inst) \ + DT_INST_PROP(inst, enable_pin_out) + +#define MCUX_ACMP_DT_INST_MODE_CONFIG_INIT(inst) \ + { \ + .offset_mode = MCUX_ACMP_DT_INST_OFFSET_MODE(inst), \ + .hysteresis_mode = MCUX_ACMP_DT_INST_HYST_MODE(inst), \ + .enable_high_speed_mode = MCUX_ACMP_DT_INST_EN_HS_MODE(inst), \ + .invert_output = MCUX_ACMP_DT_INST_INV_OUT(inst), \ + .use_unfiltered_output = MCUX_ACMP_DT_INST_USE_UNFILTERED_OUT(inst), \ + .enable_pin_output = MCUX_ACMP_DT_INST_EN_PIN_OUT(inst), \ + } + +#define MCUX_ACMP_DT_INST_P_MUX_IN(inst) \ + MCUX_ACMP_DT_INST_ENUM(inst, MUX_INPUT, positive_mux_input) + +#define MCUX_ACMP_DT_INST_N_MUX_IN(inst) \ + MCUX_ACMP_DT_INST_ENUM(inst, MUX_INPUT, negative_mux_input) + +#define MCUX_ACMP_DT_INST_P_PORT_IN(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, PORT_INPUT, positive_port_input, MUX) + +#define MCUX_ACMP_DT_INST_N_PORT_IN(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, PORT_INPUT, negative_port_input, MUX) + +#define MCUX_ACMP_DT_INST_INPUT_CONFIG_INIT(inst) \ + { \ + .positive_mux_input = MCUX_ACMP_DT_INST_P_MUX_IN(inst), \ + .negative_mux_input = MCUX_ACMP_DT_INST_N_MUX_IN(inst), \ + .positive_port_input = MCUX_ACMP_DT_INST_P_PORT_IN(inst), \ + .negative_port_input = MCUX_ACMP_DT_INST_N_PORT_IN(inst), \ + } + +#define MCUX_ACMP_DT_INST_FILTER_EN_SAMPLE(inst) \ + DT_INST_PROP(inst, filter_enable_sample) + +#define MCUX_ACMP_DT_INST_FILTER_COUNT(inst) \ + DT_INST_PROP_OR(inst, filter_count, 0) + +#define MCUX_ACMP_DT_INST_FILTER_PERIOD(inst) \ + DT_INST_PROP_OR(inst, filter_period, 0) + +#define MCUX_ACMP_DT_INST_FILTER_CONFIG_INIT(inst) \ + { \ + .enable_sample = MCUX_ACMP_DT_INST_FILTER_EN_SAMPLE(inst), \ + .filter_count = MCUX_ACMP_DT_INST_FILTER_COUNT(inst), \ + .filter_period = MCUX_ACMP_DT_INST_FILTER_PERIOD(inst), \ + } + +#define MCUX_ACMP_DT_INST_DAC_VREF_SOURCE(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, DAC_VREF_SOURCE, dac_vref_source, VIN1) + +#define MCUX_ACMP_DT_INST_DAC_VALUE(inst) \ + DT_INST_PROP_OR(inst, dac_value, 0) + +#define MCUX_ACMP_DT_INST_DAC_EN(inst) \ + DT_INST_PROP(inst, dac_enable) + +#define MCUX_ACMP_DT_INST_DAC_EN_HS(inst) \ + DT_INST_PROP(inst, dac_enable_high_speed) + +#define MCUX_ACMP_DT_INST_DAC_CONFIG_INIT(inst) \ + { \ + .vref_source = MCUX_ACMP_DT_INST_DAC_VREF_SOURCE(inst), \ + .value = MCUX_ACMP_DT_INST_DAC_VALUE(inst), \ + .enable_output = MCUX_ACMP_DT_INST_DAC_EN(inst), \ + .enable_high_speed_mode = MCUX_ACMP_DT_INST_DAC_EN_HS(inst), \ + } + +#define MCUX_ACMP_DT_INST_DM_EN_P_CH(inst) \ + DT_INST_PROP(inst, discrete_mode_enable_positive_channel) + +#define MCUX_ACMP_DT_INST_DM_EN_N_CH(inst) \ + DT_INST_PROP(inst, discrete_mode_enable_negative_channel) + +#define MCUX_ACMP_DT_INST_DM_EN_RES_DIV(inst) \ + DT_INST_PROP(inst, discrete_mode_enable_resistor_divider) + +#define MCUX_ACMP_DT_INST_DM_CLOCK_SOURCE(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, DM_CLOCK, discrete_mode_clock_source, SLOW) + +#define MCUX_ACMP_DT_INST_DM_SAMPLE_TIME(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, DM_SAMPLE_TIME, discrete_mode_sample_time, T1) + +#define MCUX_ACMP_DT_INST_DM_PHASE1_TIME(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, DM_PHASE_TIME, discrete_mode_phase1_time, ALT0) + +#define MCUX_ACMP_DT_INST_DM_PHASE2_TIME(inst) \ + MCUX_ACMP_DT_INST_ENUM_OR(inst, DM_PHASE_TIME, discrete_mode_phase2_time, ALT0) + +#define MCUX_ACMP_DT_INST_DM_CONFIG_INIT(inst) \ + { \ + .enable_positive_channel = MCUX_ACMP_DT_INST_DM_EN_P_CH(inst), \ + .enable_negative_channel = MCUX_ACMP_DT_INST_DM_EN_N_CH(inst), \ + .enable_resistor_divider = MCUX_ACMP_DT_INST_DM_EN_RES_DIV(inst), \ + .clock_source = MCUX_ACMP_DT_INST_DM_CLOCK_SOURCE(inst), \ + .sample_time = MCUX_ACMP_DT_INST_DM_SAMPLE_TIME(inst), \ + .phase1_time = MCUX_ACMP_DT_INST_DM_PHASE1_TIME(inst), \ + .phase2_time = MCUX_ACMP_DT_INST_DM_PHASE2_TIME(inst), \ + } + +#define MCUX_ACMP_DT_INST_EN_WINDOW_MODE(inst) \ + DT_INST_PROP(inst, enable_window_mode) + +struct mcux_acmp_config { + CMP_Type *base; + const struct pinctrl_dev_config *pincfg; + void (*irq_init)(void); + const struct comp_mcux_acmp_mode_config mode_config; + const struct comp_mcux_acmp_input_config input_config; + const struct comp_mcux_acmp_filter_config filter_config; + const struct comp_mcux_acmp_dac_config dac_config; +#if COMP_MCUX_ACMP_HAS_DISCRETE_MODE + const struct comp_mcux_acmp_dm_config dm_config; +#endif +#if COMP_MCUX_ACMP_HAS_WINDOW_MODE + bool enable_window_mode; +#endif +}; + +#if MCUX_ACMP_HAS_OFFSET +BUILD_ASSERT((int)kACMP_OffsetLevel0 == (int)COMP_MCUX_ACMP_OFFSET_MODE_LEVEL0); +BUILD_ASSERT((int)kACMP_OffsetLevel1 == (int)COMP_MCUX_ACMP_OFFSET_MODE_LEVEL1); +#endif + +#if COMP_MCUX_ACMP_HAS_HYSTERESIS +BUILD_ASSERT((int)kACMP_HysteresisLevel0 == (int)COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL0); +BUILD_ASSERT((int)kACMP_HysteresisLevel1 == (int)COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL1); +BUILD_ASSERT((int)kACMP_HysteresisLevel2 == (int)COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL2); +BUILD_ASSERT((int)kACMP_HysteresisLevel3 == (int)COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL3); +#endif + +BUILD_ASSERT((int)kACMP_VrefSourceVin1 == (int)COMP_MCUX_ACMP_DAC_VREF_SOURCE_VIN1); +BUILD_ASSERT((int)kACMP_VrefSourceVin2 == (int)COMP_MCUX_ACMP_DAC_VREF_SOURCE_VIN2); + +#if MCUX_ACMP_HAS_INPSEL || MCUX_ACMP_HAS_INNSEL +BUILD_ASSERT((int)kACMP_PortInputFromDAC == (int)COMP_MCUX_ACMP_PORT_INPUT_DAC); +BUILD_ASSERT((int)kACMP_PortInputFromMux == (int)COMP_MCUX_ACMP_PORT_INPUT_MUX); +#endif + +#if COMP_MCUX_ACMP_HAS_DISCRETE_MODE +BUILD_ASSERT((int)kACMP_DiscreteClockSlow == (int)COMP_MCUX_ACMP_DM_CLOCK_SLOW); +BUILD_ASSERT((int)kACMP_DiscreteClockFast == (int)COMP_MCUX_ACMP_DM_CLOCK_FAST); + +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs1T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T1); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs2T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T2); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs4T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T4); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs8T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T8); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs16T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T16); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs32T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T32); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs64T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T64); +BUILD_ASSERT((int)kACMP_DiscreteSampleTimeAs256T == (int)COMP_MCUX_ACMP_DM_SAMPLE_TIME_T256); + +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt0 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT0); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt1 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT1); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt2 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT2); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt3 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT3); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt4 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT4); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt5 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT5); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt6 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT6); +BUILD_ASSERT((int)kACMP_DiscretePhaseTimeAlt7 == (int)COMP_MCUX_ACMP_DM_PHASE_TIME_ALT7); +#endif + +struct mcux_acmp_data { + uint32_t interrupt_mask; + comparator_callback_t callback; + void *user_data; +}; + +#if CONFIG_PM_DEVICE +static bool mcux_acmp_is_resumed(const struct device *dev) +{ + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + return state == PM_DEVICE_STATE_ACTIVE; +} +#else +static bool mcux_acmp_is_resumed(const struct device *dev) +{ + ARG_UNUSED(dev); + return true; +} +#endif + +static int mcux_acmp_get_output(const struct device *dev) +{ + const struct mcux_acmp_config *config = dev->config; + uint32_t status; + + status = ACMP_GetStatusFlags(config->base); + return (status & kACMP_OutputAssertEventFlag) ? 1 : 0; +} + +static int mcux_acmp_set_trigger(const struct device *dev, + enum comparator_trigger trigger) +{ + const struct mcux_acmp_config *config = dev->config; + struct mcux_acmp_data *data = dev->data; + + ACMP_DisableInterrupts(config->base, UINT32_MAX); + + switch (trigger) { + case COMPARATOR_TRIGGER_NONE: + data->interrupt_mask = 0; + break; + + case COMPARATOR_TRIGGER_RISING_EDGE: + data->interrupt_mask = kACMP_OutputRisingInterruptEnable; + break; + + case COMPARATOR_TRIGGER_FALLING_EDGE: + data->interrupt_mask = kACMP_OutputFallingInterruptEnable; + break; + + case COMPARATOR_TRIGGER_BOTH_EDGES: + data->interrupt_mask = kACMP_OutputFallingInterruptEnable | + kACMP_OutputRisingInterruptEnable; + break; + } + + if (data->interrupt_mask && data->callback != NULL) { + ACMP_EnableInterrupts(config->base, data->interrupt_mask); + } + + return 0; +} + +static int mcux_acmp_set_trigger_callback(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + const struct mcux_acmp_config *config = dev->config; + struct mcux_acmp_data *data = dev->data; + + ACMP_DisableInterrupts(config->base, UINT32_MAX); + + data->callback = callback; + data->user_data = user_data; + + if (data->callback == NULL) { + return 0; + } + + if (data->interrupt_mask) { + ACMP_EnableInterrupts(config->base, data->interrupt_mask); + } + + return 0; +} + +static int mcux_acmp_trigger_is_pending(const struct device *dev) +{ + const struct mcux_acmp_config *config = dev->config; + struct mcux_acmp_data *data = dev->data; + uint32_t status_flags; + + status_flags = ACMP_GetStatusFlags(config->base); + ACMP_ClearStatusFlags(config->base, UINT32_MAX); + + if ((data->interrupt_mask & kACMP_OutputRisingInterruptEnable) && + (status_flags & kACMP_OutputRisingEventFlag)) { + return 1; + } + + if ((data->interrupt_mask & kACMP_OutputFallingInterruptEnable) && + (status_flags & kACMP_OutputFallingEventFlag)) { + return 1; + } + + return 0; +} + +static const struct comparator_driver_api mcux_acmp_comp_api = { + .get_output = mcux_acmp_get_output, + .set_trigger = mcux_acmp_set_trigger, + .set_trigger_callback = mcux_acmp_set_trigger_callback, + .trigger_is_pending = mcux_acmp_trigger_is_pending, +}; + +static void comp_mcux_acmp_init_mode_config(const struct device *dev, + const struct comp_mcux_acmp_mode_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + acmp_config_t acmp_config; + +#if COMP_MCUX_ACMP_HAS_OFFSET + acmp_config.offsetMode = (acmp_offset_mode_t)config->offset_mode; +#endif + +#if COMP_MCUX_ACMP_HAS_HYSTERESIS + acmp_config.hysteresisMode = (acmp_hysteresis_mode_t)config->hysteresis_mode; +#endif + + acmp_config.enableHighSpeed = config->enable_high_speed_mode; + acmp_config.enableInvertOutput = config->invert_output; + acmp_config.useUnfilteredOutput = config->use_unfiltered_output; + acmp_config.enablePinOut = config->enable_pin_output; + + ACMP_Init(dev_config->base, &acmp_config); +} + +int comp_mcux_acmp_set_mode_config(const struct device *dev, + const struct comp_mcux_acmp_mode_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + + comp_mcux_acmp_init_mode_config(dev, config); + + if (mcux_acmp_is_resumed(dev)) { + ACMP_Enable(dev_config->base, true); + } + + return 0; +} + +int comp_mcux_acmp_set_input_config(const struct device *dev, + const struct comp_mcux_acmp_input_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + acmp_channel_config_t acmp_channel_config; + +#if COMP_MCUX_ACMP_HAS_INPSEL + acmp_channel_config.positivePortInput = (acmp_port_input_t)config->positive_port_input; +#endif + + acmp_channel_config.plusMuxInput = (uint32_t)config->positive_mux_input; + +#if COMP_MCUX_ACMP_HAS_INNSEL + acmp_channel_config.negativePortInput = (acmp_port_input_t)config->negative_port_input; +#endif + + acmp_channel_config.minusMuxInput = (uint32_t)config->negative_mux_input; + + ACMP_SetChannelConfig(dev_config->base, &acmp_channel_config); + return 0; +} + +int comp_mcux_acmp_set_filter_config(const struct device *dev, + const struct comp_mcux_acmp_filter_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + acmp_filter_config_t acmp_filter_config; + + if (config->enable_sample && config->filter_count == 0) { + return -EINVAL; + } + + if (config->filter_count > 7) { + return -EINVAL; + } + + acmp_filter_config.enableSample = config->enable_sample; + acmp_filter_config.filterCount = config->filter_count; + acmp_filter_config.filterPeriod = config->filter_period; + + ACMP_SetFilterConfig(dev_config->base, &acmp_filter_config); + return 0; +} + +int comp_mcux_acmp_set_dac_config(const struct device *dev, + const struct comp_mcux_acmp_dac_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + acmp_dac_config_t acmp_dac_config; + + acmp_dac_config.referenceVoltageSource = + (acmp_reference_voltage_source_t)config->vref_source; + + acmp_dac_config.DACValue = config->value; + +#if COMP_MCUX_ACMP_HAS_DAC_OUT_ENABLE + acmp_dac_config.enableOutput = config->enable_output; +#endif + +#if COMP_MCUX_ACMP_HAS_DAC_WORK_MODE + acmp_dac_config.workMode = config->enable_high_speed_mode + ? kACMP_DACWorkHighSpeedMode + : kACMP_DACWorkLowSpeedMode; +#endif + + ACMP_SetDACConfig(dev_config->base, &acmp_dac_config); + return 0; +} + +#if COMP_MCUX_ACMP_HAS_DISCRETE_MODE +int comp_mcux_acmp_set_dm_config(const struct device *dev, + const struct comp_mcux_acmp_dm_config *config) +{ + const struct mcux_acmp_config *dev_config = dev->config; + acmp_discrete_mode_config_t acmp_dm_config; + + acmp_dm_config.enablePositiveChannelDiscreteMode = config->enable_positive_channel; + acmp_dm_config.enableNegativeChannelDiscreteMode = config->enable_negative_channel; + acmp_dm_config.enableResistorDivider = config->enable_resistor_divider; + acmp_dm_config.clockSource = (acmp_discrete_clock_source_t)config->clock_source; + acmp_dm_config.sampleTime = (acmp_discrete_sample_time_t)config->sample_time; + acmp_dm_config.phase1Time = (acmp_discrete_phase_time_t)config->phase1_time; + acmp_dm_config.phase2Time = (acmp_discrete_phase_time_t)config->phase2_time; + + ACMP_SetDiscreteModeConfig(dev_config->base, &acmp_dm_config); + return 0; +} +#endif + +#if COMP_MCUX_ACMP_HAS_WINDOW_MODE +int comp_mcux_acmp_set_window_mode(const struct device *dev, bool enable) +{ + const struct mcux_acmp_config *config = dev->config; + + ACMP_EnableWindowMode(config->base, enable); + return 0; +} +#endif + +static int mcux_acmp_pm_callback(const struct device *dev, enum pm_device_action action) +{ + const struct mcux_acmp_config *config = dev->config; + + if (action == PM_DEVICE_ACTION_RESUME) { + ACMP_Enable(config->base, true); + } + +#if CONFIG_PM_DEVICE + if (action == PM_DEVICE_ACTION_SUSPEND) { + ACMP_Enable(config->base, false); + } +#endif + + return 0; +} + +static void mcux_acmp_irq_handler(const struct device *dev) +{ + const struct mcux_acmp_config *config = dev->config; + struct mcux_acmp_data *data = dev->data; + + ACMP_ClearStatusFlags(config->base, UINT32_MAX); + + if (data->callback == NULL) { + return; + } + + data->callback(dev, data->user_data); +} + +static int mcux_acmp_init(const struct device *dev) +{ + const struct mcux_acmp_config *config = dev->config; + int ret; + + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret) { + LOG_ERR("failed to set %s", "pincfg"); + return ret; + } + + comp_mcux_acmp_init_mode_config(dev, &config->mode_config); + + ret = comp_mcux_acmp_set_input_config(dev, &config->input_config); + if (ret) { + LOG_ERR("failed to set %s", "input config"); + return ret; + } + + ret = comp_mcux_acmp_set_filter_config(dev, &config->filter_config); + if (ret) { + LOG_ERR("failed to set %s", "filter config"); + return ret; + } + + ret = comp_mcux_acmp_set_dac_config(dev, &config->dac_config); + if (ret) { + LOG_ERR("failed to set %s", "dac config"); + return ret; + } + +#if COMP_MCUX_ACMP_HAS_DISCRETE_MODE + ret = comp_mcux_acmp_set_dm_config(dev, &config->dm_config); + if (ret) { + LOG_ERR("failed to set %s", "discrete mode config"); + return ret; + } +#endif + +#if COMP_MCUX_ACMP_HAS_WINDOW_MODE + ret = comp_mcux_acmp_set_window_mode(dev, config->enable_window_mode); + if (ret) { + LOG_ERR("failed to set %s", "window mode"); + return ret; + } +#endif + + ACMP_DisableInterrupts(config->base, UINT32_MAX); + config->irq_init(); + + return pm_device_driver_init(dev, mcux_acmp_pm_callback); +} + +#define MCUX_ACMP_IRQ_HANDLER_SYM(inst) \ + _CONCAT(mcux_acmp_irq_init, inst) + +#define MCUX_ACMP_IRQ_HANDLER_DEFINE(inst) \ + static void MCUX_ACMP_IRQ_HANDLER_SYM(inst)(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), \ + DT_INST_IRQ(inst, priority), \ + mcux_acmp_irq_handler, \ + DEVICE_DT_INST_GET(inst), \ + 0); \ + \ + irq_enable(DT_INST_IRQN(inst)); \ + } + +#define MCUX_ACMP_DEVICE(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + static struct mcux_acmp_data _CONCAT(data, inst); \ + \ + MCUX_ACMP_IRQ_HANDLER_DEFINE(inst) \ + \ + static const struct mcux_acmp_config _CONCAT(config, inst) = { \ + .base = (CMP_Type *)DT_INST_REG_ADDR(inst), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .irq_init = MCUX_ACMP_IRQ_HANDLER_SYM(inst), \ + .mode_config = MCUX_ACMP_DT_INST_MODE_CONFIG_INIT(inst), \ + .input_config = MCUX_ACMP_DT_INST_INPUT_CONFIG_INIT(inst), \ + .filter_config = MCUX_ACMP_DT_INST_FILTER_CONFIG_INIT(inst), \ + .dac_config = MCUX_ACMP_DT_INST_DAC_CONFIG_INIT(inst), \ + IF_ENABLED(COMP_MCUX_ACMP_HAS_DISCRETE_MODE, \ + (.dm_config = MCUX_ACMP_DT_INST_DM_CONFIG_INIT(inst),)) \ + IF_ENABLED(COMP_MCUX_ACMP_HAS_WINDOW_MODE, \ + (.enable_window_mode = MCUX_ACMP_DT_INST_EN_WINDOW_MODE(inst),)) \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, mcux_acmp_pm_callback); \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + mcux_acmp_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &_CONCAT(data, inst), \ + &_CONCAT(config, inst), \ + POST_KERNEL, \ + CONFIG_COMPARATOR_INIT_PRIORITY, \ + &mcux_acmp_comp_api); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_ACMP_DEVICE) diff --git a/dts/bindings/comparator/nxp,kinetis-acmp.yaml b/dts/bindings/comparator/nxp,kinetis-acmp.yaml index 76ce24b5bba..21db936c2bf 100644 --- a/dts/bindings/comparator/nxp,kinetis-acmp.yaml +++ b/dts/bindings/comparator/nxp,kinetis-acmp.yaml @@ -2,7 +2,39 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -description: NXP Kinetis ACMP (Analog CoMParator) +description: | + NXP Kinetis ACMP (Analog CoMParator) + + The following example displays the minimum node layout: + + acmp0: acmp@deadbeef { + compatible = "nxp,kinetis-acmp"; + reg = <0xdeadbeef 0x1000>; + interrupts = <0 0>; + clocks = <&scg KINETIS_SCG_BUS_CLK>; + status = "disabled"; + }; + + Enabling the comparator node requires setting the minimum default + configuration of the comparator. This includes selecting the + positive and negative inputs, and routing them using pinctrl: + + &pinctrl { + acmp0_default: acmp0_default { + group0 { + ... + }; + }; + }; + + &acmp0 { + status = "okay"; + pinctrl-0 = <&acmp0_default>; + pinctrl-names = "default"; + + positive-mux-input = "IN0"; + negative-mux-input = "IN1"; + }; compatible: "nxp,kinetis-acmp" diff --git a/include/zephyr/drivers/comparator/mcux_acmp.h b/include/zephyr/drivers/comparator/mcux_acmp.h new file mode 100644 index 00000000000..3d06644f0e8 --- /dev/null +++ b/include/zephyr/drivers/comparator/mcux_acmp.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_COMP_MCUX_ACMP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_COMP_MCUX_ACMP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum comp_mcux_acmp_offset_mode { + COMP_MCUX_ACMP_OFFSET_MODE_LEVEL0 = 0, + COMP_MCUX_ACMP_OFFSET_MODE_LEVEL1, +}; + +enum comp_mcux_acmp_hysteresis_mode { + COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL0 = 0, + COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL1, + COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL2, + COMP_MCUX_ACMP_HYSTERESIS_MODE_LEVEL3, +}; + +struct comp_mcux_acmp_mode_config { + enum comp_mcux_acmp_offset_mode offset_mode; + enum comp_mcux_acmp_hysteresis_mode hysteresis_mode; + bool enable_high_speed_mode; + bool invert_output; + bool use_unfiltered_output; + bool enable_pin_output; +}; + +enum comp_mcux_acmp_mux_input { + COMP_MCUX_ACMP_MUX_INPUT_IN0 = 0, + COMP_MCUX_ACMP_MUX_INPUT_IN1, + COMP_MCUX_ACMP_MUX_INPUT_IN2, + COMP_MCUX_ACMP_MUX_INPUT_IN3, + COMP_MCUX_ACMP_MUX_INPUT_IN4, + COMP_MCUX_ACMP_MUX_INPUT_IN5, + COMP_MCUX_ACMP_MUX_INPUT_IN6, + COMP_MCUX_ACMP_MUX_INPUT_IN7, +}; + +enum comp_mcux_acmp_port_input { + COMP_MCUX_ACMP_PORT_INPUT_DAC = 0, + COMP_MCUX_ACMP_PORT_INPUT_MUX, +}; + +struct comp_mcux_acmp_input_config { + enum comp_mcux_acmp_mux_input positive_mux_input; + enum comp_mcux_acmp_mux_input negative_mux_input; + enum comp_mcux_acmp_port_input positive_port_input; + enum comp_mcux_acmp_port_input negative_port_input; +}; + +struct comp_mcux_acmp_filter_config { + bool enable_sample; + uint8_t filter_count; + uint8_t filter_period; +}; + +enum comp_mcux_acmp_dac_vref_source { + COMP_MCUX_ACMP_DAC_VREF_SOURCE_VIN1 = 0, + COMP_MCUX_ACMP_DAC_VREF_SOURCE_VIN2, +}; + +struct comp_mcux_acmp_dac_config { + enum comp_mcux_acmp_dac_vref_source vref_source; + uint8_t value; + bool enable_output; + bool enable_high_speed_mode; +}; + +enum comp_mcux_acmp_dm_clock { + COMP_MCUX_ACMP_DM_CLOCK_SLOW = 0, + COMP_MCUX_ACMP_DM_CLOCK_FAST, +}; + +enum comp_mcux_acmp_dm_sample_time { + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T1 = 0, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T2, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T4, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T8, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T16, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T32, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T64, + COMP_MCUX_ACMP_DM_SAMPLE_TIME_T256, +}; + +enum comp_mcux_acmp_dm_phase_time { + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT0 = 0, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT1, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT2, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT3, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT4, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT5, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT6, + COMP_MCUX_ACMP_DM_PHASE_TIME_ALT7, +}; + +struct comp_mcux_acmp_dm_config { + bool enable_positive_channel; + bool enable_negative_channel; + bool enable_resistor_divider; + enum comp_mcux_acmp_dm_clock clock_source; + enum comp_mcux_acmp_dm_sample_time sample_time; + enum comp_mcux_acmp_dm_phase_time phase1_time; + enum comp_mcux_acmp_dm_phase_time phase2_time; +}; + +int comp_mcux_acmp_set_mode_config(const struct device *dev, + const struct comp_mcux_acmp_mode_config *config); + +int comp_mcux_acmp_set_input_config(const struct device *dev, + const struct comp_mcux_acmp_input_config *config); + +int comp_mcux_acmp_set_filter_config(const struct device *dev, + const struct comp_mcux_acmp_filter_config *config); + +int comp_mcux_acmp_set_dac_config(const struct device *dev, + const struct comp_mcux_acmp_dac_config *config); + +int comp_mcux_acmp_set_dm_config(const struct device *dev, + const struct comp_mcux_acmp_dm_config *config); + +int comp_mcux_acmp_set_window_mode(const struct device *dev, bool enable); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_COMP_MCUX_ACMP_H_ */ From d0f1de24cc941fc0730686d9199f52aacff45374 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 5 Sep 2024 13:32:24 +0200 Subject: [PATCH 12/21] [nrf fromtree] tests: drivers: build_all: comparator: add mcux_acmp Add mcux_acmp device driver to build_all test suite. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 6ed855a53f8f911ba247f4d0c6414030a909df42) (cherry picked from commit ef7cbeeac9531ba315d9ef0744bdad974aa49bff) --- .../mcux_acmp/mimxrt1176_mux_dac.dts | 46 +++++++++++++++++++ .../mcux_acmp/mimxrt1176_mux_mux.dts | 26 +++++++++++ .../comparator/mcux_acmp/mke15z7_mux_dac.dts | 22 +++++++++ .../comparator/mcux_acmp/mke15z7_mux_mux.dts | 16 +++++++ .../comparator/mcux_acmp/mke15z7_pinctrl.dtsi | 20 ++++++++ .../build_all/comparator/testcase.yaml | 22 +++++++++ 6 files changed, 152 insertions(+) create mode 100644 tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_dac.dts create mode 100644 tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_mux.dts create mode 100644 tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_dac.dts create mode 100644 tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_mux.dts create mode 100644 tests/drivers/build_all/comparator/mcux_acmp/mke15z7_pinctrl.dtsi diff --git a/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_dac.dts b/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_dac.dts new file mode 100644 index 00000000000..86ee224d74c --- /dev/null +++ b/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_dac.dts @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + acmp1_default: acmp1_default { + group0 { + pinmux = <&iomuxc_gpio_ad_01_acmp1_in2>; + drive-strength = "high"; + bias-pull-up; + slew-rate = "fast"; + }; + }; +}; + +&acmp1 { + status = "okay"; + pinctrl-0 = <&acmp1_default>; + pinctrl-names = "default"; + + positive-mux-input = "IN2"; + positive-port-input = "MUX"; + negative-mux-input = "IN2"; + negative-port-input = "DAC"; + + dac-vref-source = "VIN1"; + dac-value = <128>; + dac-enable; + + offset-mode = "LEVEL0"; + hysteresis-mode = "LEVEL0"; + enable-high-speed-mode; + + filter-enable-sample; + filter-count = <4>; + filter-period = <32>; + + discrete-mode-enable-positive-channel; + discrete-mode-enable-resistor-divider; + discrete-mode-clock-source = "FAST"; + discrete-mode-sample-time = "T1"; + discrete-mode-phase1-time = "ALT4"; + discrete-mode-phase2-time = "ALT7"; +}; diff --git a/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_mux.dts b/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_mux.dts new file mode 100644 index 00000000000..a240e8ce4fb --- /dev/null +++ b/tests/drivers/build_all/comparator/mcux_acmp/mimxrt1176_mux_mux.dts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + acmp1_default: acmp1_default { + group0 { + pinmux = <&iomuxc_gpio_ad_00_acmp1_in1>, + <&iomuxc_gpio_ad_01_acmp1_in2>; + drive-strength = "high"; + bias-pull-up; + slew-rate = "fast"; + }; + }; +}; + +&acmp1 { + status = "okay"; + pinctrl-0 = <&acmp1_default>; + pinctrl-names = "default"; + + positive-mux-input = "IN1"; + negative-mux-input = "IN2"; +}; diff --git a/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_dac.dts b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_dac.dts new file mode 100644 index 00000000000..23f8bb7c4fd --- /dev/null +++ b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_dac.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mke15z7_pinctrl.dtsi" + +&cmp0 { + pinctrl-0 = <&cmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + positive-mux-input = "IN0"; + positive-port-input = "MUX"; + negative-mux-input = "IN0"; + negative-port-input = "DAC"; + + dac-vref-source = "VIN1"; + dac-value = <128>; + dac-enable; +}; diff --git a/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_mux.dts b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_mux.dts new file mode 100644 index 00000000000..61e0353d5db --- /dev/null +++ b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_mux_mux.dts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mke15z7_pinctrl.dtsi" + +&cmp0 { + pinctrl-0 = <&cmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + positive-mux-input = "IN0"; + negative-mux-input = "IN1"; +}; diff --git a/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_pinctrl.dtsi b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_pinctrl.dtsi new file mode 100644 index 00000000000..62bddf7b924 --- /dev/null +++ b/tests/drivers/build_all/comparator/mcux_acmp/mke15z7_pinctrl.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + cmp0_default: cmp0_default { + group0 { + pinmux = , + , + , + ; + + drive-strength = "high"; + }; + }; +}; diff --git a/tests/drivers/build_all/comparator/testcase.yaml b/tests/drivers/build_all/comparator/testcase.yaml index 8dbc9dfb32a..a0578daa9ff 100644 --- a/tests/drivers/build_all/comparator/testcase.yaml +++ b/tests/drivers/build_all/comparator/testcase.yaml @@ -66,3 +66,25 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf9280pdk/nrf9280/cpuapp + drivers.build_all.comparator.mcux_acmp.mimxrt1176_mux_dac: + extra_args: + - DTC_OVERLAY_FILE="mcux_acmp/mimxrt1176_mux_dac.dts" + platform_allow: + - mimxrt1170_evk/mimxrt1176/cm4 + - mimxrt1170_evk/mimxrt1176/cm7 + drivers.build_all.comparator.mcux_acmp.mimxrt1176_mux_mux: + extra_args: + - DTC_OVERLAY_FILE="mcux_acmp/mimxrt1176_mux_mux.dts" + platform_allow: + - mimxrt1170_evk/mimxrt1176/cm4 + - mimxrt1170_evk/mimxrt1176/cm7 + drivers.build_all.comparator.mcux_acmp.mke15z7_mux_dac: + extra_args: + - DTC_OVERLAY_FILE="mcux_acmp/mke15z7_mux_dac.dts" + platform_allow: + - frdm_ke15z + drivers.build_all.comparator.mcux_acmp.mke15z7_mux_mux: + extra_args: + - DTC_OVERLAY_FILE="mcux_acmp/mke15z7_mux_mux.dts" + platform_allow: + - frdm_ke15z From 8b41e78561c1748a1cae537998905d30b811cac3 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 1 Sep 2024 17:35:19 +0200 Subject: [PATCH 13/21] [nrf fromtree] drivers: comparator: add shell Add shell for comparator device drivers. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit b7648f89c460641b34dfd90101bf995d584e8c7e) (cherry picked from commit c12fade881c46ca0a081619350fc2d2563b4a66f) --- drivers/comparator/CMakeLists.txt | 1 + drivers/comparator/Kconfig | 1 + drivers/comparator/Kconfig.shell | 21 ++ drivers/comparator/comparator_shell.c | 279 ++++++++++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/comparator/Kconfig.shell create mode 100644 drivers/comparator/comparator_shell.c diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index b5fe633a333..f4378c76a77 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_MCUX_ACMP comparator_mcux_acmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_SHELL comparator_shell.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 871ee5d9ed6..f49ff182562 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -21,5 +21,6 @@ config COMPARATOR_INIT_PRIORITY rsource "Kconfig.mcux_acmp" rsource "Kconfig.nrf_comp" rsource "Kconfig.nrf_lpcomp" +rsource "Kconfig.shell" endif # COMPARATOR diff --git a/drivers/comparator/Kconfig.shell b/drivers/comparator/Kconfig.shell new file mode 100644 index 00000000000..de244619be3 --- /dev/null +++ b/drivers/comparator/Kconfig.shell @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_SHELL + bool "Comparator shell" + default y + depends on SHELL + help + Comparator device driver shell. + +if COMPARATOR_SHELL + +config COMPARATOR_SHELL_AWAIT_TRIGGER_DEFAULT_TIMEOUT + int "Default timeout for await_trigger command in seconds" + default 10 + +config COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT + int "Max timeout for await_trigger command in seconds" + default 60 + +endif # COMPARATOR_SHELL diff --git a/drivers/comparator/comparator_shell.c b/drivers/comparator/comparator_shell.c new file mode 100644 index 00000000000..2d747530871 --- /dev/null +++ b/drivers/comparator/comparator_shell.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#define AWAIT_TRIGGER_DEFAULT_TIMEOUT \ + CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_DEFAULT_TIMEOUT + +#define AWAIT_TRIGGER_MAX_TIMEOUT \ + CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT + +/* Mapped 1-1 to enum comparator_trigger */ +static const char *const trigger_lookup[] = { + "NONE", + "RISING_EDGE", + "FALLING_EDGE", + "BOTH_EDGES", +}; + +static K_SEM_DEFINE(triggered_sem, 0, 1); + +static int get_device_from_str(const struct shell *sh, + const char *dev_str, + const struct device **dev) +{ + *dev = device_get_binding(dev_str); + + if (*dev == NULL) { + shell_error(sh, "%s not %s", dev_str, "found"); + return -ENODEV; + } + + if (!device_is_ready(*dev)) { + shell_error(sh, "%s not %s", dev_str, "ready"); + return -ENODEV; + } + + return 0; +} + +static int cmd_get_output(const struct shell *sh, size_t argc, char **argv) +{ + int ret; + const char *dev_str; + const struct device *dev; + + ARG_UNUSED(argc); + + dev_str = argv[1]; + ret = get_device_from_str(sh, dev_str, &dev); + if (ret < 0) { + return ret; + } + + ret = comparator_get_output(dev); + if (ret < 0) { + shell_error(sh, "failed to %s %s", "get", "output"); + return -EIO; + } + + shell_print(sh, "%i", ret); + return 0; +} + +static int get_trigger_from_str(const struct shell *sh, + const char *trigger_str, + enum comparator_trigger *trigger) +{ + ARRAY_FOR_EACH(trigger_lookup, i) { + if (strcmp(trigger_lookup[i], trigger_str) == 0) { + *trigger = (enum comparator_trigger)i; + return 0; + } + } + + shell_error(sh, "%s not %s", trigger_str, "valid"); + return -EINVAL; +} + +static int cmd_set_trigger(const struct shell *sh, size_t argc, char **argv) +{ + const char *dev_str; + const char *trigger_str; + int ret; + const struct device *dev; + enum comparator_trigger trigger; + + ARG_UNUSED(argc); + + dev_str = argv[1]; + ret = get_device_from_str(sh, dev_str, &dev); + if (ret < 0) { + return ret; + } + + trigger_str = argv[2]; + ret = get_trigger_from_str(sh, trigger_str, &trigger); + if (ret < 0) { + return ret; + } + + ret = comparator_set_trigger(dev, trigger); + if (ret < 0) { + shell_error(sh, "failed to %s %s", "set", "trigger"); + return -EIO; + } + + return 0; +} + +static int get_timeout_from_str(const struct shell *sh, + const char *timeout_str, + k_timeout_t *timeout) +{ + long seconds; + char *end; + + seconds = strtol(timeout_str, &end, 10); + if ((*end != '\0') || + (seconds < 1) || + (seconds > AWAIT_TRIGGER_MAX_TIMEOUT)) { + shell_error(sh, "%s not %s", timeout_str, "valid"); + return -EINVAL; + } + + *timeout = K_SECONDS(seconds); + return 0; +} + +static void trigger_cb(const struct device *dev, void *user_data) +{ + ARG_UNUSED(dev); + ARG_UNUSED(user_data); + + k_sem_give(&triggered_sem); +} + +static int cmd_await_trigger(const struct shell *sh, size_t argc, char **argv) +{ + const char *dev_str; + const char *timeout_str; + int ret; + const struct device *dev; + k_timeout_t timeout; + + dev_str = argv[1]; + ret = get_device_from_str(sh, dev_str, &dev); + if (ret < 0) { + return ret; + } + + if (argc == 3) { + timeout_str = argv[2]; + ret = get_timeout_from_str(sh, timeout_str, &timeout); + if (ret < 0) { + return ret; + } + } else { + timeout = K_SECONDS(AWAIT_TRIGGER_DEFAULT_TIMEOUT); + } + + k_sem_reset(&triggered_sem); + + ret = comparator_set_trigger_callback(dev, trigger_cb, NULL); + if (ret < 0) { + shell_error(sh, "failed to %s %s", "set", "trigger callback"); + return -EIO; + } + + ret = k_sem_take(&triggered_sem, timeout); + if (ret == 0) { + shell_print(sh, "triggered"); + } else if (ret == -EAGAIN) { + shell_print(sh, "timed out"); + } else { + shell_error(sh, "internal error"); + } + + ret = comparator_set_trigger_callback(dev, NULL, NULL); + if (ret < 0) { + shell_error(sh, "failed to %s %s", "clear", "trigger callback"); + return -EIO; + } + + return 0; +} + +static int cmd_trigger_is_pending(const struct shell *sh, size_t argc, char **argv) +{ + int ret; + const char *dev_str; + const struct device *dev; + + ARG_UNUSED(argc); + + dev_str = argv[1]; + ret = get_device_from_str(sh, dev_str, &dev); + if (ret < 0) { + return ret; + } + + ret = comparator_trigger_is_pending(dev); + if (ret < 0) { + shell_error(sh, "failed to %s %s", "get", "trigger status"); + return -EIO; + } + + shell_print(sh, "%i", ret); + return 0; +} + +static void dsub_set_trigger_lookup_1(size_t idx, struct shell_static_entry *entry) +{ + entry->syntax = (idx < ARRAY_SIZE(trigger_lookup)) ? trigger_lookup[idx] : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + +SHELL_DYNAMIC_CMD_CREATE(dsub_set_trigger_1, dsub_set_trigger_lookup_1); + +static void dsub_set_trigger_lookup_0(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = dev != NULL ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = &dsub_set_trigger_1; +} + +SHELL_DYNAMIC_CMD_CREATE(dsub_set_trigger_0, dsub_set_trigger_lookup_0); + +static void dsub_device_lookup_0(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + +SHELL_DYNAMIC_CMD_CREATE(dsub_device_0, dsub_device_lookup_0); + +#define GET_OUTPUT_HELP \ + ("comp get_output ") + +#define SET_TRIGGER_HELP \ + ("comp set_trigger ") + +#define AWAIT_TRIGGER_HELP \ + ("comp await_trigger [timeout] (default " \ + STRINGIFY(AWAIT_TRIGGER_DEFAULT_TIMEOUT) \ + "s, max " \ + STRINGIFY(AWAIT_TRIGGER_MAX_TIMEOUT) \ + "s)") + +#define TRIGGER_PENDING_HELP \ + ("comp trigger_is_pending ") + +SHELL_STATIC_SUBCMD_SET_CREATE( + sub_comp, + SHELL_CMD_ARG(get_output, &dsub_device_0, GET_OUTPUT_HELP, cmd_get_output, 2, 0), + SHELL_CMD_ARG(set_trigger, &dsub_set_trigger_0, SET_TRIGGER_HELP, cmd_set_trigger, 3, 0), + SHELL_CMD_ARG(await_trigger, &dsub_device_0, AWAIT_TRIGGER_HELP, cmd_await_trigger, 2, 1), + SHELL_CMD_ARG(trigger_is_pending, &dsub_device_0, TRIGGER_PENDING_HELP, + cmd_trigger_is_pending, 2, 1), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(comp, &sub_comp, "Comparator device commands", NULL); From 731df043cf06c49886c7786496b9fc7f78bebfba Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 6 Sep 2024 10:51:31 +0200 Subject: [PATCH 14/21] [nrf fromtree] drivers: comparator: add fake comparator Add fake comparator driver and bindings for use with testing. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 2fbe105a473bf58747cf868bfb8c3b3daf7ab089) (cherry picked from commit 5a43ffeb705b70790625a7e83d08a69bc4e524f4) --- drivers/comparator/CMakeLists.txt | 1 + drivers/comparator/Kconfig | 1 + drivers/comparator/Kconfig.fake_comp | 8 +++ drivers/comparator/comparator_fake_comp.c | 65 +++++++++++++++++++ dts/bindings/comparator/zephyr,comp-fake.yaml | 8 +++ include/zephyr/drivers/comparator/fake_comp.h | 40 ++++++++++++ 6 files changed, 123 insertions(+) create mode 100644 drivers/comparator/Kconfig.fake_comp create mode 100644 drivers/comparator/comparator_fake_comp.c create mode 100644 dts/bindings/comparator/zephyr,comp-fake.yaml create mode 100644 include/zephyr/drivers/comparator/fake_comp.h diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index f4378c76a77..43462d64288 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/comparator.h) zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_FAKE_COMP comparator_fake_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_MCUX_ACMP comparator_mcux_acmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index f49ff182562..978adc03251 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -18,6 +18,7 @@ config COMPARATOR_INIT_PRIORITY help Comparator device driver initialization priority. +rsource "Kconfig.fake_comp" rsource "Kconfig.mcux_acmp" rsource "Kconfig.nrf_comp" rsource "Kconfig.nrf_lpcomp" diff --git a/drivers/comparator/Kconfig.fake_comp b/drivers/comparator/Kconfig.fake_comp new file mode 100644 index 00000000000..5fca8db1878 --- /dev/null +++ b/drivers/comparator/Kconfig.fake_comp @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_FAKE_COMP + bool "Fake comparator driver" + default y + depends on DT_HAS_ZEPHYR_FAKE_COMP_ENABLED + depends on ZTEST diff --git a/drivers/comparator/comparator_fake_comp.c b/drivers/comparator/comparator_fake_comp.c new file mode 100644 index 00000000000..85abbad2174 --- /dev/null +++ b/drivers/comparator/comparator_fake_comp.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#ifdef CONFIG_ZTEST +#include +#endif + +#define DT_DRV_COMPAT zephyr_fake_comp + +DEFINE_FAKE_VALUE_FUNC(int, + comp_fake_comp_get_output, + const struct device *); + +DEFINE_FAKE_VALUE_FUNC(int, + comp_fake_comp_set_trigger, + const struct device *, + enum comparator_trigger); + +DEFINE_FAKE_VALUE_FUNC(int, + comp_fake_comp_set_trigger_callback, + const struct device *, + comparator_callback_t, + void *); + +DEFINE_FAKE_VALUE_FUNC(int, + comp_fake_comp_trigger_is_pending, + const struct device *); + +static const struct comparator_driver_api fake_comp_api = { + .get_output = comp_fake_comp_get_output, + .set_trigger = comp_fake_comp_set_trigger, + .set_trigger_callback = comp_fake_comp_set_trigger_callback, + .trigger_is_pending = comp_fake_comp_trigger_is_pending, +}; + +#ifdef CONFIG_ZTEST +static void fake_comp_reset_rule_before(const struct ztest_unit_test *test, void *fixture) +{ + ARG_UNUSED(test); + ARG_UNUSED(fixture); + + RESET_FAKE(comp_fake_comp_get_output); + RESET_FAKE(comp_fake_comp_set_trigger); + RESET_FAKE(comp_fake_comp_set_trigger_callback); + RESET_FAKE(comp_fake_comp_trigger_is_pending); +} + +ZTEST_RULE(comp_fake_comp_reset_rule, fake_comp_reset_rule_before, NULL); +#endif + +DEVICE_DT_INST_DEFINE( + 0, + NULL, + NULL, + NULL, + NULL, + POST_KERNEL, + CONFIG_COMPARATOR_INIT_PRIORITY, + &fake_comp_api +); diff --git a/dts/bindings/comparator/zephyr,comp-fake.yaml b/dts/bindings/comparator/zephyr,comp-fake.yaml new file mode 100644 index 00000000000..ac344f4639c --- /dev/null +++ b/dts/bindings/comparator/zephyr,comp-fake.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Fake comparator device used as stub or mock for testing + +compatible: "zephyr,fake-comp" + +include: base.yaml diff --git a/include/zephyr/drivers/comparator/fake_comp.h b/include/zephyr/drivers/comparator/fake_comp.h new file mode 100644 index 00000000000..c24858c1997 --- /dev/null +++ b/include/zephyr/drivers/comparator/fake_comp.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_FAKE_H_ +#define ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_FAKE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DECLARE_FAKE_VALUE_FUNC(int, + comp_fake_comp_get_output, + const struct device *); + +DECLARE_FAKE_VALUE_FUNC(int, + comp_fake_comp_set_trigger, + const struct device *, + enum comparator_trigger); + +DECLARE_FAKE_VALUE_FUNC(int, + comp_fake_comp_set_trigger_callback, + const struct device *, + comparator_callback_t, + void *); + +DECLARE_FAKE_VALUE_FUNC(int, + comp_fake_comp_trigger_is_pending, + const struct device *); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_COMPARATOR_FAKE_H_ */ From fb99fd6193d0c3514c33b9ed8e8f39d293f51d16 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 15 Sep 2024 18:06:37 +0200 Subject: [PATCH 15/21] [nrf fromtree] tests: drivers: comparator: add shell test suite Add test suite for comparator device driver shell. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 4ff9886e48a31b79da35a4fbc465cfb5735984ce) (cherry picked from commit c99b9328fef98806c892541c6d0c7af6706e4899) --- tests/drivers/comparator/shell/CMakeLists.txt | 8 + tests/drivers/comparator/shell/app.overlay | 12 + tests/drivers/comparator/shell/prj.conf | 10 + tests/drivers/comparator/shell/src/test.c | 357 ++++++++++++++++++ tests/drivers/comparator/shell/testcase.yaml | 12 + 5 files changed, 399 insertions(+) create mode 100644 tests/drivers/comparator/shell/CMakeLists.txt create mode 100644 tests/drivers/comparator/shell/app.overlay create mode 100644 tests/drivers/comparator/shell/prj.conf create mode 100644 tests/drivers/comparator/shell/src/test.c create mode 100644 tests/drivers/comparator/shell/testcase.yaml diff --git a/tests/drivers/comparator/shell/CMakeLists.txt b/tests/drivers/comparator/shell/CMakeLists.txt new file mode 100644 index 00000000000..c2f34f71e68 --- /dev/null +++ b/tests/drivers/comparator/shell/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(comparator_shell) + +target_sources(app PRIVATE src/test.c) diff --git a/tests/drivers/comparator/shell/app.overlay b/tests/drivers/comparator/shell/app.overlay new file mode 100644 index 00000000000..3bb03b5a569 --- /dev/null +++ b/tests/drivers/comparator/shell/app.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + fake_comp: fake_comp { + compatible = "zephyr,fake-comp"; + status = "okay"; + }; +}; diff --git a/tests/drivers/comparator/shell/prj.conf b/tests/drivers/comparator/shell/prj.conf new file mode 100644 index 00000000000..a1eb4324cee --- /dev/null +++ b/tests/drivers/comparator/shell/prj.conf @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SHELL=y +CONFIG_SHELL_BACKEND_SERIAL=n +CONFIG_SHELL_VT100_COMMANDS=n +CONFIG_SHELL_BACKEND_DUMMY=y +CONFIG_COMPARATOR=y +CONFIG_COMPARATOR_SHELL=y +CONFIG_ZTEST=y diff --git a/tests/drivers/comparator/shell/src/test.c b/tests/drivers/comparator/shell/src/test.c new file mode 100644 index 00000000000..dacefc9311a --- /dev/null +++ b/tests/drivers/comparator/shell/src/test.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +DEFINE_FFF_GLOBALS; + +#define FAKE_COMP_NODE DT_NODELABEL(fake_comp) +#define FAKE_COMP_NAME DEVICE_DT_NAME(FAKE_COMP_NODE) + +#define TEST_TRIGGER_DELAY K_SECONDS(1) + +#define TEST_AWAIT_TRIGGER_TIMEOUT_BELOW_MIN_CMD \ + ("comp await_trigger " FAKE_COMP_NAME " 0") + +#define TEST_AWAIT_TRIGGER_TIMEOUT_ABOVE_MAX_CMD \ + ("comp await_trigger " FAKE_COMP_NAME " " \ + STRINGIFY(CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT + 1)) + +#define TEST_AWAIT_TRIGGER_TIMEOUT_BROKEN_CMD \ + ("comp await_trigger " FAKE_COMP_NAME " d") + +static const struct shell *test_sh; +static const struct device *test_dev = DEVICE_DT_GET(FAKE_COMP_NODE); +static comparator_callback_t test_callback; +static void *test_callback_user_data; +static struct k_spinlock test_callback_spinlock; +static struct k_work_delayable test_trigger_dwork; + +static int test_get_output_stub_1(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 1; +} + +static int test_get_output_stub_0(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +static int test_get_output_stub_eio(const struct device *dev) +{ + ARG_UNUSED(dev); + + return -EIO; +} + +static int test_set_trigger_stub_ok(const struct device *dev, enum comparator_trigger trigger) +{ + ARG_UNUSED(dev); + ARG_UNUSED(trigger); + + return 0; +} + +static int test_set_trigger_stub_eio(const struct device *dev, enum comparator_trigger trigger) +{ + ARG_UNUSED(dev); + ARG_UNUSED(trigger); + + return -EIO; +} + +static int test_set_trigger_callback_mock_0(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + ARG_UNUSED(dev); + + K_SPINLOCK(&test_callback_spinlock) { + test_callback = callback; + test_callback_user_data = user_data; + } + + return 0; +} + +static int test_set_trigger_callback_stub_0(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + ARG_UNUSED(dev); + ARG_UNUSED(callback); + ARG_UNUSED(user_data); + + return 0; +} + +static int test_set_trigger_callback_stub_eio(const struct device *dev, + comparator_callback_t callback, + void *user_data) +{ + ARG_UNUSED(dev); + ARG_UNUSED(callback); + ARG_UNUSED(user_data); + + return -EIO; +} + +static int test_trigger_is_pending_stub_1(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 1; +} + +static int test_trigger_is_pending_stub_0(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +static int test_trigger_is_pending_stub_eio(const struct device *dev) +{ + ARG_UNUSED(dev); + + return -EIO; +} + + +static void test_trigger_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + test_callback(test_dev, test_callback_user_data); +} + +static void test_schedule_trigger(void) +{ + k_work_schedule(&test_trigger_dwork, TEST_TRIGGER_DELAY); +} + +static void test_cancel_trigger(void) +{ + struct k_work_sync sync; + + k_work_cancel_delayable_sync(&test_trigger_dwork, &sync); +} + +static void *test_setup(void) +{ + k_work_init_delayable(&test_trigger_dwork, test_trigger_handler); + test_sh = shell_backend_dummy_get_ptr(); + WAIT_FOR(shell_ready(test_sh), 20000, k_msleep(1)); + zassert_true(shell_ready(test_sh), "timed out waiting for dummy shell backend"); + return NULL; +} + +static void test_after(void *f) +{ + ARG_UNUSED(f); + + test_cancel_trigger(); +} + +ZTEST(comparator_shell, test_get_output) +{ + int ret; + const char *out; + size_t out_size; + + shell_backend_dummy_clear_output(test_sh); + comp_fake_comp_get_output_fake.custom_fake = test_get_output_stub_1; + ret = shell_execute_cmd(test_sh, "comp get_output " FAKE_COMP_NAME); + zassert_ok(ret); + zassert_equal(comp_fake_comp_get_output_fake.call_count, 1); + zassert_equal(comp_fake_comp_get_output_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\n1\r\n"); + + comp_fake_comp_get_output_fake.custom_fake = test_get_output_stub_0; + ret = shell_execute_cmd(test_sh, "comp get_output " FAKE_COMP_NAME); + zassert_ok(ret); + zassert_equal(comp_fake_comp_get_output_fake.call_count, 2); + zassert_equal(comp_fake_comp_get_output_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\n0\r\n"); + + comp_fake_comp_get_output_fake.custom_fake = test_get_output_stub_eio; + ret = shell_execute_cmd(test_sh, "comp get_output " FAKE_COMP_NAME); + zassert_equal(ret, -EIO); + zassert_equal(comp_fake_comp_get_output_fake.call_count, 3); + zassert_equal(comp_fake_comp_get_output_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\nfailed to get output\r\n"); +} + +ZTEST(comparator_shell, test_set_trigger) +{ + int ret; + const char *out; + size_t out_size; + + comp_fake_comp_set_trigger_fake.custom_fake = test_set_trigger_stub_ok; + + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " NONE"); + zassert_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 1); + zassert_equal(comp_fake_comp_set_trigger_fake.arg0_val, test_dev); + zassert_equal(comp_fake_comp_set_trigger_fake.arg1_val, COMPARATOR_TRIGGER_NONE); + + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " RISING_EDGE"); + zassert_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 2); + zassert_equal(comp_fake_comp_set_trigger_fake.arg0_val, test_dev); + zassert_equal(comp_fake_comp_set_trigger_fake.arg1_val, COMPARATOR_TRIGGER_RISING_EDGE); + + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " FALLING_EDGE"); + zassert_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 3); + zassert_equal(comp_fake_comp_set_trigger_fake.arg0_val, test_dev); + zassert_equal(comp_fake_comp_set_trigger_fake.arg1_val, COMPARATOR_TRIGGER_FALLING_EDGE); + + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " BOTH_EDGES"); + zassert_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 4); + zassert_equal(comp_fake_comp_set_trigger_fake.arg0_val, test_dev); + zassert_equal(comp_fake_comp_set_trigger_fake.arg1_val, COMPARATOR_TRIGGER_BOTH_EDGES); + + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " INVALID"); + zassert_equal(ret, -EINVAL); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 4); + + comp_fake_comp_set_trigger_fake.custom_fake = test_set_trigger_stub_eio; + + shell_backend_dummy_clear_output(test_sh); + ret = shell_execute_cmd(test_sh, "comp set_trigger " FAKE_COMP_NAME " BOTH_EDGES"); + zassert_equal(ret, -EIO); + zassert_equal(comp_fake_comp_set_trigger_fake.call_count, 5); + zassert_equal(comp_fake_comp_set_trigger_fake.arg0_val, test_dev); + zassert_equal(comp_fake_comp_set_trigger_fake.arg1_val, COMPARATOR_TRIGGER_BOTH_EDGES); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\nfailed to set trigger\r\n"); +} + +ZTEST(comparator_shell, test_await_trigger_set_callback_fail) +{ + int ret; + const char *out; + size_t out_size; + + shell_backend_dummy_clear_output(test_sh); + comp_fake_comp_set_trigger_callback_fake.custom_fake = test_set_trigger_callback_stub_eio; + ret = shell_execute_cmd(test_sh, "comp await_trigger " FAKE_COMP_NAME); + zassert_ok(0); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 1); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.return_val, 0); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\nfailed to set trigger callback\r\n"); +} + +ZTEST(comparator_shell, test_await_trigger_timeout) +{ + int ret; + const char *out; + size_t out_size; + + shell_backend_dummy_clear_output(test_sh); + comp_fake_comp_set_trigger_callback_fake.custom_fake = test_set_trigger_callback_stub_0; + ret = shell_execute_cmd(test_sh, "comp await_trigger " FAKE_COMP_NAME); + zassert_ok(0); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 2); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.return_val_history[0], 0); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.return_val_history[1], 0); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\ntimed out\r\n"); +} + +ZTEST(comparator_shell, test_await_trigger_invalid_timeout_arg) +{ + int ret; + + ret = shell_execute_cmd(test_sh, TEST_AWAIT_TRIGGER_TIMEOUT_BELOW_MIN_CMD); + zassert_not_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 0); + + ret = shell_execute_cmd(test_sh, TEST_AWAIT_TRIGGER_TIMEOUT_ABOVE_MAX_CMD); + zassert_not_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 0); + + ret = shell_execute_cmd(test_sh, TEST_AWAIT_TRIGGER_TIMEOUT_BROKEN_CMD); + zassert_not_ok(ret); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 0); +} + +ZTEST(comparator_shell, test_await_trigger) +{ + int ret; + const char *out; + size_t out_size; + comparator_api_set_trigger_callback seq[2]; + + shell_backend_dummy_clear_output(test_sh); + seq[0] = test_set_trigger_callback_mock_0; + seq[1] = test_set_trigger_callback_stub_0; + comp_fake_comp_set_trigger_callback_fake.custom_fake_seq = seq; + comp_fake_comp_set_trigger_callback_fake.custom_fake_seq_len = ARRAY_SIZE(seq); + test_schedule_trigger(); + ret = shell_execute_cmd(test_sh, "comp await_trigger " FAKE_COMP_NAME); + zassert_ok(0); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.call_count, 2); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.arg0_history[0], test_dev); + zassert_not_equal(comp_fake_comp_set_trigger_callback_fake.arg1_history[0], NULL); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.return_val_history[0], 0); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.arg0_history[1], test_dev); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.arg1_history[1], NULL); + zassert_equal(comp_fake_comp_set_trigger_callback_fake.return_val_history[1], 0); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\ntriggered\r\n"); +} + +ZTEST(comparator_shell, test_trigger_is_pending) +{ + int ret; + const char *out; + size_t out_size; + + shell_backend_dummy_clear_output(test_sh); + comp_fake_comp_trigger_is_pending_fake.custom_fake = test_trigger_is_pending_stub_1; + ret = shell_execute_cmd(test_sh, "comp trigger_is_pending " FAKE_COMP_NAME); + zassert_ok(ret); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.call_count, 1); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\n1\r\n"); + + comp_fake_comp_trigger_is_pending_fake.custom_fake = test_trigger_is_pending_stub_0; + ret = shell_execute_cmd(test_sh, "comp trigger_is_pending " FAKE_COMP_NAME); + zassert_ok(ret); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.call_count, 2); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\n0\r\n"); + + comp_fake_comp_trigger_is_pending_fake.custom_fake = test_trigger_is_pending_stub_eio; + ret = shell_execute_cmd(test_sh, "comp trigger_is_pending " FAKE_COMP_NAME); + zassert_equal(ret, -EIO); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.call_count, 3); + zassert_equal(comp_fake_comp_trigger_is_pending_fake.arg0_val, test_dev); + out = shell_backend_dummy_get_output(test_sh, &out_size); + zassert_str_equal(out, "\r\nfailed to get trigger status\r\n"); +} + +ZTEST_SUITE(comparator_shell, NULL, test_setup, test_after, NULL, NULL); diff --git a/tests/drivers/comparator/shell/testcase.yaml b/tests/drivers/comparator/shell/testcase.yaml new file mode 100644 index 00000000000..9fa6249c833 --- /dev/null +++ b/tests/drivers/comparator/shell/testcase.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.comparator.shell: + integration_platforms: + - native_sim + - native_sim/native/64 + tags: + - drivers + - comparator + - shell From 9210340d9fba70593983db554c90111fb3ed7a33 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 22 Sep 2024 13:22:25 +0200 Subject: [PATCH 16/21] [nrf fromtree] docs: hardware: peripherals: add comparator docs Add documentation for the comparator peripheral and shell. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 183e58b19019bd6a83c4f2bb258db7452d17bd29) (cherry picked from commit 45db13890b8af5ae41beae4ec8afd4c3804ef0c5) --- doc/hardware/peripherals/comparator.rst | 69 +++++++++++++++++++++++++ doc/hardware/peripherals/index.rst | 1 + 2 files changed, 70 insertions(+) create mode 100644 doc/hardware/peripherals/comparator.rst diff --git a/doc/hardware/peripherals/comparator.rst b/doc/hardware/peripherals/comparator.rst new file mode 100644 index 00000000000..e0e63407661 --- /dev/null +++ b/doc/hardware/peripherals/comparator.rst @@ -0,0 +1,69 @@ +.. _comparator_api: + +Comparator +########## + +Overview +******** + +An analog comparator compares the voltages of two analog signals connected to its negative and +positive inputs. If the voltage at the positive input is higher than the negative input, the +comparator's output will be high, otherwise, it will be low. + +Comparators can typically set a trigger which triggers on output changes. This trigger can +either invoke a callback, or its status can be polled. + +Related configuration options: + +* :kconfig:option:`CONFIG_COMPARATOR` + +Configuration +************* + +Embedded comparators can typically be configured at runtime. When enabled, an initial +configuration must be provided using the devicetree. At runtime, comparators can have their +configuration updated using device driver specific APIs. The configuration will be applied +when the comparator is resumed. + +Power management +**************** + +Comparators are enabled using power management. When resumed, the comparator will actively +compare its inputs, producing an output and detecting edges. When suspended, the comparator +will be inactive. + +Comparator shell +**************** + +The comparator shell provides the ``comp`` command with a set of subcommands for the +:ref:`shell ` module. + +The ``comp`` shell command provides the following subcommands: + +* ``get_output`` See :c:func:`comparator_get_output` +* ``set_trigger`` See :c:func:`comparator_set_trigger` +* ``await_trigger`` Awaits trigger using the following flow: + * Set trigger callback using :c:func:`comparator_set_trigger_callback` + * Await callback or time out after default or optionally provided timeout + * Clear trigger callback using :c:func:`comparator_set_trigger_callback` +* ``trigger_is_pending`` See :c:func:`comparator_trigger_is_pending` + +Related configuration options: + +* :kconfig:option:`CONFIG_SHELL` +* :kconfig:option:`CONFIG_COMPARATOR_SHELL` +* :kconfig:option:`CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_DEFAULT_TIMEOUT` +* :kconfig:option:`CONFIG_COMPARATOR_SHELL_AWAIT_TRIGGER_MAX_TIMEOUT` + +.. note:: + The power management shell can optionally be enabled alongside the comparator shell. + + Related configuration options: + + * :kconfig:option:`CONFIG_PM_DEVICE` + * :kconfig:option:`CONFIG_PM_DEVICE_SHELL` + +API Reference +************* + +.. doxygengroup:: comparator_interface diff --git a/doc/hardware/peripherals/index.rst b/doc/hardware/peripherals/index.rst index e2574e75993..2a7405aced2 100644 --- a/doc/hardware/peripherals/index.rst +++ b/doc/hardware/peripherals/index.rst @@ -18,6 +18,7 @@ Peripherals clock_control.rst can/index.rst charger.rst + comparator.rst coredump.rst counter.rst dac.rst From c95e1302774f8ade2173790e1cc305ff78112dd3 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 22 Sep 2024 18:52:28 +0200 Subject: [PATCH 17/21] [nrf fromtree] doc: release notes: added comparator release notes Added comparator support to release notes for release 4.0 Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 43f88ca8e12596abcab2b33587c3aa8957b90235) (cherry picked from commit 55e96fa1f4c6d9b5db156773306853e261537825) --- doc/releases/release-notes-4.0.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/releases/release-notes-4.0.rst b/doc/releases/release-notes-4.0.rst index 70ed64dd770..85c2523ab00 100644 --- a/doc/releases/release-notes-4.0.rst +++ b/doc/releases/release-notes-4.0.rst @@ -145,6 +145,14 @@ Drivers and Sensors * Clock control +* Comparator + + * Introduced comparator device driver subsystem selected with :kconfig:option:`CONFIG_COMPARATOR` + * Introduced comparator shell commands selected with :kconfig:option:`CONFIG_COMPARATOR_SHELL` + * Added support for Nordic nRF COMP (:dtcompatible:`nordic,nrf-comp`) + * Added support for Nordic nRF LPCOMP (:dtcompatible:`nordic,nrf-lpcomp`) + * Added support for NXP Kinetis ACMP (:dtcompatible:`nxp,kinetis-acmp`) + * Counter * DAC From 797d2602d5cdacc4497b3ac94ae3f197262ab28e Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Sun, 22 Sep 2024 19:23:01 +0200 Subject: [PATCH 18/21] [nrf fromtree] MAINTAINERS: add entry for comparator drivers Add entry for comparator drivers Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit e40fa8914fade81b91c6ef4f1e618ca5d9adf444) (cherry picked from commit 82e1b01c4660be350baac668908c6c8cc66aa22f) --- MAINTAINERS.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index cc7cb9a1411..ad9c9bfde27 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1156,6 +1156,25 @@ Release Notes: tests: - drivers.clock +"Drivers: Comparator": + status: maintained + maintainers: + - bjarki-andreasen + files: + - drivers/comparator/ + - dts/bindings/comparator/ + - include/zephyr/drivers/comparator.h + - include/zephyr/drivers/comparator/ + - include/zephyr/drivers/comparator/ + - include/zephyr/dt-bindings/clock/ + - tests/drivers/build_all/comparator/ + - tests/drivers/comparator/ + - doc/hardware/peripherals/comparator.rst + labels: + - "area: Comparator" + tests: + - drivers.comparator + "Drivers: Console": status: odd fixes files: From 226487f7b94b822fa8cf067d296a2638dac1bb75 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 11 Oct 2024 23:20:37 +0200 Subject: [PATCH 19/21] [nrf fromtree] MAINTAINERS.yml: patch comparator drivers area The comparator drivers area contains the following incorrect area: files: - include/zephyr/dt-bindings/clock/ and contains the following duplicate area: files: - include/zephyr/drivers/comparator/ this commit removes them. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 1635d77c751e724dc1cdd710b23f47639dd3561b) (cherry picked from commit 54ceaf9699c646ae9f1fa5d8c1a4cae65e1228f4) --- MAINTAINERS.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index ad9c9bfde27..a77bbf643c0 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1165,8 +1165,6 @@ Release Notes: - dts/bindings/comparator/ - include/zephyr/drivers/comparator.h - include/zephyr/drivers/comparator/ - - include/zephyr/drivers/comparator/ - - include/zephyr/dt-bindings/clock/ - tests/drivers/build_all/comparator/ - tests/drivers/comparator/ - doc/hardware/peripherals/comparator.rst From 724183829b7cf9a6475640532754e19746075376 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 11 Oct 2024 15:06:05 +0200 Subject: [PATCH 20/21] [nrf fromtree] tests: drivers: comparator: add gpio_loopback test suite Add test suite which uses GPIO loopback to produce a "very low" and "very high" voltage at the positive input of the comparator using the output of a GPIO. The negative input is set to a voltage between the high and low output voltages of the GPIO using whichever internal reference is available to the comparator. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 3272db87a41b178f1a8943713f0874fd95f0a27b) (cherry picked from commit cd0d63d3dcd929e7caa59a950cc044c2db8e49ed) --- .../comparator/gpio_loopback/CMakeLists.txt | 8 ++ .../gpio_loopback/boards/frdm_ke15z.overlay | 50 ++++++++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 25 ++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 35 ++++++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 25 ++++ .../drivers/comparator/gpio_loopback/prj.conf | 6 + .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 16 +++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 16 +++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 16 +++ .../snippets/nrf_comp/snippet.yml | 15 +++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 12 ++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 12 ++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 12 ++ .../snippets/nrf_lpcomp/snippet.yml | 15 +++ .../comparator/gpio_loopback/src/test.c | 119 ++++++++++++++++++ .../comparator/gpio_loopback/testcase.yaml | 27 ++++ 16 files changed, 409 insertions(+) create mode 100644 tests/drivers/comparator/gpio_loopback/CMakeLists.txt create mode 100644 tests/drivers/comparator/gpio_loopback/boards/frdm_ke15z.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/prj.conf create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml create mode 100644 tests/drivers/comparator/gpio_loopback/src/test.c create mode 100644 tests/drivers/comparator/gpio_loopback/testcase.yaml diff --git a/tests/drivers/comparator/gpio_loopback/CMakeLists.txt b/tests/drivers/comparator/gpio_loopback/CMakeLists.txt new file mode 100644 index 00000000000..43c6821adab --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(comparator_gpio_loopback) + +target_sources(app PRIVATE src/test.c) diff --git a/tests/drivers/comparator/gpio_loopback/boards/frdm_ke15z.overlay b/tests/drivers/comparator/gpio_loopback/boards/frdm_ke15z.overlay new file mode 100644 index 00000000000..531275ceb63 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/frdm_ke15z.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * PTA1 looped back to PTA0 + */ + +/ { + aliases { + test-comp = &cmp0; + }; + + zephyr,user { + test-gpios = <&gpioa 1 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpioa { + status = "okay"; +}; + +&pinctrl { + cmp0_default: cmp0_default { + group0 { + pinmux = ; + drive-strength = "high"; + }; + }; +}; + +&cmp0 { + pinctrl-0 = <&cmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + positive-mux-input = "IN0"; + positive-port-input = "MUX"; + negative-mux-input = "IN0"; + negative-port-input = "DAC"; + + dac-vref-source = "VIN1"; + dac-value = <128>; + dac-enable; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..a837527e342 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* + * P0.05 looped back to P0.04 + */ + +/ { + aliases { + test-comp = ∁ + }; + + zephyr,user { + test-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio0{ + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..aa39ab60e9e --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* + * P1.03 looped back to P1.02 + */ + +/ { + aliases { + test-comp = ∁ + }; + + zephyr,user { + test-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio1 { + status = "okay"; +}; + +/* Temporary workaround to reserve P1.03 for cpuapp */ +&led1 { + gpios = < &gpio1 0x3 0x0 >; +}; + +/* Temporary workaround to reserve P1.02 for cpuapp */ +&led2 { + gpios = < &gpio1 0x2 0x0 >; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..768965e7c58 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* + * P1.10 looped back to P1.11 + */ + +/ { + aliases { + test-comp = ∁ + }; + + zephyr,user { + test-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/prj.conf b/tests/drivers/comparator/gpio_loopback/prj.conf new file mode 100644 index 00000000000..5ca57533d76 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/prj.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_GPIO=y +CONFIG_COMPARATOR=y diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..e11bdcd3173 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN0"; /* P0.04 */ + refsel = "VDD"; + sp-mode = "HIGH"; + th-up = <34>; + th-down = <30>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..f90c2051255 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN2"; /* P1.02 */ + refsel = "INT_1V2"; + sp-mode = "HIGH"; + th-up = <63>; + th-down = <59>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..3a7a8f0ef81 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN4"; /* P1.11 */ + refsel = "INT_1V2"; + sp-mode = "HIGH"; + th-up = <63>; + th-down = <59>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml new file mode 100644 index 00000000000..e030c0e5543 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml @@ -0,0 +1,15 @@ +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +name: gpio_loopback_nrf_comp + +boards: + nrf54h20dk/nrf54h20/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay + nrf54l15dk/nrf54l15/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay + nrf5340dk/nrf5340/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..d35a20dfc22 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN0"; /* P0.04 */ + refsel = "VDD_4_8"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..349cd7051f9 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN2"; /* P1.02 */ + refsel = "VDD_4_8"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..ebb652bdd87 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN4"; /* P1.11 */ + refsel = "VDD_4_8"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml new file mode 100644 index 00000000000..70ff2a7e314 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml @@ -0,0 +1,15 @@ +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +name: gpio_loopback_nrf_lpcomp + +boards: + nrf54h20dk/nrf54h20/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay + nrf54l15dk/nrf54l15/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay + nrf5340dk/nrf5340/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/src/test.c b/tests/drivers/comparator/gpio_loopback/src/test.c new file mode 100644 index 00000000000..930422b1a65 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/src/test.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +static const struct device *test_dev = DEVICE_DT_GET(DT_ALIAS(test_comp)); +static const struct gpio_dt_spec test_pin = GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), test_gpios); +static K_SEM_DEFINE(test_sem, 0, 1); + +static void test_callback(const struct device *dev, void *user_data) +{ + zassert_equal(&test_sem, user_data); + k_sem_give(&test_sem); +} + +static void *test_setup(void) +{ + zassert_ok(gpio_pin_configure_dt(&test_pin, GPIO_OUTPUT_INACTIVE)); + return NULL; +} + +static void test_before(void *f) +{ + ARG_UNUSED(f); + + k_sem_reset(&test_sem); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + zassert_ok(comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_NONE)); + zassert_ok(comparator_set_trigger_callback(test_dev, NULL, NULL)); + zassert_between_inclusive(comparator_trigger_is_pending(test_dev), 0, 1); +} + +ZTEST_SUITE(comparator_gpio_loopback, NULL, test_setup, test_before, NULL, NULL); + +ZTEST(comparator_gpio_loopback, test_get_output) +{ + zassert_equal(comparator_get_output(test_dev), 0); + k_msleep(1); + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_equal(comparator_get_output(test_dev), 1); + k_msleep(1); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + k_msleep(1); + zassert_equal(comparator_get_output(test_dev), 0); +} + +ZTEST(comparator_gpio_loopback, test_no_trigger_no_pending) +{ + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); +} + +ZTEST(comparator_gpio_loopback, test_trigger_rising_edge_pending) +{ + zassert_ok(comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_RISING_EDGE)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); +} + +ZTEST(comparator_gpio_loopback, test_trigger_falling_edge_pending) +{ + zassert_ok(comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_FALLING_EDGE)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); +} + +ZTEST(comparator_gpio_loopback, test_trigger_both_edges_pending) +{ + zassert_ok(comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_BOTH_EDGES)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); + zassert_ok(gpio_pin_set_dt(&test_pin, 0)); + k_msleep(1); + zassert_equal(comparator_trigger_is_pending(test_dev), 1); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); +} + +ZTEST(comparator_gpio_loopback, test_trigger_callback) +{ + zassert_ok(comparator_set_trigger_callback(test_dev, test_callback, &test_sem)); + k_msleep(1); + zassert_equal(k_sem_take(&test_sem, K_NO_WAIT), -EBUSY); + zassert_ok(comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_RISING_EDGE)); + k_msleep(1); + zassert_equal(k_sem_take(&test_sem, K_NO_WAIT), -EBUSY); + zassert_ok(gpio_pin_set_dt(&test_pin, 1)); + k_msleep(1); + zassert_ok(k_sem_take(&test_sem, K_NO_WAIT)); + zassert_equal(comparator_trigger_is_pending(test_dev), 0); +} diff --git a/tests/drivers/comparator/gpio_loopback/testcase.yaml b/tests/drivers/comparator/gpio_loopback/testcase.yaml new file mode 100644 index 00000000000..beb5cd39276 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/testcase.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +common: + harness_config: + fixture: gpio_loopback + tags: + - drivers + - comparator +tests: + drivers.comparator.gpio_loopback.mcux_acmp: + platform_allow: + - frdm_ke15z + drivers.comparator.gpio_loopback.nrf_comp: + extra_args: + - SNIPPET="gpio_loopback_nrf_comp" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf5340dk/nrf5340/cpuapp + drivers.comparator.gpio_loopback.nrf_lpcomp: + extra_args: + - SNIPPET="gpio_loopback_nrf_lpcomp" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf5340dk/nrf5340/cpuapp From 0b1c23bd03802465f13ced56c465623a30ed9fce Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 18 Oct 2024 12:28:56 +0200 Subject: [PATCH 21/21] [nrf fromtree] tests: drivers: comparator: shell: use platform_allow Change integration_platform -> platform_allow to not build the shell test suite for all supported boards. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/80049 Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 0502189729a1020aaa10c3be312872d1a684fb88) (cherry picked from commit 8a776b3bc2a927d819c623555bb50d85cd4c8c7d) --- tests/drivers/comparator/shell/testcase.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/comparator/shell/testcase.yaml b/tests/drivers/comparator/shell/testcase.yaml index 9fa6249c833..26d1fc169c3 100644 --- a/tests/drivers/comparator/shell/testcase.yaml +++ b/tests/drivers/comparator/shell/testcase.yaml @@ -3,7 +3,7 @@ tests: drivers.comparator.shell: - integration_platforms: + platform_allow: - native_sim - native_sim/native/64 tags: