Files
zephyr/drivers/comparator/comparator_mchp_ac_g1.c
Arunprasath P 8b53661096 drivers: comparator: microchip: Add G1 Comparator Driver
Add G1 Comparator driver for Microchip Analog Comparator Peripherals.

Signed-off-by: Arunprasath P <arunprasath.p@microchip.com>
2025-11-14 10:28:22 +02:00

579 lines
21 KiB
C

/*
* Copyright (c) 2025 Microchip Technology Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <soc.h>
#include <zephyr/drivers/comparator.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>
#include <zephyr/irq.h>
#define DT_DRV_COMPAT microchip_ac_g1_comparator
LOG_MODULE_REGISTER(comparator_mchp_ac_g1, CONFIG_COMPARATOR_LOG_LEVEL);
/* clang-format off */
#define AC_REG (((const struct comparator_mchp_dev_config *)(dev)->config)->regs)
#define TIMEOUT_VALUE_US 1000
#define DELAY_US 2
#define COMPARATOR_INT_STATUS_NONE (-1)
/* clang-format on */
enum mchp_comp_pos_input {
MCHP_COMP_POS_INPUT_PIN0 = 0,
MCHP_COMP_POS_INPUT_PIN1,
MCHP_COMP_POS_INPUT_PIN2,
MCHP_COMP_POS_INPUT_PIN3,
MCHP_COMP_POS_INPUT_VSCALE,
};
enum mchp_comp_neg_input {
MCHP_COMP_NEG_INPUT_PIN0 = 0,
MCHP_COMP_NEG_INPUT_PIN1,
MCHP_COMP_NEG_INPUT_PIN2,
MCHP_COMP_NEG_INPUT_PIN3,
MCHP_COMP_NEG_INPUT_GND,
MCHP_COMP_NEG_INPUT_VSCALE,
MCHP_COMP_NEG_INPUT_BANDGAP,
MCHP_COMP_NEG_INPUT_DAC,
};
enum mchp_comp_output_mode {
MCHP_COMP_OUTPUT_OFF = 0,
MCHP_COMP_OUTPUT_ASYNC,
MCHP_COMP_OUTPUT_SYNC,
};
enum mchp_comp_filter {
MCHP_COMP_FILTER_OFF = 0,
MCHP_COMP_FILTER_MAJ3,
MCHP_COMP_FILTER_MAJ5,
};
enum mchp_comp_hysteresis {
MCHP_COMP_HYST_50MV = 0,
MCHP_COMP_HYST_100MV,
MCHP_COMP_HYST_150MV,
};
struct comparator_mchp_channel_cfg {
uint8_t channel_id;
enum mchp_comp_pos_input pos_input;
enum mchp_comp_neg_input neg_input;
enum mchp_comp_output_mode output_mode;
enum mchp_comp_filter filter_length;
enum mchp_comp_hysteresis hysteresis_level;
uint8_t vddana_scale_value;
bool single_shot_mode;
bool hysteresis_enable;
bool run_standby;
bool event_input_enable;
bool event_output_enable;
bool swap_inputs;
};
struct comparator_mchp_dev_data {
uint32_t interrupt_mask; /* Configured interrupt trigger type */
uint32_t interrupt_status; /* Last interrupt status or edge detected */
comparator_callback_t callback;
void *user_data;
};
struct comparator_mchp_clock {
const struct device *clock_dev;
clock_control_subsys_t mclk_sys;
clock_control_subsys_t gclk_sys;
};
struct comparator_mchp_dev_config {
ac_registers_t *regs;
const struct pinctrl_dev_config *pcfg;
struct comparator_mchp_clock comparator_clock;
void (*config_func)(const struct device *dev);
struct comparator_mchp_channel_cfg channel_config;
};
#if CONFIG_COMPARATOR_LOG_LEVEL_DBG
/* Print channel configuration */
static void comparator_print_channel_cfg(const struct comparator_mchp_channel_cfg *cfg)
{
static const char *const pos_input_names[] = {"PIN0", "PIN1", "PIN2", "PIN3", "VSCALE"};
static const char *const neg_input_names[] = {"PIN0", "PIN1", "PIN2", "PIN3",
"GND", "VSCALE", "BANDGAP", "DAC"};
static const char *const output_mode_names[] = {"OFF", "ASYNC", "SYNC"};
static const char *const filter_names[] = {"OFF", "MAJ3", "MAJ5"};
static const char *const hysteresis_names[] = {"HYST50", "HYST100", "HYST150"};
LOG_DBG("=== Comparator Channel Configuration ===");
LOG_DBG("Channel ID : %u", cfg->channel_id);
LOG_DBG("Positive Input : %s", pos_input_names[cfg->pos_input]);
LOG_DBG("Negative Input : %s", neg_input_names[cfg->neg_input]);
LOG_DBG("Output Mode : %s", output_mode_names[cfg->output_mode]);
LOG_DBG("Filter Length : %s", filter_names[cfg->filter_length]);
LOG_DBG("Hysteresis Enabled : %s", cfg->hysteresis_enable ? "Yes" : "No");
LOG_DBG("Hysteresis Level : %s", hysteresis_names[cfg->hysteresis_level]);
LOG_DBG("Single-shot Mode : %s", cfg->single_shot_mode ? "Yes" : "No");
LOG_DBG("Run in Standby : %s", cfg->run_standby ? "Yes" : "No");
LOG_DBG("Swap Inputs : %s", cfg->swap_inputs ? "Yes" : "No");
LOG_DBG("Event Input Enabled : %s", cfg->event_input_enable ? "Yes" : "No");
LOG_DBG("Event Output Enabled : %s", cfg->event_output_enable ? "Yes" : "No");
LOG_DBG("========================================");
}
/* Print all the comparator register values */
static void comparator_print_reg(const struct device *dev)
{
LOG_DBG("=============== Comparator Registers ===============");
LOG_DBG("%-20s: 0x%02x", "AC_CTRLA", AC_REG->AC_CTRLA);
LOG_DBG("%-20s: 0x%02x", "AC_CTRLB", AC_REG->AC_CTRLB);
LOG_DBG("%-20s: 0x%04x", "AC_EVCTRL", AC_REG->AC_EVCTRL);
LOG_DBG("%-20s: 0x%02x", "AC_INTENCLR", AC_REG->AC_INTENCLR);
LOG_DBG("%-20s: 0x%02x", "AC_INTENSET", AC_REG->AC_INTENSET);
LOG_DBG("%-20s: 0x%02x", "AC_INTFLAG", AC_REG->AC_INTFLAG);
LOG_DBG("%-20s: 0x%02x", "AC_STATUSA", AC_REG->AC_STATUSA);
LOG_DBG("%-20s: 0x%02x", "AC_STATUSB", AC_REG->AC_STATUSB);
LOG_DBG("%-20s: 0x%02x", "AC_DBGCTRL", AC_REG->AC_DBGCTRL);
LOG_DBG("%-20s: 0x%02x", "AC_WINCTRL", AC_REG->AC_WINCTRL);
LOG_DBG("%-20s: 0x%02x", "AC_SCALER[0]", AC_REG->AC_SCALER[0]);
LOG_DBG("%-20s: 0x%02x", "AC_SCALER[1]", AC_REG->AC_SCALER[1]);
LOG_DBG("%-20s: 0x%08x", "AC_COMPCTRL[0]", (uint32_t)AC_REG->AC_COMPCTRL[0]);
LOG_DBG("%-20s: 0x%08x", "AC_COMPCTRL[1]", (uint32_t)AC_REG->AC_COMPCTRL[1]);
LOG_DBG("%-20s: 0x%08x", "AC_SYNCBUSY", (uint32_t)AC_REG->AC_SYNCBUSY);
LOG_DBG("%-20s: 0x%04x", "AC_CALIB", AC_REG->AC_CALIB);
LOG_DBG("===================================================");
}
#endif /* CONFIG_COMPARATOR_LOG_LEVEL_DBG */
/* Wait for synchronization */
static void ac_wait_sync(ac_registers_t *ac_reg, uint32_t mask)
{
if (WAIT_FOR(((ac_reg->AC_SYNCBUSY & mask) != mask), TIMEOUT_VALUE_US,
k_busy_wait(DELAY_US)) == false) {
LOG_ERR("Timeout waiting for AC_SYNCBUSY bits to clear (mask=0x%X)", mask);
}
}
/* AC utility functions for enabling, configuring, and syncing the analog comparator */
static void ac_enable(ac_registers_t *ac_reg, bool enable)
{
if (enable == true) {
ac_reg->AC_CTRLA |= AC_CTRLA_ENABLE_Msk;
} else {
ac_reg->AC_CTRLA &= ~AC_CTRLA_ENABLE_Msk;
}
ac_wait_sync(ac_reg, AC_SYNCBUSY_ENABLE_Msk);
}
/* Enable a specific comparator channel and wait for sync */
static void ac_channel_enable(ac_registers_t *ac_reg, uint8_t channel_id)
{
ac_reg->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_ENABLE_Msk;
/* Only 2 possible values for channel_id: 0 or 1 */
if (channel_id == 0) {
ac_wait_sync(ac_reg, AC_SYNCBUSY_COMPCTRL0_Msk);
} else {
ac_wait_sync(ac_reg, AC_SYNCBUSY_COMPCTRL1_Msk);
}
}
/* Enable interrupt for the given comparator channel */
static inline void ac_enable_interrupt(ac_registers_t *ac_reg, uint8_t channel_id)
{
if (channel_id == 0) {
ac_reg->AC_INTENSET = AC_INTENSET_COMP0_Msk;
} else {
ac_reg->AC_INTENSET = AC_INTENSET_COMP1_Msk;
}
}
/* Disable interrupt for the given comparator channel */
static inline void ac_disable_interrupt(ac_registers_t *ac_reg, uint8_t channel_id)
{
if (channel_id == 0) {
ac_reg->AC_INTENCLR = AC_INTENCLR_COMP0_Msk;
} else {
ac_reg->AC_INTENCLR = AC_INTENCLR_COMP1_Msk;
}
}
/* Trigger a single-shot comparison for the specified channel */
static inline void ac_start_conversion(ac_registers_t *ac_reg, uint8_t channel_id)
{
ac_reg->AC_CTRLB |= (AC_CTRLB_START0_Msk << channel_id);
}
/* Wait until the comparator result for the specified channel is ready */
static int ac_wait_for_conversion(ac_registers_t *ac_reg, uint8_t channel_id)
{
uint32_t ready_mask = AC_STATUSB_READY0_Msk << channel_id;
if (WAIT_FOR(((ac_reg->AC_STATUSB & ready_mask) == ready_mask), TIMEOUT_VALUE_US,
k_busy_wait(DELAY_US)) == false) {
LOG_ERR("Timeout waiting for AC_STATUSB ready (channel=%u)", channel_id);
return -ETIMEDOUT;
}
return 0;
}
/* Get the current comparator output state for the specified channel
* Returns true if output is HIGH, false if LOW
*/
static inline bool ac_get_result(ac_registers_t *ac_reg, uint8_t channel_id)
{
uint32_t state_mask = AC_STATUSA_STATE0_Msk << channel_id;
return (ac_reg->AC_STATUSA & state_mask) != 0;
}
/* Configure comparator channel: inputs, mode, hysteresis, output, interrupt, scaler, etc. */
static int ac_configure_channel(const struct device *dev)
{
/* Get device config */
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
const struct comparator_mchp_channel_cfg *channel_config = &dev_cfg->channel_config;
uint8_t channel_id = channel_config->channel_id;
/* Reset COMPCTRL before new config */
AC_REG->AC_COMPCTRL[channel_id] = 0;
/* Set single-shot or continuous mode */
AC_REG->AC_COMPCTRL[channel_id] = AC_COMPCTRL_SINGLE(channel_config->single_shot_mode);
/* Set MUX inputs */
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_MUXPOS(channel_config->pos_input);
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_MUXNEG(channel_config->neg_input);
/* Configure VDDANA scaler if used */
if ((channel_config->neg_input == MCHP_COMP_NEG_INPUT_VSCALE) ||
(channel_config->pos_input == MCHP_COMP_POS_INPUT_VSCALE)) {
AC_REG->AC_SCALER[channel_id] = AC_SCALER_VALUE(channel_config->vddana_scale_value);
}
/* Set Output mode */
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_OUT(channel_config->output_mode);
/* Set Filter length */
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_FLEN(channel_config->filter_length);
if (channel_config->single_shot_mode == false) {
/* Enable hysterisis */
AC_REG->AC_COMPCTRL[channel_id] |=
AC_COMPCTRL_HYSTEN(channel_config->hysteresis_enable ? 1 : 0);
/* Set hysterisis */
if (channel_config->hysteresis_enable == true) {
AC_REG->AC_COMPCTRL[channel_id] |=
AC_COMPCTRL_HYST(channel_config->hysteresis_level);
}
}
/* Set Comparator speed */
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_SPEED(AC_COMPCTRL_SPEED_HIGH_Val);
/* Run in standby if enabled */
if (channel_config->run_standby == true) {
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_RUNSTDBY(1);
}
LOG_DBG("Configuration done AC_REG->AC_COMPCTRL[0] : 0x%x",
AC_REG->AC_COMPCTRL[channel_id]);
/* Interrupt Enable */
ac_enable_interrupt(AC_REG, channel_id);
return 0;
}
static void comparator_mchp_isr(const struct device *dev)
{
struct comparator_mchp_dev_data *const dev_data = dev->data;
/* Store comparator status (latched value from AC_STATUSA) */
dev_data->interrupt_status = AC_REG->AC_STATUSA;
/* Clear interrupt flags (write 1 to clear) */
AC_REG->AC_INTFLAG = AC_INTFLAG_Msk;
if (dev_data->callback != NULL) {
dev_data->callback(dev, dev_data->user_data);
}
}
static int comparator_mchp_get_output(const struct device *dev)
{
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
const struct comparator_mchp_channel_cfg *channel_config = &dev_cfg->channel_config;
uint8_t channel_id = channel_config->channel_id;
int ret = 0;
bool result = false;
#if CONFIG_COMPARATOR_LOG_LEVEL_DBG
/* Optional debug */
comparator_print_channel_cfg(channel_config);
#endif /* CONFIG_COMPARATOR_LOG_LEVEL_DBG */
/* Trigger conversion in single-shot mode */
if (channel_config->single_shot_mode == true) {
ac_start_conversion(AC_REG, channel_id);
}
ret = ac_wait_for_conversion(AC_REG, channel_id);
if (ret == 0) {
#if CONFIG_COMPARATOR_LOG_LEVEL_DBG
/* Optional debug */
comparator_print_reg(dev);
#endif /* CONFIG_COMPARATOR_LOG_LEVEL_DBG */
result = ac_get_result(AC_REG, channel_id);
ret = result ? 1 : 0;
LOG_DBG("AC comparator result: %s", result ? "HIGH" : "LOW");
}
return ret;
}
static int comparator_mchp_set_trigger(const struct device *dev, enum comparator_trigger trigger)
{
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
struct comparator_mchp_dev_data *const dev_data = dev->data;
const struct comparator_mchp_channel_cfg *channel_config = &dev_cfg->channel_config;
uint8_t channel_id = channel_config->channel_id;
uint8_t intsel_val;
LOG_DBG("Setting comparator trigger mode: %d", trigger);
/* Map trigger enum to hardware INTSEL value */
switch (trigger) {
case COMPARATOR_TRIGGER_NONE:
intsel_val = AC_COMPCTRL_INTSEL_EOC_Val;
break;
case COMPARATOR_TRIGGER_RISING_EDGE:
intsel_val = AC_COMPCTRL_INTSEL_RISING_Val;
break;
case COMPARATOR_TRIGGER_FALLING_EDGE:
intsel_val = AC_COMPCTRL_INTSEL_FALLING_Val;
break;
case COMPARATOR_TRIGGER_BOTH_EDGES:
intsel_val = AC_COMPCTRL_INTSEL_TOGGLE_Val;
break;
default:
LOG_ERR("Invalid comparator trigger: %d, defaulting to NONE", trigger);
intsel_val = AC_COMPCTRL_INTSEL_EOC_Val;
trigger = COMPARATOR_TRIGGER_NONE;
break;
}
/* Update INTSEL field */
AC_REG->AC_COMPCTRL[channel_id] &= ~AC_COMPCTRL_INTSEL_Msk;
AC_REG->AC_COMPCTRL[channel_id] |= AC_COMPCTRL_INTSEL(intsel_val);
if (trigger != COMPARATOR_TRIGGER_NONE) {
ac_enable_interrupt(AC_REG, channel_id);
} else {
ac_disable_interrupt(AC_REG, channel_id);
}
LOG_DBG("Trigger mode: %d, INTSEL set to: %d", trigger, intsel_val);
/* Store trigger mode (not INTSEL value!) */
dev_data->interrupt_mask = trigger;
dev_data->interrupt_status = COMPARATOR_INT_STATUS_NONE;
return 0;
}
static int comparator_mchp_set_trigger_callback(const struct device *dev,
comparator_callback_t callback, void *user_data)
{
struct comparator_mchp_dev_data *const dev_data = dev->data;
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
const struct comparator_mchp_channel_cfg *channel_config = &dev_cfg->channel_config;
uint8_t channel_id = channel_config->channel_id;
ac_disable_interrupt(AC_REG, channel_id);
dev_data->callback = callback;
dev_data->user_data = user_data;
ac_enable_interrupt(AC_REG, channel_id);
return 0;
}
static int comparator_mchp_trigger_is_pending(const struct device *dev)
{
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
struct comparator_mchp_dev_data *const dev_data = dev->data;
const struct comparator_mchp_channel_cfg *channel_config = &dev_cfg->channel_config;
uint8_t channel_id = channel_config->channel_id;
int ret = 0;
uint32_t state_mask = AC_STATUSA_STATE0_Msk << channel_id;
LOG_DBG("Checking if comparator trigger is pending...");
/* Only process in polling mode (no callback handler registered) */
if (dev_data->callback == NULL &&
dev_data->interrupt_status != COMPARATOR_INT_STATUS_NONE) {
switch (dev_data->interrupt_mask) {
case COMPARATOR_TRIGGER_RISING_EDGE:
if ((dev_data->interrupt_status & state_mask) != 0) {
LOG_DBG("Rising edge trigger is pending");
ret = 1;
}
break;
case COMPARATOR_TRIGGER_FALLING_EDGE:
if ((dev_data->interrupt_status & state_mask) == 0) {
LOG_DBG("Falling edge trigger is pending");
ret = 1;
}
break;
case COMPARATOR_TRIGGER_BOTH_EDGES:
LOG_DBG("Both edge trigger is pending");
ret = 1;
break;
default:
break;
}
/* Mark as consumed */
dev_data->interrupt_status = COMPARATOR_INT_STATUS_NONE;
}
return ret;
}
static int comparator_mchp_init(const struct device *dev)
{
const struct comparator_mchp_dev_config *const dev_cfg = dev->config;
struct comparator_mchp_dev_data *const dev_data = dev->data;
int ret;
uint8_t channel_id = dev_cfg->channel_config.channel_id;
uint32_t sw0_reg;
dev_data->interrupt_status = COMPARATOR_INT_STATUS_NONE;
/* Turn on GCLK for AC */
ret = clock_control_on(dev_cfg->comparator_clock.clock_dev,
dev_cfg->comparator_clock.gclk_sys);
if (ret < 0 && ret != -EALREADY) {
LOG_ERR("Failed to enable GCLK for COMP: %d", ret);
return ret;
}
/* Turn on MCLK for AC */
ret = clock_control_on(dev_cfg->comparator_clock.clock_dev,
dev_cfg->comparator_clock.mclk_sys);
if (ret < 0 && ret != -EALREADY) {
LOG_ERR("Failed to enable MCLK for COMP: %d", ret);
return ret;
}
/* Apply pinctrl default state */
ret = pinctrl_apply_state(dev_cfg->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
LOG_ERR("Failed to apply pinctrl state: %d", ret);
return ret;
}
/* Reset the comparator peripheral */
AC_REG->AC_CTRLA = AC_CTRLA_SWRST_Msk;
ac_wait_sync(AC_REG, AC_SYNCBUSY_SWRST_Msk);
/* Configure calibration */
sw0_reg = ((fuses_sw0_fuses_registers_t *)SW0_ADDR)->FUSES_SW0_WORD_0;
dev_cfg->regs->AC_CALIB =
(sw0_reg & FUSES_SW0_WORD_0_AC_BIAS0_Msk) >> FUSES_SW0_WORD_0_AC_BIAS0_Pos;
/* Configure ISR */
dev_cfg->config_func(dev);
ac_configure_channel(dev);
ac_channel_enable(AC_REG, channel_id);
#if CONFIG_COMPARATOR_LOG_LEVEL_DBG
comparator_print_reg(dev);
#endif /* CONFIG_COMPARATOR_LOG_LEVEL_DBG */
ac_enable(AC_REG, true);
ac_wait_sync(AC_REG, AC_SYNCBUSY_ENABLE_Msk);
/* If everything is OK but the clocks are already enabled, return 0. */
return (ret == -EALREADY) ? 0 : ret;
}
static DEVICE_API(comparator, comparator_mchp_api) = {
.get_output = comparator_mchp_get_output,
.set_trigger = comparator_mchp_set_trigger,
.set_trigger_callback = comparator_mchp_set_trigger_callback,
.trigger_is_pending = comparator_mchp_trigger_is_pending,
};
#define COMPARATOR_MCHP_DATA_DEFN(n) \
static struct comparator_mchp_dev_data comparator_mchp_data_##n;
/* Connect a single IRQ for instance n at index idx */
#define COMPARATOR_MCHP_IRQ_CONNECT(idx, n) \
IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, idx), \
( \
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq), \
DT_INST_IRQ_BY_IDX(n, idx, priority), \
comparator_mchp_isr, \
DEVICE_DT_INST_GET(n), 0); \
irq_enable(DT_INST_IRQ_BY_IDX(n, idx, irq)); \
) \
)
/* Generate config function for instance n */
#define COMPARATOR_MCHP_DEFINE_CONFIG_FUNC(n) \
static void comparator_mchp_config_##n(const struct device *dev) \
{ \
/* Connect all IRQs declared in devicetree */ \
LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), \
COMPARATOR_MCHP_IRQ_CONNECT, \
(), n); \
}
#define COMPARATOR_MCHP_CONFIG_DEFN(n) \
static void comparator_mchp_config_##n(const struct device *dev); \
static const struct comparator_mchp_dev_config comparator_mchp_cfg_##n = { \
.regs = (ac_registers_t *)DT_INST_REG_ADDR(n), \
.config_func = comparator_mchp_config_##n, \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.comparator_clock.clock_dev = DEVICE_DT_GET(DT_NODELABEL(clock)), \
.comparator_clock.mclk_sys = \
(void *)(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, subsystem)), \
.comparator_clock.gclk_sys = \
(void *)(DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, subsystem)), \
.channel_config = { \
.channel_id = DT_PROP_OR(DT_DRV_INST(n), comparator_channel, 0), \
.pos_input = DT_ENUM_IDX_OR(DT_DRV_INST(n), positive_mux_input, 0), \
.neg_input = DT_ENUM_IDX_OR(DT_DRV_INST(n), negative_mux_input, 0), \
.output_mode = DT_ENUM_IDX_OR(DT_DRV_INST(n), output_mode, 0), \
.filter_length = DT_ENUM_IDX_OR(DT_DRV_INST(n), filter_length, 0), \
.hysteresis_level = DT_ENUM_IDX_OR(DT_DRV_INST(n), hysteresis_level, 0), \
.vddana_scale_value = DT_PROP_OR(DT_DRV_INST(n), vddana_scale_value, 0), \
.single_shot_mode = DT_PROP_OR(DT_DRV_INST(n), single_shot_mode, 0), \
.hysteresis_enable = DT_PROP_OR(DT_DRV_INST(n), hysteresis_enable, 0), \
.run_standby = DT_PROP_OR(DT_DRV_INST(n), run_standby, 0), \
.event_input_enable = DT_PROP_OR(DT_DRV_INST(n), event_input_enable, 0), \
.event_output_enable = DT_PROP_OR(DT_DRV_INST(n), event_output_enable, 0), \
.swap_inputs = DT_PROP_OR(DT_DRV_INST(n), swap_inputs, 0), \
}}
#define COMPARATOR_MCHP_DEVICE_INIT(n) \
PINCTRL_DT_INST_DEFINE(n); \
COMPARATOR_MCHP_CONFIG_DEFN(n); \
COMPARATOR_MCHP_DATA_DEFN(n); \
DEVICE_DT_INST_DEFINE(n, comparator_mchp_init, NULL, &comparator_mchp_data_##n, \
&comparator_mchp_cfg_##n, POST_KERNEL, \
CONFIG_COMPARATOR_INIT_PRIORITY, &comparator_mchp_api); \
COMPARATOR_MCHP_DEFINE_CONFIG_FUNC(n);
DT_INST_FOREACH_STATUS_OKAY(COMPARATOR_MCHP_DEVICE_INIT);