Repository: zephyrproject-rtos/zephyr
Pull request #86536: drivers: comparator: Add Comparator support for Renesas RA devices
Author: login: khoa-nguyen-18
Labels: name: area: Process
name: area: Samples
description: Samples
name: manifest
name: area: Pinctrl
name: manifest-hal_renesas
name: platform: Renesas RA
description: Renesas Electronics Corporation, RA
name: area: Comparator
Created: 2025-03-03T04:11:32Z | Merged: 2025-03-13T06:22:00Z

- Support Comparator driver for the Renesas boards: `ek_ra8m1`, `ek_ra8d1`, `mck_ra8t1`.
- Add the `samples/boards/renesas/comparator` sample.


Diff:
diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml
index 9a4b1ef83e9b9..37d08a0a704ff 100644
--- a/MAINTAINERS.yml
+++ b/MAINTAINERS.yml
@@ -4068,6 +4068,7 @@ Renesas RA Platforms:
     - dts/arm/renesas/ra/
     - dts/bindings/*/*renesas,ra*
     - soc/renesas/ra/
+    - samples/boards/renesas/
   labels:
     - "platform: Renesas RA"
   description: >-
diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi
index 4ae1dcec244a2..3c39fd7072e5f 100644
--- a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi
+++ b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi
@@ -279,4 +279,51 @@
 			drive-strength = "high";
 		};
 	};
+
+	/omit-if-no-ref/ acmphs_ivref0: acmphs_ivref0 {
+		group1 {
+			/* IVREF0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 1)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_ivref1: acmphs_ivref1 {
+		group1 {
+			/* IVREF1 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 3)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp0: acmphs0_ivcmp0 {
+		group1 {
+			/* CH0 IVCMP0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 10)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp2: acmphs0_ivcmp2 {
+		group1 {
+			/* CH0 IVCMP2 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 4)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp3: acmphs0_ivcmp3 {
+		group1 {
+			/* CH0 IVCMP3 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 6)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_vcout: acmphs_vcout {
+		group1 {
+			/* VCOUT */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS_VCOUT, 2, 8)>;
+		};
+	};
 };
diff --git a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi
index cdb7b3f9c9337..21eafedf37105 100644
--- a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi
+++ b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi
@@ -156,4 +156,51 @@
 			drive-strength = "high";
 		};
 	};
+
+	/omit-if-no-ref/ acmphs_ivref0: acmphs_ivref0 {
+		group1 {
+			/* IVREF0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 1)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_ivref1: acmphs_ivref1 {
+		group1 {
+			/* IVREF1 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 3)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp0: acmphs0_ivcmp0 {
+		group1 {
+			/* CH0 IVCMP0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 10)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp2: acmphs0_ivcmp2 {
+		group1 {
+			/* CH0 IVCMP2 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 4)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp3: acmphs0_ivcmp3 {
+		group1 {
+			/* CH0 IVCMP3 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 6)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_vcout: acmphs_vcout {
+		group1 {
+			/* VCOUT */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS_VCOUT, 2, 8)>;
+		};
+	};
 };
diff --git a/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi b/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi
index 1ceb15c547e87..981903e69d459 100644
--- a/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi
+++ b/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi
@@ -113,4 +113,51 @@
 			drive-strength = "high";
 		};
 	};
+
+	/omit-if-no-ref/ acmphs_ivref0: acmphs_ivref0 {
+		group1 {
+			/* IVREF0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 1)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_ivref1: acmphs_ivref1 {
+		group1 {
+			/* IVREF1 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 3)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp0: acmphs0_ivcmp0 {
+		group1 {
+			/* CH0 IVCMP0 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 10)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp2: acmphs0_ivcmp2 {
+		group1 {
+			/* CH0 IVCMP2 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 4)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs0_ivcmp3: acmphs0_ivcmp3 {
+		group1 {
+			/* CH0 IVCMP3 */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS, 0, 6)>;
+			renesas,analog-enable;
+		};
+	};
+
+	/omit-if-no-ref/ acmphs_vcout: acmphs_vcout {
+		group1 {
+			/* VCOUT */
+			psels = <RA_PSEL(RA_PSEL_ACMPHS_VCOUT, 2, 8)>;
+		};
+	};
 };
diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt
index cbfa301d580f3..5d8ef05546165 100644
--- a/drivers/comparator/CMakeLists.txt
+++ b/drivers/comparator/CMakeLists.txt
@@ -12,3 +12,4 @@ 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)
+zephyr_library_sources_ifdef(CONFIG_COMPARATOR_RENESAS_RA comparator_renesas_ra.c)
diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig
index 79538a6cc2221..2cc02c2408510 100644
--- a/drivers/comparator/Kconfig
+++ b/drivers/comparator/Kconfig
@@ -24,5 +24,6 @@ rsource "Kconfig.mcux_acmp"
 rsource "Kconfig.nrf_comp"
 rsource "Kconfig.nrf_lpcomp"
 rsource "Kconfig.shell"
+rsource "Kconfig.renesas_ra"
 
 endif # COMPARATOR
