Skip to content

Commit a29e15d

Browse files
author
Thinh Le Cong
committed
drivers: adc: Adding ADC 16-bit driver support for board EK-RA2A1
Adding ADC 16-bit driver support for board EK-RA2A1 Signed-off-by: Thinh Le Cong <[email protected]>
1 parent c7e6034 commit a29e15d

File tree

2 files changed

+168
-29
lines changed

2 files changed

+168
-29
lines changed

drivers/adc/adc_renesas_ra.c

Lines changed: 149 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,27 @@ LOG_MODULE_REGISTER(adc_ra, CONFIG_ADC_LOG_LEVEL);
2121
#define ADC_CONTEXT_USES_KERNEL_TIMER
2222
#include "adc_context.h"
2323

24-
#define ADC_RA_MAX_RESOLUTION 12
25-
#define ADC_AVERAGE_1 ADC_ADD_OFF
26-
#define ADC_AVERAGE_2 ADC_ADD_AVERAGE_TWO
27-
#define ADC_AVERAGE_4 ADC_ADD_AVERAGE_FOUR
28-
#define ADC_AVERAGE_8 ADC_ADD_AVERAGE_EIGHT
29-
#define ADC_AVERAGE_16 ADC_ADD_AVERAGE_SIXTEEN
24+
#define ADC_AVERAGE_1 ADC_ADD_OFF
25+
#define ADC_AVERAGE_2 ADC_ADD_AVERAGE_TWO
26+
#define ADC_AVERAGE_4 ADC_ADD_AVERAGE_FOUR
27+
#define ADC_AVERAGE_8 ADC_ADD_AVERAGE_EIGHT
28+
#define ADC_AVERAGE_16 ADC_ADD_AVERAGE_SIXTEEN
3029

31-
void adc_scan_end_isr(void);
30+
#define ADC_RES_12 ADC_RESOLUTION_12_BIT
31+
#define ADC_RES_16 ADC_RESOLUTION_16_BIT
32+
33+
#define ADC_VARIANT_ADC12 12
34+
#define ADC_VARIANT_ADC16 16
35+
36+
#define ADC_CHANNEL_BIT_MASK (0x01U)
37+
38+
enum ra_adc_reference {
39+
RA_ADC_REF_VDD,
40+
RA_ADC_REF_INTERNAL,
41+
RA_ADC_REF_EXTERNAL,
42+
};
43+
44+
extern void adc_scan_end_isr(void);
3245

3346
/**
3447
* @brief RA ADC config
@@ -40,6 +53,12 @@ struct adc_ra_config {
4053
uint32_t channel_available_mask;
4154
/** pinctrl configs */
4255
const struct pinctrl_dev_config *pcfg;
56+
/** Variant support ADC16 or ADC12 */
57+
uint8_t variant;
58+
/** Mapping reference voltage */
59+
uint32_t reference;
60+
/** Resolution support */
61+
uint8_t resolution;
4362
/** function pointer to irq setup */
4463
void (*irq_configure)(void);
4564
};
@@ -66,6 +85,8 @@ struct adc_ra_data {
6685
uint32_t channels;
6786
/** Buffer id */
6887
uint16_t buf_id;
88+
/** Calibration process semaphore */
89+
struct k_sem calibrate_sem;
6990
};
7091

