| // 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_ADC_CTRL_H_ |
| #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ADC_CTRL_H_ |
| |
| /** |
| * @file |
| * @brief <a href="/hw/ip/adc_ctrl/doc/">ADC Controller</a> Device Interface |
| * Functions |
| */ |
| |
| #include "adc_ctrl_regs.h" // Generated. |
| #include "sw/device/lib/dif/autogen/dif_adc_ctrl_autogen.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif // __cplusplus |
| |
| /** |
| * Helper X macro for defining enums and case statements related to ADC |
| * Controller channels. If an additional channel is ever added to the hardware, |
| * this list can be updated. |
| */ |
| #define DIF_ADC_CTRL_CHANNEL_LIST(X) \ |
| X(0) \ |
| X(1) |
| |
| /** |
| * Helper X macro for defining enums and case statements related to ADC |
| * Controller filters. If an additional filter is ever added to the hardware, |
| * this list can be updated. |
| */ |
| #define DIF_ADC_CTRL_FILTER_LIST(X) \ |
| X(0) \ |
| X(1) \ |
| X(2) \ |
| X(3) \ |
| X(4) \ |
| X(5) \ |
| X(6) \ |
| X(7) |
| |
| /** |
| * Helper macro for defining a `dif_adc_ctrl_channel_t` enumeration constant. |
| * @channel_ ADC Controller channel of the enumeration constant. |
| */ |
| #define DIF_ADC_CTRL_CHANNEL_ENUM_INIT_(channel_) \ |
| kDifAdcCtrlChannel##channel_ = channel_, |
| |
| /** |
| * An ADC Controller Channel. |
| */ |
| typedef enum dif_adc_ctrl_channel { |
| DIF_ADC_CTRL_CHANNEL_LIST(DIF_ADC_CTRL_CHANNEL_ENUM_INIT_) |
| } dif_adc_ctrl_channel_t; |
| |
| #undef DIF_ADC_CTRL_CHANNEL_ENUM_INIT_ |
| |
| /** |
| * Helper macro for defining a `dif_adc_ctrl_filter_t` enumeration constant. |
| * @filter_ ADC Controller filter of the enumeration constant. |
| */ |
| #define DIF_ADC_CTRL_FILTER_ENUM_INIT_(filter_) \ |
| kDifAdcCtrlFilter##filter_ = filter_, |
| |
| /** |
| * An ADC Controller filter. |
| * |
| * Each channel has a separate instance of each filter. For example, if there |
| * are two channels and eight filters, there would be a total of 16 filter |
| * instances that may be configured. |
| */ |
| typedef enum dif_adc_ctrl_filter { |
| DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_FILTER_ENUM_INIT_) |
| } dif_adc_ctrl_filter_t; |
| |
| #undef DIF_ADC_CTRL_FILTER_ENUM_INIT_ |
| |
| /** |
| * Helper macro for defining a `dif_adc_ctrl_irq_cause_t` enumeration constant. |
| * @filter_cause_ ADC Controller IRQ filter cause of the enumeration constant. |
| */ |
| #define DIF_ADC_CTRL_IRQ_CAUSE_ENUM_INIT_(filter_cause_) \ |
| kDifAdcCtrlIrqCauseFilter##filter_cause_ = 1U << filter_cause_, |
| |
| /** |
| * An ADC Controller IRQ cause. |
| * |
| * The ADC Controller can only generate a single interrupt (the `debug_cable` |
| * interrupt). However, depending on how the ADC Controller is configured, there |
| * are several causes that could trigger this interrupt. These include filter |
| * matches (when in Normal Power Scan mode), or sample completion (when in |
| * Oneshot mode). |
| */ |
| typedef enum dif_adc_ctrl_irq_cause { |
| DIF_ADC_CTRL_FILTER_LIST(DIF_ADC_CTRL_IRQ_CAUSE_ENUM_INIT_) |
| /** |
| * Sample ready cause in Oneshot mode. |
| */ |
| kDifAdcCtrlIrqCauseOneshot = 1U << ADC_CTRL_ADC_INTR_STATUS_ONESHOT_BIT, |
| /** |
| * All IRQ causes ORed together. |
| * |
| * This is useful when clearing all IRQ causes at once, to initialize the ADC |
| * Controller. |
| */ |
| kDifAdcCtrlIrqCauseAll = |
| (1U << (ADC_CTRL_ADC_INTR_STATUS_ONESHOT_BIT + 1)) - 1, |
| } dif_adc_ctrl_irq_cause_t; |
| |
| #undef DIF_ADC_CTRL_IRQ_CAUSE_ENUM_INIT_ |
| |
| /** |
| * Operation mode of the ADC Controller. |
| */ |
| typedef enum dif_adc_ctrl_mode { |
| /** |
| * Low Power (Continuous) Scan mode. |
| * |
| * In Low Power Scan mode, the ADC periodically samples enabled channels, and |
| * upon matching a set of enabled filters, a set number of times, will |
| * transition to Normal Power Scan mode. If no filters are enabled, then the |
| * ADC controller will never transition to Normal Power Scan mode. |
| */ |
| kDifAdcCtrlLowPowerScanMode = 0, |
| /** |
| * Normal Power (Continuous) Scan mode. |
| * |
| * In Normal Power Scan mode, the ADC samples enabled channels as fast as |
| * possible, and upon matching a set of enabled filters, a set number of |
| * consecutive times, may trigger a system wakeup and/or IRQ. Similar to Low |
| * Power Scan mode, if no filters are enabled, then a system wakeup and/or IRQ |
| * will never be triggered. |
| */ |
| kDifAdcCtrlNormalPowerScanMode = 1, |
| /** |
| * Oneshot mode. |
| * |
| * In Oneshot mode, an ADC channel is triggered to take a single sample, upon |
| * being enabled, and optionally, raises an interrupt upon completion. Unlike |
| * the Scan modes, in Oneshot mode, the ADC Controller does not attempt to |
| * filter samples. Rather, an IRQ may be raised immediately upon the sample |
| * being ready, regardless of what the sample is. After the sample is |
| * completed the ADC is powered down, until another sample is triggered, |
| * either by toggling the channel's enable bit on and off, or by resetting the |
| * sampling FSM. |
| */ |
| kDifAdcCtrlOneshotMode = 2, |
| } dif_adc_ctrl_mode_t; |
| |
| /** |
| * Runtime configuration for an ADC Controller. |
| */ |
| typedef struct dif_adc_ctrl_config { |
| /** |
| * The sampling mode to configure the ADC Controller in. |
| */ |
| dif_adc_ctrl_mode_t mode; |
| /** |
| * The time to allow the ADC to power up. |
| * |
| * Units: always-on clock cycles |
| */ |
| uint8_t power_up_time_aon_cycles; |
| /** |
| * The sampling period when in Low Power Scan mode, i.e., how often the ADC |
| * Controller wakes up the ADC to take a sample. |
| * |
| * Units: always-on clock cycles |
| * |
| * Only relevant in Low Power Scan mode. |
| */ |
| uint32_t wake_up_time_aon_cycles; |
| /** |
| * The number of filter-matching samples to count in Low Power Scan mode |
| * before switching to Normal Power Scan mode. |
| * |
| * Only relevant in Low Power Scan mode. |
| */ |
| uint8_t num_low_power_samples; |
| /** |
| * The number of filter-matching samples to count in Normal Power Scan mode |
| * before triggering a system wakeup and/or interrupt. |
| */ |
| uint16_t num_normal_power_samples; |
| } dif_adc_ctrl_config_t; |
| |
| /** |
| * Runtime configuration for an ADC Controller filter. |
| */ |
| typedef struct dif_adc_ctrl_filter_config { |
| /** |
| * The ADC Controller filter this configuration applies to. |
| */ |
| dif_adc_ctrl_filter_t filter; |
| /** |
| * The minimum voltage (inclusive) of the range defined by this filter. |
| * |
| * Valid range: [0, 1024) |
| * Units: 2.148 mV (i.e., range / 2 ^ 10) |
| */ |
| uint16_t min_voltage; |
| /** |
| * The maximum voltage (inclusive) of the range defined by this filter. |
| * |
| * Valid range: [0, 1024) |
| * Units: 2.148 mV (i.e., range / 2 ^ 10) |
| */ |
| uint16_t max_voltage; |
| /** |
| * Where a filter hit is classfied as an (inclusive) in-range hit, or |
| * (exclusive) out-of-range hit. |
| */ |
| bool in_range; |
| /** |
| * Whether to generate a system wakeup on a filter match after saturating the |
| * `num_normal_power_samples` threshold in Normal Power Scan mode. |
| */ |
| bool generate_wakeup_on_match; |
| /** |
| * Whether to generate a `debug_cable` interrupt on a filter match after |
| * saturating the `num_normal_power_samples` threshold in Normal Power Scan |
| * mode. |
| */ |
| bool generate_irq_on_match; |
| } dif_adc_ctrl_filter_config_t; |
| |
| /** |
| * Configures an ADC Controller. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param config Runtime configuration parameters. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_configure(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_config_t config); |
| |
| /** |
| * Configures a channel filter. |
| * |
| * This should be invoked for each desired filter _before_ the sampling sequence |
| * is enabled via `dif_adc_ctrl_set_enabled()`. |
| * |
| * This only applies in Low / Normal Power Scan sampling modes. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param channel The channel of the filter to configure. |
| * @param config Runtime configuration parameters for the filter. |
| * @param enabled The enablement state to configure the filter in. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_configure_filter(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_channel_t channel, |
| dif_adc_ctrl_filter_config_t config, |
| dif_toggle_t enabled); |
| |
| /** |
| * Sets the enablement state of the ADC Controller. |
| * |
| * Enabling the ADC Controller powers it up, while disabling the ADC Controller |
| * powers it down and resets the sampling FSM. After powering up, sampling |
| * begins, regardless of the operation mode. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param enabled The enablement state to configure the ADC Controller in. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_set_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| dif_toggle_t enabled); |
| |
| /** |
| * Gets the enablement state of the ADC Controller. |
| * |
| * If the ADC Controller is enabled, it is powered up, or being powered up. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param[out] is_enabled The enablement state of the ADC Controller. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_get_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| dif_toggle_t *is_enabled); |
| |
| /** |
| * Sets the enablement state of the specified filter for the specified channel. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param channel The channel the filter resides in. |
| * @param filter The filter to set the enablement state of. |
| * @param enabled The enablement state to configure the filter in. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_filter_set_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_channel_t channel, |
| dif_adc_ctrl_filter_t filter, |
| dif_toggle_t enabled); |
| |
| /** |
| * Gets the enablement state of the specified filter for the specified channel. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param channel The channel the filter resides in. |
| * @param filter The filter to get the enablement state of. |
| * @param[out] is_enabled The enablement state of the filter. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_filter_get_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_channel_t channel, |
| dif_adc_ctrl_filter_t filter, |
| dif_toggle_t *enabled); |
| |
| /** |
| * Get the sampled value from the specified channel that triggered the IRQ. |
| * |
| * Values are 10-bits in the range from 0V to 2.2V. Based on this, the |
| * resolution (and units) of the sample are in increments of 2.148mV. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param channel The channel to read the sample from. |
| * @param[out] value The value of the sample. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_get_triggered_value(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_channel_t channel, |
| uint16_t *value); |
| |
| /** |
| * Get the latest sampled value from the specified channel. |
| * |
| * Since in Normal Power Scan mode, sampling continues even after an IRQ has |
| * been raised, the value returned by this function may be different than the |
| * value returned by `dif_adc_ctrl_get_irq_value()`. |
| * |
| * Values are 10-bits in the range from 0V to 2.2V. Based on this, the |
| * resolution (and units) of the sample are in increments of 2.148mV. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param channel The channel to read the sample from. |
| * @param[out] value The value of the sample. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_get_latest_value(const dif_adc_ctrl_t *adc_ctrl, |
| dif_adc_ctrl_channel_t channel, |
| uint16_t *value); |
| |
| /** |
| * Reset all ADC Controller FSMs and counters, and if enabled, begin sampling |
| * sequence. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_reset(const dif_adc_ctrl_t *adc_ctrl); |
| |
| /** |
| * Gets the cause(s) of a `debug_cable` IRQ. |
| * |
| * IRQs can be triggered by filter matches in Normal Power Scan mode (after |
| * saturating the `num_normal_power_samples` threshold), or after a single |
| * sample capture in Oneshot mode. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param[out] causes The causes of the IRQ (one or more |
| * `dif_adc_ctrl_irq_cause_t`s ORed together). |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_irq_get_causes(const dif_adc_ctrl_t *adc_ctrl, |
| uint32_t *causes); |
| |
| /** |
| * Clears the cause(s) of a `debug_cable` IRQ. |
| * |
| * TODO(lowRISC/opentitan:#11354): future releases of the HW should hide the |
| * filter and interrupt status registers behind the standardized IRQ registers. |
| * For now, the autogenerated `dif_adc_ctrl_irq_acknowledge[_all]()` DIF may be |
| * used to clear the main IRQ status register, while this DIF may be used to |
| * clear the local cause / filter status registers. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param causes The causes of the IRQ (one or more `dif_adc_ctrl_irq_cause_t`s |
| * ORed together). |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_irq_clear_causes(const dif_adc_ctrl_t *adc_ctrl, |
| uint32_t causes); |
| |
| /** |
| * Sets the enablement of generating system wakeups on a filter match. |
| * |
| * Only relevant in Normal Power Scan mode (and Low Power Scan mode, which can |
| * transition to Normal Power Scan mode). |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param filter A filter to enable wakeup triggering for. |
| * @param enabled The enablement state to set. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_filter_match_wakeup_set_enabled( |
| const dif_adc_ctrl_t *adc_ctrl, dif_adc_ctrl_filter_t filter, |
| dif_toggle_t enabled); |
| |
| /** |
| * Gets the enablement of generating system wakeups on a filter match. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param filter A filter to enable wakeup triggering for. |
| * @param[out] is_enabled The enablement state retrieved. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_filter_match_wakeup_get_enabled( |
| const dif_adc_ctrl_t *adc_ctrl, dif_adc_ctrl_filter_t filter, |
| dif_toggle_t *is_enabled); |
| |
| /** |
| * Sets the enablement of generating a `debug_cable` IRQ for given cause(s). |
| * |
| * Causes can be filter matches (in Normal Power Scan mode), or when a sample is |
| * complete (in Oneshot mode). |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param causes Causes (one or more `dif_adc_ctrl_irq_cause_t`s ORed together) |
| * to generate the `debug_cable` IRQ for. |
| * @param enabled The enablement state to set. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_irq_cause_set_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| uint32_t causes, |
| dif_toggle_t enabled); |
| |
| /** |
| * Gets the causes that will generate a `debug_cable` IRQ. |
| * |
| * @param adc_ctrl An adc_ctrl handle. |
| * @param[out] enabled_causes Causes (one or more `dif_adc_ctrl_irq_cause_t`s |
| * ORed together) that will generate the |
| * `debug_cable` IRQ. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_adc_ctrl_irq_cause_get_enabled(const dif_adc_ctrl_t *adc_ctrl, |
| uint32_t *enabled_causes); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ADC_CTRL_H_ |