diff --git a/drivers/comparator/Kconfig.renesas_ra b/drivers/comparator/Kconfig.renesas_ra
new file mode 100644
index 0000000000000..f66390a32ab55
--- /dev/null
+++ b/drivers/comparator/Kconfig.renesas_ra
@@ -0,0 +1,11 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config COMPARATOR_RENESAS_RA
+	bool "Renesas RA ACMPHS"
+	default y
+	depends on DT_HAS_RENESAS_RA_ACMPHS_ENABLED
+	select USE_RA_FSP_ACMPHS
+	select PINCTRL
+	help
+	  Enable Renesas RA ACMPHS Driver.
diff --git a/drivers/comparator/comparator_renesas_ra.c b/drivers/comparator/comparator_renesas_ra.c
new file mode 100644
index 0000000000000..6b0cb98249b6b
--- /dev/null
+++ b/drivers/comparator/comparator_renesas_ra.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT renesas_ra_acmphs
+
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/sys/atomic.h>
+#include <zephyr/kernel.h>
+#include <zephyr/irq.h>
+#include <soc.h>
+#include "r_acmphs.h"
+
+LOG_MODULE_REGISTER(acmphs_renesas_ra, CONFIG_COMPARATOR_LOG_LEVEL);
+
+#define ACMPHS_RENESAS_RA_FLAG_HS BIT(0)
+
+void comp_hs_int_isr(void);
+
+struct acmphs_renesas_ra_global_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_data {
+	const struct device *dev;
+	acmphs_instance_ctrl_t acmphs;
+	comparator_cfg_t fsp_config;
+	comparator_callback_t user_cb;
+	void *user_cb_data;
+	atomic_t flags;
+};
+
+static int acmphs_renesas_get_output(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_status_t status;
+	fsp_err_t fsp_err;
+
+	fsp_err = R_ACMPHS_StatusGet(&data->acmphs, &status);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	switch (status.state) {
+	case COMPARATOR_STATE_OUTPUT_LOW:
+		return 0;
+
+	case COMPARATOR_STATE_OUTPUT_HIGH:
+		return 1;
+
+	case COMPARATOR_STATE_OUTPUT_DISABLED:
+		LOG_ERR("Need to set trigger to open comparator first");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger(const struct device *dev, enum comparator_trigger trigger)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	switch (trigger) {
+	case COMPARATOR_TRIGGER_RISING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_RISING;
+		break;
+
+	case COMPARATOR_TRIGGER_FALLING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_FALLING;
+		break;
+
+	case COMPARATOR_TRIGGER_BOTH_EDGES:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_BOTH_EDGE;
+		break;
+
+	case COMPARATOR_TRIGGER_NONE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_NO_EDGE;
+		break;
+	}
+
+	data->acmphs.p_reg->CMPCTL |= (data->fsp_config.trigger << R_ACMPHS0_CMPCTL_CEG_Pos);
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger_callback(const struct device *dev,
+					       comparator_callback_t callback, void *user_data)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	data->user_cb = callback;
+	data->user_cb_data = user_data;
+
+	/* Enable interrupt */
+	data->acmphs.p_reg->CMPCTL |= (data->fsp_config.trigger << R_ACMPHS0_CMPCTL_CEG_Pos);
+
+	return 0;
+}
+
+static int acmphs_renesas_trigger_is_pending(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	if (data->flags & ACMPHS_RENESAS_RA_FLAG_HS) {
+		atomic_and(&data->flags, ~ACMPHS_RENESAS_RA_FLAG_HS);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void acmphs_renesas_ra_hs_isr(comparator_callback_args_t *fsp_args)
+{
+	const struct device *dev = fsp_args->p_context;
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_callback_t cb = data->user_cb;
+
+	if (cb != NULL) {
+		cb(dev, data->user_cb_data);
+		return;
+	}
+
+	atomic_or(&data->flags, ACMPHS_RENESAS_RA_FLAG_HS);
+}
+
+static int acmphs_renesas_ra_global_init(const struct device *dev)
+{
+	const struct acmphs_renesas_ra_global_config *cfg = dev->config;
+	int ret;
+
+	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
+	if (ret < 0) {
+		LOG_DBG("pin VCOUT initial failed");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_ra_init(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	const struct acmphs_renesas_ra_config *cfg = dev->config;
+	fsp_err_t fsp_err;
+	int ret;
+
+	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
+	if (ret < 0) {
+		LOG_DBG("pin default initial failed");
+		return ret;
+	}
+
+	data->fsp_config.p_context = dev;
+
+	fsp_err = R_ACMPHS_Open(&data->acmphs, &data->fsp_config);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	/*
+	 * Once the analog comparator is configurate, the program must wait
+	 * for the ACMPHS stabilization time (300ns enabling + 200ns input switching)
+	 * before using the comparator.
+	 */
+	k_usleep(5);
+
+	fsp_err = R_ACMPHS_OutputEnable(&data->acmphs);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static DEVICE_API(comparator, acmphs_renesas_ra_api) = {
+	.get_output = acmphs_renesas_get_output,
+	.set_trigger = acmphs_renesas_set_trigger,
+	.set_trigger_callback = acmphs_renesas_set_trigger_callback,
+	.trigger_is_pending = acmphs_renesas_trigger_is_pending,
+};
+
+PINCTRL_DT_DEFINE(DT_INST(0, renesas_ra_acmphs_global));
+
+static const struct acmphs_renesas_ra_global_config acmphs_renesas_ra_global_config = {
+	.pcfg = PINCTRL_DT_DEV_CONFIG_GET(DT_INST(0, renesas_ra_acmphs_global)),
+};
+
+DEVICE_DT_DEFINE(DT_COMPAT_GET_ANY_STATUS_OKAY(renesas_ra_acmphs_global),
+		 acmphs_renesas_ra_global_init, NULL, NULL, &acmphs_renesas_ra_global_config,
+		 PRE_KERNEL_2, CONFIG_COMPARATOR_INIT_PRIORITY, NULL)
+
+#define ACMPHS_RENESAS_RA_IRQ_INIT(idx)                                                            \
+	{                                                                                          \
+		R_ICU->IELSR_b[DT_INST_IRQ_BY_NAME(idx, hs, irq)].IELS =                           \
+			BSP_PRV_IELS_ENUM(CONCAT(EVENT_ACMPHS, DT_INST_PROP(idx, channel), _INT)); \
+                                                                                                   \
+		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, hs, irq),                                     \
+			    DT_INST_IRQ_BY_NAME(idx, hs, priority), comp_hs_int_isr,               \
+			    DEVICE_DT_INST_GET(idx), 0);                                           \
+                                                                                                   \
+		irq_enable(DT_INST_IRQ_BY_NAME(idx, hs, irq));                                     \
+	}
+
+#define FILTER_PARAMETER(idx)                                                                      \
+	COND_CODE_1(IS_EQ(DT_INST_PROP(idx, noise_filter), 1),                                     \
+	(COMPARATOR_FILTER_OFF), (UTIL_CAT(COMPARATOR_FILTER_, DT_INST_PROP(idx, noise_filter))))
+
+#define INVERT_PARAMETER(idx)                                                                      \
+	COND_CODE_1(DT_INST_PROP(idx, output_invert_polarity),                                     \
+	(COMPARATOR_POLARITY_INVERT_ON), (COMPARATOR_POLARITY_INVERT_OFF))
+
+#define PIN_OUTPUT_PARAMETER(idx)                                                                  \
+	COND_CODE_1(DT_INST_PROP(idx, pin_output_enable),                                          \
+	(COMPARATOR_PIN_OUTPUT_ON), (COMPARATOR_PIN_OUTPUT_OFF))
+
+#define IRQ_PARAMETER(idx)                                                                         \
+	COND_CODE_1(DT_INST_IRQ_HAS_NAME(idx, hs),                                                 \
+	(DT_INST_IRQ_BY_NAME(idx, hs, irq)), (FSP_INVALID_VECTOR))
+
+#define IPL_PARAMETER(idx)                                                                         \
+	COND_CODE_1(DT_INST_IRQ_HAS_NAME(idx, hs),                                                 \
+	(DT_INST_IRQ_BY_NAME(idx, hs, priority)), (BSP_IRQ_DISABLED))
+
+#define IRQ_INIT_MACRO_FUNCTION(idx)                                                               \
+	COND_CODE_1(DT_INST_IRQ_HAS_NAME(idx, hs), (ACMPHS_RENESAS_RA_IRQ_INIT(idx);), ())
+
+#define ACMPHS_RENESAS_RA_INIT(idx)                                                                \
+	PINCTRL_DT_INST_DEFINE(idx);                                                               \
+	static r_acmphs_extended_cfg_t g_acmphs_cfg_extend_##idx = {                               \
+		.input_voltage = UTIL_CAT(ACMPHS_INPUT_,                                           \
+					  DT_INST_STRING_UPPER_TOKEN(idx, compare_input_source)),  \
+		.reference_voltage =                                                               \
+			UTIL_CAT(ACMPHS_REFERENCE_,                                                \
+				 DT_INST_STRING_UPPER_TOKEN(idx, reference_input_source)),         \
+		.maximum_status_retries = 1024,                                                    \
+	};                                                                                         \
+	static const struct acmphs_renesas_ra_config acmphs_renesas_ra_config_##idx = {            \
+		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),                                       \
+	};                                                                                         \
+	static struct acmphs_renesas_ra_data acmphs_renesas_ra_data_##idx = {                      \
+		.dev = DEVICE_DT_INST_GET(idx),                                                    \
+		.fsp_config =                                                                      \
+			{                                                                          \
+				.channel = DT_INST_PROP(idx, channel),                             \
+				.mode = COMPARATOR_MODE_NORMAL,                                    \
+				.trigger = COMPARATOR_TRIGGER_NO_EDGE,                             \
+				.filter = FILTER_PARAMETER(idx),                                   \
+				.invert = INVERT_PARAMETER(idx),                                   \
+				.pin_output = PIN_OUTPUT_PARAMETER(idx),                           \
+				.p_extend = &g_acmphs_cfg_extend_##idx,                            \
+				.irq = IRQ_PARAMETER(idx),                                         \
+				.ipl = IPL_PARAMETER(idx),                                         \
+				.p_callback = acmphs_renesas_ra_hs_isr,                            \
+			},                                                                         \
+		.flags = 0,                                                                        \
+	};                                                                                         \
+	static int acmphs_renesas_ra_init##idx(const struct device *dev)                           \
+	{                                                                                          \
+		IRQ_INIT_MACRO_FUNCTION(idx)                                                       \
+		return acmphs_renesas_ra_init(dev);                                                \
+	}                                                                                          \
+                                                                                                   \
+	DEVICE_DT_INST_DEFINE(idx, acmphs_renesas_ra_init##idx, NULL,                              \
+			      &acmphs_renesas_ra_data_##idx, &acmphs_renesas_ra_config_##idx,      \
+			      POST_KERNEL, CONFIG_COMPARATOR_INIT_PRIORITY,                        \
+			      &acmphs_renesas_ra_api)
+
+DT_INST_FOREACH_STATUS_OKAY(ACMPHS_RENESAS_RA_INIT);
diff --git a/dts/arm/renesas/ra/ra8/ra8x1.dtsi b/dts/arm/renesas/ra/ra8/ra8x1.dtsi
index db33dd8892455..613947f3c612c 100644
--- a/dts/arm/renesas/ra/ra8/ra8x1.dtsi
+++ b/dts/arm/renesas/ra/ra8/ra8x1.dtsi
@@ -786,6 +786,24 @@
 				status = "disabled";
 			};
 		};
