1 /*
2 * Copyright (c) 2019 Vestas Wind Systems A/S
3 *
4 * Based on adc_mcux_adc16.c, which is:
5 * Copyright (c) 2017-2018, NXP
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #define DT_DRV_COMPAT nxp_kinetis_adc12
11
12 #include <zephyr/drivers/adc.h>
13 #include <fsl_adc12.h>
14 #include <zephyr/drivers/pinctrl.h>
15
16 #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 #include <zephyr/irq.h>
19 LOG_MODULE_REGISTER(adc_mcux_adc12);
20
21 #define ADC_CONTEXT_USES_KERNEL_TIMER
22 #include "adc_context.h"
23
24 struct mcux_adc12_config {
25 ADC_Type *base;
26 adc12_clock_source_t clock_src;
27 adc12_clock_divider_t clock_div;
28 adc12_reference_voltage_source_t ref_src;
29 uint32_t sample_clk_count;
30 void (*irq_config_func)(const struct device *dev);
31 const struct pinctrl_dev_config *pincfg;
32 };
33
34 struct mcux_adc12_data {
35 const struct device *dev;
36 struct adc_context ctx;
37 uint16_t *buffer;
38 uint16_t *repeat_buffer;
39 uint32_t channels;
40 uint8_t channel_id;
41 };
42
mcux_adc12_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)43 static int mcux_adc12_channel_setup(const struct device *dev,
44 const struct adc_channel_cfg *channel_cfg)
45 {
46 uint8_t channel_id = channel_cfg->channel_id;
47
48 if (channel_id > (ADC_SC1_ADCH_MASK >> ADC_SC1_ADCH_SHIFT)) {
49 LOG_ERR("Invalid channel %d", channel_id);
50 return -EINVAL;
51 }
52
53 if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
54 LOG_ERR("Unsupported channel acquisition time");
55 return -ENOTSUP;
56 }
57
58 if (channel_cfg->differential) {
59 LOG_ERR("Differential channels are not supported");
60 return -ENOTSUP;
61 }
62
63 if (channel_cfg->gain != ADC_GAIN_1) {
64 LOG_ERR("Unsupported channel gain %d", channel_cfg->gain);
65 return -ENOTSUP;
66 }
67
68 if (channel_cfg->reference != ADC_REF_INTERNAL) {
69 LOG_ERR("Unsupported channel reference");
70 return -ENOTSUP;
71 }
72
73 return 0;
74 }
75
mcux_adc12_start_read(const struct device * dev,const struct adc_sequence * sequence)76 static int mcux_adc12_start_read(const struct device *dev,
77 const struct adc_sequence *sequence)
78 {
79 const struct mcux_adc12_config *config = dev->config;
80 struct mcux_adc12_data *data = dev->data;
81 adc12_hardware_average_mode_t mode;
82 adc12_resolution_t resolution;
83 ADC_Type *base = config->base;
84 int error;
85 uint32_t tmp32;
86
87 switch (sequence->resolution) {
88 case 8:
89 resolution = kADC12_Resolution8Bit;
90 break;
91 case 10:
92 resolution = kADC12_Resolution10Bit;
93 break;
94 case 12:
95 resolution = kADC12_Resolution12Bit;
96 break;
97 default:
98 LOG_ERR("Unsupported resolution %d", sequence->resolution);
99 return -ENOTSUP;
100 }
101
102 tmp32 = base->CFG1 & ~(ADC_CFG1_MODE_MASK);
103 tmp32 |= ADC_CFG1_MODE(resolution);
104 base->CFG1 = tmp32;
105
106 switch (sequence->oversampling) {
107 case 0:
108 mode = kADC12_HardwareAverageDisabled;
109 break;
110 case 2:
111 mode = kADC12_HardwareAverageCount4;
112 break;
113 case 3:
114 mode = kADC12_HardwareAverageCount8;
115 break;
116 case 4:
117 mode = kADC12_HardwareAverageCount16;
118 break;
119 case 5:
120 mode = kADC12_HardwareAverageCount32;
121 break;
122 default:
123 LOG_ERR("Unsupported oversampling value %d",
124 sequence->oversampling);
125 return -ENOTSUP;
126 }
127 ADC12_SetHardwareAverage(config->base, mode);
128
129 data->buffer = sequence->buffer;
130 adc_context_start_read(&data->ctx, sequence);
131 error = adc_context_wait_for_completion(&data->ctx);
132
133 return error;
134 }
135
mcux_adc12_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)136 static int mcux_adc12_read_async(const struct device *dev,
137 const struct adc_sequence *sequence,
138 struct k_poll_signal *async)
139 {
140 struct mcux_adc12_data *data = dev->data;
141 int error;
142
143 adc_context_lock(&data->ctx, async ? true : false, async);
144 error = mcux_adc12_start_read(dev, sequence);
145 adc_context_release(&data->ctx, error);
146
147 return error;
148 }
149
mcux_adc12_read(const struct device * dev,const struct adc_sequence * sequence)150 static int mcux_adc12_read(const struct device *dev,
151 const struct adc_sequence *sequence)
152 {
153 return mcux_adc12_read_async(dev, sequence, NULL);
154 }
155
mcux_adc12_start_channel(const struct device * dev)156 static void mcux_adc12_start_channel(const struct device *dev)
157 {
158 const struct mcux_adc12_config *config = dev->config;
159 struct mcux_adc12_data *data = dev->data;
160
161 adc12_channel_config_t channel_config;
162 uint32_t channel_group = 0U;
163
164 data->channel_id = find_lsb_set(data->channels) - 1;
165
166 LOG_DBG("Starting channel %d", data->channel_id);
167 channel_config.enableInterruptOnConversionCompleted = true;
168 channel_config.channelNumber = data->channel_id;
169 ADC12_SetChannelConfig(config->base, channel_group, &channel_config);
170 }
171
adc_context_start_sampling(struct adc_context * ctx)172 static void adc_context_start_sampling(struct adc_context *ctx)
173 {
174 struct mcux_adc12_data *data =
175 CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
176
177 data->channels = ctx->sequence.channels;
178 data->repeat_buffer = data->buffer;
179
180 mcux_adc12_start_channel(data->dev);
181 }
182
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)183 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
184 bool repeat_sampling)
185 {
186 struct mcux_adc12_data *data =
187 CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
188
189 if (repeat_sampling) {
190 data->buffer = data->repeat_buffer;
191 }
192 }
193
mcux_adc12_isr(const struct device * dev)194 static void mcux_adc12_isr(const struct device *dev)
195 {
196 const struct mcux_adc12_config *config = dev->config;
197 struct mcux_adc12_data *data = dev->data;
198 ADC_Type *base = config->base;
199 uint32_t channel_group = 0U;
200 uint16_t result;
201
202 result = ADC12_GetChannelConversionValue(base, channel_group);
203 LOG_DBG("Finished channel %d. Result is 0x%04x",
204 data->channel_id, result);
205
206 *data->buffer++ = result;
207 data->channels &= ~BIT(data->channel_id);
208
209 if (data->channels) {
210 mcux_adc12_start_channel(dev);
211 } else {
212 adc_context_on_sampling_done(&data->ctx, dev);
213 }
214 }
215
mcux_adc12_init(const struct device * dev)216 static int mcux_adc12_init(const struct device *dev)
217 {
218 const struct mcux_adc12_config *config = dev->config;
219 struct mcux_adc12_data *data = dev->data;
220 ADC_Type *base = config->base;
221 adc12_config_t adc_config;
222 int err;
223
224 ADC12_GetDefaultConfig(&adc_config);
225
226 adc_config.referenceVoltageSource = config->ref_src;
227 adc_config.clockSource = config->clock_src;
228 adc_config.clockDivider = config->clock_div;
229 adc_config.sampleClockCount = config->sample_clk_count;
230 adc_config.resolution = kADC12_Resolution12Bit;
231 adc_config.enableContinuousConversion = false;
232
233 ADC12_Init(base, &adc_config);
234 ADC12_DoAutoCalibration(base);
235 ADC12_EnableHardwareTrigger(base, false);
236
237 config->irq_config_func(dev);
238 data->dev = dev;
239
240 err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
241 if (err) {
242 return err;
243 }
244
245 adc_context_unlock_unconditionally(&data->ctx);
246
247 return 0;
248 }
249
250 static const struct adc_driver_api mcux_adc12_driver_api = {
251 .channel_setup = mcux_adc12_channel_setup,
252 .read = mcux_adc12_read,
253 #ifdef CONFIG_ADC_ASYNC
254 .read_async = mcux_adc12_read_async,
255 #endif
256 };
257
258 #define ASSERT_WITHIN_RANGE(val, min, max, str) \
259 BUILD_ASSERT(val >= min && val <= max, str)
260 #define ASSERT_ADC12_CLK_DIV_VALID(val, str) \
261 BUILD_ASSERT(val == 1 || val == 2 || val == 4 || val == 8, str)
262 #define TO_ADC12_CLOCK_SRC(val) _DO_CONCAT(kADC12_ClockSourceAlt, val)
263 #define TO_ADC12_CLOCK_DIV(val) _DO_CONCAT(kADC12_ClockDivider, val)
264
265 #define ADC12_REF_SRC(n) \
266 COND_CODE_1(DT_INST_PROP(0, alternate_voltage_reference), \
267 (kADC12_ReferenceVoltageSourceValt), \
268 (kADC12_ReferenceVoltageSourceVref))
269
270 #define ACD12_MCUX_INIT(n) \
271 static void mcux_adc12_config_func_##n(const struct device *dev); \
272 \
273 PINCTRL_DT_INST_DEFINE(n); \
274 \
275 ASSERT_WITHIN_RANGE(DT_INST_PROP(n, clk_source), 0, 3, \
276 "Invalid clock source"); \
277 ASSERT_ADC12_CLK_DIV_VALID(DT_INST_PROP(n, clk_divider), \
278 "Invalid clock divider"); \
279 ASSERT_WITHIN_RANGE(DT_INST_PROP(n, sample_time), 2, 256, \
280 "Invalid sample time"); \
281 static const struct mcux_adc12_config mcux_adc12_config_##n = { \
282 .base = (ADC_Type *)DT_INST_REG_ADDR(n), \
283 .clock_src = TO_ADC12_CLOCK_SRC(DT_INST_PROP(n, clk_source)),\
284 .clock_div = \
285 TO_ADC12_CLOCK_DIV(DT_INST_PROP(n, clk_divider)),\
286 .ref_src = ADC12_REF_SRC(n), \
287 .sample_clk_count = DT_INST_PROP(n, sample_time), \
288 .irq_config_func = mcux_adc12_config_func_##n, \
289 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
290 }; \
291 \
292 static struct mcux_adc12_data mcux_adc12_data_##n = { \
293 ADC_CONTEXT_INIT_TIMER(mcux_adc12_data_##n, ctx), \
294 ADC_CONTEXT_INIT_LOCK(mcux_adc12_data_##n, ctx), \
295 ADC_CONTEXT_INIT_SYNC(mcux_adc12_data_##n, ctx), \
296 }; \
297 \
298 DEVICE_DT_INST_DEFINE(n, &mcux_adc12_init, \
299 NULL, &mcux_adc12_data_##n, \
300 &mcux_adc12_config_##n, POST_KERNEL, \
301 CONFIG_ADC_INIT_PRIORITY, \
302 &mcux_adc12_driver_api); \
303 \
304 static void mcux_adc12_config_func_##n(const struct device *dev) \
305 { \
306 IRQ_CONNECT(DT_INST_IRQN(n), \
307 DT_INST_IRQ(n, priority), mcux_adc12_isr, \
308 DEVICE_DT_INST_GET(n), 0); \
309 \
310 irq_enable(DT_INST_IRQN(n)); \
311 }
312
313 DT_INST_FOREACH_STATUS_OKAY(ACD12_MCUX_INIT)
314