7192
/**
@@ -114,32 +135,86 @@ static int adc_ra_channel_setup(const struct device *dev, const struct adc_chann
114135
return 0;
115136
}
116137

117-
/**
118-
* Interrupt handler
119-
*/
120-
static void adc_ra_isr(const struct device *dev)
138+
static void renesas_ra_adc_callback(adc_callback_args_t *p_args)
121139
{
140+
const struct device *dev = p_args->p_context;
122141
struct adc_ra_data *data = dev->data;
123142
fsp_err_t fsp_err = FSP_SUCCESS;
124143
adc_channel_t channel_id = 0;
125144
uint32_t channels = 0;
126145
int16_t *sample_buffer = (int16_t *)data->buf;
127146

128-
channels = data->channels;
129-
for (channel_id = 0; channels > 0; channel_id++) {
130-
/* Check if it is right channel id */
131-
if ((channels & 0x01) != 0) {
132-
fsp_err = R_ADC_Read(&data->adc, channel_id, &sample_buffer[data->buf_id]);
133-
if (FSP_SUCCESS != fsp_err) {
134-
break;
147+
if (p_args->event == ADC_EVENT_SCAN_COMPLETE) {
148+
channels = data->channels;
149+
for (channel_id = 0; channels > 0; channel_id++) {
150+
/* Check if it is right channel id */
151+
if ((channels & ADC_CHANNEL_BIT_MASK) != 0) {
152+
fsp_err = R_ADC_Read(&data->adc, channel_id,
153+
&sample_buffer[data->buf_id]);
154+
if (FSP_SUCCESS != fsp_err) {
155+
break;
156+
}
157+
/* Do not return negative value for single-ended configuration */
158+
if (sample_buffer[data->buf_id] < 0) {
159+
sample_buffer[data->buf_id] = 0;
160+
}
161+
data->buf_id = data->buf_id + 1;
162+
163+
fsp_err = R_ADC_ScanStop(&data->adc);
164+
if (FSP_SUCCESS != fsp_err) {
165+
break;
166+
}
135167
}
136-
data->buf_id = data->buf_id + 1;
168+
169+
channels = channels >> 1;
137170
}
171+
adc_context_on_sampling_done(&data->ctx, dev);
172+
}
138173

139-
channels = channels >> 1;
174+
else if (p_args->event == ADC_EVENT_CALIBRATION_COMPLETE) {
175+
k_sem_give(&data->calibrate_sem);
176+
}
177+
}
178+
179+
/**
180+
* Voltage reference covert handler
181+
*/
182+
static int adc_map_vref(const struct adc_ra_config *cfg, adc_extended_cfg_t *extend)
183+
{
184+
switch (cfg->variant) {
185+
case ADC_VARIANT_ADC16:
186+
switch (cfg->reference) {
187+
case RA_ADC_REF_INTERNAL:
188+
extend->adc_vref_control = ADC_VREF_CONTROL_2_5V_OUTPUT;
189+
return 0;
190+
case RA_ADC_REF_EXTERNAL:
191+
extend->adc_vref_control = ADC_VREF_CONTROL_VREFH;
192+
return 0;
193+
default:
194+
LOG_ERR("Reference %d not supported", cfg->reference);
195+
return -ENOTSUP;
196+
}
197+
198+
case ADC_VARIANT_ADC12:
199+
switch (cfg->reference) {
200+
case RA_ADC_REF_VDD:
201+
extend->adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0;
202+
return 0;
203+
case RA_ADC_REF_EXTERNAL:
204+
extend->adc_vref_control = ADC_VREF_CONTROL_VREFH0_VREFL0;
205+
return 0;
206+
case RA_ADC_REF_INTERNAL:
207+
extend->adc_vref_control = ADC_VREF_CONTROL_IVREF_AVSS0;
208+
return 0;
209+
default:
210+
LOG_ERR("Reference %d not supported", cfg->reference);
211+
return -ENOTSUP;
212+
}
213+
214+
default:
215+
LOG_ERR("Variant %d not supported", cfg->variant);
216+
return -ENOTSUP;
140217
}
141-
adc_scan_end_isr();
142-
adc_context_on_sampling_done(&data->ctx, dev);
143218
}
144219

145220
/**
@@ -187,9 +262,18 @@ static int adc_ra_start_read(const struct device *dev, const struct adc_sequence
187262
{
188263
const struct adc_ra_config *config = dev->config;
189264
struct adc_ra_data *data = dev->data;
265+
fsp_err_t fsp_err = FSP_SUCCESS;
190266
int err;
191267

192-
if (sequence->resolution > ADC_RA_MAX_RESOLUTION || sequence->resolution == 0) {
268+
if (config->variant == ADC_VARIANT_ADC16) {
269+
uint8_t expected = config->resolution - 1;
270+
271+
if (sequence->resolution != expected) {
272+
LOG_ERR("unsupported resolution %d for single-ended mode, must be %d",
273+
sequence->resolution, expected);
274+
return -ENOTSUP;
275+
}
276+
} else if (sequence->resolution != config->resolution) {
193277
LOG_ERR("unsupported resolution %d", sequence->resolution);
194278
return -ENOTSUP;
195279
}
@@ -207,6 +291,21 @@ static int adc_ra_start_read(const struct device *dev, const struct adc_sequence
207291

208292
data->buf_id = 0;
209293
data->buf = sequence->buffer;
294+
295+
if (config->variant == ADC_VARIANT_ADC16) {
296+
if (!sequence->calibrate) {
297+
return -ENOTSUP;
298+
}
299+
300+
/* Start calibration process */
301+
k_sem_reset(&data->calibrate_sem);
302+
fsp_err = R_ADC_Calibrate(&data->adc, NULL);
303+
if (FSP_SUCCESS != fsp_err) {
304+
return -EIO;
305+
}
306+
k_sem_take(&data->calibrate_sem, K_FOREVER);
307+
}
308+
210309
adc_context_start_read(&data->ctx, sequence);
211310

212311
adc_context_wait_for_completion(&data->ctx);
@@ -294,11 +393,20 @@ static int adc_ra_init(const struct device *dev)
294393
int ret;
295394
fsp_err_t fsp_err = FSP_SUCCESS;
296395

396+
/* Override reference voltage */
397+
adc_extended_cfg_t *extend = (adc_extended_cfg_t *)data->f_config.p_extend;
398+
ret = adc_map_vref(config, extend);
399+
if (ret < 0) {
400+
return ret;
401+
}
402+
297403
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
298404
if (ret < 0) {
299405
return ret;
300406
}
301407

408+
k_sem_init(&data->calibrate_sem, 0, 1);
409+
302410
/* Open ADC module */
303411
fsp_err = R_ADC_Open(&data->adc, &data->f_config);
304412
if (FSP_SUCCESS != fsp_err) {
@@ -307,6 +415,15 @@ static int adc_ra_init(const struct device *dev)
307415

308416
config->irq_configure();
309417

418+
if (config->variant == ADC_VARIANT_ADC16) {
419+
/* Start calibration process */
420+
fsp_err = R_ADC_Calibrate(&data->adc, NULL);
421+
if (FSP_SUCCESS != fsp_err) {
422+
return -EIO;
423+
}
424+
k_sem_take(&data->calibrate_sem, K_FOREVER);
425+
}
426+
310427
adc_context_unlock_unconditionally(&data->ctx);
311428
return 0;
312429
}
@@ -318,8 +435,8 @@ static int adc_ra_init(const struct device *dev)
318435
{ \
319436
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(idx, scanend, irq)] = EVENT_ADC_SCAN_END(idx); \
320437
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, scanend, irq), \
321-
DT_INST_IRQ_BY_NAME(idx, scanend, priority), adc_ra_isr, \
322-
DEVICE_DT_INST_GET(idx), 0); \
438+
DT_INST_IRQ_BY_NAME(idx, scanend, priority), adc_scan_end_isr, NULL, \
439+
0); \
323440
irq_enable(DT_INST_IRQ_BY_NAME(idx, scanend, irq)); \
324441
}
325442