+
+		acmphs_global: acmphs_global@40236000 {
+			compatible = "renesas,ra-acmphs-global";
+			reg = <0x40236000 0x200>;
+			status = "disabled";
+
+			acmphs0: acmphs0 {
+				compatible = "renesas,ra-acmphs";
+				channel = <0>;
+				status = "disabled";
+			};
+
+			acmphs1: acmphs1 {
+				compatible = "renesas,ra-acmphs";
+				channel = <1>;
+				status = "disabled";
+			};
+		};
 	};
 
 	usbfs_phy: usbfs-phy {
diff --git a/dts/bindings/comparator/renesas,ra-acmphs-global.yaml b/dts/bindings/comparator/renesas,ra-acmphs-global.yaml
new file mode 100644
index 0000000000000..900d3b5259719
--- /dev/null
+++ b/dts/bindings/comparator/renesas,ra-acmphs-global.yaml
@@ -0,0 +1,49 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  Renesas RA ACMPHS (High-Speed Analog COMParator) Global
+
+  The following example displays the minimum node layout:
+
+    acmphs_global: acmphs_global@deadbeef {
+            compatible = "renesas,ra-acmphs-global";
+            reg = <0xdeadbeef 0x200>;
+            status = "disabled";
+
+            acmphs0: acmphs0 {
+                    ...
+            };
+    };
+
+  If the pin-output-enable is selected in the comparator controller node,
+  this global node needs to define the VCOUT pin to enable output on that pin.
+
+  Note: The VCOUT pinctrl for the comparator global node is already defined
+  on each board that supported comparator. Please check the board’s pinctrl
+  before defining it.
+
+    acmphs_vcout: acmphs_vcout {
+            group1 {
+                    /* VCOUT */
+                    psels = <RA_PSEL(RA_PSEL_ACMPHS_VCOUT, ..., ...)>;
+            };
+    };
+
+    &acmphs_global {
+            pinctrl-0 = <&acmphs_vcout>;
+            pinctrl-names = "default";
+            status = "okay";
+
+            acmphs0 {
+                    ...
+            };
+    };
+
+  Note: There is only one VCOUT shared across all comparator controller nodes.
+  Therefore, the VCOUT value is the logical OR of the output signals from all
+  comparator controllers that have pin-output-enable enabled.
+
+compatible: "renesas,ra-acmphs-global"
+
+include: [base.yaml, pinctrl-device.yaml]
diff --git a/dts/bindings/comparator/renesas,ra-acmphs.yaml b/dts/bindings/comparator/renesas,ra-acmphs.yaml
new file mode 100644
index 0000000000000..252d161bdec07
--- /dev/null
+++ b/dts/bindings/comparator/renesas,ra-acmphs.yaml
@@ -0,0 +1,119 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  Renesas RA ACMPHS (High-Speed Analog COMParator) Controller
+
+  The following example displays the minimum node layout:
+
+    acmphs_global: acmphs_global@deadbeef {
+            ...
+
+            acmphs0: acmphs0 {
+                    compatible = "renesas,ra-acmphs";
+                    channel = <0>;
+                    status = "disabled";
+            };
+    };
+
+  Enabling the comparator controller node requires setting the minimum
+  default configuration of the comparator. This includes selecting the
+  positive and negative inputs, and routing them using pinctrl:
+
+  Note: A set of pinctrl for the default comparator controller node is
+  already defined on each board that supported comparator. Please check
+  the board’s pinctrl before defining it.
+
+  &pinctrl {
+          acmphs_ivref0: acmphs_ivref0 {
+                  group1 {
+                          /* IVREF0 */
+                          psels = <RA_PSEL(RA_PSEL_ACMPHS, ..., ...)>;
+                          renesas,analog-enable;
+                  };
+          };
+
+          acmphs0_ivcmp0: acmphs0_ivcmp0 {
+                  group1 {
+                          /* CH0 IVCMP0 */
+                          psels = <RA_PSEL(RA_PSEL_ACMPHS, ..., ...)>;
+                          renesas,analog-enable;
+                  };
+          };
+  };
+
+  &acmphs_global {
+          status = "okay";
+
+          acmphs0 {
+                  pinctrl-0 = <&acmphs_ivref0 &acmphs0_ivcmp0>;
+                  pinctrl-names = "default";
+                  interrupts = <90 12>;
+                  interrupt-names = "hs";
+                  reference-input-source = "ivref0";
+                  compare-input-source = "ivcmp0";
+                  status = "okay";
+          };
+  };
+
+compatible: "renesas,ra-acmphs"
+
+include: [base.yaml, pinctrl-device.yaml]
+
+properties:
+  channel:
+    type: int
+    required: true
+
+  interrupts:
+    description: |
+      IRQ number and priority to use for interrupt Comparator:
+      - "hs": generated on valid edge detection from comparison result
+      Note: when this interrupts property is not defined, none of the trigger APIs
+            can be used (set_trigger, set_trigger_callback, trigger_is_pending).
+
+  reference-input-source:
+    type: string
+    required: true
+    enum:
+      - "ivref0"
+      - "ivref1"
+      - "ivref2"
+      - "ivref3"
+    description: |
+      Select the Analog reference voltage source.
+      Note: ivref2 is connected to Vref
+            ivref3 is connected to DA0 (DAC)
+            If either of these is selected, there is no need to configure pinsel for pinctrl.
+
+  compare-input-source:
+    type: string
+    required: true
+    enum:
+      - "ivcmp0"
+      - "ivcmp1"
+      - "ivcmp2"
+      - "ivcmp3"
+    description: |
+      Select the Analog compare voltage source.
+      Note: ivcmp1 is connected to DA0 (DAC)
+            If ivcmp1 is selected, there is no need to configure pinsel for pinctrl.
+
+  noise-filter:
+    type: int
+    enum: [1, 8, 16, 32]
+    default: 32
+    description: |
+      Select the PCLK divisor for the hardware digital debounce filter.
+      Larger divisors provide a longer debounce and take longer for the output to update.
+
+  output-invert-polarity:
+    type: boolean
+    description: |
+      When enabled comparator output is inverted.
+
+  pin-output-enable:
+    type: boolean
+    description: |
+      Turn this on to enable the CMPOUTn signal for this channel.
+      The CMPOUTn signal for each channel is OR'd together and the result is output to VCOUT.
diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h
index 42b095a3d077e..cbb3dac6ffdc4 100644
--- a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h
+++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h
@@ -16,6 +16,7 @@
 #define RA_PSEL_HIZ_JTAG_SWD 0x0
 #define RA_PSEL_ADC          0x0
 #define RA_PSEL_DAC          0x0
+#define RA_PSEL_ACMPHS       0x0
 #define RA_PSEL_AGT          0x1
 #define RA_PSEL_GPT0         0x2
 #define RA_PSEL_GPT1         0x3
@@ -32,6 +33,7 @@
 #define RA_PSEL_SPI          0x6
 #define RA_PSEL_I2C          0x7
 #define RA_PSEL_CLKOUT_RTC   0x9
+#define RA_PSEL_ACMPHS_VCOUT 0x9
 #define RA_PSEL_CAC_ADC      0xa
 #define RA_PSEL_CAC_DAC      0xa
 #define RA_PSEL_BUS          0xb
diff --git a/modules/Kconfig.renesas_fsp b/modules/Kconfig.renesas_fsp
index bf3bf15789578..11bb37b404135 100644
--- a/modules/Kconfig.renesas_fsp
+++ b/modules/Kconfig.renesas_fsp
@@ -154,6 +154,11 @@ config USE_RA_FSP_DAC
 	help
 	  Enable RA FSP DAC driver
 
+config USE_RA_FSP_ACMPHS
+	bool
+	help
+	  Enable RA FSP ACMPHS driver
+
 endif # HAS_RENESAS_RA_FSP
 
 if HAS_RENESAS_RZ_FSP
diff --git a/samples/boards/renesas/comparator/CMakeLists.txt b/samples/boards/renesas/comparator/CMakeLists.txt
new file mode 100644
index 0000000000000..3fffa20e3ffcb
--- /dev/null
+++ b/samples/boards/renesas/comparator/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+cmake_minimum_required(VERSION 3.20.0)
+find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
+project(renesas_comparator)
+
+FILE(GLOB app_sources src/*.c)
+target_sources(app PRIVATE ${app_sources})
diff --git a/samples/boards/renesas/comparator/Kconfig b/samples/boards/renesas/comparator/Kconfig
new file mode 100644
index 0000000000000..97b44b8c88696
--- /dev/null
+++ b/samples/boards/renesas/comparator/Kconfig
@@ -0,0 +1,13 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+mainmenu "Comparator sample additional options"
+
+source "Kconfig.zephyr"
+
+ZEPHYR_USER := zephyr,user
+
+config DAC_REFERENCE_SOURCE
+	bool
+	select DAC
+	default y if $(dt_node_has_prop,/$(ZEPHYR_USER),vref-dac)
diff --git a/samples/boards/renesas/comparator/README.rst b/samples/boards/renesas/comparator/README.rst
new file mode 100644
index 0000000000000..d9fefcf422259
--- /dev/null
+++ b/samples/boards/renesas/comparator/README.rst
@@ -0,0 +1,48 @@
+.. zephyr:code-sample:: renesas_comparator
+   :name: Renesas comparator
+
+   Monitor the output of comparator.
+
+Overview
+********
+
+A sample that help to monitor the output of comparator.
+
+Hardware Setup
+**************
+
+* The IVREF is connected to the internal output of DA0 (DAC module).
+  By default, DA0 is set to ~1.75V (half of the full-scale voltage).
+
+* For IVCOMP, the user can connect the IVCMP3 input to either:
+
+   * Case 1: IVCMP3 with SW0 (button on board, on ek_ra8m1 is P600).
+   * Case 2: IVCMP3 with external voltage for comparison.
+
+Building and Running
+********************
+
+This application can be built and executed on RA boards as follows:
+
+.. zephyr-app-commands::
+   :zephyr-app: samples/boards/renesas/comparator
+   :board: ek_ra8m1
+   :goals: build flash
+   :compact:
+
+The comparator's output controls LED0:
+
+   * If the comparator output is HIGH, LED0 turns on.
+   * If the comparator output is LOW, LED0 turns off.
+
+   Example case:
+
+   * Case 1: IVCMP3 connected to SW0 (Pull up)
+
+      * SW0 not pressed --> Comparator output HIGH --> LED0 on
+      * SW0 pressed --> Comparator output LOW --> LED0 off
+
+   * Case 2: IVCMP3 connected to another reference voltage
+
+      * IVCMP3 HIGH --> Comparator output HIGH --> LED0 on
+      * IVCMP3 LOW --> Comparator output LOW --> LED0 off
diff --git a/samples/boards/renesas/comparator/boards/ek_ra8d1.overlay b/samples/boards/renesas/comparator/boards/ek_ra8d1.overlay
new file mode 100644
index 0000000000000..ea9bcf5b4870b
--- /dev/null
+++ b/samples/boards/renesas/comparator/boards/ek_ra8d1.overlay
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		sample-comp = &acmphs0;
+	};
+
+	zephyr,user {
+		vref-dac = <&dac0>;
+	};
+};
+
+&acmphs_global {
+	status = "okay";
+
+	acmphs0 {
+		/*
+		 * Since ivref3 is internally routed from to DA0 (DAC),
+		 * there is no need to add pinsel of ivref3.
+		 */
+		pinctrl-0 = <&acmphs0_ivcmp3>;
+		pinctrl-names = "default";
+		interrupts = <90 12>;
+		interrupt-names = "hs";
+		reference-input-source = "ivref3";
+		compare-input-source = "ivcmp3";
+		status = "okay";
+	};
+};
diff --git a/samples/boards/renesas/comparator/boards/ek_ra8m1.overlay b/samples/boards/renesas/comparator/boards/ek_ra8m1.overlay
new file mode 100644
index 0000000000000..5d97c6005a2cb
--- /dev/null
+++ b/samples/boards/renesas/comparator/boards/ek_ra8m1.overlay
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/ {
+	aliases {
+		sample-comp = &acmphs0;
+	};
+
+	zephyr,user {
+		vref-dac = <&dac0>;
+	};
+};
+
+&acmphs_global {
+	status = "okay";
+
+	acmphs0 {
+		/*
+		 * Since ivref3 is internally routed from to DA0 (DAC),
+		 * there is no need to add pinsel of ivref3.
+		 */
+		pinctrl-0 = <&acmphs0_ivcmp3>;
+		pinctrl-names = "default";
+		interrupts = <90 12>;
+		interrupt-names = "hs";
+		reference-input-source = "ivref3";
+		compare-input-source = "ivcmp3";
+		status = "okay";
+	};
+};
diff --git a/samples/boards/renesas/comparator/prj.conf b/samples/boards/renesas/comparator/prj.conf
new file mode 100644
index 0000000000000..94d0c848f17ef
--- /dev/null
+++ b/samples/boards/renesas/comparator/prj.conf
@@ -0,0 +1,5 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+CONFIG_GPIO=y
+CONFIG_COMPARATOR=y
diff --git a/samples/boards/renesas/comparator/sample.yaml b/samples/boards/renesas/comparator/sample.yaml
new file mode 100644
index 0000000000000..133521066a75e
--- /dev/null
+++ b/samples/boards/renesas/comparator/sample.yaml
@@ -0,0 +1,9 @@
+sample:
+  name: Comparator
+tests:
+  sample.boards.renesas.comparator:
+    build_only: true
+    platform_allow:
+      - ek_ra8m1
+      - ek_ra8d1
+    tags: comparator
diff --git a/samples/boards/renesas/comparator/src/main.c b/samples/boards/renesas/comparator/src/main.c
new file mode 100644
index 0000000000000..053280da0e4a5
--- /dev/null
+++ b/samples/boards/renesas/comparator/src/main.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/kernel.h>
+#include <zephyr/device.h>
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/gpio.h>
+#include <zephyr/kernel.h>
+#include <zephyr/sys/util.h>
+#include <zephyr/sys/printk.h>
+#ifdef CONFIG_DAC_REFERENCE_SOURCE
+#include <zephyr/drivers/dac.h>
+#endif
+
+/*
+ * Get button configuration from the devicetree sw0 alias. This is mandatory.
+ */
+#define SW0_NODE DT_ALIAS(sw0)
+#if !DT_NODE_HAS_STATUS_OKAY(SW0_NODE)
+#error "Unsupported board: sw0 devicetree alias is not defined"
+#endif
+
+static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
+static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0});
+static const struct device *comp_dev = DEVICE_DT_GET(DT_ALIAS(sample_comp));
+
+#ifdef CONFIG_DAC_REFERENCE_SOURCE
+static const struct dac_channel_cfg dac_ch_cfg = {
+	.channel_id = 0,
+	.resolution = 12,
+	.buffered = true,
+};
+
+static const struct device *init_dac(void)
+{
+	int ret;
+	const struct device *const dac_dev = DEVICE_DT_GET(DT_PROP(DT_PATH(zephyr_user), vref_dac));
+
+	ret = device_is_ready(dac_dev);
+	if (ret != true) {
+		printk("DAC device is not ready\n");
+		return NULL;
+	}
+
+	ret = dac_channel_setup(dac_dev, &dac_ch_cfg);
+	if (ret != 0) {
+		printk("Setting up of the first channel failed with code %d\n", ret);
+		return NULL;
+	}
+
+	return dac_dev;
+}
+#endif
+
+static void comp_callback(const struct device *dev, void *user_data)
+{
+	int val = comparator_get_output(comp_dev);
+
+	gpio_pin_set_dt(&led, val);
+	printk("Comparator output value %d\n", val);
+}
+
+int main(void)
+{
+	int ret;
+#ifdef CONFIG_DAC_REFERENCE_SOURCE
+	const struct device *dac_dev = init_dac();
+
+	if (dac_dev == NULL) {
+		printk("Init_dac failed\n");
+		return 0;
+	}
+	/* write a value of half the full scale resolution */
+	ret = dac_write_value(dac_dev, dac_ch_cfg.channel_id, (1U << dac_ch_cfg.resolution) / 2);
+	if (ret != 0) {
+		printk("dac_write_value() failed with code %d", ret);
+		return 0;
+	}
+#endif
+
+	if (!gpio_is_ready_dt(&button)) {
+		printk("Error: button device %s is not ready\n", button.port->name);
+		return 0;
+	}
+
+	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
+	if (ret != 0) {
+		printk("Error %d: failed to configure %s pin %d\n", ret, button.port->name,
+		       button.pin);
+		return 0;
+	}
+
+	if (led.port && !gpio_is_ready_dt(&led)) {
+		printk("Error %d: LED device %s is not ready; ignoring it\n", ret, led.port->name);
+		led.port = NULL;
+	}
+
+	if (led.port) {
+		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
+		if (ret != 0) {
+			printk("Error %d: failed to configure LED device %s pin %d\n", ret,
+			       led.port->name, led.pin);
+			led.port = NULL;
+		}
+	}
+
+	comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
+	comparator_set_trigger_callback(comp_dev, comp_callback, NULL);
+
+	printk("Press the button\n");
+
+	return 0;
+}
diff --git a/tests/drivers/comparator/gpio_loopback/boards/ek_ra8d1.overlay b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8d1.overlay
new file mode 100644
index 0000000000000..dfae394d3d1f9
--- /dev/null
+++ b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8d1.overlay
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		test-comp = &acmphs0;
+	};
+
+	zephyr,user {
+		test-gpios = <&ioport6 0 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&acmphs_global {
+	status = "okay";
+
+	acmphs0 {
+		pinctrl-0 = <&acmphs_ivref0 &acmphs0_ivcmp0>;
+		pinctrl-names = "default";
+		interrupts = <90 12>;
+		interrupt-names = "hs";
+		reference-input-source = "ivref0";
+		compare-input-source = "ivcmp0";
+		noise-filter = <1>;
+		status = "okay";
+	};
+};
diff --git a/tests/drivers/comparator/gpio_loopback/boards/ek_ra8m1.overlay b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8m1.overlay
new file mode 100644
index 0000000000000..dfae394d3d1f9
--- /dev/null
+++ b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8m1.overlay
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		test-comp = &acmphs0;
+	};
+
+	zephyr,user {
+		test-gpios = <&ioport6 0 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&acmphs_global {
+	status = "okay";
+
+	acmphs0 {
+		pinctrl-0 = <&acmphs_ivref0 &acmphs0_ivcmp0>;
+		pinctrl-names = "default";
+		interrupts = <90 12>;
+		interrupt-names = "hs";
+		reference-input-source = "ivref0";
+		compare-input-source = "ivcmp0";
+		noise-filter = <1>;
+		status = "okay";
+	};
+};
diff --git a/tests/drivers/comparator/gpio_loopback/boards/mck_ra8t1.overlay b/tests/drivers/comparator/gpio_loopback/boards/mck_ra8t1.overlay
new file mode 100644
index 0000000000000..e933c71f364b6
--- /dev/null
+++ b/tests/drivers/comparator/gpio_loopback/boards/mck_ra8t1.overlay
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		test-comp = &acmphs0;
+	};
+
+	zephyr,user {
+		test-gpios = <&ioport6 6 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&acmphs_global {
+	status = "okay";
+
+	acmphs0 {
+		pinctrl-0 = <&acmphs_ivref0 &acmphs0_ivcmp0>;
+		pinctrl-names = "default";
+		interrupts = <90 12>;
+		interrupt-names = "hs";
+		reference-input-source = "ivref0";
+		compare-input-source = "ivcmp0";
+		noise-filter = <1>;
+		status = "okay";
+	};
+};
diff --git a/west.yml b/west.yml
index 687ddd3016917..2fcb693677da7 100644
--- a/west.yml
+++ b/west.yml
@@ -219,7 +219,7 @@ manifest:
         - hal
     - name: hal_renesas
       path: modules/hal/renesas
-      revision: 3204903bdc5eda6869a40363560a69369c8d0e22
+      revision: cc1323049d15647eb93b60cffe042a5b772ed0de
       groups:
         - hal
     - name: hal_rpi_pico


Reviews:
user: login: bjarki-andreasen
body: Initial impressions are good, do the RA devices not have fixed voltage references for the comparators? I would like to avoid the added complexity of introducing DACs to the gpio loopback test suite which is specifically for testing the comparator's behavior, for which a fixed voltage is sufficient :)
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T12:39:00Z
user: login: bjarki-andreasen
body: Only the unsafe set_trigger is blocking, other notes are just suggestions :)
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T10:02:32Z
user: login: khoa-nguyen-18
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T10:36:20Z
user: login: khoa-nguyen-18
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T10:38:43Z
user: login: khoa-nguyen-18
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T10:40:48Z
user: login: bjarki-andreasen
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T13:21:27Z
user: login: bjarki-andreasen
body: Nice work! :)
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T17:40:30Z
user: login: thaoluonguw
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T01:51:08Z

