diff --git a/boards/renesas/ek_ra2a1/ek_ra2a1-pinctrl.dtsi b/boards/renesas/ek_ra2a1/ek_ra2a1-pinctrl.dtsi index b18dd709a6e81..5cdbb9f776091 100644 --- a/boards/renesas/ek_ra2a1/ek_ra2a1-pinctrl.dtsi +++ b/boards/renesas/ek_ra2a1/ek_ra2a1-pinctrl.dtsi @@ -45,6 +45,14 @@ }; }; + adc0_default: adc0_default { + group1 { + /* input */ + psels = ; + renesas,analog-enable; + }; + }; + dac0_default: dac0_default { group1 { /* output */ diff --git a/boards/renesas/ek_ra2a1/ek_ra2a1.dts b/boards/renesas/ek_ra2a1/ek_ra2a1.dts index adfce639290de..47493ac67fc9e 100644 --- a/boards/renesas/ek_ra2a1/ek_ra2a1.dts +++ b/boards/renesas/ek_ra2a1/ek_ra2a1.dts @@ -7,6 +7,7 @@ #include #include +#include #include #include "ek_ra2a1-pinctrl.dtsi" @@ -119,6 +120,12 @@ status = "okay"; }; +&adc0 { + status = "okay"; + pinctrl-0 = <&adc0_default>; + pinctrl-names = "default"; +}; + &dac0 { pinctrl-0 = <&dac0_default>; pinctrl-names = "default"; diff --git a/doc/releases/migration-guide-4.3.rst b/doc/releases/migration-guide-4.3.rst index 00a529067cda0..b357fe320ec6d 100644 --- a/doc/releases/migration-guide-4.3.rst +++ b/doc/releases/migration-guide-4.3.rst @@ -58,6 +58,17 @@ Device Drivers and Devicetree .. zephyr-keep-sorted-start re(^\w) +ADC +=== + +* The :dtcompatible:`renesas,ra-adc` compatible has been replaced by + :dtcompatible:`renesas,ra-adc12`. Applications using the old compatible + must update their devicetree nodes. + +* The :dtcompatible:`renesas,ra-adc16` compatible was added. This must be + used when working with the EK-RA2A1 board, which provides a 16-bit ADC + resolution. + MFD === diff --git a/drivers/adc/Kconfig.renesas_ra b/drivers/adc/Kconfig.renesas_ra index b63050b7f5353..d2b626779fc57 100644 --- a/drivers/adc/Kconfig.renesas_ra +++ b/drivers/adc/Kconfig.renesas_ra @@ -6,7 +6,7 @@ config ADC_RENESAS_RA bool "Renesas RA ADC" default y - depends on DT_HAS_RENESAS_RA_ADC_ENABLED + depends on DT_HAS_RENESAS_RA_ADC12_ENABLED || DT_HAS_RENESAS_RA_ADC16_ENABLED select USE_RA_FSP_ADC select PINCTRL help diff --git a/drivers/adc/adc_renesas_ra.c b/drivers/adc/adc_renesas_ra.c index e448fcb4c4026..cab4476ef5260 100644 --- a/drivers/adc/adc_renesas_ra.c +++ b/drivers/adc/adc_renesas_ra.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT renesas_ra_adc - #include #include #include @@ -14,6 +12,8 @@ #include #include +#include "rp_adc.h" + #include LOG_MODULE_REGISTER(adc_ra, CONFIG_ADC_LOG_LEVEL); @@ -21,14 +21,24 @@ LOG_MODULE_REGISTER(adc_ra, CONFIG_ADC_LOG_LEVEL); #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" -#define ADC_RA_MAX_RESOLUTION 12 -#define ADC_AVERAGE_1 ADC_ADD_OFF -#define ADC_AVERAGE_2 ADC_ADD_AVERAGE_TWO -#define ADC_AVERAGE_4 ADC_ADD_AVERAGE_FOUR -#define ADC_AVERAGE_8 ADC_ADD_AVERAGE_EIGHT -#define ADC_AVERAGE_16 ADC_ADD_AVERAGE_SIXTEEN +#define ADC_AVERAGE_1 ADC_ADD_OFF +#define ADC_AVERAGE_2 ADC_ADD_AVERAGE_TWO +#define ADC_AVERAGE_4 ADC_ADD_AVERAGE_FOUR +#define ADC_AVERAGE_8 ADC_ADD_AVERAGE_EIGHT +#define ADC_AVERAGE_16 ADC_ADD_AVERAGE_SIXTEEN + +#define ADC_VARIANT_ADC12 12 +#define ADC_VARIANT_ADC16 16 + +#define ADC_CHANNEL_BIT_MASK (0x01U) + +enum ra_adc_reference { + RA_ADC_REF_VDD, + RA_ADC_REF_INTERNAL, + RA_ADC_REF_EXTERNAL, +}; -void adc_scan_end_isr(void); +extern void adc_scan_end_isr(void); /** * @brief RA ADC config @@ -40,6 +50,14 @@ struct adc_ra_config { uint32_t channel_available_mask; /** pinctrl configs */ const struct pinctrl_dev_config *pcfg; + /** Variant support ADC16 or ADC12 */ + uint8_t variant; + /** Mapping reference voltage */ + uint32_t reference; + /** Resolution support */ + uint8_t resolution; + /** Sampling time in nanoseconds */ + uint32_t sampling_time_ns; /** function pointer to irq setup */ void (*irq_configure)(void); }; @@ -66,23 +84,27 @@ struct adc_ra_data { uint32_t channels; /** Buffer id */ uint16_t buf_id; + /** Calibration process semaphore */ + struct k_sem calibrate_sem; }; -/** - * @brief Setup channels before starting to scan ADC - * - * @param dev RA ADC device - * @param channel_cfg channel configuration - * - * @return 0 on success - * @return -ENOTSUP if channel id or differential is wrong value - * @return -EINVAL if channel configuration is invalid - */ +static adc_sample_state_reg_t map_channel_to_sample_state_reg(uint8_t channel_id) +{ + if (channel_id <= 15) { + return (adc_sample_state_reg_t)channel_id; + } + + /* Channel IDs 16–31 share the same sample state register */ + return ADC_SAMPLE_STATE_CHANNEL_16_TO_31; +} + static int adc_ra_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { fsp_err_t fsp_err = FSP_SUCCESS; struct adc_ra_data *data = dev->data; const struct adc_ra_config *config = dev->config; + adc_sample_state_t sample_state; + uint32_t sample_states = 0; if (!((config->channel_available_mask & (1 << channel_cfg->channel_id)) != 0)) { LOG_ERR("unsupported channel id '%d'", channel_cfg->channel_id); @@ -104,6 +126,18 @@ static int adc_ra_channel_setup(const struct device *dev, const struct adc_chann return -EINVAL; } + fsp_err = RP_ADC_SampleStateCalculation(config->sampling_time_ns, &sample_states); + if (FSP_SUCCESS != fsp_err) { + return -ENOTSUP; + } + + sample_state.reg_id = map_channel_to_sample_state_reg(channel_cfg->channel_id); + sample_state.num_states = sample_states; + fsp_err = R_ADC_SampleStateCountSet(&data->adc, &sample_state); + if (FSP_SUCCESS != fsp_err) { + return -ENOTSUP; + } + data->f_channel_cfg.scan_mask |= (1U << channel_cfg->channel_id); /* Configure ADC channel specific settings */ fsp_err = R_ADC_ScanCfg(&data->adc, &data->f_channel_cfg); @@ -114,43 +148,85 @@ static int adc_ra_channel_setup(const struct device *dev, const struct adc_chann return 0; } -/** - * Interrupt handler - */ -static void adc_ra_isr(const struct device *dev) +static void renesas_ra_adc_callback(adc_callback_args_t *p_args) { + const struct device *dev = p_args->p_context; struct adc_ra_data *data = dev->data; fsp_err_t fsp_err = FSP_SUCCESS; adc_channel_t channel_id = 0; uint32_t channels = 0; int16_t *sample_buffer = (int16_t *)data->buf; - channels = data->channels; - for (channel_id = 0; channels > 0; channel_id++) { - /* Check if it is right channel id */ - if ((channels & 0x01) != 0) { - fsp_err = R_ADC_Read(&data->adc, channel_id, &sample_buffer[data->buf_id]); - if (FSP_SUCCESS != fsp_err) { - break; + if (p_args->event == ADC_EVENT_SCAN_COMPLETE) { + channels = data->channels; + for (channel_id = 0; channels > 0; channel_id++) { + /* Check if it is right channel id */ + if ((channels & ADC_CHANNEL_BIT_MASK) != 0) { + fsp_err = R_ADC_Read(&data->adc, channel_id, + &sample_buffer[data->buf_id]); + if (FSP_SUCCESS != fsp_err) { + break; + } + /* Do not return negative value for single-ended configuration */ + if (sample_buffer[data->buf_id] < 0) { + sample_buffer[data->buf_id] = 0; + } + data->buf_id = data->buf_id + 1; + + fsp_err = R_ADC_ScanStop(&data->adc); + if (FSP_SUCCESS != fsp_err) { + break; + } } - data->buf_id = data->buf_id + 1; + + channels = channels >> 1; } + adc_context_on_sampling_done(&data->ctx, dev); + } - channels = channels >> 1; + else if (p_args->event == ADC_EVENT_CALIBRATION_COMPLETE) { + k_sem_give(&data->calibrate_sem); + } +} + +static int adc_map_vref(const struct adc_ra_config *cfg, adc_extended_cfg_t *extend) +{ + switch (cfg->variant) { + case ADC_VARIANT_ADC16: + switch (cfg->reference) { + case RA_ADC_REF_INTERNAL: + extend->adc_vref_control = ADC_VREF_CONTROL_2_5V_OUTPUT; + return 0; + case RA_ADC_REF_EXTERNAL: + extend->adc_vref_control = ADC_VREF_CONTROL_VREFH; + return 0; + default: + LOG_ERR("Reference %d not supported", cfg->reference); + return -ENOTSUP; + } + + case ADC_VARIANT_ADC12: + switch (cfg->reference) { + case RA_ADC_REF_VDD: + extend->adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0; + return 0; + case RA_ADC_REF_EXTERNAL: + extend->adc_vref_control = ADC_VREF_CONTROL_VREFH0_VREFL0; + return 0; + case RA_ADC_REF_INTERNAL: + extend->adc_vref_control = ADC_VREF_CONTROL_IVREF_AVSS0; + return 0; + default: + LOG_ERR("Reference %d not supported", cfg->reference); + return -ENOTSUP; + } + + default: + LOG_ERR("Variant %d not supported", cfg->variant); + return -ENOTSUP; } - adc_scan_end_isr(); - adc_context_on_sampling_done(&data->ctx, dev); } -/** - * @brief Check if buffer in @p sequence is big enough to hold all ADC samples - * - * @param dev RA ADC device - * @param sequence ADC sequence description - * - * @return 0 on success - * @return -ENOMEM if buffer is not big enough - */ static int adc_ra_check_buffer_size(const struct device *dev, const struct adc_sequence *sequence) { uint8_t channels = 0; @@ -170,26 +246,22 @@ static int adc_ra_check_buffer_size(const struct device *dev, const struct adc_s return 0; } -/** - * @brief Start processing read request - * - * @param dev RA ADC device - * @param sequence ADC sequence description - * - * @return 0 on success - * @return -ENOTSUP if requested resolution or channel is out side of supported - * range - * @return -ENOMEM if buffer is not big enough - * (see @ref adc_ra_check_buffer_size) - * @return other error code returned by adc_context_wait_for_completion - */ static int adc_ra_start_read(const struct device *dev, const struct adc_sequence *sequence) { const struct adc_ra_config *config = dev->config; struct adc_ra_data *data = dev->data; + fsp_err_t fsp_err = FSP_SUCCESS; int err; - if (sequence->resolution > ADC_RA_MAX_RESOLUTION || sequence->resolution == 0) { + if (config->variant == ADC_VARIANT_ADC16) { + uint8_t expected = config->resolution - 1; + + if (sequence->resolution != expected) { + LOG_ERR("unsupported resolution %d for single-ended mode, must be %d", + sequence->resolution, expected); + return -ENOTSUP; + } + } else if (sequence->resolution != config->resolution) { LOG_ERR("unsupported resolution %d", sequence->resolution); return -ENOTSUP; } @@ -207,6 +279,21 @@ static int adc_ra_start_read(const struct device *dev, const struct adc_sequence data->buf_id = 0; data->buf = sequence->buffer; + + if (config->variant == ADC_VARIANT_ADC16) { + if (!sequence->calibrate) { + return -ENOTSUP; + } + + /* Start calibration process */ + k_sem_reset(&data->calibrate_sem); + fsp_err = R_ADC_Calibrate(&data->adc, NULL); + if (FSP_SUCCESS != fsp_err) { + return -EIO; + } + k_sem_take(&data->calibrate_sem, K_FOREVER); + } + adc_context_start_read(&data->ctx, sequence); adc_context_wait_for_completion(&data->ctx); @@ -214,20 +301,6 @@ static int adc_ra_start_read(const struct device *dev, const struct adc_sequence return 0; } -/** - * @brief Start processing read request asynchronously - * - * @param dev RA ADC device - * @param sequence ADC sequence description - * @param async async pointer to asynchronous signal - * - * @return 0 on success - * @return -ENOTSUP if requested resolution or channel is out side of supported - * range - * @return -ENOMEM if buffer is not big enough - * (see @ref adc_ra_check_buffer_size) - * @return other error code returned by adc_context_wait_for_completion - */ static int adc_ra_read_async(const struct device *dev, const struct adc_sequence *sequence, struct k_poll_signal *async) { @@ -241,19 +314,6 @@ static int adc_ra_read_async(const struct device *dev, const struct adc_sequence return err; } -/** - * @brief Start processing read request synchronously - * - * @param dev RA ADC device - * @param sequence ADC sequence description - * - * @return 0 on success - * @return -ENOTSUP if requested resolution or channel is out side of supported - * range - * @return -ENOMEM if buffer is not big enough - * (see @ref adc_ra_check_buffer_size) - * @return other error code returned by adc_context_wait_for_completion - */ static int adc_ra_read(const struct device *dev, const struct adc_sequence *sequence) { return adc_ra_read_async(dev, sequence, NULL); @@ -277,28 +337,27 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repe } } -/** - * @brief Function called on init for each RA ADC device. It setups all - * channels to return constant 0 mV and create acquisition thread. - * - * @param dev RA ADC device - * - * @return -EIO if error - * - * @return 0 on success - */ static int adc_ra_init(const struct device *dev) { const struct adc_ra_config *config = dev->config; struct adc_ra_data *data = dev->data; int ret; fsp_err_t fsp_err = FSP_SUCCESS; + adc_extended_cfg_t *extend = (adc_extended_cfg_t *)data->f_config.p_extend; + + /* Override reference voltage */ + ret = adc_map_vref(config, extend); + if (ret < 0) { + return ret; + } ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (ret < 0) { return ret; } + k_sem_init(&data->calibrate_sem, 0, 1); + /* Open ADC module */ fsp_err = R_ADC_Open(&data->adc, &data->f_config); if (FSP_SUCCESS != fsp_err) { @@ -307,28 +366,38 @@ static int adc_ra_init(const struct device *dev) config->irq_configure(); + if (config->variant == ADC_VARIANT_ADC16) { + /* Start calibration process */ + fsp_err = R_ADC_Calibrate(&data->adc, NULL); + if (FSP_SUCCESS != fsp_err) { + return -EIO; + } + k_sem_take(&data->calibrate_sem, K_FOREVER); + } + adc_context_unlock_unconditionally(&data->ctx); return 0; } -#define EVENT_ADC_SCAN_END(idx) BSP_PRV_IELS_ENUM(CONCAT(EVENT_ADC, idx, _SCAN_END)) +#define EVENT_ADC_SCAN_END(unit) BSP_PRV_IELS_ENUM(CONCAT(EVENT_ADC, unit, _SCAN_END)) #define IRQ_CONFIGURE_FUNC(idx) \ static void adc_ra_configure_func_##idx(void) \ { \ - R_ICU->IELSR[DT_INST_IRQ_BY_NAME(idx, scanend, irq)] = EVENT_ADC_SCAN_END(idx); \ + R_ICU->IELSR[DT_INST_IRQ_BY_NAME(idx, scanend, irq)] = \ + EVENT_ADC_SCAN_END(DT_PROP(DT_DRV_INST(idx), unit)); \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, scanend, irq), \ - DT_INST_IRQ_BY_NAME(idx, scanend, priority), adc_ra_isr, \ - DEVICE_DT_INST_GET(idx), 0); \ + DT_INST_IRQ_BY_NAME(idx, scanend, priority), adc_scan_end_isr, NULL, \ + 0); \ irq_enable(DT_INST_IRQ_BY_NAME(idx, scanend, irq)); \ } #define IRQ_CONFIGURE_DEFINE(idx) .irq_configure = adc_ra_configure_func_##idx -#define ADC_RA_INIT(idx) \ +#define ADC_RA_INIT_VARIANT(idx, VARIANT, RES_NUM, RES_ENUM) \ IRQ_CONFIGURE_FUNC(idx) \ PINCTRL_DT_INST_DEFINE(idx); \ - static const adc_extended_cfg_t g_adc_cfg_extend_##idx = { \ + static adc_extended_cfg_t g_adc_cfg_extend_##idx = { \ .add_average_count = UTIL_CAT(ADC_AVERAGE_, DT_INST_PROP(idx, average_count)), \ .clearing = ADC_CLEAR_AFTER_READ_ON, \ .trigger_group_b = ADC_START_SOURCE_DISABLED, \ @@ -345,9 +414,13 @@ static int adc_ra_init(const struct device *dev) .channel_setup = adc_ra_channel_setup, \ .read = adc_ra_read, \ .ref_internal = DT_INST_PROP(idx, vref_mv), \ - IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = adc_ra_read_async))}; \ + IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = adc_ra_read_async))}; \ static const struct adc_ra_config adc_ra_config_##idx = { \ .channel_available_mask = DT_INST_PROP(idx, channel_available_mask), \ + .variant = VARIANT, \ + .reference = DT_INST_ENUM_IDX(idx, reference), \ + .resolution = RES_NUM, \ + .sampling_time_ns = DT_INST_PROP_OR(idx, sampling_time_ns, UNSPECIFIED), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ IRQ_CONFIGURE_DEFINE(idx), \ }; \ @@ -358,13 +431,13 @@ static int adc_ra_init(const struct device *dev) .dev = DEVICE_DT_INST_GET(idx), \ .f_config = \ { \ - .unit = idx, \ + .unit = DT_INST_PROP(idx, unit), \ .mode = ADC_MODE_SINGLE_SCAN, \ - .resolution = ADC_RESOLUTION_12_BIT, \ + .resolution = RES_ENUM, \ .alignment = (adc_alignment_t)ADC_ALIGNMENT_RIGHT, \ .trigger = 0, \ - .p_callback = NULL, \ - .p_context = NULL, \ + .p_callback = renesas_ra_adc_callback, \ + .p_context = (void *)DEVICE_DT_GET(DT_DRV_INST(idx)), \ .p_extend = &g_adc_cfg_extend_##idx, \ .scan_end_irq = DT_INST_IRQ_BY_NAME(idx, scanend, irq), \ .scan_end_ipl = DT_INST_IRQ_BY_NAME(idx, scanend, priority), \ @@ -386,4 +459,10 @@ static int adc_ra_init(const struct device *dev) DEVICE_DT_INST_DEFINE(idx, adc_ra_init, NULL, &adc_ra_data_##idx, &adc_ra_config_##idx, \ POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, &adc_ra_api_##idx) -DT_INST_FOREACH_STATUS_OKAY(ADC_RA_INIT); +#define DT_DRV_COMPAT renesas_ra_adc12 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_RA_INIT_VARIANT, ADC_VARIANT_ADC12, 12, ADC_RESOLUTION_12_BIT) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT renesas_ra_adc16 +DT_INST_FOREACH_STATUS_OKAY_VARGS(ADC_RA_INIT_VARIANT, ADC_VARIANT_ADC16, 16, ADC_RESOLUTION_16_BIT) +#undef DT_DRV_COMPAT diff --git a/dts/arm/renesas/ra/ra2/ra2l1.dtsi b/dts/arm/renesas/ra/ra2/ra2l1.dtsi index fe6ff9896072b..9285aa1a0df6f 100644 --- a/dts/arm/renesas/ra/ra2/ra2l1.dtsi +++ b/dts/arm/renesas/ra/ra2/ra2l1.dtsi @@ -422,7 +422,8 @@ }; adc0: adc@4005c000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; + unit = <0>; reg = <0x4005c000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra2/ra2xx.dtsi b/dts/arm/renesas/ra/ra2/ra2xx.dtsi index 8f32511c9cec9..89cae5032e34e 100644 --- a/dts/arm/renesas/ra/ra2/ra2xx.dtsi +++ b/dts/arm/renesas/ra/ra2/ra2xx.dtsi @@ -260,7 +260,20 @@ #size-cells = <1>; }; - agt0: agt@40084000 { + adc0: adc@4005c000 { + compatible = "renesas,ra-adc-16"; + unit = <0>; + reg = <0x4005c000 0x100>; + #io-channel-cells = <1>; + vref-mv = <3300>; + channel-available-mask = <0x00ff01ff>; + reference = "external"; + average-count = <16>; + variant = <16>; + status = "disabled"; + }; + + agt0: agt@40084000 { compatible = "renesas,ra-agt"; channel = <0>; reg = <0x40084000 0x100>; diff --git a/dts/arm/renesas/ra/ra4/r7fa4c1bx.dtsi b/dts/arm/renesas/ra/ra4/r7fa4c1bx.dtsi index 66b563207c42b..80d9b843cefb9 100644 --- a/dts/arm/renesas/ra/ra4/r7fa4c1bx.dtsi +++ b/dts/arm/renesas/ra/ra4/r7fa4c1bx.dtsi @@ -269,7 +269,8 @@ }; adc0: adc@40170000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; + unit = <0>; reg = <0x40170000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra4/r7fa4l1bx.dtsi b/dts/arm/renesas/ra/ra4/r7fa4l1bx.dtsi index be1c7973d6156..7d63edd236c73 100644 --- a/dts/arm/renesas/ra/ra4/r7fa4l1bx.dtsi +++ b/dts/arm/renesas/ra/ra4/r7fa4l1bx.dtsi @@ -264,9 +264,10 @@ }; adc0: adc@40170000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <38 1>; interrupt-names = "scanend"; + unit = <0>; reg = <0x40170000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra4/ra4-cm33-common.dtsi b/dts/arm/renesas/ra/ra4/ra4-cm33-common.dtsi index 28cb01aeb1bb7..88c57147074fa 100644 --- a/dts/arm/renesas/ra/ra4/ra4-cm33-common.dtsi +++ b/dts/arm/renesas/ra/ra4/ra4-cm33-common.dtsi @@ -284,9 +284,10 @@ }; adc0: adc@40170000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <38 1>; interrupt-names = "scanend"; + unit = <0>; reg = <0x40170000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; @@ -294,9 +295,10 @@ }; adc1: adc@40170200 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <39 1>; interrupt-names = "scanend"; + unit = <1>; reg = <0x40170200 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra4/ra4-cm4-common.dtsi b/dts/arm/renesas/ra/ra4/ra4-cm4-common.dtsi index 27b9ec78a301c..74009f89d3549 100644 --- a/dts/arm/renesas/ra/ra4/ra4-cm4-common.dtsi +++ b/dts/arm/renesas/ra/ra4/ra4-cm4-common.dtsi @@ -231,8 +231,9 @@ }; adc0: adc@4005c000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupt-names = "scanend"; + unit = <0>; reg = <0x4005c000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra6/ra6-cm33-common.dtsi b/dts/arm/renesas/ra/ra6/ra6-cm33-common.dtsi index 2d2a08198ab83..40026f015d529 100644 --- a/dts/arm/renesas/ra/ra6/ra6-cm33-common.dtsi +++ b/dts/arm/renesas/ra/ra6/ra6-cm33-common.dtsi @@ -281,9 +281,10 @@ }; adc0: adc@40170000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <38 1>; interrupt-names = "scanend"; + unit = <0>; reg = <0x40170000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; @@ -291,9 +292,10 @@ }; adc1: adc@40170200 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <39 1>; interrupt-names = "scanend"; + unit = <1>; reg = <0x40170200 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra6/ra6-cm4-common.dtsi b/dts/arm/renesas/ra/ra6/ra6-cm4-common.dtsi index c6d82b8b3c406..d46567e6a5f92 100644 --- a/dts/arm/renesas/ra/ra6/ra6-cm4-common.dtsi +++ b/dts/arm/renesas/ra/ra6/ra6-cm4-common.dtsi @@ -304,9 +304,10 @@ }; adc0: adc@4005c000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <38 1>; interrupt-names = "scanend"; + unit = <0>; reg = <0x4005c000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; @@ -317,6 +318,7 @@ compatible = "renesas,ra-adc"; interrupts = <39 1>; interrupt-names = "scanend"; + unit = <1>; reg = <0x4005c200 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/arm/renesas/ra/ra8/ra8x1.dtsi b/dts/arm/renesas/ra/ra8/ra8x1.dtsi index dfef2cb19b92c..35082910c4c94 100644 --- a/dts/arm/renesas/ra/ra8/ra8x1.dtsi +++ b/dts/arm/renesas/ra/ra8/ra8x1.dtsi @@ -369,9 +369,10 @@ }; adc0: adc@40332000 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <38 1>; interrupt-names = "scanend"; + unit = <0>; reg = <0x40332000 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; @@ -380,9 +381,10 @@ }; adc1: adc@40332200 { - compatible = "renesas,ra-adc"; + compatible = "renesas,ra-adc-12"; interrupts = <39 1>; interrupt-names = "scanend"; + unit = <1>; reg = <0x40332200 0x100>; #io-channel-cells = <1>; vref-mv = <3300>; diff --git a/dts/bindings/adc/renesas,ra-adc.yaml b/dts/bindings/adc/renesas,ra-adc-base.yaml similarity index 52% rename from dts/bindings/adc/renesas,ra-adc.yaml rename to dts/bindings/adc/renesas,ra-adc-base.yaml index 0ce2649529a8d..2542c918873d4 100644 --- a/dts/bindings/adc/renesas,ra-adc.yaml +++ b/dts/bindings/adc/renesas,ra-adc-base.yaml @@ -1,10 +1,6 @@ -# Copyright (c) 2024 Renesas Electronics Corporation +# Copyright (c) 2025 Renesas Electronics Corporation # SPDX-License-Identifier: Apache-2.0 -description: Renesas RA ADC node - -compatible: "renesas,ra-adc" - include: [adc-controller.yaml, pinctrl-device.yaml] properties: @@ -32,5 +28,29 @@ properties: The ADC module will take multiple samples of an analog signal and averages them to reduce noise and enhance accuracy + reference: + type: string + enum: + - vdd + - internal + - external + default: vdd + description: | + ADC reference voltage source: + - vdd: use VDD as reference + - internal: use internal reference + - external: use external reference + + sampling-time-ns: + type: int + description: | + Sampling time in nanoseconds, i.e. the duration the ADC input + signal is sampled before conversion starts. + + unit: + type: int + required: true + description: Indicates the unit number of the ADC device. + io-channel-cells: - input diff --git a/dts/bindings/adc/renesas,ra-adc12.yaml b/dts/bindings/adc/renesas,ra-adc12.yaml new file mode 100644 index 0000000000000..5ab09951e600d --- /dev/null +++ b/dts/bindings/adc/renesas,ra-adc12.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA 12-bit resolution (ADC12) device binding. + +compatible: "renesas,ra-adc12" + +include: renesas,ra-adc-base.yaml diff --git a/dts/bindings/adc/renesas,ra-adc16.yaml b/dts/bindings/adc/renesas,ra-adc16.yaml new file mode 100644 index 0000000000000..322eabf45e259 --- /dev/null +++ b/dts/bindings/adc/renesas,ra-adc16.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA 16-bit resolution (ADC16) device binding. + +compatible: "renesas,ra-adc16" + +include: renesas,ra-adc-base.yaml diff --git a/samples/drivers/adc/adc_dt/boards/ek_ra2a1.overlay b/samples/drivers/adc/adc_dt/boards/ek_ra2a1.overlay new file mode 100644 index 0000000000000..96337abf1ced5 --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/ek_ra2a1.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc0 0>, <&adc0 1>; + }; +}; + +&pinctrl { + adc0_default: adc0_default { + group1 { + /* input */ + psels = , + ; + renesas,analog-enable; + }; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <31 1>; + interrupt-names = "scanend"; + + /* + * Channel 0 is used in single ended mode, with 15 bit resolution + */ + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,resolution = <15>; + zephyr,acquisition-time = ; + zephyr,vref-mv = <3300>; + }; + + /* + * Channel 1 is used in single ended mode, with 15 bit resolution + */ + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,resolution = <15>; + zephyr,acquisition-time = ; + zephyr,vref-mv = <3300>; + }; +}; diff --git a/samples/drivers/adc/adc_dt/src/main.c b/samples/drivers/adc/adc_dt/src/main.c index cb607a0ff0d17..2766a863c0770 100644 --- a/samples/drivers/adc/adc_dt/src/main.c +++ b/samples/drivers/adc/adc_dt/src/main.c @@ -38,6 +38,9 @@ int main(void) .buffer = &buf, /* buffer size in bytes, not number of samples */ .buffer_size = sizeof(buf), +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_adc_16) + .calibrate = true, +#endif }; /* Configure channels individually prior to sampling. */ diff --git a/tests/drivers/adc/adc_accuracy_test/Kconfig b/tests/drivers/adc/adc_accuracy_test/Kconfig index cc9e640a25728..b36698f73bb65 100644 --- a/tests/drivers/adc/adc_accuracy_test/Kconfig +++ b/tests/drivers/adc/adc_accuracy_test/Kconfig @@ -23,6 +23,10 @@ config NUMBER_OF_PASSES int "Number of passes" default 5 +config TEST_ADC_CALIBRATE_REQUIRED + bool "Require calibrate field in ADC test" + default y if DT_HAS_RENESAS_RA_ADC_16_ENABLED + if DAC_SOURCE_TEST config DAC_BUFFER_NOT_SUPPORTED diff --git a/tests/drivers/adc/adc_accuracy_test/boards/ek_ra2a1.overlay b/tests/drivers/adc/adc_accuracy_test/boards/ek_ra2a1.overlay new file mode 100644 index 0000000000000..7c22df9082dd0 --- /dev/null +++ b/tests/drivers/adc/adc_accuracy_test/boards/ek_ra2a1.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024-2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc0 3>; + dac = <&dac0>; + dac-channel-id = <0>; + dac-resolution = <12>; + }; +}; + +&pinctrl { + adc0_default: adc0_default { + group1 { + /* input */ + psels = ; + renesas,analog-enable; + }; + }; +}; + +&adc0{ + #address-cells = <1>; + #size-cells = <0>; + interrupts = <31 1>; + interrupt-names = "scanend"; + status = "okay"; + + /* + * Channel 3 is used in single ended mode, with 15 bit resolution + */ + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,acquisition-time = ; + zephyr,resolution = <15>; + zephyr,vref-mv = <3300>; + }; +}; diff --git a/tests/drivers/adc/adc_accuracy_test/src/dac_source.c b/tests/drivers/adc/adc_accuracy_test/src/dac_source.c index 23b832a66ed3f..a4063d095c7be 100644 --- a/tests/drivers/adc/adc_accuracy_test/src/dac_source.c +++ b/tests/drivers/adc/adc_accuracy_test/src/dac_source.c @@ -43,6 +43,9 @@ static int test_dac_to_adc(void) struct adc_sequence sequence = { .buffer = &sample_buffer, .buffer_size = sizeof(sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; const struct device *dac_dev = init_dac(); diff --git a/tests/drivers/adc/adc_accuracy_test/testcase.yaml b/tests/drivers/adc/adc_accuracy_test/testcase.yaml index 03f122f9cdaae..aaaf633196c23 100644 --- a/tests/drivers/adc/adc_accuracy_test/testcase.yaml +++ b/tests/drivers/adc/adc_accuracy_test/testcase.yaml @@ -12,20 +12,8 @@ tests: fixture: dac_adc_loopback platform_allow: - frdm_k64f - drivers.adc.accuracy.ref_volt: - harness_config: - fixture: adc_ref_volt - platform_allow: - - frdm_kl25z - - ek_ra8m1 - - frdm_mcxc242 - - frdm_mcxc444 - - nrf52840dk/nrf52840 - - nrf54h20dk/nrf54h20/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - - nrf54lm20dk/nrf54lm20a/cpuapp - - ophelia4ev/nrf54l15/cpuapp - ek_ra8d1 + - ek_ra8m1 - mck_ra8t1 - ek_ra6e2 - ek_ra6m1 @@ -36,14 +24,32 @@ tests: - fpb_ra6e1 - fpb_ra6e2 - ek_ra4e2 + - ek_ra4l1 + - ek_ra4m1 - ek_ra4m2 - ek_ra4m3 - ek_ra4w1 + - fpb_ra4e1 + - ek_ra2a1 + - ek_ra2l1 + drivers.adc.accuracy.ref_volt: + harness_config: + fixture: adc_ref_volt + platform_allow: + - frdm_kl25z + - frdm_mcxc242 + - frdm_mcxc444 + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - ophelia4ev/nrf54l15/cpuapp - xg24_dk2601b - xg24_rb4187c - xg27_dk2602a - xg29_rb4412a - bg29_rb4420a + - ek_ra4c1 integration_platforms: - frdm_kl25z - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/drivers/adc/adc_api/Kconfig b/tests/drivers/adc/adc_api/Kconfig index f4748c6d3805e..0ec8d996680b5 100644 --- a/tests/drivers/adc/adc_api/Kconfig +++ b/tests/drivers/adc/adc_api/Kconfig @@ -13,3 +13,7 @@ config ADC_API_SAMPLE_INTERVAL_US config ADC_32_BITS_DATA bool "ADC data is 32-bits long" + +config TEST_ADC_CALIBRATE_REQUIRED + bool "Require calibrate field in ADC test" + default y if DT_HAS_RENESAS_RA_ADC_16_ENABLED diff --git a/tests/drivers/adc/adc_api/boards/ek_ra2a1.overlay b/tests/drivers/adc/adc_api/boards/ek_ra2a1.overlay new file mode 100644 index 0000000000000..96337abf1ced5 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/ek_ra2a1.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc0 0>, <&adc0 1>; + }; +}; + +&pinctrl { + adc0_default: adc0_default { + group1 { + /* input */ + psels = , + ; + renesas,analog-enable; + }; + }; +}; + +&adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <31 1>; + interrupt-names = "scanend"; + + /* + * Channel 0 is used in single ended mode, with 15 bit resolution + */ + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,resolution = <15>; + zephyr,acquisition-time = ; + zephyr,vref-mv = <3300>; + }; + + /* + * Channel 1 is used in single ended mode, with 15 bit resolution + */ + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,resolution = <15>; + zephyr,acquisition-time = ; + zephyr,vref-mv = <3300>; + }; +}; diff --git a/tests/drivers/adc/adc_api/src/test_adc.c b/tests/drivers/adc/adc_api/src/test_adc.c index 49af36dc0d4c5..d3a7186db84ee 100644 --- a/tests/drivers/adc/adc_api/src/test_adc.c +++ b/tests/drivers/adc/adc_api/src/test_adc.c @@ -136,6 +136,9 @@ static int test_task_one_channel(void) struct adc_sequence sequence = { .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; init_adc(); @@ -163,6 +166,9 @@ static int test_task_multiple_channels(void) struct adc_sequence sequence = { .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; init_adc(); @@ -210,6 +216,9 @@ static int test_task_asynchronous_call(void) .options = &options, .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; struct k_poll_event async_evt = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, @@ -272,6 +281,9 @@ static int test_task_with_interval(void) .options = &options, .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; init_adc(); @@ -349,6 +361,9 @@ static int test_task_repeated_samplings(void) .options = &options, .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; init_adc(); @@ -383,6 +398,9 @@ static int test_task_invalid_request(void) .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), .resolution = 0, /* intentionally invalid value */ +#if CONFIG_TEST_ADC_CALIBRATE_REQUIRED + .calibrate = true, +#endif }; init_adc(); diff --git a/west.yml b/west.yml index 035976239cb90..6fe872f7c4b82 100644 --- a/west.yml +++ b/west.yml @@ -226,7 +226,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: d8ee5f18e95b9f4616a481be65e2c9ee0af1779f + revision: pull/143/head groups: - hal - name: hal_rpi_pico