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