drivers: pwm: Update Renesas RA PWM driver to integrate Renesas ELC

Update the Renesas RA PWM driver to integration
with the Renesas Event Link Controller.

Signed-off-by: Khanh Nguyen <khanh.nguyen.wz@bp.renesas.com>
This commit is contained in:
Khanh Nguyen 2025-03-28 13:41:54 +07:00 committed by Benjamin Cabé
commit c6de306949
2 changed files with 111 additions and 3 deletions

View file

@ -14,6 +14,10 @@
#include <zephyr/logging/log.h>
#include <stdio.h>
#ifdef CONFIG_RENESAS_RA_ELC
#include <zephyr/drivers/misc/interconn/renesas_elc/renesas_elc.h>
#endif
LOG_MODULE_REGISTER(pwm_renesas_ra, CONFIG_PWM_LOG_LEVEL);
#define DT_DRV_COMPAT renesas_ra_pwm
@ -39,6 +43,12 @@ struct pwm_renesas_ra_data {
gpt_instance_ctrl_t fsp_ctrl;
timer_cfg_t fsp_cfg;
gpt_extended_cfg_t extend_cfg;
#ifdef CONFIG_RENESAS_RA_ELC
struct renesas_elc_dt_spec start_renesas_elc;
struct renesas_elc_dt_spec stop_renesas_elc;
#endif /* CONFIG_RENESAS_RA_ELC */
uint16_t capture_a_event;
uint16_t overflow_event;
@ -181,6 +191,17 @@ static int pwm_renesas_ra_set_cycles(const struct device *dev, uint32_t pin, uin
return -EIO;
}
#ifdef CONFIG_RENESAS_RA_ELC
/* Enables external event triggers */
if (data->extend_cfg.start_source != GPT_SOURCE_NONE ||
data->extend_cfg.stop_source != GPT_SOURCE_NONE) {
err = R_GPT_Enable(&data->fsp_ctrl);
if (err != FSP_SUCCESS) {
return -EIO;
}
}
#endif /* CONFIG_RENESAS_RA_ELC */
LOG_DBG("channel %u, pin %u, pulse %u, period %u, prescaler: %u.", data->fsp_cfg.channel,
pin, pulse_cycles, period_cycles, data->fsp_cfg.source_div);
@ -475,6 +496,28 @@ static int pwm_renesas_ra_init(const struct device *dev)
data->fsp_cfg.p_context = dev;
#endif /* defined(CONFIG_PWM_CAPTURE) */
#ifdef CONFIG_RENESAS_RA_ELC
if (device_is_ready(data->start_renesas_elc.dev) && data->start_renesas_elc.event != 0) {
err = renesas_elc_link_set(data->start_renesas_elc.dev,
data->start_renesas_elc.peripheral,
data->start_renesas_elc.event);
if (err) {
LOG_ERR("Failed to set Renesas ELC link for PWM start source(%d)", err);
return err;
}
}
if (device_is_ready(data->stop_renesas_elc.dev) && data->stop_renesas_elc.event != 0) {
err = renesas_elc_link_set(data->stop_renesas_elc.dev,
data->stop_renesas_elc.peripheral,
data->stop_renesas_elc.event);
if (err) {
LOG_ERR("Failed to set Renesas ELC link for PWM stop source(%d)", err);
return err;
}
}
#endif /* CONFIG_RENESAS_RA_ELC */
data->fsp_cfg.p_extend = &data->extend_cfg;
err = R_GPT_Open(&data->fsp_ctrl, &data->fsp_cfg);
@ -490,6 +533,24 @@ static int pwm_renesas_ra_init(const struct device *dev)
#define EVENT_GPT_COUNTER_OVERFLOW(channel) \
BSP_PRV_IELS_ENUM(CONCAT(EVENT_GPT, channel, _COUNTER_OVERFLOW))
#ifdef CONFIG_RENESAS_RA_ELC
#define PWM_RENESAS_ELC_DATA(index) \
.start_renesas_elc = \
{ \
.dev = RENESAS_ELC_DT_SPEC_DEVICE_INST_GET_BY_NAME_OR_NULL(index, start), \
.peripheral = RENESAS_ELC_DT_SPEC_PERIPHERAL_INST_GET_BY_NAME_OR( \
index, start, 0), \
.event = RENESAS_ELC_DT_SPEC_EVENT_INST_GET_BY_NAME_OR(index, start, 0), \
}, \
.stop_renesas_elc = { \
.dev = RENESAS_ELC_DT_SPEC_DEVICE_INST_GET_BY_NAME_OR_NULL(index, stop), \
.peripheral = RENESAS_ELC_DT_SPEC_PERIPHERAL_INST_GET_BY_NAME_OR(index, stop, 0), \
.event = RENESAS_ELC_DT_SPEC_EVENT_INST_GET_BY_NAME_OR(index, stop, 0), \
},
#else
#define PWM_RENESAS_ELC_DATA(index)
#endif
#ifdef CONFIG_PWM_CAPTURE
#define PWM_RA_IRQ_CONFIG_INIT(index) \
do { \
@ -506,6 +567,9 @@ static int pwm_renesas_ra_init(const struct device *dev)
#define PWM_RA_IRQ_CONFIG_INIT(index)
#endif /* CONFIG_PWM_CAPTURE */
#define PWM_INST_SOURCE_OR(index, prop, default_value) \
DT_INST_STRING_TOKEN_OR(index, prop, default_value)
#define PWM_RA8_INIT(index) \
PINCTRL_DT_INST_DEFINE(index); \
static const gpt_extended_cfg_t g_timer1_extend_##index = { \
@ -519,8 +583,10 @@ static int pwm_renesas_ra_init(const struct device *dev)
.output_enabled = false, \
.stop_level = GPT_PIN_LEVEL_LOW, \
}, \
.start_source = (gpt_source_t)(GPT_SOURCE_NONE), \
.stop_source = (gpt_source_t)(GPT_SOURCE_NONE), \
.start_source = \
(gpt_source_t)(PWM_INST_SOURCE_OR(index, start_source, GPT_SOURCE_NONE)), \
.stop_source = \
(gpt_source_t)(PWM_INST_SOURCE_OR(index, stop_source, GPT_SOURCE_NONE)), \
.clear_source = (gpt_source_t)(GPT_SOURCE_NONE), \
.count_up_source = (gpt_source_t)(GPT_SOURCE_NONE), \
.count_down_source = (gpt_source_t)(GPT_SOURCE_NONE), \
@ -545,7 +611,8 @@ static int pwm_renesas_ra_init(const struct device *dev)
.cycle_end_irq = DT_INST_IRQ_BY_NAME(index, overflow, irq), \
}, \
.extend_cfg = g_timer1_extend_##index, \
.capture_a_event = EVENT_GPT_CAPTURE_COMPARE_A(DT_INST_PROP(index, channel)), \
PWM_RENESAS_ELC_DATA(index).capture_a_event = \
EVENT_GPT_CAPTURE_COMPARE_A(DT_INST_PROP(index, channel)), \
.overflow_event = EVENT_GPT_COUNTER_OVERFLOW(DT_INST_PROP(index, channel)), \
}; \
static const struct pwm_renesas_ra_config pwm_renesas_ra_config_##index = { \

