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_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 #if defined(CONFIG_SOC_S32K146) || defined(CONFIG_SOC_S32K148)
170 if (data->channel_id >= 16) {
171 /*
172 * channels 16..31 are encoded as 100000b..101111b in
173 * SC1[ADCH] field
174 */
175 channel_config.channelNumber += 16;
176 }
177 #endif
178 ADC12_SetChannelConfig(config->base, channel_group, &channel_config);
179 }
180
adc_context_start_sampling(struct adc_context * ctx)181 static void adc_context_start_sampling(struct adc_context *ctx)
182 {
183 struct mcux_adc12_data *data =
184 CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
185
186 data->channels = ctx->sequence.channels;
187 data->repeat_buffer = data->buffer;
188
189 mcux_adc12_start_channel(data->dev);
190 }
191
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)192 static void adc_context_update_buffer_pointer(struct adc_context *ctx,
193 bool repeat_sampling)
194 {
195 struct mcux_adc12_data *data =
196 CONTAINER_OF(ctx, struct mcux_adc12_data, ctx);
197
198 if (repeat_sampling) {
199 data->buffer = data->repeat_buffer;
200 }
201 }
202
mcux_adc12_isr(const struct device * dev)203 static void mcux_adc12_isr(const struct device *dev)
204 {
205 const struct mcux_adc12_config *config = dev->config;
206 struct mcux_adc12_data *data = dev->data;
207 ADC_Type *base = config->base;
208 uint32_t channel_group = 0U;
209 uint16_t result;
210
211 result = ADC12_GetChannelConversionValue(base, channel_group);
212 LOG_DBG("Finished channel %d. Result is 0x%04x",
213 data->channel_id, result);
214
215 *data->buffer++ = result;
216 data->channels &= ~BIT(data->channel_id);
217
218 if (data->channels) {
219 mcux_adc12_start_channel(dev);
220 } else {
221 adc_context_on_sampling_done(&data->ctx, dev);
222 }
223 }
224
mcux_adc12_init(const struct device * dev)225 static int mcux_adc12_init(const struct device *dev)
226 {
227 const struct mcux_adc12_config *config = dev->config;
228 struct mcux_adc12_data *data = dev->data;
229 ADC_Type *base = config->base;
230 adc12_config_t adc_config;
231 int err;
232
233 ADC12_GetDefaultConfig(&adc_config);
234
235 adc_config.referenceVoltageSource = config->ref_src;
236 adc_config.clockSource = config->clock_src;
237 adc_config.clockDivider = config->clock_div;
238 adc_config.sampleClockCount = config->sample_clk_count;
239 adc_config.resolution = kADC12_Resolution12Bit;
240 adc_config.enableContinuousConversion = false;
241
242 ADC12_Init(base, &adc_config);
243 ADC12_DoAutoCalibration(base);
244 ADC12_EnableHardwareTrigger(base, false);
245
246 config->irq_config_func(dev);
247 data->dev = dev;
248
249 err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
250 if (err) {
251 return err;
252 }
253
254 adc_context_unlock_unconditionally(&data->ctx);
255
256 return 0;
257 }
258
259 #define ASSERT_WITHIN_RANGE(val, min, max, str) \
260 BUILD_ASSERT(val >= min && val <= max, str)
261 #define ASSERT_ADC12_CLK_DIV_VALID(val, str) \
262 BUILD_ASSERT(val == 1 || val == 2 || val == 4 || val == 8, str)
263 #define TO_ADC12_CLOCK_SRC(val) _DO_CONCAT(kADC12_ClockSourceAlt, val)
264 #define TO_ADC12_CLOCK_DIV(val) _DO_CONCAT(kADC12_ClockDivider, val)
265
266 #define ADC12_REF_SRC(n) \
267 COND_CODE_1(DT_INST_PROP(0, alternate_voltage_reference), \
268 (kADC12_ReferenceVoltageSourceValt), \
269 (kADC12_ReferenceVoltageSourceVref))
270
271 #define ADC12_MCUX_DRIVER_API(n) \
272 static DEVICE_API(adc, mcux_adc12_driver_api_##n) = { \
273 .channel_setup = mcux_adc12_channel_setup, \
274 .read = mcux_adc12_read, \
275 IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = mcux_adc12_read_async,)) \
276 .ref_internal = DT_INST_PROP(n, vref_mv), \
277 };
278
279 #define ACD12_MCUX_INIT(n) \
280 static void mcux_adc12_config_func_##n(const struct device *dev); \
281 \
282 PINCTRL_DT_INST_DEFINE(n); \
283 ADC12_MCUX_DRIVER_API(n); \
284 \
285 ASSERT_WITHIN_RANGE(DT_INST_PROP(n, clk_source), 0, 3, \
286 "Invalid clock source"); \
287 ASSERT_ADC12_CLK_DIV_VALID(DT_INST_PROP(n, clk_divider), \
288 "Invalid clock divider"); \
289 ASSERT_WITHIN_RANGE(DT_INST_PROP(n, sample_time), 2, 256, \
290 "Invalid sample time"); \
291 static const struct mcux_adc12_config mcux_adc12_config_##n = { \
292 .base = (ADC_Type *)DT_INST_REG_ADDR(n), \
293 .clock_src = TO_ADC12_CLOCK_SRC(DT_INST_PROP(n, clk_source)),\
294 .clock_div = \
295 TO_ADC12_CLOCK_DIV(DT_INST_PROP(n, clk_divider)),\
296 .ref_src = ADC12_REF_SRC(n), \
297 .sample_clk_count = DT_INST_PROP(n, sample_time), \
298 .irq_config_func = mcux_adc12_config_func_##n, \
299 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
300 }; \
301 \
302 static struct mcux_adc12_data mcux_adc12_data_##n = { \
303 ADC_CONTEXT_INIT_TIMER(mcux_adc12_data_##n, ctx), \
304 ADC_CONTEXT_INIT_LOCK(mcux_adc12_data_##n, ctx), \
305 ADC_CONTEXT_INIT_SYNC(mcux_adc12_data_##n, ctx), \
306 }; \
307 \
308 DEVICE_DT_INST_DEFINE(n, &mcux_adc12_init, \
309 NULL, &mcux_adc12_data_##n, \
310 &mcux_adc12_config_##n, POST_KERNEL, \
311 CONFIG_ADC_INIT_PRIORITY, \
312 &mcux_adc12_driver_api_##n); \
313 \
314 static void mcux_adc12_config_func_##n(const struct device *dev) \
315 { \
316 IRQ_CONNECT(DT_INST_IRQN(n), \
317 DT_INST_IRQ(n, priority), mcux_adc12_isr, \
318 DEVICE_DT_INST_GET(n), 0); \
319 \
320 irq_enable(DT_INST_IRQN(n)); \
321 }
322
323 DT_INST_FOREACH_STATUS_OKAY(ACD12_MCUX_INIT)
324