blob: c241e8e18fdbce8ccd9e4b14a7ae32d92dde10ef [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
#include <assert.h>
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sysrst_ctrl_regs.h" // Generated.
static_assert(SYSRST_CTRL_PARAM_NUM_COMBO == 4,
"Number of key combinations has changed. Update the "
"dif_sysrst_ctrl_key_combo_t enum.");
static_assert(SYSRST_CTRL_KEY_INTR_STATUS_FLASH_WP_L_L2H_BIT == 13,
"Flash write-protect key interrupt bit has changed. Update the "
"dif_sysrst_ctrl_input_change_irq_get_causes() DIF.");
dif_result_t dif_sysrst_ctrl_key_combo_detect_configure(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_key_combo_t key_combo,
dif_sysrst_ctrl_key_combo_config_t config) {
if (sysrst_ctrl == NULL || config.keys > kDifSysrstCtrlKeyAll ||
config.actions > kDifSysrstCtrlKeyComboActionAll) {
return kDifBadArg;
}
ptrdiff_t combo_select_ctl_reg_offset;
ptrdiff_t combo_detect_ctl_reg_offset;
ptrdiff_t combo_action_ctl_reg_offset;
switch (key_combo) {
case kDifSysrstCtrlKeyCombo0:
combo_select_ctl_reg_offset = SYSRST_CTRL_COM_SEL_CTL_0_REG_OFFSET;
combo_detect_ctl_reg_offset = SYSRST_CTRL_COM_DET_CTL_0_REG_OFFSET;
combo_action_ctl_reg_offset = SYSRST_CTRL_COM_OUT_CTL_0_REG_OFFSET;
break;
case kDifSysrstCtrlKeyCombo1:
combo_select_ctl_reg_offset = SYSRST_CTRL_COM_SEL_CTL_1_REG_OFFSET;
combo_detect_ctl_reg_offset = SYSRST_CTRL_COM_DET_CTL_1_REG_OFFSET;
combo_action_ctl_reg_offset = SYSRST_CTRL_COM_OUT_CTL_1_REG_OFFSET;
break;
case kDifSysrstCtrlKeyCombo2:
combo_select_ctl_reg_offset = SYSRST_CTRL_COM_SEL_CTL_2_REG_OFFSET;
combo_detect_ctl_reg_offset = SYSRST_CTRL_COM_DET_CTL_2_REG_OFFSET;
combo_action_ctl_reg_offset = SYSRST_CTRL_COM_OUT_CTL_2_REG_OFFSET;
break;
case kDifSysrstCtrlKeyCombo3:
combo_select_ctl_reg_offset = SYSRST_CTRL_COM_SEL_CTL_3_REG_OFFSET;
combo_detect_ctl_reg_offset = SYSRST_CTRL_COM_DET_CTL_3_REG_OFFSET;
combo_action_ctl_reg_offset = SYSRST_CTRL_COM_OUT_CTL_3_REG_OFFSET;
break;
default:
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
mmio_region_write32(sysrst_ctrl->base_addr, combo_select_ctl_reg_offset,
config.keys);
mmio_region_write32(sysrst_ctrl->base_addr, combo_detect_ctl_reg_offset,
config.detection_time_threshold);
mmio_region_write32(sysrst_ctrl->base_addr, combo_action_ctl_reg_offset,
config.actions);
if (config.actions & kDifSysrstCtrlKeyComboActionEcReset) {
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_EC_RST_CTL_REG_OFFSET,
config.embedded_controller_reset_duration);
}
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_input_change_detect_configure(
const dif_sysrst_ctrl_t *sysrst_ctrl,
dif_sysrst_ctrl_input_change_config_t config) {
if (sysrst_ctrl == NULL || config.input_changes > kDifSysrstCtrlInputAll) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INTR_CTL_REG_OFFSET,
config.input_changes);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INTR_DEBOUNCE_CTL_REG_OFFSET,
config.debounce_time_threshold);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_output_pin_override_configure(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t output_pin,
dif_sysrst_ctrl_pin_config_t config) {
if (sysrst_ctrl == NULL ||
(config.override_value == true && config.allow_one == false) ||
(config.override_value == false && config.allow_zero == false) ||
!dif_is_valid_toggle(config.enabled)) {
return kDifBadArg;
}
uint32_t pin_out_ctl_bit_index;
uint32_t pin_out_value_bit_index;
uint32_t pin_out_allow_0_bit_index;
uint32_t pin_out_allow_1_bit_index;
switch (output_pin) {
case kDifSysrstCtrlPinKey0Out:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY0_OUT_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY0_OUT_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY0_OUT_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY0_OUT_1_BIT;
break;
case kDifSysrstCtrlPinKey1Out:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY1_OUT_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY1_OUT_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY1_OUT_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY1_OUT_1_BIT;
break;
case kDifSysrstCtrlPinKey2Out:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY2_OUT_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY2_OUT_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY2_OUT_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY2_OUT_1_BIT;
break;
case kDifSysrstCtrlPinPowerButtonOut:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_PWRB_OUT_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_PWRB_OUT_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_PWRB_OUT_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_PWRB_OUT_1_BIT;
break;
case kDifSysrstCtrlPinBatteryDisableOut:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_BAT_DISABLE_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_BAT_DISABLE_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_BAT_DISABLE_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_BAT_DISABLE_1_BIT;
break;
case kDifSysrstCtrlPinZ3WakeupOut:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_Z3_WAKEUP_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_Z3_WAKEUP_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_Z3_WAKEUP_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_Z3_WAKEUP_1_BIT;
break;
case kDifSysrstCtrlPinEcResetInOut:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_EC_RST_L_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_EC_RST_L_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_EC_RST_L_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_EC_RST_L_1_BIT;
break;
case kDifSysrstCtrlPinFlashWriteProtectInOut:
pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_FLASH_WP_L_BIT;
pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_FLASH_WP_L_BIT;
pin_out_allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_FLASH_WP_L_0_BIT;
pin_out_allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_FLASH_WP_L_1_BIT;
break;
default:
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
// Configure output pin control register.
uint32_t pin_out_ctl_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_CTL_REG_OFFSET);
pin_out_ctl_reg = bitfield_bit32_write(pin_out_ctl_reg, pin_out_ctl_bit_index,
dif_toggle_to_bool(config.enabled));
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_OUT_CTL_REG_OFFSET, pin_out_ctl_reg);
// Configure output pin override value register.
uint32_t pin_out_value_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_VALUE_REG_OFFSET);
pin_out_value_reg = bitfield_bit32_write(
pin_out_value_reg, pin_out_value_bit_index, config.override_value);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_OUT_VALUE_REG_OFFSET, pin_out_value_reg);
// Configure output pin allowed values register.
uint32_t pin_out_allowed_values_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_ALLOWED_CTL_REG_OFFSET);
pin_out_allowed_values_reg = bitfield_bit32_write(
pin_out_allowed_values_reg, pin_out_allow_0_bit_index, config.allow_zero);
pin_out_allowed_values_reg = bitfield_bit32_write(
pin_out_allowed_values_reg, pin_out_allow_1_bit_index, config.allow_one);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_ALLOWED_CTL_REG_OFFSET,
pin_out_allowed_values_reg);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_ulp_wakeup_configure(
const dif_sysrst_ctrl_t *sysrst_ctrl,
dif_sysrst_ctrl_ulp_wakeup_config_t config) {
if (sysrst_ctrl == NULL || !dif_is_valid_toggle(config.enabled)) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
mmio_region_write32(sysrst_ctrl->base_addr, SYSRST_CTRL_ULP_CTL_REG_OFFSET,
dif_toggle_to_bool(config.enabled));
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_ULP_AC_DEBOUNCE_CTL_REG_OFFSET,
config.ac_power_debounce_time_threshold);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_ULP_LID_DEBOUNCE_CTL_REG_OFFSET,
config.lid_open_debounce_time_threshold);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_ULP_PWRB_DEBOUNCE_CTL_REG_OFFSET,
config.power_button_debounce_time_threshold);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_ulp_wakeup_set_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_toggle_t enabled) {
if (sysrst_ctrl == NULL || !dif_is_valid_toggle(enabled)) {
return kDifBadArg;
}
mmio_region_write32(sysrst_ctrl->base_addr, SYSRST_CTRL_ULP_CTL_REG_OFFSET,
dif_toggle_to_bool(enabled));
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_ulp_wakeup_get_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_toggle_t *is_enabled) {
if (sysrst_ctrl == NULL || is_enabled == NULL) {
return kDifBadArg;
}
*is_enabled = dif_bool_to_toggle(mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_ULP_CTL_REG_OFFSET));
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_pins_set_inverted(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t pins, bool inverted) {
if (sysrst_ctrl == NULL || pins > kDifSysrstCtrlPinAllNonOpenDrain) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
uint32_t inverted_pins = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_KEY_INVERT_CTL_REG_OFFSET);
if (inverted) {
inverted_pins |= pins;
} else {
inverted_pins &= ~pins;
}
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INVERT_CTL_REG_OFFSET, inverted_pins);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_pins_get_inverted(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t *inverted_pins) {
if (sysrst_ctrl == NULL || inverted_pins == NULL) {
return kDifBadArg;
}
*inverted_pins = mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INVERT_CTL_REG_OFFSET);
return kDifOk;
}
static bool get_output_pin_allowed_bit_indices(dif_sysrst_ctrl_pin_t pin,
uint32_t *allow_0_bit_index,
uint32_t *allow_1_bit_index) {
switch (pin) {
case kDifSysrstCtrlPinKey0Out:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY0_OUT_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY0_OUT_1_BIT;
break;
case kDifSysrstCtrlPinKey1Out:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY1_OUT_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY1_OUT_1_BIT;
break;
case kDifSysrstCtrlPinKey2Out:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY2_OUT_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_KEY2_OUT_1_BIT;
break;
case kDifSysrstCtrlPinPowerButtonOut:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_PWRB_OUT_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_PWRB_OUT_1_BIT;
break;
case kDifSysrstCtrlPinBatteryDisableOut:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_BAT_DISABLE_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_BAT_DISABLE_1_BIT;
break;
case kDifSysrstCtrlPinZ3WakeupOut:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_Z3_WAKEUP_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_Z3_WAKEUP_1_BIT;
break;
case kDifSysrstCtrlPinEcResetInOut:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_EC_RST_L_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_EC_RST_L_1_BIT;
break;
case kDifSysrstCtrlPinFlashWriteProtectInOut:
*allow_0_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_FLASH_WP_L_0_BIT;
*allow_1_bit_index = SYSRST_CTRL_PIN_ALLOWED_CTL_FLASH_WP_L_1_BIT;
break;
default:
return false;
}
return true;
}
dif_result_t dif_sysrst_ctrl_output_pin_override_set_allowed(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
bool allow_zero, bool allow_one) {
if (sysrst_ctrl == NULL) {
return kDifBadArg;
}
uint32_t allow_0_bit_index;
uint32_t allow_1_bit_index;
if (!get_output_pin_allowed_bit_indices(pin, &allow_0_bit_index,
&allow_1_bit_index)) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
uint32_t allowed_values_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_ALLOWED_CTL_REG_OFFSET);
allowed_values_reg =
bitfield_bit32_write(allowed_values_reg, allow_0_bit_index, allow_zero);
allowed_values_reg =
bitfield_bit32_write(allowed_values_reg, allow_1_bit_index, allow_one);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_ALLOWED_CTL_REG_OFFSET,
allowed_values_reg);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_output_pin_override_get_allowed(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
bool *allow_zero, bool *allow_one) {
if (sysrst_ctrl == NULL || allow_zero == NULL || allow_one == NULL) {
return kDifBadArg;
}
uint32_t allow_0_bit_index;
uint32_t allow_1_bit_index;
if (!get_output_pin_allowed_bit_indices(pin, &allow_0_bit_index,
&allow_1_bit_index)) {
return kDifBadArg;
}
uint32_t allowed_values_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_ALLOWED_CTL_REG_OFFSET);
*allow_zero = bitfield_bit32_read(allowed_values_reg, allow_0_bit_index);
*allow_one = bitfield_bit32_read(allowed_values_reg, allow_1_bit_index);
return kDifOk;
}
static bool get_output_pin_ctl_bit_index(dif_sysrst_ctrl_pin_t pin,
uint32_t *pin_out_ctl_bit_index) {
switch (pin) {
case kDifSysrstCtrlPinKey0Out:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY0_OUT_BIT;
break;
case kDifSysrstCtrlPinKey1Out:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY1_OUT_BIT;
break;
case kDifSysrstCtrlPinKey2Out:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_KEY2_OUT_BIT;
break;
case kDifSysrstCtrlPinPowerButtonOut:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_PWRB_OUT_BIT;
break;
case kDifSysrstCtrlPinBatteryDisableOut:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_BAT_DISABLE_BIT;
break;
case kDifSysrstCtrlPinZ3WakeupOut:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_Z3_WAKEUP_BIT;
break;
case kDifSysrstCtrlPinEcResetInOut:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_EC_RST_L_BIT;
break;
case kDifSysrstCtrlPinFlashWriteProtectInOut:
*pin_out_ctl_bit_index = SYSRST_CTRL_PIN_OUT_CTL_FLASH_WP_L_BIT;
break;
default:
return false;
}
return true;
}
dif_result_t dif_sysrst_ctrl_output_pin_override_set_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
dif_toggle_t enabled) {
if (sysrst_ctrl == NULL || !dif_is_valid_toggle(enabled)) {
return kDifBadArg;
}
uint32_t pin_out_ctl_bit_index;
if (!get_output_pin_ctl_bit_index(pin, &pin_out_ctl_bit_index)) {
return kDifBadArg;
}
uint32_t pin_out_ctl_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_CTL_REG_OFFSET);
pin_out_ctl_reg = bitfield_bit32_write(pin_out_ctl_reg, pin_out_ctl_bit_index,
dif_toggle_to_bool(enabled));
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_OUT_CTL_REG_OFFSET, pin_out_ctl_reg);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_output_pin_override_get_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
dif_toggle_t *is_enabled) {
if (sysrst_ctrl == NULL || is_enabled == NULL) {
return kDifBadArg;
}
uint32_t pin_out_ctl_bit_index;
if (!get_output_pin_ctl_bit_index(pin, &pin_out_ctl_bit_index)) {
return kDifBadArg;
}
uint32_t pin_out_ctl_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_CTL_REG_OFFSET);
*is_enabled = bitfield_bit32_read(pin_out_ctl_reg, pin_out_ctl_bit_index);
return kDifOk;
}
static bool get_output_pin_value_bit_index(dif_sysrst_ctrl_pin_t pin,
uint32_t *pin_out_value_bit_index) {
switch (pin) {
case kDifSysrstCtrlPinKey0Out:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY0_OUT_BIT;
break;
case kDifSysrstCtrlPinKey1Out:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY1_OUT_BIT;
break;
case kDifSysrstCtrlPinKey2Out:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_KEY2_OUT_BIT;
break;
case kDifSysrstCtrlPinPowerButtonOut:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_PWRB_OUT_BIT;
break;
case kDifSysrstCtrlPinBatteryDisableOut:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_BAT_DISABLE_BIT;
break;
case kDifSysrstCtrlPinZ3WakeupOut:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_Z3_WAKEUP_BIT;
break;
case kDifSysrstCtrlPinEcResetInOut:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_EC_RST_L_BIT;
break;
case kDifSysrstCtrlPinFlashWriteProtectInOut:
*pin_out_value_bit_index = SYSRST_CTRL_PIN_OUT_VALUE_FLASH_WP_L_BIT;
break;
default:
return false;
}
return true;
}
dif_result_t dif_sysrst_ctrl_output_pin_set_override(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
bool value) {
if (sysrst_ctrl == NULL) {
return kDifBadArg;
}
uint32_t pin_out_value_bit_index;
if (!get_output_pin_value_bit_index(pin, &pin_out_value_bit_index)) {
return kDifBadArg;
}
uint32_t pin_out_value_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_VALUE_REG_OFFSET);
pin_out_value_reg =
bitfield_bit32_write(pin_out_value_reg, pin_out_value_bit_index, value);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_PIN_OUT_VALUE_REG_OFFSET, pin_out_value_reg);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_output_pin_get_override(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
bool *value) {
if (sysrst_ctrl == NULL || value == NULL) {
return kDifBadArg;
}
uint32_t pin_out_value_bit_index;
if (!get_output_pin_value_bit_index(pin, &pin_out_value_bit_index)) {
return kDifBadArg;
}
uint32_t pin_out_value_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_OUT_VALUE_REG_OFFSET);
*value = bitfield_bit32_read(pin_out_value_reg, pin_out_value_bit_index);
return kDifOk;
}
static bool get_input_pin_value_bit_index(dif_sysrst_ctrl_pin_t pin,
uint32_t *pin_in_value_bit_index) {
switch (pin) {
case kDifSysrstCtrlPinKey0In:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_KEY0_IN_BIT;
break;
case kDifSysrstCtrlPinKey1In:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_KEY1_IN_BIT;
break;
case kDifSysrstCtrlPinKey2In:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_KEY2_IN_BIT;
break;
case kDifSysrstCtrlPinPowerButtonIn:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_PWRB_IN_BIT;
break;
case kDifSysrstCtrlPinAcPowerPresentIn:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_AC_PRESENT_BIT;
break;
case kDifSysrstCtrlPinLidOpenIn:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_LID_OPEN_BIT;
break;
case kDifSysrstCtrlPinEcResetInOut:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_EC_RST_L_BIT;
break;
case kDifSysrstCtrlPinFlashWriteProtectInOut:
*pin_in_value_bit_index = SYSRST_CTRL_PIN_IN_VALUE_FLASH_WP_L_BIT;
break;
default:
return false;
}
return true;
}
dif_result_t dif_sysrst_ctrl_input_pin_read(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_pin_t pin,
bool *value) {
if (sysrst_ctrl == NULL || value == NULL) {
return kDifBadArg;
}
uint32_t pin_in_value_bit_index;
if (!get_input_pin_value_bit_index(pin, &pin_in_value_bit_index)) {
return kDifBadArg;
}
uint32_t pin_in_value_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_PIN_IN_VALUE_REG_OFFSET);
*value = bitfield_bit32_read(pin_in_value_reg, pin_in_value_bit_index);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_auto_override_configure(
const dif_sysrst_ctrl_t *sysrst_ctrl,
dif_sysrst_ctrl_auto_override_config_t config, dif_toggle_t enabled) {
if (sysrst_ctrl == NULL || !dif_is_valid_toggle(config.override_key_0) ||
!dif_is_valid_toggle(config.override_key_1) ||
!dif_is_valid_toggle(config.override_key_2) ||
!dif_is_valid_toggle(enabled)) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
// Configure Auto Block Debounce Control register.
uint32_t auto_block_ctl_reg = bitfield_bit32_write(
0, SYSRST_CTRL_AUTO_BLOCK_DEBOUNCE_CTL_AUTO_BLOCK_ENABLE_BIT,
dif_toggle_to_bool(enabled));
auto_block_ctl_reg = bitfield_field32_write(
auto_block_ctl_reg,
SYSRST_CTRL_AUTO_BLOCK_DEBOUNCE_CTL_DEBOUNCE_TIMER_FIELD,
config.debounce_time_threshold);
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_AUTO_BLOCK_DEBOUNCE_CTL_REG_OFFSET,
auto_block_ctl_reg);
// Configure Auto Block Output Control register.
auto_block_ctl_reg =
bitfield_bit32_write(0, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY0_OUT_SEL_BIT,
dif_toggle_to_bool(config.override_key_0));
auto_block_ctl_reg = bitfield_bit32_write(
auto_block_ctl_reg, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY0_OUT_VALUE_BIT,
dif_toggle_to_bool(config.key_0_override_value));
auto_block_ctl_reg = bitfield_bit32_write(
auto_block_ctl_reg, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY1_OUT_SEL_BIT,
dif_toggle_to_bool(config.override_key_1));
auto_block_ctl_reg = bitfield_bit32_write(
auto_block_ctl_reg, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY1_OUT_VALUE_BIT,
dif_toggle_to_bool(config.key_1_override_value));
auto_block_ctl_reg = bitfield_bit32_write(
auto_block_ctl_reg, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY2_OUT_SEL_BIT,
dif_toggle_to_bool(config.override_key_2));
auto_block_ctl_reg = bitfield_bit32_write(
auto_block_ctl_reg, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY2_OUT_VALUE_BIT,
dif_toggle_to_bool(config.key_2_override_value));
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_REG_OFFSET,
auto_block_ctl_reg);
return kDifOk;
}
static bool get_key_auto_override_en_bit_index(dif_sysrst_ctrl_key_t key,
uint32_t *en_bit_index) {
switch (key) {
case kDifSysrstCtrlKey0:
*en_bit_index = SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY0_OUT_SEL_BIT;
break;
case kDifSysrstCtrlKey1:
*en_bit_index = SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY1_OUT_SEL_BIT;
break;
case kDifSysrstCtrlKey2:
*en_bit_index = SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_KEY2_OUT_SEL_BIT;
break;
default:
return false;
}
return true;
}
dif_result_t dif_sysrst_ctrl_auto_override_set_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_key_t key,
dif_toggle_t enabled) {
if (sysrst_ctrl == NULL || !dif_is_valid_toggle(enabled)) {
return kDifBadArg;
}
uint32_t en_bit_index;
if (!get_key_auto_override_en_bit_index(key, &en_bit_index)) {
return kDifBadArg;
}
if (!mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET)) {
return kDifLocked;
}
uint32_t auto_block_ctl_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_REG_OFFSET);
auto_block_ctl_reg = bitfield_bit32_write(auto_block_ctl_reg, en_bit_index,
dif_toggle_to_bool(enabled));
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_REG_OFFSET,
auto_block_ctl_reg);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_auto_override_get_enabled(
const dif_sysrst_ctrl_t *sysrst_ctrl, dif_sysrst_ctrl_key_t key,
dif_toggle_t *is_enabled) {
if (sysrst_ctrl == NULL || is_enabled == NULL) {
return kDifBadArg;
}
uint32_t en_bit_index;
if (!get_key_auto_override_en_bit_index(key, &en_bit_index)) {
return kDifBadArg;
}
uint32_t auto_block_ctl_reg = mmio_region_read32(
sysrst_ctrl->base_addr, SYSRST_CTRL_AUTO_BLOCK_OUT_CTL_REG_OFFSET);
*is_enabled =
dif_bool_to_toggle(bitfield_bit32_read(auto_block_ctl_reg, en_bit_index));
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_key_combo_irq_get_causes(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t *causes) {
if (sysrst_ctrl == NULL || causes == NULL) {
return kDifBadArg;
}
*causes = mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_COMBO_INTR_STATUS_REG_OFFSET);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_key_combo_irq_clear_causes(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t causes) {
if (sysrst_ctrl == NULL || causes >= (1U << SYSRST_CTRL_PARAM_NUM_COMBO)) {
return kDifBadArg;
}
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_COMBO_INTR_STATUS_REG_OFFSET, causes);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_input_change_irq_get_causes(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t *causes) {
if (sysrst_ctrl == NULL || causes == NULL) {
return kDifBadArg;
}
*causes = mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INTR_STATUS_REG_OFFSET);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_input_change_irq_clear_causes(
const dif_sysrst_ctrl_t *sysrst_ctrl, uint32_t causes) {
if (sysrst_ctrl == NULL ||
causes >= (1U << (SYSRST_CTRL_KEY_INTR_STATUS_FLASH_WP_L_L2H_BIT + 1))) {
return kDifBadArg;
}
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_KEY_INTR_STATUS_REG_OFFSET, causes);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_ulp_wakeup_get_status(
const dif_sysrst_ctrl_t *sysrst_ctrl, bool *wakeup_detected) {
if (sysrst_ctrl == NULL || wakeup_detected == NULL) {
return kDifBadArg;
}
*wakeup_detected = mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_WKUP_STATUS_REG_OFFSET);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_ulp_wakeup_clear_status(
const dif_sysrst_ctrl_t *sysrst_ctrl) {
if (sysrst_ctrl == NULL) {
return kDifBadArg;
}
mmio_region_write32(sysrst_ctrl->base_addr,
SYSRST_CTRL_WKUP_STATUS_REG_OFFSET, 1);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_lock(const dif_sysrst_ctrl_t *sysrst_ctrl) {
if (sysrst_ctrl == NULL) {
return kDifBadArg;
}
mmio_region_write32(sysrst_ctrl->base_addr, SYSRST_CTRL_REGWEN_REG_OFFSET, 0);
return kDifOk;
}
dif_result_t dif_sysrst_ctrl_is_locked(const dif_sysrst_ctrl_t *sysrst_ctrl,
bool *is_locked) {
if (sysrst_ctrl == NULL || is_locked == NULL) {
return kDifBadArg;
}
*is_locked = !mmio_region_read32(sysrst_ctrl->base_addr,
SYSRST_CTRL_REGWEN_REG_OFFSET);
return kDifOk;
}