1 /*
2 * Copyright (c) 2024 ENE Technology Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ene_kb1200_adc
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/adc.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <errno.h>
13 #include <reg/adc.h>
14 #include <zephyr/logging/log.h>
15
16 #define ADC_CONTEXT_USES_KERNEL_TIMER
17 #include "adc_context.h"
18
19 LOG_MODULE_REGISTER(adc_ene_kb1200, CONFIG_ADC_LOG_LEVEL);
20
21 struct adc_kb1200_config {
22 /* ADC Register base address */
23 struct adc_regs *adc;
24 /* Pin control */
25 const struct pinctrl_dev_config *pcfg;
26 };
27
28 struct adc_kb1200_data {
29 struct adc_context ctx;
30 const struct device *adc_dev;
31 uint16_t *buffer;
32 uint16_t *repeat_buffer;
33 uint16_t *buf_end;
34 };
35
36 /* ADC local functions */
adc_kb1200_validate_buffer_size(const struct adc_sequence * sequence)37 static bool adc_kb1200_validate_buffer_size(const struct adc_sequence *sequence)
38 {
39 int chan_count = 0;
40 size_t buff_need;
41 uint32_t chan_mask;
42
43 for (chan_mask = 0x80; chan_mask != 0; chan_mask >>= 1) {
44 if (chan_mask & sequence->channels) {
45 chan_count++;
46 }
47 }
48
49 buff_need = chan_count * sizeof(uint16_t);
50
51 if (sequence->options) {
52 buff_need *= 1 + sequence->options->extra_samplings;
53 }
54
55 if (buff_need > sequence->buffer_size) {
56 return false;
57 }
58
59 return true;
60 }
61 /* ADC Sample Flow (by using adc_context.h api function)
62 * 1. Start ADC sampling (set up flag ctx->sync)
63 * adc_context_start_read() -> adc_context_start_sampling()
64 * 2. Wait ADC sample finish (by monitor flag ctx->sync)
65 * adc_context_wait_for_completion
66 * 3. Finish ADC sample (isr clear flag ctx->sync)
67 * adc_context_on_sampling_done -> adc_context_complete
68 */
adc_kb1200_start_read(const struct device * dev,const struct adc_sequence * sequence)69 static int adc_kb1200_start_read(const struct device *dev, const struct adc_sequence *sequence)
70 {
71 const struct adc_kb1200_config *config = dev->config;
72 struct adc_kb1200_data *data = dev->data;
73 int error = 0;
74
75 if (!sequence->channels || (sequence->channels & ~BIT_MASK(ADC_MAX_CHAN))) {
76 LOG_ERR("Invalid ADC channels.");
77 return -EINVAL;
78 }
79 /* Fixed 10 bit resolution of ene ADC */
80 if (sequence->resolution != ADC_RESOLUTION) {
81 LOG_ERR("Unfixed 10 bit ADC resolution.");
82 return -ENOTSUP;
83 }
84 /* Check sequence->buffer_size is enough */
85 if (!adc_kb1200_validate_buffer_size(sequence)) {
86 LOG_ERR("ADC buffer size too small.");
87 return -ENOMEM;
88 }
89
90 /* assign record buffer pointer */
91 data->buffer = sequence->buffer;
92 data->buf_end = data->buffer + sequence->buffer_size / sizeof(uint16_t);
93 /* store device for adc_context_start_read() */
94 data->adc_dev = dev;
95 /* Inform adc start sampling */
96 adc_context_start_read(&data->ctx, sequence);
97 /* Since kb1200 adc has no irq. So need polling the adc conversion
98 * flag to be valid, then record adc value.
99 */
100 uint32_t channels = (config->adc->ADCCFG & ADC_CHANNEL_BIT_MASK) >> ADC_CHANNEL_BIT_POS;
101
102 while (channels) {
103 int count;
104 int ch_num;
105
106 count = 0;
107 ch_num = find_lsb_set(channels) - 1;
108 /* wait valid flag */
109 while (config->adc->ADCDAT[ch_num] & ADC_INVALID_VALUE) {
110 k_busy_wait(ADC_WAIT_TIME);
111 count++;
112 if (count >= ADC_WAIT_CNT) {
113 LOG_ERR("ADC busy timeout...");
114 error = -EBUSY;
115 break;
116 }
117 }
118 /* check buffer size is enough then record adc value */
119 if (data->buffer < data->buf_end) {
120 *data->buffer = (uint16_t)(config->adc->ADCDAT[ch_num]);
121 data->buffer++;
122 } else {
123 error = -EINVAL;
124 break;
125 }
126
127 /* clear completed channel */
128 channels &= ~BIT(ch_num);
129 }
130 /* Besause polling the adc conversion flag. don't need wait_for_completion*/
131
132 /* Inform adc sampling is done */
133 adc_context_on_sampling_done(&data->ctx, dev);
134 return error;
135 }
136
137 /* ADC api functions */
adc_kb1200_channel_setup(const struct device * dev,const struct adc_channel_cfg * channel_cfg)138 static int adc_kb1200_channel_setup(const struct device *dev,
139 const struct adc_channel_cfg *channel_cfg)
140 {
141 if (channel_cfg->channel_id >= ADC_MAX_CHAN) {
142 LOG_ERR("Invalid channel %d.", channel_cfg->channel_id);
143 return -EINVAL;
144 }
145
146 if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) {
147 LOG_ERR("Unsupported channel acquisition time.");
148 return -ENOTSUP;
149 }
150
151 if (channel_cfg->differential) {
152 LOG_ERR("Differential channels are not supported.");
153 return -ENOTSUP;
154 }
155
156 if (channel_cfg->gain != ADC_GAIN_1) {
157 LOG_ERR("Unsupported channel gain %d.", channel_cfg->gain);
158 return -ENOTSUP;
159 }
160
161 if (channel_cfg->reference != ADC_REF_INTERNAL) {
162 LOG_ERR("Unsupported channel reference.");
163 return -ENOTSUP;
164 }
165 LOG_DBG("ADC channel %d configured.", channel_cfg->channel_id);
166 return 0;
167 }
168
adc_kb1200_read(const struct device * dev,const struct adc_sequence * sequence)169 static int adc_kb1200_read(const struct device *dev, const struct adc_sequence *sequence)
170 {
171 struct adc_kb1200_data *data = dev->data;
172 int error;
173
174 adc_context_lock(&data->ctx, false, NULL);
175 error = adc_kb1200_start_read(dev, sequence);
176 adc_context_release(&data->ctx, error);
177
178 return error;
179 }
180
181 #if defined(CONFIG_ADC_ASYNC)
adc_kb1200_read_async(const struct device * dev,const struct adc_sequence * sequence,struct k_poll_signal * async)182 static int adc_kb1200_read_async(const struct device *dev, const struct adc_sequence *sequence,
183 struct k_poll_signal *async)
184 {
185 struct adc_kb1200_data *data = dev->data;
186 int error;
187
188 adc_context_lock(&data->ctx, true, async);
189 error = adc_kb1200_start_read(dev, sequence);
190 adc_context_release(&data->ctx, error);
191
192 return error;
193 }
194 #endif /* CONFIG_ADC_ASYNC */
195
196 /* ADC api function (using by adc_context.H function) */
adc_context_start_sampling(struct adc_context * ctx)197 static void adc_context_start_sampling(struct adc_context *ctx)
198 {
199 struct adc_kb1200_data *data = CONTAINER_OF(ctx, struct adc_kb1200_data, ctx);
200 const struct device *dev = data->adc_dev;
201 const struct adc_kb1200_config *config = dev->config;
202
203 data->repeat_buffer = data->buffer;
204 config->adc->ADCCFG = (config->adc->ADCCFG & ~ADC_CHANNEL_BIT_MASK) |
205 (ctx->sequence.channels << ADC_CHANNEL_BIT_POS);
206 config->adc->ADCCFG |= ADC_FUNCTION_ENABLE;
207 }
208
adc_context_update_buffer_pointer(struct adc_context * ctx,bool repeat_sampling)209 static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
210 {
211 struct adc_kb1200_data *data = CONTAINER_OF(ctx, struct adc_kb1200_data, ctx);
212
213 if (repeat_sampling) {
214 data->buffer = data->repeat_buffer;
215 }
216 }
217
218 static DEVICE_API(adc, adc_kb1200_api) = {
219 .channel_setup = adc_kb1200_channel_setup,
220 .read = adc_kb1200_read,
221 .ref_internal = ADC_VREF_ANALOG,
222 #if defined(CONFIG_ADC_ASYNC)
223 .read_async = adc_kb1200_read_async,
224 #endif
225 };
226
adc_kb1200_init(const struct device * dev)227 static int adc_kb1200_init(const struct device *dev)
228 {
229 const struct adc_kb1200_config *config = dev->config;
230 struct adc_kb1200_data *data = dev->data;
231 int ret;
232
233 adc_context_unlock_unconditionally(&data->ctx);
234 /* Configure pin-mux for ADC device */
235 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
236 if (ret < 0) {
237 LOG_ERR("ADC pinctrl setup failed (%d).", ret);
238 return ret;
239 }
240
241 return 0;
242 }
243
244 #define ADC_KB1200_DEVICE(inst) \
245 PINCTRL_DT_INST_DEFINE(inst); \
246 static struct adc_kb1200_data adc_kb1200_data_##inst = { \
247 ADC_CONTEXT_INIT_TIMER(adc_kb1200_data_##inst, ctx), \
248 ADC_CONTEXT_INIT_LOCK(adc_kb1200_data_##inst, ctx), \
249 ADC_CONTEXT_INIT_SYNC(adc_kb1200_data_##inst, ctx), \
250 }; \
251 static const struct adc_kb1200_config adc_kb1200_config_##inst = { \
252 .adc = (struct adc_regs *)DT_INST_REG_ADDR(inst), \
253 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
254 }; \
255 DEVICE_DT_INST_DEFINE(inst, adc_kb1200_init, NULL, &adc_kb1200_data_##inst, \
256 &adc_kb1200_config_##inst, PRE_KERNEL_1, \
257 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &adc_kb1200_api);
258
259 DT_INST_FOREACH_STATUS_OKAY(ADC_KB1200_DEVICE)
260