1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #define DT_DRV_COMPAT renesas_rz_adc
7
8 #include <zephyr/drivers/adc.h>
9 #include <zephyr/irq.h>
10 #include <zephyr/logging/log.h>
11 #include "r_adc_c.h"
12
13 LOG_MODULE_REGISTER(adc_renesas_rz, CONFIG_ADC_LOG_LEVEL);
14
15 #define ADC_CONTEXT_USES_KERNEL_TIMER
16 #include "adc_context.h"
17
18 #define ADC_RZ_MAX_RESOLUTION 12
19
20 void adc_c_scan_end_isr(void);
21
22 /**
23 * @brief RZ ADC config
24 *
25 * This structure contains constant config data for given instance of RZ ADC.
26 */
27 struct adc_rz_config {
28 /** Mask for channels existed in each board */
29 uint32_t channel_available_mask;
30 /** Structure that handle FSP API */
31 const adc_api_t *fsp_api;
32 };
33
34 /**
35 * @brief RZ ADC data
36 *
37 * This structure contains data structures used by a RZ ADC.
38 */
39 struct adc_rz_data {
40 /** Structure that handle state of ongoing read operation */
41 struct adc_context ctx;
42 /** Pointer to RZ ADC own device structure */
43 const struct device *dev;
44 /** Structure that handle fsp ADC */
45 adc_c_instance_ctrl_t fsp_ctrl;
46 /** Structure that handle fsp ADC config */
47 struct st_adc_cfg fsp_cfg;
48 /** Structure that handle fsp ADC channel config */
49 adc_c_channel_cfg_t fsp_channel_cfg;
50 /** Pointer to memory where next sample will be written */
51 uint16_t *buf;
52 /** Mask with channels that will be sampled */
53 uint32_t channels;
54 /** Buffer id */
55 uint16_t buf_id;
56 };
57
58 /**
59 * @brief Setup channels before starting to scan ADC
60 *
61 * @param dev RZ ADC device
62 * @param channel_cfg channel configuration (user-defined)
63 *
64 * @return 0 on success
65 * @return -ENOTSUP if channel id or differential is wrong value
66 * @return -EINVAL if channel configuration is invalid
67 */
adc_rz_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)68 static int adc_rz_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg)
69 {
70
71 fsp_err_t fsp_err = FSP_SUCCESS;
72 struct adc_rz_data *data = dev->data;
73 const struct adc_rz_config *config = dev->config;
74
75 if (!((config->channel_available_mask & BIT(channel_cfg->channel_id)) != 0)) {
76 LOG_ERR("unsupported channel id '%d'", channel_cfg->channel_id);
77 return -ENOTSUP;
78 }
79
80 if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
81 LOG_ERR("Unsupported channel acquisition time");
82 return -ENOTSUP;
83 }
84
85 if (channel_cfg->differential) {
86 LOG_ERR("Differential channels are not supported");
87 return -ENOTSUP;
88 }
89
90 if (channel_cfg->gain != ADC_GAIN_1) {
91 LOG_ERR("Unsupported channel gain %d", channel_cfg->gain);
92 return -ENOTSUP;
93 }
94
95 if (channel_cfg->reference != ADC_REF_INTERNAL) {
96 LOG_ERR("Unsupported channel reference");
97 return -ENOTSUP;
98 }
99 data->fsp_channel_cfg.scan_mask |= (1U << channel_cfg->channel_id);
100 /** Enable channels. */
101 config->fsp_api->scanCfg(&data->fsp_ctrl, &data->fsp_channel_cfg);
102
103 if (FSP_SUCCESS != fsp_err) {
104 return -ENOTSUP;
105 }
106
107 return 0;
108 }
109
110 /**
111 * Interrupt handler
112 */
adc_rz_isr(const struct device * dev)113 static void adc_rz_isr(const struct device *dev)
114 {
115 struct adc_rz_data *data = dev->data;
116 const struct adc_rz_config *config = dev->config;
117 fsp_err_t fsp_err = FSP_SUCCESS;
118 adc_channel_t channel_id = 0;
119 uint32_t channels = 0;
120 int16_t *sample_buffer = (int16_t *)data->buf;
121
122 channels = data->channels;
123 for (channel_id = 0; channels > 0; channel_id++) {
124 /** Get channel ids from scan mask "channels" */
125 if ((channels & 0x01) != 0) {
126 /** Read converted data */
127 config->fsp_api->read(&data->fsp_ctrl, channel_id,
128 &sample_buffer[data->buf_id]);
129 if (FSP_SUCCESS != fsp_err) {
130 break;
131 }
132 data->buf_id = data->buf_id + 1;
133 }
134 channels = channels >> 1;
135 }
136 adc_c_scan_end_isr();
137 adc_context_on_sampling_done(&data->ctx, dev);
138 }
139
140 /**
141 * @brief Check if buffer in @p sequence is big enough to hold all ADC samples
142 *
143 * @param dev RZ ADC device
144 * @param sequence ADC sequence description
145 *
146 * @return 0 on success
147 * @return -ENOMEM if buffer is not big enough
148 */
adc_rz_check_buffer_size(const struct device * dev,const struct adc_sequence * sequence)149 static int adc_rz_check_buffer_size(const struct device *dev, const struct adc_sequence *sequence)
150 {
151 uint8_t channels = 0;
152 size_t needed;
153
154 channels = POPCOUNT(sequence->channels);
155 needed = channels * sizeof(uint16_t);
156
157 if (sequence->options) {
158 needed *= (1 + sequence->options->extra_samplings);
159 }
160
161 if (sequence->buffer_size < needed) {
162 return -ENOMEM;
163 }
164
165 return 0;
166 }
167
168 /**
169 * @brief Start processing read request
170 *
171 * @param dev RZ ADC device
172 * @param sequence ADC sequence description
173 *
174 * @return 0 on success
175 * @return -ENOTSUP if requested resolution or channel is out side of supported
176 * range
177 * @return -ENOMEM if buffer is not big enough
178 * (see @ref adc_rz_check_buffer_size)
179 * @return other error code returned by adc_context_wait_for_completion
180 */
adc_rz_start_read(const struct device * dev,const struct adc_sequence * sequence)181 static int adc_rz_start_read(const struct device *dev, const struct adc_sequence *sequence)
182 {
183 const struct adc_rz_config *config = dev->config;
184 struct adc_rz_data *data = dev->data;
185 int err;
186
187 if (sequence->resolution > ADC_RZ_MAX_RESOLUTION || sequence->resolution == 0) {
188 LOG_ERR("unsupported resolution %d", sequence->resolution);
189 return -ENOTSUP;
190 }
191
192 if ((sequence->channels & ~config->channel_available_mask) != 0) {
193 LOG_ERR("unsupported channels in mask: 0x%08x", sequence->channels);
194 return -ENOTSUP;
195 }
196 err = adc_rz_check_buffer_size(dev, sequence);
197
198 if (err) {
199 LOG_ERR("buffer size too small");
200 return err;
201 }
202 data->buf_id = 0;
203 data->buf = sequence->buffer;
204 adc_context_start_read(&data->ctx, sequence);
205 adc_context_wait_for_completion(&data->ctx);
206
207 return 0;
208 }
209
210 /**
211 * @brief Start processing read request asynchronously.
212 *
213 * @param dev RZ ADC device
214 * @param sequence ADC sequence description
215 * @param async async pointer to asynchronous signal
216 *
217 * @return 0 on success
218 * @return -ENOTSUP if requested resolution or channel is out side of supported
219 * range
220 * @return -ENOMEM if buffer is not big enough
221 * (see @ref adc_rz_check_buffer_size)
222 * @return other error code returned by adc_context_wait_for_completion
223 */
adc_rz_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)224 static int adc_rz_read_async(const struct device *dev, const struct adc_sequence *sequence,
225 struct k_poll_signal *async)
226 {
227 struct adc_rz_data *data = dev->data;
228 int err;
229
230 adc_context_lock(&data->ctx, async ? true : false, async);
231 err = adc_rz_start_read(dev, sequence);
232 adc_context_release(&data->ctx, err);
233
234 return err;
235 }
236
237 /**
238 * @brief Start processing read request synchronously.
239 *
240 * @param dev RZ ADC device
241 * @param sequence ADC sequence description
242 *
243 * @return 0 on success
244 * @return -ENOTSUP if requested resolution or channel is out side of supported
245 * range
246 * @return -ENOMEM if buffer is not big enough
247 * (see @ref adc_rz_check_buffer_size)
248 * @return other error code returned by adc_context_wait_for_completion
249 */
adc_rz_read(const struct device * dev,const struct adc_sequence * sequence)250 static int adc_rz_read(const struct device *dev, const struct adc_sequence *sequence)
251 {
252 return adc_rz_read_async(dev, sequence, NULL);
253 }
254
adc_context_start_sampling(struct adc_context * ctx)255 static void adc_context_start_sampling(struct adc_context *ctx)
256 {
257 struct adc_rz_data *data = CONTAINER_OF(ctx, struct adc_rz_data, ctx);
258 const struct device *dev = data->dev;
259 const struct adc_rz_config *config = dev->config;
260
261 data->channels = ctx->sequence.channels;
262 /** Start a scan */
263 config->fsp_api->scanStart(&data->fsp_ctrl);
264 }
265
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)266 static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
267 {
268 struct adc_rz_data *data = CONTAINER_OF(ctx, struct adc_rz_data, ctx);
269
270 if (repeat_sampling) {
271 data->buf_id = 0;
272 }
273 }
274
275 /**
276 * @brief Function called on init for each RZ ADC device. It setups all
277 * channels.
278 *
279 * @param dev RZ ADC device
280 *
281 * @return -EIO if error
282 *
283 * @return 0 on success
284 */
adc_rz_init(const struct device * dev)285 static int adc_rz_init(const struct device *dev)
286 {
287 const struct adc_rz_config *config = dev->config;
288 struct adc_rz_data *data = dev->data;
289 fsp_err_t fsp_err = FSP_SUCCESS;
290 /**Open the ADC module */
291 config->fsp_api->open(&data->fsp_ctrl, &data->fsp_cfg);
292
293 if (FSP_SUCCESS != fsp_err) {
294 return -EIO;
295 }
296 /** Release context unconditionally */
297 adc_context_unlock_unconditionally(&data->ctx);
298
299 return 0;
300 }
301
302 /**
303 * ************************* DRIVER REGISTER SECTION ***************************
304 */
305
306 #define ADC_RZG_IRQ_CONNECT(idx, irq_name, isr) \
307 do { \
308 IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, irq_name, irq), \
309 DT_INST_IRQ_BY_NAME(idx, irq_name, priority), isr, \
310 DEVICE_DT_INST_GET(idx), 0); \
311 irq_enable(DT_INST_IRQ_BY_NAME(idx, irq_name, irq)); \
312 } while (0)
313
314 #define ADC_RZG_CONFIG_FUNC(idx) ADC_RZG_IRQ_CONNECT(idx, scanend, adc_rz_isr);
315
316 #define ADC_RZG_INIT(idx) \
317 static const adc_c_extended_cfg_t g_adc##idx##_cfg_extend = { \
318 .trigger_mode = ADC_C_TRIGGER_MODE_SOFTWARE, \
319 .trigger_source = ADC_C_ACTIVE_TRIGGER_EXTERNAL, \
320 .trigger_edge = ADC_C_TRIGGER_EDGE_FALLING, \
321 .input_mode = ADC_C_INPUT_MODE_AUTO, \
322 .operating_mode = ADC_C_OPERATING_MODE_SCAN, \
323 .buffer_mode = ADC_C_BUFFER_MODE_1, \
324 .sampling_time = 100, \
325 .external_trigger_filter = ADC_C_FILTER_STAGE_SETTING_DISABLE, \
326 }; \
327 static DEVICE_API(adc, adc_rz_api_##idx) = { \
328 .channel_setup = adc_rz_channel_setup, \
329 .read = adc_rz_read, \
330 .ref_internal = DT_INST_PROP(idx, vref_mv), \
331 IF_ENABLED(CONFIG_ADC_ASYNC, \
332 (.read_async = adc_rz_read_async))}; \
333 static const struct adc_rz_config adc_rz_config_##idx = { \
334 .channel_available_mask = DT_INST_PROP(idx, channel_available_mask), \
335 .fsp_api = &g_adc_on_adc, \
336 }; \
337 static struct adc_rz_data adc_rz_data_##idx = { \
338 ADC_CONTEXT_INIT_TIMER(adc_rz_data_##idx, ctx), \
339 ADC_CONTEXT_INIT_LOCK(adc_rz_data_##idx, ctx), \
340 ADC_CONTEXT_INIT_SYNC(adc_rz_data_##idx, ctx), \
341 .dev = DEVICE_DT_INST_GET(idx), \
342 .fsp_cfg = \
343 { \
344 .mode = ADC_MODE_SINGLE_SCAN, \
345 .p_callback = NULL, \
346 .p_context = NULL, \
347 .p_extend = &g_adc##idx##_cfg_extend, \
348 .scan_end_irq = DT_INST_IRQ_BY_NAME(idx, scanend, irq), \
349 .scan_end_ipl = DT_INST_IRQ_BY_NAME(idx, scanend, priority), \
350 }, \
351 .fsp_channel_cfg = \
352 { \
353 .scan_mask = 0, \
354 .interrupt_setting = ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE, \
355 }, \
356 }; \
357 static int adc_rz_init_##idx(const struct device *dev) \
358 { \
359 ADC_RZG_CONFIG_FUNC(idx) \
360 return adc_rz_init(dev); \
361 } \
362 DEVICE_DT_INST_DEFINE(idx, adc_rz_init_##idx, NULL, &adc_rz_data_##idx, \
363 &adc_rz_config_##idx, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \
364 &adc_rz_api_##idx)
365
366 DT_INST_FOREACH_STATUS_OKAY(ADC_RZG_INIT);
367