Review comments:
diff_hunk: @@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT renesas_ra_acmphs
+
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/kernel.h>
+#include <zephyr/irq.h>
+#include <soc.h>
+#include "r_acmphs.h"
+
+LOG_MODULE_REGISTER(acmphs_renesas_ra, CONFIG_COMPARATOR_LOG_LEVEL);
+
+void comp_hs_int_isr(void);
+
+struct acmphs_renesas_ra_global_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_data {
+	const struct device *dev;
+	acmphs_instance_ctrl_t acmphs;
+	comparator_cfg_t fsp_config;
+	comparator_callback_t user_cb;
+	void *user_cb_data;
+	bool is_pending;
+};
+
+static int acmphs_renesas_get_output(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_status_t status;
+	fsp_err_t fsp_err;
+
+	fsp_err = R_ACMPHS_StatusGet(&data->acmphs, &status);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	switch (status.state) {
+	case COMPARATOR_STATE_OUTPUT_LOW:
+		return 0;
+
+	case COMPARATOR_STATE_OUTPUT_HIGH:
+		return 1;
+
+	case COMPARATOR_STATE_OUTPUT_DISABLED:
+		LOG_ERR("Need to set trigger to open comparator first");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger(const struct device *dev, enum comparator_trigger trigger)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	switch (trigger) {
+	case COMPARATOR_TRIGGER_RISING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_RISING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_RISING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_FALLING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_FALLING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_FALLING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_BOTH_EDGES:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_BOTH_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_BOTH_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_NONE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_NO_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_NO_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger_callback(const struct device *dev,
+					       comparator_callback_t callback, void *user_data)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	data->user_cb = callback;
+	data->user_cb_data = user_data;
path: drivers/comparator/comparator_renesas_ra.c
user: login: bjarki-andreasen
body: These will need to be protected by a sem or disabling the trigger interrupt :) The callback and userdata are a pair, if one is changed before the other, and an interrupt/trigger occurs, the wrong data is passed to the wrong callback :)
created_at: 2025-03-05T09:50:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT renesas_ra_acmphs
+
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/kernel.h>
+#include <zephyr/irq.h>
+#include <soc.h>
+#include "r_acmphs.h"
+
+LOG_MODULE_REGISTER(acmphs_renesas_ra, CONFIG_COMPARATOR_LOG_LEVEL);
+
+void comp_hs_int_isr(void);
+
+struct acmphs_renesas_ra_global_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_data {
+	const struct device *dev;
+	acmphs_instance_ctrl_t acmphs;
+	comparator_cfg_t fsp_config;
+	comparator_callback_t user_cb;
+	void *user_cb_data;
+	bool is_pending;
+};
+
+static int acmphs_renesas_get_output(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_status_t status;
+	fsp_err_t fsp_err;
+
+	fsp_err = R_ACMPHS_StatusGet(&data->acmphs, &status);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	switch (status.state) {
+	case COMPARATOR_STATE_OUTPUT_LOW:
+		return 0;
+
+	case COMPARATOR_STATE_OUTPUT_HIGH:
+		return 1;
+
+	case COMPARATOR_STATE_OUTPUT_DISABLED:
+		LOG_ERR("Need to set trigger to open comparator first");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger(const struct device *dev, enum comparator_trigger trigger)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	switch (trigger) {
+	case COMPARATOR_TRIGGER_RISING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_RISING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_RISING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_FALLING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_FALLING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_FALLING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_BOTH_EDGES:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_BOTH_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_BOTH_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_NONE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_NO_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_NO_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger_callback(const struct device *dev,
+					       comparator_callback_t callback, void *user_data)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	data->user_cb = callback;
+	data->user_cb_data = user_data;
+
+	return 0;
+}
+
+static int acmphs_renesas_trigger_is_pending(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	if (data->is_pending) {
path: drivers/comparator/comparator_renesas_ra.c
user: login: bjarki-andreasen
body: You may need to use an atomic here if reading the bool is not guaranteed to be atomic for all platforms using this driver :)
created_at: 2025-03-05T09:51:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+description: Renesas RA Comparator Controller
path: dts/bindings/comparator/renesas,ra-acmphs.yaml
user: login: bjarki-andreasen
body: Please expand this description and the `acmphs-global` one with an example devicetree layout :) That will make it easier to understand that the acmphs is a child of the acmphs-global, and expand upon what the `channel` property means as well :)
created_at: 2025-03-05T10:01:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+description: Renesas RA Comparator Controller
path: dts/bindings/comparator/renesas,ra-acmphs.yaml
user: login: bjarki-andreasen
body: Something like https://github.com/zephyrproject-rtos/zephyr/blob/b136f6da555b27a2a985aa71a8947306d3d2b645/dts/bindings/comparator/nordic%2Cnrf-comp.yaml#L4-L17
created_at: 2025-03-05T10:01:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT renesas_ra_acmphs
+
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/kernel.h>
+#include <zephyr/irq.h>
+#include <soc.h>
+#include "r_acmphs.h"
+
+LOG_MODULE_REGISTER(acmphs_renesas_ra, CONFIG_COMPARATOR_LOG_LEVEL);
+
+void comp_hs_int_isr(void);
+
+struct acmphs_renesas_ra_global_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_data {
+	const struct device *dev;
+	acmphs_instance_ctrl_t acmphs;
+	comparator_cfg_t fsp_config;
+	comparator_callback_t user_cb;
+	void *user_cb_data;
+	bool is_pending;
+};
+
+static int acmphs_renesas_get_output(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_status_t status;
+	fsp_err_t fsp_err;
+
+	fsp_err = R_ACMPHS_StatusGet(&data->acmphs, &status);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	switch (status.state) {
+	case COMPARATOR_STATE_OUTPUT_LOW:
+		return 0;
+
+	case COMPARATOR_STATE_OUTPUT_HIGH:
+		return 1;
+
+	case COMPARATOR_STATE_OUTPUT_DISABLED:
+		LOG_ERR("Need to set trigger to open comparator first");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger(const struct device *dev, enum comparator_trigger trigger)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	switch (trigger) {
+	case COMPARATOR_TRIGGER_RISING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_RISING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_RISING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_FALLING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_FALLING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_FALLING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_BOTH_EDGES:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_BOTH_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_BOTH_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_NONE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_NO_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_NO_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger_callback(const struct device *dev,
+					       comparator_callback_t callback, void *user_data)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	data->user_cb = callback;
+	data->user_cb_data = user_data;
path: drivers/comparator/comparator_renesas_ra.c
user: login: khoa-nguyen-18
body: Thank you. I have updated it by disabling the interrupt.
created_at: 2025-03-07T10:36:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT renesas_ra_acmphs
+
+#include <zephyr/drivers/comparator.h>
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/kernel.h>
+#include <zephyr/irq.h>
+#include <soc.h>
+#include "r_acmphs.h"
+
+LOG_MODULE_REGISTER(acmphs_renesas_ra, CONFIG_COMPARATOR_LOG_LEVEL);
+
+void comp_hs_int_isr(void);
+
+struct acmphs_renesas_ra_global_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_config {
+	const struct pinctrl_dev_config *pcfg;
+};
+
+struct acmphs_renesas_ra_data {
+	const struct device *dev;
+	acmphs_instance_ctrl_t acmphs;
+	comparator_cfg_t fsp_config;
+	comparator_callback_t user_cb;
+	void *user_cb_data;
+	bool is_pending;
+};
+
+static int acmphs_renesas_get_output(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+	comparator_status_t status;
+	fsp_err_t fsp_err;
+
+	fsp_err = R_ACMPHS_StatusGet(&data->acmphs, &status);
+	if (FSP_SUCCESS != fsp_err) {
+		return -EIO;
+	}
+
+	switch (status.state) {
+	case COMPARATOR_STATE_OUTPUT_LOW:
+		return 0;
+
+	case COMPARATOR_STATE_OUTPUT_HIGH:
+		return 1;
+
+	case COMPARATOR_STATE_OUTPUT_DISABLED:
+		LOG_ERR("Need to set trigger to open comparator first");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger(const struct device *dev, enum comparator_trigger trigger)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	/* Disable interrupt */
+	data->acmphs.p_reg->CMPCTL &= ~R_ACMPHS0_CMPCTL_CEG_Msk;
+
+	switch (trigger) {
+	case COMPARATOR_TRIGGER_RISING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_RISING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_RISING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_FALLING_EDGE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_FALLING;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_FALLING << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_BOTH_EDGES:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_BOTH_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_BOTH_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+
+	case COMPARATOR_TRIGGER_NONE:
+		data->fsp_config.trigger = COMPARATOR_TRIGGER_NO_EDGE;
+		data->acmphs.p_reg->CMPCTL |=
+			(COMPARATOR_TRIGGER_NO_EDGE << R_ACMPHS0_CMPCTL_CEG_Pos);
+		break;
+	}
+
+	return 0;
+}
+
+static int acmphs_renesas_set_trigger_callback(const struct device *dev,
+					       comparator_callback_t callback, void *user_data)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	data->user_cb = callback;
+	data->user_cb_data = user_data;
+
+	return 0;
+}
+
+static int acmphs_renesas_trigger_is_pending(const struct device *dev)
+{
+	struct acmphs_renesas_ra_data *data = dev->data;
+
+	if (data->is_pending) {
path: drivers/comparator/comparator_renesas_ra.c
user: login: khoa-nguyen-18
body: Thank you for your suggestion! Using atomic makes sense to me, and I appreciate your recommendation. I have updated it.
created_at: 2025-03-07T10:38:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,66 @@
+# Copyright (c) 2025 Renesas Electronics Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+description: Renesas RA Comparator Controller
path: dts/bindings/comparator/renesas,ra-acmphs.yaml
user: login: khoa-nguyen-18
body: Thank you! In my opinion, expanding the description like this makes it clearer and more detailed. I appreciate it. I have updated the binding.
created_at: 2025-03-07T10:40:48Z
author_association: CONTRIBUTOR

PR comments:
user: login: zephyrbot
created_at: 2025-03-03T04:12:32Z
body: The following west manifest projects have changed revision in this Pull Request:

| Name | Old Revision | New Revision | Diff |
| ---- | ------------ | ------------ |------|
| hal_renesas | https://github.com/zephyrproject-rtos/hal_renesas/commit/3204903bdc5eda6869a40363560a69369c8d0e22 | https://github.com/zephyrproject-rtos/hal_renesas/commit/cc1323049d15647eb93b60cffe042a5b772ed0de (`main`)| [zephyrproject-rtos/hal_renesas@3204903b..cc132304](https://github.com/zephyrproject-rtos/hal_renesas/compare/3204903bdc5eda6869a40363560a69369c8d0e22..cc1323049d15647eb93b60cffe042a5b772ed0de) |

✅ **All manifest checks OK**

*Note: This message is automatically posted and updated by the Manifest GitHub Action.* 
author_association: NONE
user: login: khoa-nguyen-18
created_at: 2025-03-05T01:53:00Z
body: > Initial impressions are good, do the RA devices not have fixed voltage references for the comparators? I would like to avoid the added complexity of introducing DACs to the gpio loopback test suite which is specifically for testing the comparator's behavior, for which a fixed voltage is sufficient :)

Sorry for the late reply. RA devices offer multiple options for using fixed voltage references for the comparators. Besides these options, it also provides the ability to use a DAC as a voltage reference. This DAC feature is also available in the comparators of other vendors, such as STM32. I think allowing the DAC option to be selectable in the test could make it more flexible and familiar. However, if you feel it adds unnecessary complexity, I’m happy to remove it.
author_association: CONTRIBUTOR
user: login: bjarki-andreasen
created_at: 2025-03-05T05:51:19Z
body: > > Initial impressions are good, do the RA devices not have fixed voltage references for the comparators? I would like to avoid the added complexity of introducing DACs to the gpio loopback test suite which is specifically for testing the comparator's behavior, for which a fixed voltage is sufficient :)
> 
> Sorry for the late reply. RA devices offer multiple options for using fixed voltage references for the comparators. Besides these options, it also provides the ability to use a DAC as a voltage reference. This DAC feature is also available in the comparators of other vendors, such as STM32. I think allowing the DAC option to be selectable in the test could make it more flexible and familiar. However, if you feel it adds unnecessary complexity, I’m happy to remove it.

To be clear, I want the `gpio_loopback` test to just test the comparators adherence to the comparator API, in the simplest way possible :) The DAC is not needed for this :)

Testing the DAC as a variable input reference to the comp could be a test suite of its own, it allows us to test that the the comparator actually switches its output at specific voltage levels, rather than the "rail to rail" flip of the GPIO, this test suite would not need a gpio looped back at all :) 
author_association: CONTRIBUTOR
user: login: khoa-nguyen-18
created_at: 2025-03-05T08:04:33Z
body: > To be clear, I want the `gpio_loopback` test to just test the comparators adherence to the comparator API, in the simplest way possible :) The DAC is not needed for this :)
> 
> Testing the DAC as a variable input reference to the comp could be a test suite of its own, it allows us to test that the the comparator actually switches its output at specific voltage levels, rather than the "rail to rail" flip of the GPIO, this test suite would not need a gpio looped back at all :)

Many thanks for your explanation.
At first, I thought we needed to apply a middle voltage to the negative input so the comparator could determine the "rail-to-rail" voltage of the GPIO on the positive input. I used the DAC to provide this middle range.
However, after reading your comment, I realized that this is unnecessary.
I sincerely apologize for my misunderstanding. I'll remove this redundant DAC option. Thank you again!
author_association: CONTRIBUTOR
user: login: khoa-nguyen-18
created_at: 2025-03-05T09:32:13Z
body: Removed support for the DAC_REFERENCE_SOURCE option from the gpio_loopback test app. The PR is ready for review.
author_association: CONTRIBUTOR
user: login: khoa-nguyen-18
created_at: 2025-03-07T10:42:33Z
body: Sorry for combining the update and rebase together. It would be better to push the update first and then rebase.
author_association: CONTRIBUTOR
user: login: khoa-nguyen-18
created_at: 2025-03-12T02:18:56Z
body: - Rebase to solve conflicts in `samples/boards/renesas`.
- Update the revision of `hal_renesas` since the HAL PR has been merged.
author_association: CONTRIBUTOR
user: login: khoa-nguyen-18
created_at: 2025-03-12T04:43:08Z
body: The runner failed due to a Python package installation failure. I will rebase and push again to restart the check job.
author_association: CONTRIBUTOR