@@ -345,9 +462,12 @@ static int adc_ra_init(const struct device *dev)
345462
.channel_setup = adc_ra_channel_setup, \
346463
.read = adc_ra_read, \
347464
.ref_internal = DT_INST_PROP(idx, vref_mv), \
348-
IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = adc_ra_read_async))}; \
465+
IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = adc_ra_read_async))}; \
349466
static const struct adc_ra_config adc_ra_config_##idx = { \
350467
.channel_available_mask = DT_INST_PROP(idx, channel_available_mask), \
468+
.variant = DT_INST_PROP(idx, variant), \
469+
.reference = DT_INST_ENUM_IDX(idx, reference), \
470+
.resolution = DT_INST_PROP(idx, variant), \
351471
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
352472
IRQ_CONFIGURE_DEFINE(idx), \
353473
}; \
@@ -360,11 +480,11 @@ static int adc_ra_init(const struct device *dev)
360480
{ \
361481
.unit = idx, \
362482
.mode = ADC_MODE_SINGLE_SCAN, \
363-
.resolution = ADC_RESOLUTION_12_BIT, \
483+
.resolution = UTIL_CAT(ADC_RES_, DT_INST_PROP(idx, variant)), \
364484
.alignment = (adc_alignment_t)ADC_ALIGNMENT_RIGHT, \
365485
.trigger = 0, \
366-
.p_callback = NULL, \
367-
.p_context = NULL, \
486+
.p_callback = renesas_ra_adc_callback, \
487+
.p_context = (void *)DEVICE_DT_GET(DT_DRV_INST(idx)), \
368488
.p_extend = &g_adc_cfg_extend_##idx, \
369489
.scan_end_irq = DT_INST_IRQ_BY_NAME(idx, scanend, irq), \
370490
.scan_end_ipl = DT_INST_IRQ_BY_NAME(idx, scanend, priority), \

dts/bindings/adc/renesas,ra-adc.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,24 @@ properties:
3232
The ADC module will take multiple samples of an analog signal
3333
and averages them to reduce noise and enhance accuracy
3434

35+
reference:
36+
type: string
37+
enum:
38+
- vdd
39+
- internal
40+
- external
41+
default: vdd
42+
description: |
43+
ADC reference voltage source:
44+
- vdd: use VDD as reference
45+
- internal: use internal reference
46+
- external: use external reference
47+
48+
variant:
49+
type: int
50+
enum: [12, 16]
51+
default: 12
52+
description: Select ADC variant for RA SoC
53+
3554
io-channel-cells:
3655
- input

0 commit comments

Comments
 (0)