| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PINMUX_H_ |
| #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PINMUX_H_ |
| |
| /** |
| * @file |
| * @brief <a href="/hw/ip/pinmux/doc/">Pin Multiplexer</a> Device Interface |
| * Functions |
| */ |
| |
| /** |
| * Pin Multiplexer connects peripheral input/output signals to the Padring MIO |
| * pad input/output signals. |
| * |
| * Every peripheral input signal is fed into a multiplexer, where selects |
| * determine which Padring MIO pad input or constants should be connected to it. |
| * |
| * Every Padring MIO pad output signal is fed into a multiplexer, where selects |
| * determine which peripheral output or constants should be connected to it. |
| */ |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| |
| #include "sw/device/lib/base/macros.h" |
| #include "sw/device/lib/base/mmio.h" |
| #include "sw/device/lib/dif/dif_base.h" |
| |
| #include "sw/device/lib/dif/autogen/dif_pinmux_autogen.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif // __cplusplus |
| |
| /** |
| * Pin Multiplexer Padring pad kinds. |
| * |
| * A pad can be a Multiplexed (MIO) or Dedicated (DIO). |
| */ |
| typedef enum dif_pinmux_pad_kind { |
| /** |
| * Multiplexed Input/Output pad. Connected to a peripheral input or output |
| * via a multiplexer matrix inside the a Pin Multiplexer. |
| */ |
| kDifPinmuxPadKindMio = 0, |
| /** |
| * Dedicated Input/Output pad. Connected directly to a peripheral input |
| * or output, bypassing the multiplexer matrix. |
| */ |
| kDifPinmuxPadKindDio, |
| kDifPinmuxPadKindCount, |
| } dif_pinmux_pad_kind_t; |
| |
| /** |
| * Pin Multiplexer functionality locking. |
| * |
| * Represents a target functionality to be locked for a given |
| * pad/peripheral input. |
| */ |
| typedef enum dif_pinmux_lock_target { |
| /** |
| * Lock MIO pad input select for a given peripheral input. This means that |
| * the peripheral input connection can no longer be changed. |
| */ |
| kDifPinmuxLockTargetInsel = 0, |
| /** |
| * Lock peripheral output select for a given MIO pad output. This means |
| * that the MIO pad output connection can no longer be changed. |
| */ |
| kDifPinmuxLockTargetOutsel, |
| /** |
| * Lock the sleep mode configuration for a given MIO pad. |
| */ |
| kDifPinmuxLockTargetMioSleep, |
| /** |
| * Lock the sleep mode configuration for a given DIO pad. |
| */ |
| kDifPinmuxLockTargetDioSleep, |
| /** |
| * Lock physical characteristics configuration for a given MIO pad. |
| */ |
| kDifPinmuxLockTargetMioPadAttr, |
| /** |
| * Lock physical characteristics configuration for a given DIO pad. |
| */ |
| kDifPinmuxLockTargetDioPadAttr, |
| /** |
| * Lock wake-up detector configuration for a given detector. |
| */ |
| kDifPinmuxLockTargetWakeupDetector, |
| |
| } dif_pinmux_lock_target_t; |
| |
| /** |
| * Pin Multiplexer generic index. |
| * |
| * The meaning of this index changes between APIs, and must be documented in |
| * the corresponding function description. |
| */ |
| typedef uint32_t dif_pinmux_index_t; |
| |
| /** |
| * Pad slew rate value. |
| * |
| * This selects between available slew rate values, where the largest number |
| * produces the fastest slew rate. See the device's data sheet for the |
| * particular mapping. |
| */ |
| typedef uint8_t dif_pinmux_pad_slew_rate_t; |
| |
| /** |
| * Pad drive strength value. |
| * |
| * This selects between available drive strength values, where the largest |
| * number produces the highest drive strength. See the device's data sheet for |
| * the particular mapping. |
| */ |
| typedef uint8_t dif_pinmux_pad_drive_strength_t; |
| |
| /** |
| * Pad attribute flag values |
| * |
| * This `enum` is a bitfield, meaning that it is allowed to pass combined value |
| * of multiple individual attributes. |
| * |
| * Some attributes have defined meanings, others are implementation defined. Not |
| * all pads will support all attributes, or attribute combinations. The Pin |
| * Multiplexer DIF checks for conflicting or unsupported attributes provided by |
| * the Write-Any Read-Legal (WARL) semantics of the underlying hardware. If the |
| * combination of attributes is not supported - some/all of these attributes |
| * will still be disabled (relevant bit unset in the attribute field). |
| * |
| * IMPORTANT: |
| * - Functions are used to toggle these attributes, must signal an error if at |
| * least one of the attributes in the bitfield could not be toggled. |
| */ |
| typedef enum dif_pinmux_pad_attr_flags { |
| kDifPinmuxPadAttrInvertLevel = 1 << 0, |
| kDifPinmuxPadAttrVirtualOpenDrain = 1 << 1, |
| kDifPinmuxPadAttrPullResistorEnable = 1 << 2, |
| kDifPinmuxPadAttrPullResistorUp = 1 << 3, |
| kDifPinmuxPadAttrKeeper = 1 << 4, |
| kDifPinmuxPadAttrSchmittTrigger = 1 << 5, |
| kDifPinmuxPadAttrOpenDrain = 1 << 6, |
| } dif_pinmux_pad_attr_flags_t; |
| |
| /** |
| * Pin multiplexer padring pad attributes. |
| */ |
| typedef struct dif_pinmux_pad_attr { |
| /** |
| * Slew rate attribute. A greater number produces a faster slew rate. |
| */ |
| dif_pinmux_pad_slew_rate_t slew_rate; |
| /** |
| * Drive strength pad attribute. A greater number produces a stronger drive. |
| */ |
| dif_pinmux_pad_drive_strength_t drive_strength; |
| /** |
| * A bit map of single-bit attribute flags. See dif_pinmux_pad_attr_flags_t |
| * for the mapping and definitions. |
| */ |
| dif_pinmux_pad_attr_flags_t flags; |
| } dif_pinmux_pad_attr_t; |
| |
| /** |
| * A sleep mode for a Padring DIO/MIO pad. |
| * |
| * This determines the behaviour of a pad in deep sleep state. |
| * |
| * NOTE: |
| * After the chip has come back from deep sleep, the mode of the pad |
| * persists until it is explicitly cleared by `dif_pinmux_sleep_clear_state`. |
| * Calling `dif_pinmux_sleep_enable` will configure the pad mode for |
| * the next deep sleep, however it will not change the current mode. |
| */ |
| typedef enum dif_pinmux_sleep_mode { |
| /** |
| * The pad is driven actively to zero. |
| */ |
| kDifPinmuxSleepModeLow = 0, |
| /** |
| * The pad is driven actively to one. |
| */ |
| kDifPinmuxSleepModeHigh, |
| /** |
| * The pad is left undriven. Note that the actual driving behaviour will |
| * depend on the pull-up/-down configuration. |
| */ |
| kDifPinmuxSleepModeHighZ, |
| /** |
| * Keep last driven value (including high-Z). |
| */ |
| kDifPinmuxSleepModeKeep, |
| kDifPinmuxSleepModeCount, |
| } dif_pinmux_sleep_mode_t; |
| |
| /** |
| * A Pin Multiplexer wake-up detection mode (edge triggered). |
| */ |
| typedef enum dif_pinmux_wakeup_mode { |
| /** |
| * Trigger a wakeup request when observing a positive edge. |
| */ |
| kDifPinmuxWakeupModePositiveEdge = 0, |
| /** |
| * Trigger a wakeup request when observing a negative edge. |
| */ |
| kDifPinmuxWakeupModeNegativeEdge, |
| /** |
| * Trigger a wakeup request when observing an edge in any direction. |
| */ |
| kDifPinmuxWakeupModeAnyEdge, |
| /** |
| * Trigger a wakeup request when pin is driven HIGH for a certain amount of |
| * always-on clock cycles as configured in |
| * `dif_pinmux_wakeup_timed_config_t`, `counter_threshold` field. |
| */ |
| kDifPinmuxWakeupModeTimedHigh, |
| /** |
| * Trigger a wakeup request when pin is driven LOW for a certain amount of |
| * always-on clock cycles as configured in |
| * `dif_pinmux_wakeup_timed_config_t`, `counter_threshold` field. |
| */ |
| kDifPinmuxWakeupModeTimedLow, |
| kDifPinmuxWakeupModeCount, |
| } dif_pinmux_wakeup_mode_t; |
| |
| /** |
| * A Pin Multiplexer common wake-up configuration between different modes. |
| */ |
| typedef struct dif_pinmux_wakeup_config { |
| /** |
| * Signal filter - signal must be stable for 4 always-on clock cycles |
| * before the value is being forwarded. Can be used for debouncing. |
| */ |
| dif_toggle_t signal_filter; |
| /** |
| * Pad type (MIO or DIO) to enable the wake-up detection for. |
| */ |
| dif_pinmux_pad_kind_t pad_type; |
| /** |
| * Selects a specific pad. In the case of MIO, the pad select index is the |
| * same as used for `dif_pinmux_input_select`, meaning that index 0 and 1 just |
| * select constant 0, and the MIO pads live at indices >= 2. In the case of |
| * DIO pads, the pad select index corresponds 1:1 to the DIO pad to be |
| * selected. |
| */ |
| dif_pinmux_index_t pad_select; |
| /** |
| * Wake-up detection mode. |
| */ |
| dif_pinmux_wakeup_mode_t mode; |
| /** |
| * Counter threshold for `kDifPinmuxWakeupModeTimedLow` and |
| * `kDifPinmuxWakeupModeTimedHigh` wake-up detector modes. The threshold is in |
| * terms of always-on clock cycles. |
| */ |
| uint8_t counter_threshold; |
| } dif_pinmux_wakeup_config_t; |
| |
| /** |
| * Locks out Pin Multiplexer functionality based on the `target` and `index`. |
| * |
| * This function allows for a fine grained locking of the Pin Multiplexer |
| * parts. `index` changes meaning dependent on the `target`. For example, when |
| * `target` is `kDifPinmuxLockTargetInsel`, `index` represents a peripheral |
| * input for which the MIO input select functionality should be locked. |
| * |
| * NOTE: |
| * Locking an already locked register will succeed with the `kDifOk` |
| * return code. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param index Exact meaning is determined by the `target`, however, it |
| * represents one of the following: peripheral input index, |
| * MIO pad index, DIO pad index or a wakeup detector index. |
| * @param target Target functionality to be locked. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_lock(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t index, |
| dif_pinmux_lock_target_t target); |
| |
| /** |
| * Obtains the Pin Multiplexer Pad lock status based on `target` and `index`. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param index Exact meaning is determined by the `target`, however, it |
| * represents one of the following: peripheral input index, |
| * MIO pad index, DIO pad index or a wakeup detector index. |
| * @param target Target functionality to be locked. |
| * @param[out] is_locked Out-param for the locked state. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_is_locked(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t index, |
| dif_pinmux_lock_target_t target, |
| bool *is_locked); |
| |
| /** |
| * Sets a connection between a peripheral input and a MIO pad input. |
| * |
| * A peripheral input can be connected to any available MIO pad input. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param peripheral_input A Peripheral input index. |
| * @param insel Input connection select - a MIO pad input to be connected to |
| * a peripheral input. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_input_select(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t peripheral_input, |
| dif_pinmux_index_t insel); |
| |
| /** |
| * Sets a connection between a MIO pad output and peripheral output. |
| * |
| * A MIO pad output can be connected to any available peripheral output. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param mio_pad_output Padring MIO output index. |
| * @param outsel Peripheral output connection select - a Peripheral output to be |
| * connected to a MIO pad output. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_output_select(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t mio_pad_output, |
| dif_pinmux_index_t outsel); |
| |
| /** |
| * Writes attributes for a pad. |
| * |
| * This function completely overwrites the existing configuration of a pad, and |
| * has both enable and disable semantics. |
| * |
| * Not all pads implement all attributes and some combinations cannot be |
| * enabled together. This function returns a `kDifBadArg` error in case of |
| * invalid `attrs_in`. |
| * Conflicting attributes will be discarded by the hardware, and can be |
| * identified by comparing `attrs_in` to `attrs_out`. |
| * |
| * IMPORTANT: |
| * See `dif_pinmux_pad_attr` for information on which attributes are compulsory |
| * and which invariants are mutually exclusive. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param pad Pad index to write the attributes for. |
| * @param type Pad type (MIO or DIO). |
| * @param attrs_in Attribute values to write. |
| * @param attrs_out[out] The actual attributes written and accepted by the |
| * hardware. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_write_attrs(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type, |
| dif_pinmux_pad_attr_t attrs_in, |
| dif_pinmux_pad_attr_t *attrs_out); |
| |
| /** |
| * Get attributes for a pad. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param pad Pad index to obtain the attributes for. |
| * @param type Pad type (MIO or DIO). |
| * @param attrs[out] Obtained attributes. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_get_attrs(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type, |
| dif_pinmux_pad_attr_t *attrs); |
| |
| /** |
| * Enables deep sleep mode of a particular pad. |
| * |
| * NOTE: |
| * After the chip has come back from deep sleep, the mode of a pad persists |
| * until is explicitly cleared by `dif_pinmux_pad_sleep_clear_state`. Calling |
| * `dif_pinmux_pad_sleep_enable` will configure a pad mode for the next deep |
| * sleep, however it will not change the current mode. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param pad Pad index. |
| * @param type Pad type (MIO or DIO). |
| * @param mode Pad deep sleep mode. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_sleep_enable(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type, |
| dif_pinmux_sleep_mode_t mode); |
| |
| /** |
| * Disables deep sleep mode of a particular pad. |
| * |
| * NOTE: |
| * After the chip has come back from deep sleep, the mode of a pad persists |
| * until is explicitly cleared by `dif_pinmux_pad_sleep_clear_state`. Calling |
| * `dif_pinmux_pad_sleep_enable` will configure a pad mode for the next deep |
| * sleep, however it will not change the current mode. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param pad Pad index. |
| * @param type Pad type (MIO or DIO). |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_sleep_disable(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type); |
| |
| /** |
| * Returns the state of a particular pad. |
| * |
| * When the pad is in deep sleep mode, the mode persists until is explicitly |
| * cleared via `dif_pinmux_pad_sleep_clear_state`. |
| * |
| * @param padmux A Pin Multiplexer handle. |
| * @param pad Pad index. |
| * @param type Padring pad type (MIO or DIO). |
| * @param[out] in_sleep_mode Pad state, `true` when in deep sleep mode. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_sleep_get_state(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type, |
| bool *in_sleep_mode); |
| |
| /** |
| * Clears deep sleep mode for a particular pad. |
| * |
| * When deep sleep mode is enabled for a pad, and the device has entered deep |
| * sleep mode; upon wake-up, the deep sleep status of this pad can only be |
| * cleared by calling this function. Re-configuring this pad will only take |
| * effect during the next deep sleep. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param pad Pad index. |
| * @param type Padring pad type (MIO or DIO). |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_pad_sleep_clear_state(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t pad, |
| dif_pinmux_pad_kind_t type); |
| |
| /** |
| * Enables wake-up mode detection for a particular detector. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param detector A detector index. |
| * @param config A wake-up detector configuration. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_wakeup_detector_enable( |
| const dif_pinmux_t *pinmux, dif_pinmux_index_t detector, |
| dif_pinmux_wakeup_config_t config); |
| |
| /** |
| * Disables wake-up detection for a particular detector. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param detector A detector index. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_wakeup_detector_disable(const dif_pinmux_t *pinmux, |
| dif_pinmux_index_t detector); |
| |
| /** |
| * Clears the wake-up cause information. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_wakeup_cause_clear(const dif_pinmux_t *pinmux); |
| |
| /** |
| * Retrieves the detectors that have detected wake-up patterns. |
| * |
| * @param pinmux A Pin Multiplexer handle. |
| * @param detector_map[out] A bit map representing detectors that have detected |
| * wake-up patterns. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_pinmux_wakeup_cause_get(const dif_pinmux_t *pinmux, |
| uint32_t *detector_map); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PINMUX_H_ |