View file

@ -25,6 +25,47 @@ properties:
interrupt-names:
required: true
renesas-elcs:
type: phandle-array
description: |
Phandle array pointing to the Renesas ELC node.
The cell configuration must follow the Renesas
ELC bindings "#renesas-elc-cells".
renesas-elc-names:
type: string-array
description: |
Optional names given to the Renesas ELC specifiers
in the "renesas-elcs" property.
start-source:
type: string
description: Signal source name for start
enum:
- "GPT_SOURCE_NONE"
- "GPT_SOURCE_GPT_A"
- "GPT_SOURCE_GPT_B"
- "GPT_SOURCE_GPT_C"
- "GPT_SOURCE_GPT_D"
- "GPT_SOURCE_GPT_E"
- "GPT_SOURCE_GPT_F"
- "GPT_SOURCE_GPT_G"
- "GPT_SOURCE_GPT_H"
stop-source:
type: string
description: Signal source name for stop
enum:
- "GPT_SOURCE_NONE"
- "GPT_SOURCE_GPT_A"
- "GPT_SOURCE_GPT_B"
- "GPT_SOURCE_GPT_C"
- "GPT_SOURCE_GPT_D"
- "GPT_SOURCE_GPT_E"
- "GPT_SOURCE_GPT_F"
- "GPT_SOURCE_GPT_G"
- "GPT_SOURCE_GPT_H"
"#pwm-cells":
const: 3