-
Notifications
You must be signed in to change notification settings - Fork 8k
drivers: comparator: Add Comparator support on Renesas RX #93694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
quytranpzz
wants to merge
4
commits into
zephyrproject-rtos:main
Choose a base branch
from
renesas:renesas_rx_lvd_support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+588
−1
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
33248c0
manifest: hal: renesas: Update commit ID for Renesas HAL
quytranpzz 0d01c39
drivers: comparator: Add comparator driver support for RX
quytranpzz 2a969de
dts: renesas: rx: Add dts property nodes for LVD support
quytranpzz c49bac7
samples: boards: renesas: Add LVD sample for Renesas
quytranpzz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Copyright (c) 2025 Renesas Electronics Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config COMPARATOR_RENESAS_RX_LVD | ||
bool "Renesas RX LVD" | ||
default y | ||
depends on DT_HAS_RENESAS_RX_LVD_ENABLED | ||
select USE_RX_RDP_LVD | ||
select PINCTRL | ||
help | ||
Enable Comparator driver with Low Voltage Detection (LVD) feature for Renesas RX MCUs. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
/* | ||
* Copyright (c) 2025 Renesas Electronics Corporation | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT renesas_rx_lvd | ||
|
||
#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_lvd_rx_if.h" | ||
|
||
LOG_MODULE_REGISTER(renesas_rx_lvd, CONFIG_COMPARATOR_LOG_LEVEL); | ||
|
||
#define LVD0_NODE DT_NODELABEL(lvd0) | ||
#define LVD1_NODE DT_NODELABEL(lvd1) | ||
#define LVD_RENESAS_RX_FLAG BIT(0) | ||
/* | ||
* The extern functions below are implemented in the r_lvd_rx_hw.c source file. | ||
* For more information, please refer to r_lvd_rx_hw.c in HAL Renesas | ||
*/ | ||
extern void lvd_ch1_isr(void); | ||
extern void lvd_ch2_isr(void); | ||
extern void lvd_start_lvd(lvd_channel_t ch, lvd_trigger_t trigger); | ||
extern void lvd_stop_lvd(lvd_channel_t ch); | ||
extern void lvd_start_int(lvd_channel_t ch, void (*p_callback)(void *)); | ||
extern void lvd_stop_int(lvd_channel_t ch); | ||
extern void lvd_hw_enable_reset_int(lvd_channel_t ch, bool enable); | ||
extern void lvd_hw_enable_reg_protect(bool enable); | ||
|
||
struct lvd_renesas_rx_data { | ||
lvd_config_t lvd_config; | ||
void (*callback)(void *args); | ||
comparator_callback_t user_cb; | ||
void *user_cb_data; | ||
atomic_t flags; | ||
}; | ||
|
||
struct lvd_renesas_rx_config { | ||
lvd_channel_t channel; | ||
uint8_t vdet_target; | ||
uint8_t lvd_action; | ||
bool lvd_support_cmpa; | ||
}; | ||
|
||
static int lvd_renesas_rx_get_output(const struct device *dev) | ||
{ | ||
const struct lvd_renesas_rx_config *config = dev->config; | ||
lvd_status_position_t status_position; | ||
/* unused variable, just for API compatibility */ | ||
lvd_status_cross_t unused_status_cross; | ||
lvd_err_t err; | ||
|
||
err = R_LVD_GetStatus(config->channel, &status_position, &unused_status_cross); | ||
if (err != 0) { | ||
LOG_ERR("Failed to get status"); | ||
return -EIO; | ||
} | ||
|
||
switch (status_position) { | ||
case LVD_STATUS_POSITION_ABOVE: | ||
return 1; | ||
|
||
case LVD_STATUS_POSITION_BELOW: | ||
return 0; | ||
|
||
default: | ||
LOG_ERR("Invalid status, please check the configuration"); | ||
return -EIO; | ||
} | ||
} | ||
|
||
static int lvd_renesas_rx_set_trigger(const struct device *dev, enum comparator_trigger trigger) | ||
{ | ||
struct lvd_renesas_rx_data *data = dev->data; | ||
const struct lvd_renesas_rx_config *config = dev->config; | ||
|
||
lvd_hw_enable_reg_protect(false); | ||
lvd_stop_lvd(config->channel); | ||
lvd_stop_int(config->channel); | ||
|
||
switch (trigger) { | ||
case COMPARATOR_TRIGGER_RISING_EDGE: | ||
data->lvd_config.trigger = LVD_TRIGGER_RISE; | ||
break; | ||
|
||
case COMPARATOR_TRIGGER_FALLING_EDGE: | ||
data->lvd_config.trigger = LVD_TRIGGER_FALL; | ||
break; | ||
|
||
case COMPARATOR_TRIGGER_BOTH_EDGES: | ||
data->lvd_config.trigger = LVD_TRIGGER_BOTH; | ||
break; | ||
|
||
case COMPARATOR_TRIGGER_NONE: | ||
LOG_ERR("Trigger NONE is not supported"); | ||
return -ENOTSUP; | ||
} | ||
|
||
lvd_start_int(config->channel, data->callback); | ||
lvd_start_lvd(config->channel, data->lvd_config.trigger); | ||
lvd_hw_enable_reg_protect(true); | ||
|
||
return 0; | ||
} | ||
|
||
static int lvd_renesas_rx_set_trigger_callback(const struct device *dev, | ||
comparator_callback_t callback, void *user_data) | ||
{ | ||
struct lvd_renesas_rx_data *data = dev->data; | ||
const struct lvd_renesas_rx_config *config = dev->config; | ||
|
||
if ((config->lvd_action == 0) || (config->lvd_action == 3)) { | ||
LOG_ERR("Callback function is not supported with the current action"); | ||
return -ENOTSUP; | ||
} | ||
|
||
/* Disable interrupt */ | ||
lvd_hw_enable_reset_int(config->channel, false); | ||
|
||
data->user_cb = callback; | ||
data->user_cb_data = user_data; | ||
|
||
/* Enable interrupt */ | ||
lvd_hw_enable_reset_int(config->channel, true); | ||
return 0; | ||
} | ||
|
||
static int lvd_renesas_rx_trigger_is_pending(const struct device *dev) | ||
{ | ||
struct lvd_renesas_rx_data *data = dev->data; | ||
const struct lvd_renesas_rx_config *config = dev->config; | ||
|
||
if (data->flags & LVD_RENESAS_RX_FLAG) { | ||
atomic_and(&data->flags, ~LVD_RENESAS_RX_FLAG); | ||
R_LVD_ClearStatus(config->channel); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int renesas_rx_pin_set_cmpa(const struct device *dev) | ||
{ | ||
const struct lvd_renesas_rx_config *config = dev->config; | ||
const struct pinctrl_dev_config *pcfg; | ||
int ret; | ||
|
||
if (config->channel == 0) { | ||
if (DT_NODE_HAS_PROP(LVD0_NODE, pinctrl_0)) { | ||
PINCTRL_DT_DEFINE(LVD0_NODE); | ||
pcfg = PINCTRL_DT_DEV_CONFIG_GET(LVD0_NODE); | ||
} else { | ||
LOG_ERR("No pinctrl-0 property found in the device tree"); | ||
return -EINVAL; | ||
} | ||
} else { | ||
if (DT_NODE_HAS_PROP(LVD1_NODE, pinctrl_0)) { | ||
PINCTRL_DT_DEFINE(LVD1_NODE); | ||
pcfg = PINCTRL_DT_DEV_CONFIG_GET(LVD1_NODE); | ||
} else { | ||
LOG_ERR("No pinctrl_0 property found in the device tree"); | ||
return -EINVAL; | ||
} | ||
} | ||
|
||
/* In the case of monitoring the CMPA pin, set the CMPA pin. */ | ||
ret = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); | ||
if (ret < 0) { | ||
LOG_ERR("Failed to apply pinctrl state: %d\n", ret); | ||
return -EINVAL; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static inline void lvd_irq_connect(void) | ||
{ | ||
#if DT_NODE_HAS_STATUS_OKAY(LVD0_NODE) | ||
IRQ_CONNECT(DT_IRQN(LVD0_NODE), DT_IRQ(LVD0_NODE, priority), lvd_ch1_isr, | ||
DEVICE_DT_GET(LVD0_NODE), 0); | ||
irq_enable(DT_IRQN(LVD0_NODE)); | ||
#endif | ||
#if DT_NODE_HAS_STATUS_OKAY(LVD1_NODE) | ||
IRQ_CONNECT(DT_IRQN(LVD1_NODE), DT_IRQ(LVD1_NODE, priority), lvd_ch2_isr, | ||
DEVICE_DT_GET(LVD1_NODE), 0); | ||
irq_enable(DT_IRQN(LVD1_NODE)); | ||
#endif | ||
} | ||
|
||
static int lvd_renesas_rx_init(const struct device *dev) | ||
{ | ||
lvd_err_t err; | ||
|
||
lvd_irq_connect(); | ||
|
||
const struct lvd_renesas_rx_config *config = dev->config; | ||
const struct lvd_renesas_rx_data *data = dev->data; | ||
|
||
/* In reset or no-action when LVD is detected, callback will not be triggered. */ | ||
err = R_LVD_Open(config->channel, &data->lvd_config, data->callback); | ||
if (err != 0) { | ||
LOG_ERR("Failed to initialize LVD channel %d", config->channel); | ||
return -EIO; | ||
} | ||
|
||
/* Set the CMPA pin if the target is CMPA */ | ||
/* NOTE: For the RX130 series, CMPA is only used on channel 2. */ | ||
if ((config->lvd_support_cmpa) && (config->vdet_target == 1)) { | ||
return renesas_rx_pin_set_cmpa(dev); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static DEVICE_API(comparator, lvd_renesas_rx_api) = { | ||
.get_output = lvd_renesas_rx_get_output, | ||
.set_trigger = lvd_renesas_rx_set_trigger, | ||
.set_trigger_callback = lvd_renesas_rx_set_trigger_callback, | ||
.trigger_is_pending = lvd_renesas_rx_trigger_is_pending, | ||
}; | ||
|
||
#define LVD_RENESAS_RX_INIT(index) \ | ||
\ | ||
static const struct lvd_renesas_rx_config lvd_renesas_rx_config_##index = { \ | ||
.channel = DT_INST_PROP(index, channel), \ | ||
.lvd_action = DT_INST_ENUM_IDX(index, lvd_action), \ | ||
.vdet_target = DT_INST_ENUM_IDX(index, vdet_target), \ | ||
.lvd_support_cmpa = DT_INST_PROP(index, lvd_support_cmpa), \ | ||
}; \ | ||
\ | ||
void rx_lvd_callback_##index(void *args) \ | ||
{ \ | ||
ARG_UNUSED(args); \ | ||
const struct device *dev = DEVICE_DT_GET(DT_INST(index, renesas_rx_lvd)); \ | ||
struct lvd_renesas_rx_data *data = dev->data; \ | ||
comparator_callback_t cb = data->user_cb; \ | ||
\ | ||
/* Call the user's callback function*/ \ | ||
if (cb) { \ | ||
cb(dev, data->user_cb_data); \ | ||
return; \ | ||
} \ | ||
atomic_or(&data->flags, LVD_RENESAS_RX_FLAG); \ | ||
}; \ | ||
\ | ||
static struct lvd_renesas_rx_data lvd_renesas_rx_data_##index = { \ | ||
.lvd_config = \ | ||
{ \ | ||
.trigger = DT_INST_ENUM_IDX(index, lvd_trigger), \ | ||
}, \ | ||
.callback = rx_lvd_callback_##index, \ | ||
.flags = 0, \ | ||
}; \ | ||
\ | ||
DEVICE_DT_INST_DEFINE(index, lvd_renesas_rx_init, NULL, &lvd_renesas_rx_data_##index, \ | ||
&lvd_renesas_rx_config_##index, PRE_KERNEL_1, \ | ||
CONFIG_COMPARATOR_INIT_PRIORITY, &lvd_renesas_rx_api); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(LVD_RENESAS_RX_INIT) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@quytranpzz , This file name should be comparator_renesas_rx_lvd.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done. I updated the file name