Software APIs
dif_pinmux.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
6
11
12#include "pinmux_regs.h" // Generated.
13
14static bool dif_pinmux_get_reg_offset(dif_pinmux_index_t index,
16 ptrdiff_t mio_reg_base,
17 ptrdiff_t dio_reg_base,
18 ptrdiff_t *reg_offset) {
19 uint32_t num_pads;
20 ptrdiff_t reg_base;
21
22 switch (kind) {
24 num_pads = PINMUX_PARAM_N_MIO_PADS;
25 reg_base = mio_reg_base;
26 break;
28 num_pads = PINMUX_PARAM_N_DIO_PADS;
29 reg_base = dio_reg_base;
30 break;
31 default:
32 return false;
33 }
34 if (index >= num_pads) {
35 return false;
36 }
37 *reg_offset = reg_base + (ptrdiff_t)(index * sizeof(uint32_t));
38 return true;
39}
40
41static bool dif_pinmux_get_sleep_status_bit(dif_pinmux_pad_kind_t kind,
43 ptrdiff_t *reg_offset,
45 uint32_t num_pads;
46 ptrdiff_t reg_base;
47
48 switch (kind) {
50 num_pads = PINMUX_PARAM_N_MIO_PADS;
51 // Only platforms with few MIOs, there is a single register with no index.
52#ifdef PINMUX_MIO_PAD_SLEEP_STATUS_0_REG_OFFSET
53 reg_base = PINMUX_MIO_PAD_SLEEP_STATUS_0_REG_OFFSET;
54#else
55 reg_base = PINMUX_MIO_PAD_SLEEP_STATUS_REG_OFFSET;
56#endif
57 break;
59 num_pads = PINMUX_PARAM_N_DIO_PADS;
60 // Only platforms with few DIOs, there is a single register with no index.
61#ifdef PINMUX_DIO_PAD_SLEEP_STATUS_0_REG_OFFSET
62 reg_base = PINMUX_DIO_PAD_SLEEP_STATUS_0_REG_OFFSET;
63#else
64 reg_base = PINMUX_DIO_PAD_SLEEP_STATUS_REG_OFFSET;
65#endif
66 break;
67 default:
68 return false;
69 }
70 if (index >= num_pads) {
71 return false;
72 }
73 *reg_offset = (ptrdiff_t)index / 32 + reg_base;
74 *bit = index % 32;
75 return true;
76}
77
78static bool dif_pinmux_get_lock_reg_offset(dif_pinmux_index_t index,
80 ptrdiff_t *reg_offset) {
81 ptrdiff_t reg_base;
82 size_t reg_count;
83 switch (target) {
85 reg_base = PINMUX_MIO_PERIPH_INSEL_REGWEN_0_REG_OFFSET;
86 reg_count = PINMUX_MIO_PERIPH_INSEL_REGWEN_MULTIREG_COUNT;
87 break;
89 reg_base = PINMUX_MIO_OUTSEL_REGWEN_0_REG_OFFSET;
90 reg_count = PINMUX_MIO_OUTSEL_REGWEN_MULTIREG_COUNT;
91 break;
93 reg_base = PINMUX_MIO_PAD_SLEEP_REGWEN_0_REG_OFFSET;
94 reg_count = PINMUX_MIO_PAD_SLEEP_REGWEN_MULTIREG_COUNT;
95 break;
97 reg_base = PINMUX_DIO_PAD_SLEEP_REGWEN_0_REG_OFFSET;
98 reg_count = PINMUX_DIO_PAD_SLEEP_REGWEN_MULTIREG_COUNT;
99 break;
101 reg_base = PINMUX_MIO_PAD_ATTR_REGWEN_0_REG_OFFSET;
102 reg_count = PINMUX_MIO_PAD_ATTR_REGWEN_MULTIREG_COUNT;
103 break;
105 reg_base = PINMUX_DIO_PAD_ATTR_REGWEN_0_REG_OFFSET;
106 reg_count = PINMUX_DIO_PAD_ATTR_REGWEN_MULTIREG_COUNT;
107 break;
109 reg_base = PINMUX_WKUP_DETECTOR_REGWEN_0_REG_OFFSET;
110 reg_count = PINMUX_WKUP_DETECTOR_REGWEN_MULTIREG_COUNT;
111 break;
112 default:
113 return false;
114 }
115
116 if (index >= reg_count) {
117 return false;
118 }
119
120 *reg_offset = reg_base + (ptrdiff_t)index * (ptrdiff_t)sizeof(uint32_t);
121 return true;
122}
123
124dif_result_t dif_pinmux_lock(const dif_pinmux_t *pinmux,
125 dif_pinmux_index_t index,
127 if (pinmux == NULL) {
128 return kDifBadArg;
129 }
130
131 ptrdiff_t reg_offset;
132 if (!dif_pinmux_get_lock_reg_offset(index, target, &reg_offset)) {
133 return kDifBadArg;
134 }
135 mmio_region_write32(pinmux->base_addr, reg_offset, /*value=*/0);
136 return kDifOk;
137}
138
139dif_result_t dif_pinmux_is_locked(const dif_pinmux_t *pinmux,
140 dif_pinmux_index_t index,
142 bool *is_locked) {
143 if (pinmux == NULL || is_locked == NULL) {
144 return kDifBadArg;
145 }
146
147 ptrdiff_t reg_offset;
148 if (!dif_pinmux_get_lock_reg_offset(index, target, &reg_offset)) {
149 return kDifBadArg;
150 }
151
152 uint32_t reg_value = mmio_region_read32(pinmux->base_addr, reg_offset);
153 *is_locked = !bitfield_bit32_read(reg_value,
154 PINMUX_MIO_PERIPH_INSEL_REGWEN_0_EN_0_BIT);
155 return kDifOk;
156}
157
158dif_result_t dif_pinmux_input_select(const dif_pinmux_t *pinmux,
159 dif_pinmux_index_t peripheral_input,
160 dif_pinmux_index_t insel) {
161 if (pinmux == NULL || peripheral_input >= PINMUX_PARAM_N_MIO_PERIPH_IN ||
162 insel >= (2 + PINMUX_PARAM_N_MIO_PADS)) {
163 return kDifBadArg;
164 }
165 bool is_locked;
166 dif_result_t result = dif_pinmux_is_locked(
167 pinmux, peripheral_input, kDifPinmuxLockTargetInsel, &is_locked);
168 if (result != kDifOk) {
169 return result;
170 }
171 if (is_locked) {
172 return kDifLocked;
173 }
174 ptrdiff_t reg_offset =
175 PINMUX_MIO_PERIPH_INSEL_0_REG_OFFSET + (ptrdiff_t)(peripheral_input << 2);
176 uint32_t reg_value =
177 bitfield_field32_write(0, PINMUX_MIO_PERIPH_INSEL_0_IN_0_FIELD, insel);
178 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
179 return kDifOk;
180}
181
182dif_result_t dif_pinmux_output_select(const dif_pinmux_t *pinmux,
183 dif_pinmux_index_t mio_pad_output,
184 dif_pinmux_index_t outsel) {
185 if (pinmux == NULL || mio_pad_output >= PINMUX_PARAM_N_MIO_PADS ||
186 outsel >= (3 + PINMUX_PARAM_N_MIO_PERIPH_OUT)) {
187 return kDifBadArg;
188 }
189 bool is_locked;
190 dif_result_t result = dif_pinmux_is_locked(
191 pinmux, mio_pad_output, kDifPinmuxLockTargetOutsel, &is_locked);
192 if (result != kDifOk) {
193 return result;
194 }
195 if (is_locked) {
196 return kDifLocked;
197 }
198 ptrdiff_t reg_offset =
199 PINMUX_MIO_OUTSEL_0_REG_OFFSET + (ptrdiff_t)(mio_pad_output << 2);
200 uint32_t reg_value =
201 bitfield_field32_write(0, PINMUX_MIO_OUTSEL_0_OUT_0_FIELD, outsel);
202 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
203 return kDifOk;
204}
205
206dif_result_t dif_pinmux_mio_select_input(const dif_pinmux_t *pinmux,
207 dt_periph_io_t periph_io,
208 dt_pad_t pad) {
209 if (dt_pad_type(pad) != kDtPadTypeMio ||
211 return kDifBadArg;
212 }
213 return dif_pinmux_input_select(
214 pinmux, dt_periph_io_mio_periph_input(periph_io), dt_pad_mio_insel(pad));
215}
216
217dif_result_t dif_pinmux_mio_select_output(const dif_pinmux_t *pinmux,
218 dt_pad_t pad,
219 dt_periph_io_t periph_io) {
220 if (dt_pad_type(pad) != kDtPadTypeMio ||
222 return kDifBadArg;
223 }
224 return dif_pinmux_output_select(pinmux, dt_pad_mio_out(pad),
225 dt_periph_io_mio_outsel(periph_io));
226}
227
228static dif_pinmux_pad_attr_t dif_pinmux_reg_to_pad_attr(uint32_t reg_value) {
229 dif_pinmux_pad_attr_t pad_attrs = {0};
230 pad_attrs.slew_rate = (dif_pinmux_pad_slew_rate_t)bitfield_field32_read(
231 reg_value, PINMUX_MIO_PAD_ATTR_0_SLEW_RATE_0_FIELD);
232 pad_attrs.drive_strength =
233 (dif_pinmux_pad_drive_strength_t)bitfield_field32_read(
234 reg_value, PINMUX_MIO_PAD_ATTR_0_DRIVE_STRENGTH_0_FIELD);
235 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_INVERT_0_BIT)) {
236 pad_attrs.flags |= kDifPinmuxPadAttrInvertLevel;
237 }
238 if (bitfield_bit32_read(reg_value,
239 PINMUX_MIO_PAD_ATTR_0_VIRTUAL_OD_EN_0_BIT)) {
240 pad_attrs.flags |= kDifPinmuxPadAttrVirtualOpenDrain;
241 }
242 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_PULL_EN_0_BIT)) {
243 pad_attrs.flags |= kDifPinmuxPadAttrPullResistorEnable;
244 }
245 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_PULL_SELECT_0_BIT)) {
246 pad_attrs.flags |= kDifPinmuxPadAttrPullResistorUp;
247 }
248 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_KEEPER_EN_0_BIT)) {
249 pad_attrs.flags |= kDifPinmuxPadAttrKeeper;
250 }
251 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_SCHMITT_EN_0_BIT)) {
252 pad_attrs.flags |= kDifPinmuxPadAttrSchmittTrigger;
253 }
254 if (bitfield_bit32_read(reg_value, PINMUX_MIO_PAD_ATTR_0_OD_EN_0_BIT)) {
255 pad_attrs.flags |= kDifPinmuxPadAttrOpenDrain;
256 }
257 if (bitfield_bit32_read(reg_value,
258 PINMUX_MIO_PAD_ATTR_0_INPUT_DISABLE_0_BIT)) {
259 pad_attrs.flags |= kDifPinmuxPadAttrInputDisable;
260 }
261 return pad_attrs;
262}
263
264enum { kDifPinmuxPadAttrSpinWaitMicros = 5 };
265
266dif_result_t dif_pinmux_pad_write_attrs(const dif_pinmux_t *pinmux,
269 dif_pinmux_pad_attr_t attrs_in,
270 dif_pinmux_pad_attr_t *attrs_out) {
271 if (pinmux == NULL || attrs_out == NULL) {
272 return kDifBadArg;
273 }
274 if (attrs_in.drive_strength > PINMUX_MIO_PAD_ATTR_0_DRIVE_STRENGTH_0_MASK ||
275 attrs_in.slew_rate > PINMUX_MIO_PAD_ATTR_0_SLEW_RATE_0_MASK) {
276 return kDifBadArg;
277 }
278 ptrdiff_t reg_offset;
279 if (!dif_pinmux_get_reg_offset(pad, type, PINMUX_MIO_PAD_ATTR_0_REG_OFFSET,
280 PINMUX_DIO_PAD_ATTR_0_REG_OFFSET,
281 &reg_offset)) {
282 return kDifBadArg;
283 }
284 const dif_pinmux_lock_target_t lock_target =
287 bool is_locked;
288 dif_result_t result =
289 dif_pinmux_is_locked(pinmux, pad, lock_target, &is_locked);
290 if (result != kDifOk) {
291 return result;
292 }
293 if (is_locked) {
294 return kDifLocked;
295 }
296
297 uint32_t reg_before = mmio_region_read32(pinmux->base_addr, reg_offset);
298
299 uint32_t reg_value = bitfield_field32_write(
300 0, PINMUX_MIO_PAD_ATTR_0_SLEW_RATE_0_FIELD, attrs_in.slew_rate);
301 reg_value = bitfield_field32_write(
302 reg_value, PINMUX_MIO_PAD_ATTR_0_DRIVE_STRENGTH_0_FIELD,
303 attrs_in.drive_strength);
304 reg_value =
305 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_INVERT_0_BIT,
306 attrs_in.flags & kDifPinmuxPadAttrInvertLevel);
307 reg_value =
308 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_VIRTUAL_OD_EN_0_BIT,
309 attrs_in.flags & kDifPinmuxPadAttrVirtualOpenDrain);
310 reg_value = bitfield_bit32_write(
311 reg_value, PINMUX_MIO_PAD_ATTR_0_PULL_EN_0_BIT,
312 attrs_in.flags & kDifPinmuxPadAttrPullResistorEnable);
313 reg_value =
314 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_PULL_SELECT_0_BIT,
315 attrs_in.flags & kDifPinmuxPadAttrPullResistorUp);
316 reg_value =
317 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_KEEPER_EN_0_BIT,
318 attrs_in.flags & kDifPinmuxPadAttrKeeper);
319 reg_value =
320 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_SCHMITT_EN_0_BIT,
321 attrs_in.flags & kDifPinmuxPadAttrSchmittTrigger);
322 reg_value = bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_OD_EN_0_BIT,
323 attrs_in.flags & kDifPinmuxPadAttrOpenDrain);
324 reg_value =
325 bitfield_bit32_write(reg_value, PINMUX_MIO_PAD_ATTR_0_INPUT_DISABLE_0_BIT,
326 attrs_in.flags & kDifPinmuxPadAttrInputDisable);
327 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
328
329 // Wait for pull enable/disable changes to propagate to the physical pad.
330 dif_pinmux_pad_attr_t attrs_before = dif_pinmux_reg_to_pad_attr(reg_before);
331 if ((attrs_before.flags & kDifPinmuxPadAttrPullResistorEnable) !=
332 (attrs_in.flags & kDifPinmuxPadAttrPullResistorEnable)) {
333 busy_spin_micros(kDifPinmuxPadAttrSpinWaitMicros);
334 }
335
336 uint32_t read_value = mmio_region_read32(pinmux->base_addr, reg_offset);
337 *attrs_out = dif_pinmux_reg_to_pad_attr(read_value);
338
339 // Not all pads implement all attributes and not all target platforms support
340 // all attribute values. The underlying hardware registers implement Write-Any
341 // Read-Legal (WARL) semantics. If the specified attribute values are not
342 // supported by the hardware, return `kDifError`. The caller then needs to
343 // decide on how to resolve the situation. Unsupported attribute values can be
344 // identified by comparing `attrs_in` to `attrs_out`.
345 if (reg_value != read_value) {
346 return kDifError;
347 }
348 return kDifOk;
349}
350
351dif_result_t dif_pinmux_pad_from_dt_pad(dt_pad_t pad,
352 dif_pinmux_index_t *index_out,
353 dif_pinmux_pad_kind_t *type_out) {
354 if (index_out == NULL || type_out == NULL) {
355 return kDifBadArg;
356 }
357 switch (dt_pad_type(pad)) {
358 case kDtPadTypeMio:
359 *type_out = kDifPinmuxPadKindMio;
360 *index_out = dt_pad_mio_pad_index(pad);
361 return kDifOk;
362 case kDtPadTypeDio:
363 *type_out = kDifPinmuxPadKindDio;
364 *index_out = dt_pad_dio_pad_index(pad);
365 return kDifOk;
366 default:
367 return kDifError;
368 }
369}
370
371dif_result_t dif_pinmux_pad_write_attrs_dt(const dif_pinmux_t *pinmux,
372 dt_pad_t pad,
373 dif_pinmux_pad_attr_t attrs_in,
374 dif_pinmux_pad_attr_t *attrs_out) {
375 dif_pinmux_index_t index;
377 DIF_RETURN_IF_ERROR(dif_pinmux_pad_from_dt_pad(pad, &index, &type));
379 dif_pinmux_pad_write_attrs(pinmux, index, type, attrs_in, attrs_out));
380 return kDifOk;
381}
382
383dif_result_t dif_pinmux_pad_get_attrs(const dif_pinmux_t *pinmux,
386 dif_pinmux_pad_attr_t *attrs) {
387 if (pinmux == NULL || attrs == NULL) {
388 return kDifBadArg;
389 }
390 ptrdiff_t reg_offset;
391 if (!dif_pinmux_get_reg_offset(pad, type, PINMUX_MIO_PAD_ATTR_0_REG_OFFSET,
392 PINMUX_DIO_PAD_ATTR_0_REG_OFFSET,
393 &reg_offset)) {
394 return kDifBadArg;
395 }
396 uint32_t reg_value = mmio_region_read32(pinmux->base_addr, reg_offset);
397 *attrs = dif_pinmux_reg_to_pad_attr(reg_value);
398 return kDifOk;
399}
400
401dif_result_t dif_pinmux_pad_get_attrs_dt(const dif_pinmux_t *pinmux,
402 dt_pad_t pad,
403 dif_pinmux_pad_attr_t *attrs) {
404 dif_pinmux_index_t index;
406 DIF_RETURN_IF_ERROR(dif_pinmux_pad_from_dt_pad(pad, &index, &type));
407 DIF_RETURN_IF_ERROR(dif_pinmux_pad_get_attrs(pinmux, index, type, attrs));
408 return kDifOk;
409}
410
411dif_result_t dif_pinmux_pad_sleep_enable(const dif_pinmux_t *pinmux,
415 if (pinmux == NULL) {
416 return kDifBadArg;
417 }
418
419 ptrdiff_t en_reg_offset, mode_reg_offset;
420 if (!dif_pinmux_get_reg_offset(
421 pad, type, PINMUX_MIO_PAD_SLEEP_EN_0_REG_OFFSET,
422 PINMUX_DIO_PAD_SLEEP_EN_0_REG_OFFSET, &en_reg_offset)) {
423 return kDifBadArg;
424 }
425 if (!dif_pinmux_get_reg_offset(
426 pad, type, PINMUX_MIO_PAD_SLEEP_MODE_0_REG_OFFSET,
427 PINMUX_DIO_PAD_SLEEP_MODE_0_REG_OFFSET, &mode_reg_offset)) {
428 return kDifBadArg;
429 }
430 const dif_pinmux_lock_target_t lock_target =
433 bool is_locked;
434 dif_result_t result =
435 dif_pinmux_is_locked(pinmux, pad, lock_target, &is_locked);
436 if (result != kDifOk) {
437 return result;
438 }
439 if (is_locked) {
440 return kDifLocked;
441 }
442
443 // Sleep Mode Value
444 uint32_t reg_value;
445 switch (mode) {
447 reg_value = PINMUX_MIO_PAD_SLEEP_MODE_0_OUT_0_VALUE_TIE_LOW;
448 break;
450 reg_value = PINMUX_MIO_PAD_SLEEP_MODE_0_OUT_0_VALUE_TIE_HIGH;
451 break;
453 reg_value = PINMUX_MIO_PAD_SLEEP_MODE_0_OUT_0_VALUE_HIGH_Z;
454 break;
456 reg_value = PINMUX_MIO_PAD_SLEEP_MODE_0_OUT_0_VALUE_KEEP;
457 break;
458 default:
459 return kDifBadArg;
460 }
461 mmio_region_write32(pinmux->base_addr, mode_reg_offset, reg_value);
462
463 // Sleep Mode Enable
464 reg_value = bitfield_bit32_write(0, PINMUX_MIO_PAD_SLEEP_EN_0_EN_0_BIT, 1);
465 mmio_region_write32(pinmux->base_addr, en_reg_offset, reg_value);
466 return kDifOk;
467}
468
469dif_result_t dif_pinmux_pad_sleep_disable(const dif_pinmux_t *pinmux,
472 if (pinmux == NULL) {
473 return kDifBadArg;
474 }
475
476 ptrdiff_t en_reg_offset;
477 if (!dif_pinmux_get_reg_offset(
478 pad, type, PINMUX_MIO_PAD_SLEEP_EN_0_REG_OFFSET,
479 PINMUX_DIO_PAD_SLEEP_EN_0_REG_OFFSET, &en_reg_offset)) {
480 return kDifBadArg;
481 }
482
483 const dif_pinmux_lock_target_t lock_target =
486 bool is_locked;
487 dif_result_t result =
488 dif_pinmux_is_locked(pinmux, pad, lock_target, &is_locked);
489 if (result != kDifOk) {
490 return result;
491 }
492 if (is_locked) {
493 return kDifLocked;
494 }
495
496 mmio_region_write32(pinmux->base_addr, en_reg_offset, 0);
497 return kDifOk;
498}
499
500dif_result_t dif_pinmux_pad_sleep_get_state(const dif_pinmux_t *pinmux,
503 bool *in_sleep_mode) {
504 if (pinmux == NULL || in_sleep_mode == NULL) {
505 return kDifBadArg;
506 }
507
508 ptrdiff_t reg_offset;
510 if (!dif_pinmux_get_sleep_status_bit(type, pad, &reg_offset, &bit)) {
511 return kDifBadArg;
512 }
513
514 uint32_t reg_value = mmio_region_read32(pinmux->base_addr, reg_offset);
515 *in_sleep_mode = bitfield_bit32_read(reg_value, bit);
516 return kDifOk;
517}
518
519dif_result_t dif_pinmux_pad_sleep_clear_state(const dif_pinmux_t *pinmux,
522 if (pinmux == NULL) {
523 return kDifBadArg;
524 }
525
526 ptrdiff_t reg_offset;
528 if (!dif_pinmux_get_sleep_status_bit(type, pad, &reg_offset, &bit)) {
529 return kDifBadArg;
530 }
531
532 uint32_t reg_value = mmio_region_read32(pinmux->base_addr, reg_offset);
533 reg_value = bitfield_bit32_write(reg_value, bit, 0);
534 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
535 return kDifOk;
536}
537
538dif_result_t dif_pinmux_wakeup_detector_enable(
539 const dif_pinmux_t *pinmux, dif_pinmux_index_t detector,
541 // Disable the detector before changing config, and use that function for
542 // some input checking (null pointer, lock status, and detector validity
543 // checks).
544 dif_result_t result = dif_pinmux_wakeup_detector_disable(pinmux, detector);
545 if (result != kDifOk) {
546 return result;
547 }
548
549 bool set_count = false;
550 uint32_t reg_mode_value;
551 switch (config.mode) {
553 reg_mode_value = PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_POSEDGE;
554 break;
556 reg_mode_value = PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_NEGEDGE;
557 break;
559 reg_mode_value = PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_EDGE;
560 break;
562 set_count = true;
563 reg_mode_value = PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_TIMEDHIGH;
564 break;
566 set_count = true;
567 reg_mode_value = PINMUX_WKUP_DETECTOR_0_MODE_0_VALUE_TIMEDLOW;
568 break;
569 default:
570 return kDifBadArg;
571 }
572
573 bool reg_filter_value = dif_toggle_to_bool(config.signal_filter);
574 if (!dif_is_valid_toggle(config.signal_filter)) {
575 return kDifBadArg;
576 }
577
578 bool reg_miodio_value;
579 switch (config.pad_type) {
581 if (config.pad_select >= (2 + PINMUX_PARAM_N_MIO_PADS)) {
582 return kDifBadArg;
583 }
584 reg_miodio_value = false;
585 break;
587 if (config.pad_select >= PINMUX_PARAM_N_DIO_PADS) {
588 return kDifBadArg;
589 }
590 reg_miodio_value = true;
591 break;
592 default:
593 return kDifBadArg;
594 }
595
596 ptrdiff_t reg_offset = PINMUX_WKUP_DETECTOR_0_REG_OFFSET +
597 (ptrdiff_t)detector * (ptrdiff_t)sizeof(uint32_t);
598 uint32_t reg_value = bitfield_field32_write(
599 0, PINMUX_WKUP_DETECTOR_0_MODE_0_FIELD, reg_mode_value);
600 reg_value = bitfield_bit32_write(
601 reg_value, PINMUX_WKUP_DETECTOR_0_FILTER_0_BIT, reg_filter_value);
602 reg_value = bitfield_bit32_write(
603 reg_value, PINMUX_WKUP_DETECTOR_0_MIODIO_0_BIT, reg_miodio_value);
604 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
605
606 if (set_count) {
607 reg_offset = PINMUX_WKUP_DETECTOR_CNT_TH_0_REG_OFFSET +
608 (ptrdiff_t)detector * (ptrdiff_t)sizeof(uint32_t);
609 reg_value = bitfield_field32_write(
610 0, PINMUX_WKUP_DETECTOR_CNT_TH_0_TH_0_FIELD, config.counter_threshold);
611 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
612 }
613
614 reg_offset = PINMUX_WKUP_DETECTOR_PADSEL_0_REG_OFFSET +
615 (ptrdiff_t)detector * (ptrdiff_t)sizeof(uint32_t);
616 reg_value = bitfield_field32_write(
617 0, PINMUX_WKUP_DETECTOR_PADSEL_0_SEL_0_FIELD, config.pad_select);
618 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
619
620 reg_offset = PINMUX_WKUP_DETECTOR_EN_0_REG_OFFSET +
621 (ptrdiff_t)detector * (ptrdiff_t)sizeof(uint32_t);
622 reg_value = bitfield_bit32_write(0, PINMUX_WKUP_DETECTOR_EN_0_EN_0_BIT, true);
623 mmio_region_write32(pinmux->base_addr, reg_offset, reg_value);
624 return kDifOk;
625}
626
627dif_result_t dif_pinmux_wakeup_detector_disable(const dif_pinmux_t *pinmux,
628 dif_pinmux_index_t detector) {
629 if (pinmux == NULL) {
630 return kDifBadArg;
631 }
632 if (detector >= PINMUX_PARAM_N_WKUP_DETECT) {
633 return kDifBadArg;
634 }
635 bool is_locked;
636 dif_result_t result = dif_pinmux_is_locked(
637 pinmux, detector, kDifPinmuxLockTargetWakeupDetector, &is_locked);
638 if (result != kDifOk) {
639 return result;
640 }
641 if (is_locked) {
642 return kDifLocked;
643 }
644
645 ptrdiff_t reg_offset = PINMUX_WKUP_DETECTOR_EN_0_REG_OFFSET +
646 (ptrdiff_t)sizeof(uint32_t) * (ptrdiff_t)detector;
647 mmio_region_write32(pinmux->base_addr, reg_offset, 0);
648 return kDifOk;
649}
650
651dif_result_t dif_pinmux_wakeup_cause_clear(const dif_pinmux_t *pinmux) {
652 if (pinmux == NULL) {
653 return kDifBadArg;
654 }
655 mmio_region_write32(pinmux->base_addr, PINMUX_WKUP_CAUSE_REG_OFFSET, 0);
656 return kDifOk;
657}
658
659dif_result_t dif_pinmux_wakeup_cause_get(const dif_pinmux_t *pinmux,
660 uint32_t *detector_map) {
661 if (pinmux == NULL) {
662 return kDifBadArg;
663 }
664 *detector_map =
665 mmio_region_read32(pinmux->base_addr, PINMUX_WKUP_CAUSE_REG_OFFSET);
666 return kDifOk;
667}