1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <nrfx_comp.h>
8
9 #include <zephyr/drivers/comparator/nrf_comp.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/pm/device.h>
12
13 #define DT_DRV_COMPAT nordic_nrf_comp
14
15 #define SHIM_NRF_COMP_DT_INST_REFSEL(inst) \
16 _CONCAT(COMP_NRF_COMP_REFSEL_, DT_INST_STRING_TOKEN(inst, refsel))
17
18 #define SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(inst) \
19 DT_INST_ENUM_HAS_VALUE(inst, refsel, AREF)
20
21 #define SHIM_NRF_COMP_DT_INST_EXTREFSEL(inst) \
22 _CONCAT(COMP_NRF_COMP_EXTREFSEL_, DT_INST_STRING_TOKEN(inst, extrefsel))
23
24 #define SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(inst) \
25 DT_INST_ENUM_HAS_VALUE(inst, main_mode, SE)
26
27 #define SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_DIFF(inst) \
28 DT_INST_ENUM_HAS_VALUE(inst, main_mode, DIFF)
29
30 #define SHIM_NRF_COMP_DT_INST_TH_DOWN(inst) \
31 DT_INST_PROP(inst, th_down)
32
33 #define SHIM_NRF_COMP_DT_INST_TH_UP(inst) \
34 DT_INST_PROP(inst, th_up)
35
36 #define SHIM_NRF_COMP_DT_INST_SP_MODE(inst) \
37 _CONCAT(COMP_NRF_COMP_SP_MODE_, DT_INST_STRING_TOKEN(inst, sp_mode))
38
39 #define SHIM_NRF_COMP_DT_INST_ENABLE_HYST(inst) \
40 DT_INST_PROP(inst, enable_hyst)
41
42 #define SHIM_NRF_COMP_DT_INST_ISOURCE(inst) \
43 _CONCAT(COMP_NRF_COMP_ISOURCE_, DT_INST_STRING_TOKEN(inst, isource))
44
45 #define SHIM_NRF_COMP_DT_INST_PSEL(inst) \
46 _CONCAT(COMP_NRF_COMP_PSEL_, DT_INST_STRING_TOKEN(inst, psel))
47
48 #if defined(COMP_HYST_HYST_Hyst40mV)
49 #define NRF_COMP_HYST_ENABLED NRF_COMP_HYST_40MV
50 #elif defined(COMP_HYST_HYST_Hyst50mV)
51 #define NRF_COMP_HYST_ENABLED NRF_COMP_HYST_50MV
52 #endif
53
54 #define NRF_COMP_HYST_DISABLED NRF_COMP_HYST_NO_HYST
55
56 #if defined(NRF_COMP_HYST_ENABLED)
57 #define NRF_COMP_HAS_HYST 1
58 #else
59 #define NRF_COMP_HAS_HYST 0
60 #endif
61
62 struct shim_nrf_comp_data {
63 uint32_t event_mask;
64 bool started;
65 atomic_t triggered;
66 comparator_callback_t callback;
67 void *user_data;
68 };
69
70 #if (NRF_COMP_HAS_AIN_AS_PIN)
71 static const uint32_t shim_nrf_comp_ain_map[] = {
72 #if defined(CONFIG_SOC_NRF54H20) || defined(CONFIG_SOC_NRF9280)
73 NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1),
74 NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1),
75 NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1),
76 NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1),
77 NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1),
78 NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1),
79 NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1),
80 NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1),
81 #elif defined(CONFIG_SOC_NRF54L05) || defined(CONFIG_SOC_NRF54L10) || defined(CONFIG_SOC_NRF54L15)
82 NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1),
83 NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1),
84 NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1),
85 NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1),
86 NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1),
87 NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1),
88 NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1),
89 NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1),
90 #endif
91 };
92 #endif
93
94 #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0)
95 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_DOWN(0) < 64);
96 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_UP(0) < 64);
97 #endif
98
99 #if NRF_COMP_HAS_AIN_AS_PIN
100 BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN0 == 0));
101 BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN7 == 7));
102 BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN0 == 0));
103 BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN7 == 7));
104 #else
105 #ifndef COMP_PSEL_PSEL_AnalogInput4
106 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN4);
107 #endif
108
109 #ifndef COMP_PSEL_PSEL_AnalogInput5
110 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN5);
111 #endif
112
113 #ifndef COMP_PSEL_PSEL_AnalogInput6
114 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN6);
115 #endif
116
117 #ifndef COMP_PSEL_PSEL_AnalogInput7
118 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN7);
119 #endif
120 #endif
121
122 #ifndef COMP_PSEL_PSEL_VddDiv2
123 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDD_DIV2);
124 #endif
125
126 #ifndef COMP_PSEL_PSEL_VddhDiv5
127 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDDH_DIV5);
128 #endif
129
130 #ifndef COMP_MODE_SP_Normal
131 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_SP_MODE(0) != COMP_NRF_COMP_SP_MODE_NORMAL);
132 #endif
133
134 #if NRF_COMP_HAS_ISOURCE
135 #ifndef COMP_ISOURCE_ISOURCE_Ien2uA5
136 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_2UA5);
137 #endif
138
139 #ifndef COMP_ISOURCE_ISOURCE_Ien5uA
140 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_5UA);
141 #endif
142
143 #ifndef COMP_ISOURCE_ISOURCE_Ien10uA
144 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_10UA);
145 #endif
146 #endif
147
148 #if SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(0)
149 #ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference4
150 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN4);
151 #endif
152
153 #ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference5
154 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN5);
155 #endif
156
157 #ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference6
158 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN6);
159 #endif
160
161 #ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference7
162 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN7);
163 #endif
164 #endif
165
166 #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0)
167 #ifndef COMP_REFSEL_REFSEL_Int1V8
168 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_INT_1V8);
169 #endif
170
171 #ifndef COMP_REFSEL_REFSEL_Int2V4
172 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_INT_2V4);
173 #endif
174
175 #ifndef COMP_REFSEL_REFSEL_AVDDAO1V8
176 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_AVDDAO1V8);
177 #endif
178
179 #ifndef COMP_REFSEL_REFSEL_VDD
180 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_VDD);
181 #endif
182 #endif
183
184 #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_DIFF(0)
185 #if SHIM_NRF_COMP_DT_INST_ENABLE_HYST(0)
186 BUILD_ASSERT(NRF_COMP_HAS_HYST);
187 #endif
188 #endif
189
190 #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0)
191 static const struct comp_nrf_comp_se_config shim_nrf_comp_config0 = {
192 .psel = SHIM_NRF_COMP_DT_INST_PSEL(0),
193 .sp_mode = SHIM_NRF_COMP_DT_INST_SP_MODE(0),
194 .isource = SHIM_NRF_COMP_DT_INST_ISOURCE(0),
195 #if SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(0)
196 .extrefsel = SHIM_NRF_COMP_DT_INST_EXTREFSEL(0),
197 #endif
198 .refsel = SHIM_NRF_COMP_DT_INST_REFSEL(0),
199 .th_down = SHIM_NRF_COMP_DT_INST_TH_DOWN(0),
200 .th_up = SHIM_NRF_COMP_DT_INST_TH_UP(0),
201 };
202 #else
203 static const struct comp_nrf_comp_diff_config shim_nrf_comp_config0 = {
204 .psel = SHIM_NRF_COMP_DT_INST_PSEL(0),
205 .sp_mode = SHIM_NRF_COMP_DT_INST_SP_MODE(0),
206 .isource = SHIM_NRF_COMP_DT_INST_ISOURCE(0),
207 .extrefsel = SHIM_NRF_COMP_DT_INST_EXTREFSEL(0),
208 .enable_hyst = SHIM_NRF_COMP_DT_INST_ENABLE_HYST(0),
209 };
210 #endif
211
212 static struct shim_nrf_comp_data shim_nrf_comp_data0;
213
214 #if CONFIG_PM_DEVICE
shim_nrf_comp_is_resumed(void)215 static bool shim_nrf_comp_is_resumed(void)
216 {
217 enum pm_device_state state;
218
219 (void)pm_device_state_get(DEVICE_DT_INST_GET(0), &state);
220 return state == PM_DEVICE_STATE_ACTIVE;
221 }
222 #else
shim_nrf_comp_is_resumed(void)223 static bool shim_nrf_comp_is_resumed(void)
224 {
225 return true;
226 }
227 #endif
228
shim_nrf_comp_start(void)229 static void shim_nrf_comp_start(void)
230 {
231 if (shim_nrf_comp_data0.started) {
232 return;
233 }
234
235 nrfx_comp_start(shim_nrf_comp_data0.event_mask, 0);
236 shim_nrf_comp_data0.started = true;
237 }
238
shim_nrf_comp_stop(void)239 static void shim_nrf_comp_stop(void)
240 {
241 if (!shim_nrf_comp_data0.started) {
242 return;
243 }
244
245 nrfx_comp_stop();
246 shim_nrf_comp_data0.started = false;
247 }
248
shim_nrf_comp_pm_callback(const struct device * dev,enum pm_device_action action)249 static int shim_nrf_comp_pm_callback(const struct device *dev, enum pm_device_action action)
250 {
251 ARG_UNUSED(dev);
252
253 switch (action) {
254 case PM_DEVICE_ACTION_RESUME:
255 shim_nrf_comp_start();
256 break;
257
258 #if CONFIG_PM_DEVICE
259 case PM_DEVICE_ACTION_SUSPEND:
260 shim_nrf_comp_stop();
261 break;
262 #endif
263
264 default:
265 return -ENOTSUP;
266 }
267
268 return 0;
269 }
270
271 #if (NRF_COMP_HAS_AIN_AS_PIN)
shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim,nrf_comp_input_t * nrf)272 static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim,
273 nrf_comp_input_t *nrf)
274 {
275 if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) {
276 return -EINVAL;
277 }
278
279 *nrf = shim_nrf_comp_ain_map[(uint32_t)shim];
280 return 0;
281 }
282 #else
shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim,nrf_comp_input_t * nrf)283 static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim,
284 nrf_comp_input_t *nrf)
285 {
286 switch (shim) {
287 case COMP_NRF_COMP_PSEL_AIN0:
288 *nrf = NRF_COMP_INPUT_0;
289 break;
290
291 case COMP_NRF_COMP_PSEL_AIN1:
292 *nrf = NRF_COMP_INPUT_1;
293 break;
294
295 case COMP_NRF_COMP_PSEL_AIN2:
296 *nrf = NRF_COMP_INPUT_2;
297 break;
298
299 case COMP_NRF_COMP_PSEL_AIN3:
300 *nrf = NRF_COMP_INPUT_3;
301 break;
302
303 #if defined(COMP_PSEL_PSEL_AnalogInput4)
304 case COMP_NRF_COMP_PSEL_AIN4:
305 *nrf = NRF_COMP_INPUT_4;
306 break;
307 #endif
308
309 #if defined(COMP_PSEL_PSEL_AnalogInput5)
310 case COMP_NRF_COMP_PSEL_AIN5:
311 *nrf = NRF_COMP_INPUT_5;
312 break;
313 #endif
314
315 #if defined(COMP_PSEL_PSEL_AnalogInput6)
316 case COMP_NRF_COMP_PSEL_AIN6:
317 *nrf = NRF_COMP_INPUT_6;
318 break;
319 #endif
320
321 #if defined(COMP_PSEL_PSEL_AnalogInput7)
322 case COMP_NRF_COMP_PSEL_AIN7:
323 *nrf = NRF_COMP_INPUT_7;
324 break;
325 #endif
326
327 #if defined(COMP_PSEL_PSEL_VddDiv2)
328 case COMP_NRF_COMP_PSEL_VDD_DIV2:
329 *nrf = NRF_COMP_VDD_DIV2;
330 break;
331 #endif
332
333 #if defined(COMP_PSEL_PSEL_VddhDiv5)
334 case COMP_NRF_COMP_PSEL_VDDH_DIV5:
335 *nrf = NRF_COMP_VDDH_DIV5;
336 break;
337 #endif
338
339 default:
340 return -EINVAL;
341 }
342
343 return 0;
344 }
345 #endif
346
shim_nrf_comp_sp_mode_to_nrf(enum comp_nrf_comp_sp_mode shim,nrf_comp_sp_mode_t * nrf)347 static int shim_nrf_comp_sp_mode_to_nrf(enum comp_nrf_comp_sp_mode shim,
348 nrf_comp_sp_mode_t *nrf)
349 {
350 switch (shim) {
351 case COMP_NRF_COMP_SP_MODE_LOW:
352 *nrf = NRF_COMP_SP_MODE_LOW;
353 break;
354
355 #if defined(COMP_MODE_SP_Normal)
356 case COMP_NRF_COMP_SP_MODE_NORMAL:
357 *nrf = NRF_COMP_SP_MODE_NORMAL;
358 break;
359 #endif
360
361 case COMP_NRF_COMP_SP_MODE_HIGH:
362 *nrf = NRF_COMP_SP_MODE_HIGH;
363 break;
364
365 default:
366 return -EINVAL;
367 }
368
369 return 0;
370 }
371
372 #if NRF_COMP_HAS_ISOURCE
shim_nrf_comp_isource_to_nrf(enum comp_nrf_comp_isource shim,nrf_isource_t * nrf)373 static int shim_nrf_comp_isource_to_nrf(enum comp_nrf_comp_isource shim,
374 nrf_isource_t *nrf)
375 {
376 switch (shim) {
377 case COMP_NRF_COMP_ISOURCE_DISABLED:
378 *nrf = NRF_COMP_ISOURCE_OFF;
379 break;
380
381 #if defined(COMP_ISOURCE_ISOURCE_Ien2uA5)
382 case COMP_NRF_COMP_ISOURCE_2UA5:
383 *nrf = NRF_COMP_ISOURCE_IEN_2UA5;
384 break;
385 #endif
386
387 #if defined(COMP_ISOURCE_ISOURCE_Ien5uA)
388 case COMP_NRF_COMP_ISOURCE_5UA:
389 *nrf = NRF_COMP_ISOURCE_IEN_5UA;
390 break;
391 #endif
392
393 #if defined(COMP_ISOURCE_ISOURCE_Ien10uA)
394 case COMP_NRF_COMP_ISOURCE_10UA:
395 *nrf = NRF_COMP_ISOURCE_IEN_10UA;
396 break;
397 #endif
398
399 default:
400 return -EINVAL;
401 }
402
403 return 0;
404 }
405 #endif
406
407 #if (NRF_COMP_HAS_AIN_AS_PIN)
shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim,nrf_comp_ext_ref_t * nrf)408 static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim,
409 nrf_comp_ext_ref_t *nrf)
410 {
411 if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) {
412 return -EINVAL;
413 }
414
415 *nrf = shim_nrf_comp_ain_map[(uint32_t)shim];
416 return 0;
417 }
418 #else
shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim,nrf_comp_ext_ref_t * nrf)419 static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim,
420 nrf_comp_ext_ref_t *nrf)
421 {
422 switch (shim) {
423 case COMP_NRF_COMP_EXTREFSEL_AIN0:
424 *nrf = NRF_COMP_EXT_REF_0;
425 break;
426
427 case COMP_NRF_COMP_EXTREFSEL_AIN1:
428 *nrf = NRF_COMP_EXT_REF_1;
429 break;
430
431 case COMP_NRF_COMP_EXTREFSEL_AIN2:
432 *nrf = NRF_COMP_EXT_REF_2;
433 break;
434
435 case COMP_NRF_COMP_EXTREFSEL_AIN3:
436 *nrf = NRF_COMP_EXT_REF_3;
437 break;
438
439 #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference4)
440 case COMP_NRF_COMP_EXTREFSEL_AIN4:
441 *nrf = NRF_COMP_EXT_REF_4;
442 break;
443 #endif
444
445 #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference5)
446 case COMP_NRF_COMP_EXTREFSEL_AIN5:
447 *nrf = NRF_COMP_EXT_REF_5;
448 break;
449 #endif
450
451 #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference6)
452 case COMP_NRF_COMP_EXTREFSEL_AIN6:
453 *nrf = NRF_COMP_EXT_REF_6;
454 break;
455 #endif
456
457 #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference7)
458 case COMP_NRF_COMP_EXTREFSEL_AIN7:
459 *nrf = NRF_COMP_EXT_REF_7;
460 break;
461 #endif
462
463 default:
464 return -EINVAL;
465 }
466
467 return 0;
468 }
469 #endif
470
shim_nrf_comp_refsel_to_nrf(enum comp_nrf_comp_refsel shim,nrf_comp_ref_t * nrf)471 static int shim_nrf_comp_refsel_to_nrf(enum comp_nrf_comp_refsel shim,
472 nrf_comp_ref_t *nrf)
473 {
474 switch (shim) {
475 case COMP_NRF_COMP_REFSEL_INT_1V2:
476 *nrf = NRF_COMP_REF_INT_1V2;
477 break;
478
479 #if defined(COMP_REFSEL_REFSEL_Int1V8)
480 case COMP_NRF_COMP_REFSEL_INT_1V8:
481 *nrf = NRF_COMP_REF_INT_1V8;
482 break;
483 #endif
484
485 #if defined(COMP_REFSEL_REFSEL_Int2V4)
486 case COMP_NRF_COMP_REFSEL_INT_2V4:
487 *nrf = NRF_COMP_REF_INT_2V4;
488 break;
489 #endif
490
491 #if defined(COMP_REFSEL_REFSEL_AVDDAO1V8)
492 case COMP_NRF_COMP_REFSEL_AVDDAO1V8:
493 *nrf = NRF_COMP_REF_AVDDAO1V8;
494 break;
495 #endif
496
497 #if defined(COMP_REFSEL_REFSEL_VDD)
498 case COMP_NRF_COMP_REFSEL_VDD:
499 *nrf = NRF_COMP_REF_VDD;
500 break;
501 #endif
502
503 case COMP_NRF_COMP_REFSEL_AREF:
504 *nrf = NRF_COMP_REF_AREF;
505 break;
506
507 default:
508 return -EINVAL;
509 }
510
511 return 0;
512 }
513
shim_nrf_comp_se_config_to_nrf(const struct comp_nrf_comp_se_config * shim,nrfx_comp_config_t * nrf)514 static int shim_nrf_comp_se_config_to_nrf(const struct comp_nrf_comp_se_config *shim,
515 nrfx_comp_config_t *nrf)
516 {
517 if (shim_nrf_comp_refsel_to_nrf(shim->refsel, &nrf->reference)) {
518 return -EINVAL;
519 }
520
521 if (shim_nrf_comp_extrefsel_to_nrf(shim->extrefsel, &nrf->ext_ref)) {
522 return -EINVAL;
523 }
524
525 nrf->main_mode = NRF_COMP_MAIN_MODE_SE;
526
527 if (shim->th_down > 63 || shim->th_up > 63) {
528 return -EINVAL;
529 }
530
531 nrf->threshold.th_down = shim->th_down;
532 nrf->threshold.th_up = shim->th_up;
533
534 if (shim_nrf_comp_sp_mode_to_nrf(shim->sp_mode, &nrf->speed_mode)) {
535 return -EINVAL;
536 }
537
538 nrf->hyst = NRF_COMP_HYST_NO_HYST;
539
540 #if NRF_COMP_HAS_ISOURCE
541 if (shim_nrf_comp_isource_to_nrf(shim->isource, &nrf->isource)) {
542 return -EINVAL;
543 }
544 #else
545 if (shim->isource != COMP_NRF_COMP_ISOURCE_DISABLED) {
546 return -EINVAL;
547 }
548 #endif
549
550 if (shim_nrf_comp_psel_to_nrf(shim->psel, &nrf->input)) {
551 return -EINVAL;
552 }
553
554 nrf->interrupt_priority = 0;
555 return 0;
556 }
557
shim_nrf_comp_diff_config_to_nrf(const struct comp_nrf_comp_diff_config * shim,nrfx_comp_config_t * nrf)558 static int shim_nrf_comp_diff_config_to_nrf(const struct comp_nrf_comp_diff_config *shim,
559 nrfx_comp_config_t *nrf)
560 {
561 nrf->reference = NRF_COMP_REF_AREF;
562
563 if (shim_nrf_comp_extrefsel_to_nrf(shim->extrefsel, &nrf->ext_ref)) {
564 return -EINVAL;
565 }
566
567 nrf->main_mode = NRF_COMP_MAIN_MODE_DIFF;
568 nrf->threshold.th_down = 0;
569 nrf->threshold.th_up = 0;
570
571 if (shim_nrf_comp_sp_mode_to_nrf(shim->sp_mode, &nrf->speed_mode)) {
572 return -EINVAL;
573 }
574
575 #if NRF_COMP_HAS_HYST
576 if (shim->enable_hyst) {
577 nrf->hyst = NRF_COMP_HYST_ENABLED;
578 } else {
579 nrf->hyst = NRF_COMP_HYST_DISABLED;
580 }
581 #else
582 if (shim->enable_hyst) {
583 return -EINVAL;
584 }
585 #endif
586
587 #if NRF_COMP_HAS_ISOURCE
588 if (shim_nrf_comp_isource_to_nrf(shim->isource, &nrf->isource)) {
589 return -EINVAL;
590 }
591 #else
592 if (shim->isource != COMP_NRF_COMP_ISOURCE_DISABLED) {
593 return -EINVAL;
594 }
595 #endif
596
597 if (shim_nrf_comp_psel_to_nrf(shim->psel, &nrf->input)) {
598 return -EINVAL;
599 }
600
601 nrf->interrupt_priority = 0;
602 return 0;
603 }
604
shim_nrf_comp_get_output(const struct device * dev)605 static int shim_nrf_comp_get_output(const struct device *dev)
606 {
607 ARG_UNUSED(dev);
608
609 return nrfx_comp_sample();
610 }
611
shim_nrf_comp_set_trigger(const struct device * dev,enum comparator_trigger trigger)612 static int shim_nrf_comp_set_trigger(const struct device *dev,
613 enum comparator_trigger trigger)
614 {
615 shim_nrf_comp_stop();
616
617 switch (trigger) {
618 case COMPARATOR_TRIGGER_NONE:
619 shim_nrf_comp_data0.event_mask = 0;
620 break;
621
622 case COMPARATOR_TRIGGER_RISING_EDGE:
623 shim_nrf_comp_data0.event_mask = NRF_COMP_INT_UP_MASK;
624 break;
625
626 case COMPARATOR_TRIGGER_FALLING_EDGE:
627 shim_nrf_comp_data0.event_mask = NRF_COMP_INT_DOWN_MASK;
628 break;
629
630 case COMPARATOR_TRIGGER_BOTH_EDGES:
631 shim_nrf_comp_data0.event_mask = NRF_COMP_INT_CROSS_MASK;
632 break;
633 }
634
635 if (shim_nrf_comp_is_resumed()) {
636 shim_nrf_comp_start();
637 }
638
639 return 0;
640 }
641
shim_nrf_comp_set_trigger_callback(const struct device * dev,comparator_callback_t callback,void * user_data)642 static int shim_nrf_comp_set_trigger_callback(const struct device *dev,
643 comparator_callback_t callback,
644 void *user_data)
645 {
646 shim_nrf_comp_stop();
647
648 shim_nrf_comp_data0.callback = callback;
649 shim_nrf_comp_data0.user_data = user_data;
650
651 if (callback != NULL && atomic_test_and_clear_bit(&shim_nrf_comp_data0.triggered, 0)) {
652 callback(dev, user_data);
653 }
654
655 if (shim_nrf_comp_is_resumed()) {
656 shim_nrf_comp_start();
657 }
658
659 return 0;
660 }
661
shim_nrf_comp_trigger_is_pending(const struct device * dev)662 static int shim_nrf_comp_trigger_is_pending(const struct device *dev)
663 {
664 ARG_UNUSED(dev);
665
666 return atomic_test_and_clear_bit(&shim_nrf_comp_data0.triggered, 0);
667 }
668
669 static DEVICE_API(comparator, shim_nrf_comp_api) = {
670 .get_output = shim_nrf_comp_get_output,
671 .set_trigger = shim_nrf_comp_set_trigger,
672 .set_trigger_callback = shim_nrf_comp_set_trigger_callback,
673 .trigger_is_pending = shim_nrf_comp_trigger_is_pending,
674 };
675
shim_nrf_comp_reconfigure(const nrfx_comp_config_t * nrf)676 static int shim_nrf_comp_reconfigure(const nrfx_comp_config_t *nrf)
677 {
678 shim_nrf_comp_stop();
679
680 (void)nrfx_comp_reconfigure(nrf);
681
682 if (shim_nrf_comp_is_resumed()) {
683 shim_nrf_comp_start();
684 }
685
686 return 0;
687 }
688
comp_nrf_comp_configure_se(const struct device * dev,const struct comp_nrf_comp_se_config * config)689 int comp_nrf_comp_configure_se(const struct device *dev,
690 const struct comp_nrf_comp_se_config *config)
691 {
692 nrfx_comp_config_t nrf = {};
693
694 ARG_UNUSED(dev);
695
696 if (shim_nrf_comp_se_config_to_nrf(config, &nrf)) {
697 return -EINVAL;
698 }
699
700 return shim_nrf_comp_reconfigure(&nrf);
701 }
702
comp_nrf_comp_configure_diff(const struct device * dev,const struct comp_nrf_comp_diff_config * config)703 int comp_nrf_comp_configure_diff(const struct device *dev,
704 const struct comp_nrf_comp_diff_config *config)
705 {
706 nrfx_comp_config_t nrf = {};
707
708 ARG_UNUSED(dev);
709
710 if (shim_nrf_comp_diff_config_to_nrf(config, &nrf)) {
711 return -EINVAL;
712 }
713
714 return shim_nrf_comp_reconfigure(&nrf);
715 }
716
shim_nrf_comp_event_handler(nrf_comp_event_t event)717 static void shim_nrf_comp_event_handler(nrf_comp_event_t event)
718 {
719 ARG_UNUSED(event);
720
721 if (shim_nrf_comp_data0.callback == NULL) {
722 atomic_set_bit(&shim_nrf_comp_data0.triggered, 0);
723 return;
724 }
725
726 shim_nrf_comp_data0.callback(DEVICE_DT_INST_GET(0), shim_nrf_comp_data0.user_data);
727 atomic_clear_bit(&shim_nrf_comp_data0.triggered, 0);
728 }
729
shim_nrf_comp_init(const struct device * dev)730 static int shim_nrf_comp_init(const struct device *dev)
731 {
732 nrfx_comp_config_t nrf = {};
733
734 IRQ_CONNECT(DT_INST_IRQN(0),
735 DT_INST_IRQ(0, priority),
736 nrfx_isr,
737 nrfx_comp_irq_handler,
738 0);
739
740 irq_enable(DT_INST_IRQN(0));
741
742 #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0)
743 (void)shim_nrf_comp_se_config_to_nrf(&shim_nrf_comp_config0, &nrf);
744 #else
745 (void)shim_nrf_comp_diff_config_to_nrf(&shim_nrf_comp_config0, &nrf);
746 #endif
747
748 if (nrfx_comp_init(&nrf, shim_nrf_comp_event_handler) != NRFX_SUCCESS) {
749 return -ENODEV;
750 }
751
752 return pm_device_driver_init(dev, shim_nrf_comp_pm_callback);
753 }
754
755 PM_DEVICE_DT_INST_DEFINE(0, shim_nrf_comp_pm_callback);
756
757 DEVICE_DT_INST_DEFINE(0,
758 shim_nrf_comp_init,
759 PM_DEVICE_DT_INST_GET(0),
760 NULL,
761 NULL,
762 POST_KERNEL,
763 CONFIG_COMPARATOR_INIT_PRIORITY,
764 &shim_nrf_comp_api);
765