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