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 
14 static 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 
41 static bool dif_pinmux_get_sleep_status_bit(dif_pinmux_pad_kind_t kind,
42  dif_pinmux_index_t index,
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 
78 static 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 
124 dif_result_t dif_pinmux_lock(const dif_pinmux_t *pinmux,
125  dif_pinmux_index_t index,
126  dif_pinmux_lock_target_t target) {
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 
139 dif_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 
158 dif_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;
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 
182 dif_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;
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 
206 dif_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 ||
210  dt_periph_io_type(periph_io) != kDtPeriphIoTypeMio) {
211  return kDifBadArg;
212  }
214  pinmux, dt_periph_io_mio_periph_input(periph_io), dt_pad_mio_insel(pad));
215 }
216 
217 dif_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 ||
221  dt_periph_io_type(periph_io) != kDtPeriphIoTypeMio) {
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 
228 static dif_pinmux_pad_attr_t dif_pinmux_reg_to_pad_attr(uint32_t reg_value) {
229  dif_pinmux_pad_attr_t pad_attrs = {0};
231  reg_value, PINMUX_MIO_PAD_ATTR_0_SLEW_RATE_0_FIELD);
232  pad_attrs.drive_strength =
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 
264 enum { kDifPinmuxPadAttrSpinWaitMicros = 5 };
265 
266 dif_result_t dif_pinmux_pad_write_attrs(const dif_pinmux_t *pinmux,
267  dif_pinmux_index_t pad,
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 
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 
371 dif_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 
383 dif_result_t dif_pinmux_pad_get_attrs(const dif_pinmux_t *pinmux,
384  dif_pinmux_index_t pad,
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 
401 dif_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 
411 dif_result_t dif_pinmux_pad_sleep_enable(const dif_pinmux_t *pinmux,
412  dif_pinmux_index_t pad,
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 
469 dif_result_t dif_pinmux_pad_sleep_disable(const dif_pinmux_t *pinmux,
470  dif_pinmux_index_t pad,
471  dif_pinmux_pad_kind_t type) {
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 
500 dif_result_t dif_pinmux_pad_sleep_get_state(const dif_pinmux_t *pinmux,
501  dif_pinmux_index_t pad,
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 
520  dif_pinmux_index_t pad,
521  dif_pinmux_pad_kind_t type) {
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 
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 
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;
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 
651 dif_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 
659 dif_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 }