diff --git a/drivers/pwm/pwm_renesas_ra.c b/drivers/pwm/pwm_renesas_ra.c index fa745a0aa37..5f4ce1509bf 100644 --- a/drivers/pwm/pwm_renesas_ra.c +++ b/drivers/pwm/pwm_renesas_ra.c @@ -14,6 +14,10 @@ #include #include +#ifdef CONFIG_RENESAS_RA_ELC +#include +#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 = { \ diff --git a/dts/bindings/pwm/renesas,ra-pwm.yaml b/dts/bindings/pwm/renesas,ra-pwm.yaml index 7022d08d488..c99f1b1cdd8 100644 --- a/dts/bindings/pwm/renesas,ra-pwm.yaml +++ b/dts/bindings/pwm/renesas,ra-pwm.yaml @@ -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