1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define ADC_CONTEXT_USES_KERNEL_TIMER
8 #include "adc_context.h"
9 #include <nrfx_adc.h>
10 #include <zephyr/dt-bindings/adc/nrf-adc.h>
11 
12 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
13 #include <zephyr/logging/log.h>
14 #include <zephyr/irq.h>
15 LOG_MODULE_REGISTER(adc_nrfx_adc);
16 
17 #define DT_DRV_COMPAT nordic_nrf_adc
18 
19 /* Ensure that definitions in nrf-adc.h match MDK. */
20 BUILD_ASSERT((NRF_ADC_AIN0 == NRF_ADC_CONFIG_INPUT_0) &&
21 	     (NRF_ADC_AIN1 == NRF_ADC_CONFIG_INPUT_1) &&
22 	     (NRF_ADC_AIN2 == NRF_ADC_CONFIG_INPUT_2) &&
23 	     (NRF_ADC_AIN3 == NRF_ADC_CONFIG_INPUT_3) &&
24 	     (NRF_ADC_AIN4 == NRF_ADC_CONFIG_INPUT_4) &&
25 	     (NRF_ADC_AIN5 == NRF_ADC_CONFIG_INPUT_5) &&
26 	     (NRF_ADC_AIN6 == NRF_ADC_CONFIG_INPUT_6) &&
27 	     (NRF_ADC_AIN7 == NRF_ADC_CONFIG_INPUT_7),
28 	     "Definitions from nrf-adc.h do not match those from nrf_adc.h");
29 
30 struct driver_data {
31 	struct adc_context ctx;
32 
33 	nrf_adc_value_t *buffer;
34 	uint8_t active_channels;
35 };
36 
37 static struct driver_data m_data = {
38 	ADC_CONTEXT_INIT_TIMER(m_data, ctx),
39 	ADC_CONTEXT_INIT_LOCK(m_data, ctx),
40 	ADC_CONTEXT_INIT_SYNC(m_data, ctx),
41 };
42 
43 static nrfx_adc_channel_t m_channels[CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT];
44 
45 
46 /* Implementation of the ADC driver API function: adc_channel_setup. */
adc_nrfx_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)47 static int adc_nrfx_channel_setup(const struct device *dev,
48 				  const struct adc_channel_cfg *channel_cfg)
49 {
50 	uint8_t channel_id = channel_cfg->channel_id;
51 	nrf_adc_config_t *config = &m_channels[channel_id].config;
52 
53 	if (channel_id >= CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT) {
54 		return -EINVAL;
55 	}
56 
57 	if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
58 		LOG_ERR("Selected ADC acquisition time is not valid");
59 		return -EINVAL;
60 	}
61 
62 	if (channel_cfg->differential) {
63 		LOG_ERR("Differential channels are not supported");
64 		return -EINVAL;
65 	}
66 
67 	switch (channel_cfg->gain) {
68 	case ADC_GAIN_1_3:
69 		config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD;
70 		break;
71 	case ADC_GAIN_2_3:
72 		config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS;
73 		break;
74 	case ADC_GAIN_1:
75 		config->scaling = NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE;
76 		break;
77 	default:
78 		LOG_ERR("Selected ADC gain is not valid");
79 		return -EINVAL;
80 	}
81 
82 	switch (channel_cfg->reference) {
83 	case ADC_REF_INTERNAL:
84 		config->reference = NRF_ADC_CONFIG_REF_VBG;
85 		config->extref    = NRF_ADC_CONFIG_EXTREFSEL_NONE;
86 		break;
87 	case ADC_REF_VDD_1_2:
88 		config->reference = NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF;
89 		config->extref    = NRF_ADC_CONFIG_EXTREFSEL_NONE;
90 		break;
91 	case ADC_REF_VDD_1_3:
92 		config->reference = NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD;
93 		config->extref    = NRF_ADC_CONFIG_EXTREFSEL_NONE;
94 		break;
95 	case ADC_REF_EXTERNAL0:
96 		config->reference = NRF_ADC_CONFIG_REF_EXT;
97 		config->extref    = NRF_ADC_CONFIG_EXTREFSEL_AREF0;
98 		break;
99 	case ADC_REF_EXTERNAL1:
100 		config->reference = NRF_ADC_CONFIG_REF_EXT;
101 		config->extref    = NRF_ADC_CONFIG_EXTREFSEL_AREF1;
102 		break;
103 	default:
104 		LOG_ERR("Selected ADC reference is not valid");
105 		return -EINVAL;
106 	}
107 
108 	config->input = channel_cfg->input_positive;
109 
110 	config->resolution = NRF_ADC_CONFIG_RES_8BIT;
111 
112 	return 0;
113 }
114 
adc_context_start_sampling(struct adc_context * ctx)115 static void adc_context_start_sampling(struct adc_context *ctx)
116 {
117 	ARG_UNUSED(ctx);
118 
119 	nrfx_adc_buffer_convert(m_data.buffer, m_data.active_channels);
120 	nrfx_adc_sample();
121 }
122 
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat)123 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
124 					      bool repeat)
125 {
126 	ARG_UNUSED(ctx);
127 
128 	if (!repeat) {
129 		m_data.buffer += m_data.active_channels;
130 	}
131 }
132 
check_buffer_size(const struct adc_sequence * sequence,uint8_t active_channels)133 static int check_buffer_size(const struct adc_sequence *sequence,
134 			     uint8_t active_channels)
135 {
136 	size_t needed_buffer_size;
137 
138 	needed_buffer_size = active_channels * sizeof(nrf_adc_value_t);
139 	if (sequence->options) {
140 		needed_buffer_size *= (1 + sequence->options->extra_samplings);
141 	}
142 
143 	if (sequence->buffer_size < needed_buffer_size) {
144 		LOG_ERR("Provided buffer is too small (%u/%u)",
145 				sequence->buffer_size, needed_buffer_size);
146 		return -ENOMEM;
147 	}
148 
149 	return 0;
150 }
151 
start_read(const struct device * dev,const struct adc_sequence * sequence)152 static int start_read(const struct device *dev,
153 		      const struct adc_sequence *sequence)
154 {
155 	int error;
156 	uint32_t selected_channels = sequence->channels;
157 	uint8_t active_channels;
158 	uint8_t channel_id;
159 	nrf_adc_config_resolution_t nrf_resolution;
160 
161 	/* Signal an error if channel selection is invalid (no channels or
162 	 * a non-existing one is selected).
163 	 */
164 	if (!selected_channels ||
165 	    (selected_channels &
166 			~BIT_MASK(CONFIG_ADC_NRFX_ADC_CHANNEL_COUNT))) {
167 		LOG_ERR("Invalid selection of channels");
168 		return -EINVAL;
169 	}
170 
171 	if (sequence->oversampling != 0U) {
172 		LOG_ERR("Oversampling is not supported");
173 		return -EINVAL;
174 	}
175 
176 	switch (sequence->resolution) {
177 	case  8:
178 		nrf_resolution = NRF_ADC_CONFIG_RES_8BIT;
179 		break;
180 	case  9:
181 		nrf_resolution = NRF_ADC_CONFIG_RES_9BIT;
182 		break;
183 	case 10:
184 		nrf_resolution = NRF_ADC_CONFIG_RES_10BIT;
185 		break;
186 	default:
187 		LOG_ERR("ADC resolution value %d is not valid",
188 			    sequence->resolution);
189 		return -EINVAL;
190 	}
191 
192 	active_channels = 0U;
193 	nrfx_adc_all_channels_disable();
194 
195 	/* Enable the channels selected for the pointed sequence.
196 	 */
197 	channel_id = 0U;
198 	while (selected_channels) {
199 		if (selected_channels & BIT(0)) {
200 			/* The nrfx driver requires setting the resolution
201 			 * for each enabled channel individually.
202 			 */
203 			m_channels[channel_id].config.resolution =
204 				nrf_resolution;
205 			nrfx_adc_channel_enable(&m_channels[channel_id]);
206 			++active_channels;
207 		}
208 		selected_channels >>= 1;
209 		++channel_id;
210 	}
211 
212 	error = check_buffer_size(sequence, active_channels);
213 	if (error) {
214 		return error;
215 	}
216 
217 	m_data.buffer = sequence->buffer;
218 	m_data.active_channels = active_channels;
219 
220 	adc_context_start_read(&m_data.ctx, sequence);
221 
222 	error = adc_context_wait_for_completion(&m_data.ctx);
223 	return error;
224 }
225 
226 /* Implementation of the ADC driver API function: adc_read. */
adc_nrfx_read(const struct device * dev,const struct adc_sequence * sequence)227 static int adc_nrfx_read(const struct device *dev,
228 			 const struct adc_sequence *sequence)
229 {
230 	int error;
231 
232 	adc_context_lock(&m_data.ctx, false, NULL);
233 	error = start_read(dev, sequence);
234 	adc_context_release(&m_data.ctx, error);
235 
236 	return error;
237 }
238 
239 #ifdef CONFIG_ADC_ASYNC
240 /* Implementation of the ADC driver API function: adc_read_sync. */
adc_nrfx_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)241 static int adc_nrfx_read_async(const struct device *dev,
242 			       const struct adc_sequence *sequence,
243 			       struct k_poll_signal *async)
244 {
245 	int error;
246 
247 	adc_context_lock(&m_data.ctx, true, async);
248 	error = start_read(dev, sequence);
249 	adc_context_release(&m_data.ctx, error);
250 
251 	return error;
252 }
253 #endif /* CONFIG_ADC_ASYNC */
254 
event_handler(const nrfx_adc_evt_t * p_event)255 static void event_handler(const nrfx_adc_evt_t *p_event)
256 {
257 	const struct device *const dev = DEVICE_DT_INST_GET(0);
258 
259 	if (p_event->type == NRFX_ADC_EVT_DONE) {
260 		adc_context_on_sampling_done(&m_data.ctx, dev);
261 	}
262 }
263 
init_adc(const struct device * dev)264 static int init_adc(const struct device *dev)
265 {
266 	const nrfx_adc_config_t config = NRFX_ADC_DEFAULT_CONFIG;
267 
268 	nrfx_err_t result = nrfx_adc_init(&config, event_handler);
269 
270 	if (result != NRFX_SUCCESS) {
271 		LOG_ERR("Failed to initialize device: %s",
272 			    dev->name);
273 		return -EBUSY;
274 	}
275 
276 	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
277 		    nrfx_isr, nrfx_adc_irq_handler, 0);
278 
279 	adc_context_unlock_unconditionally(&m_data.ctx);
280 
281 	return 0;
282 }
283 
284 static const struct adc_driver_api adc_nrfx_driver_api = {
285 	.channel_setup = adc_nrfx_channel_setup,
286 	.read          = adc_nrfx_read,
287 #ifdef CONFIG_ADC_ASYNC
288 	.read_async    = adc_nrfx_read_async,
289 #endif
290 	.ref_internal  = 1200,
291 };
292 
293 /*
294  * There is only one instance on supported SoCs, so inst is guaranteed
295  * to be 0 if any instance is okay. (We use adc_0 above, so the driver
296  * is relying on the numeric instance value in a way that happens to
297  * be safe.)
298  *
299  * Just in case that assumption becomes invalid in the future, we use
300  * a BUILD_ASSERT().
301  */
302 #define ADC_INIT(inst)							\
303 	BUILD_ASSERT((inst) == 0,					\
304 		     "multiple instances not supported");		\
305 	DEVICE_DT_INST_DEFINE(0,					\
306 			    init_adc, NULL, NULL, NULL,			\
307 			    POST_KERNEL,				\
308 			    CONFIG_ADC_INIT_PRIORITY,			\
309 			    &adc_nrfx_driver_api);
310 
311 DT_INST_FOREACH_STATUS_OKAY(ADC_INIT)
312