[dif/sysrst_ctrl] add IRQ status and clear DIFs

This adds the (only remaining) IRQ status and status clear DIFs and
corresponding unit tests.

Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/sw/device/lib/dif/dif_sysrst_ctrl.c b/sw/device/lib/dif/dif_sysrst_ctrl.c
index 1b90d90..69e02bc 100644
--- a/sw/device/lib/dif/dif_sysrst_ctrl.c
+++ b/sw/device/lib/dif/dif_sysrst_ctrl.c
@@ -12,6 +12,13 @@
 
 #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) {
@@ -700,6 +707,54 @@
   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) {
diff --git a/sw/device/lib/dif/dif_sysrst_ctrl_unittest.cc b/sw/device/lib/dif/dif_sysrst_ctrl_unittest.cc
index 7d815fe..0385408 100644
--- a/sw/device/lib/dif/dif_sysrst_ctrl_unittest.cc
+++ b/sw/device/lib/dif/dif_sysrst_ctrl_unittest.cc
@@ -691,6 +691,78 @@
   EXPECT_EQ(is_enabled, kDifToggleEnabled);
 }
 
+class KeyComboIrqGetCausesTest : public SysrstCtrlTest {};
+
+TEST_F(KeyComboIrqGetCausesTest, NullArgs) {
+  uint32_t causes;
+  EXPECT_DIF_BADARG(dif_sysrst_ctrl_key_combo_irq_get_causes(nullptr, &causes));
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_key_combo_irq_get_causes(&sysrst_ctrl_, nullptr));
+  EXPECT_DIF_BADARG(dif_sysrst_ctrl_key_combo_irq_get_causes(nullptr, nullptr));
+}
+
+TEST_F(KeyComboIrqGetCausesTest, Success) {
+  uint32_t causes;
+  EXPECT_READ32(SYSRST_CTRL_COMBO_INTR_STATUS_REG_OFFSET, 0xf);
+  EXPECT_DIF_OK(
+      dif_sysrst_ctrl_key_combo_irq_get_causes(&sysrst_ctrl_, &causes));
+  EXPECT_EQ(causes, 0xf);
+}
+
+class KeyComboIrqClearCausesTest : public SysrstCtrlTest {};
+
+TEST_F(KeyComboIrqClearCausesTest, NullArgs) {
+  EXPECT_DIF_BADARG(dif_sysrst_ctrl_key_combo_irq_clear_causes(nullptr, 0xf));
+}
+
+TEST_F(KeyComboIrqClearCausesTest, BadCauses) {
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_key_combo_irq_clear_causes(&sysrst_ctrl_, 0x1f));
+}
+
+TEST_F(KeyComboIrqClearCausesTest, Success) {
+  EXPECT_WRITE32(SYSRST_CTRL_COMBO_INTR_STATUS_REG_OFFSET, 0xf);
+  EXPECT_DIF_OK(dif_sysrst_ctrl_key_combo_irq_clear_causes(&sysrst_ctrl_, 0xf));
+}
+
+class InputChangeIrqGetCausesTest : public SysrstCtrlTest {};
+
+TEST_F(InputChangeIrqGetCausesTest, NullArgs) {
+  uint32_t causes;
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_input_change_irq_get_causes(nullptr, &causes));
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_input_change_irq_get_causes(&sysrst_ctrl_, nullptr));
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_input_change_irq_get_causes(nullptr, nullptr));
+}
+
+TEST_F(InputChangeIrqGetCausesTest, Success) {
+  uint32_t causes;
+  EXPECT_READ32(SYSRST_CTRL_KEY_INTR_STATUS_REG_OFFSET, 0x3f);
+  EXPECT_DIF_OK(
+      dif_sysrst_ctrl_input_change_irq_get_causes(&sysrst_ctrl_, &causes));
+  EXPECT_EQ(causes, 0x3f);
+}
+
+class InputChangeIrqClearCausesTest : public SysrstCtrlTest {};
+
+TEST_F(InputChangeIrqClearCausesTest, NullArgs) {
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_input_change_irq_clear_causes(nullptr, 0xf));
+}
+
+TEST_F(InputChangeIrqClearCausesTest, BadCauses) {
+  EXPECT_DIF_BADARG(
+      dif_sysrst_ctrl_input_change_irq_clear_causes(&sysrst_ctrl_, 0x4000));
+}
+
+TEST_F(InputChangeIrqClearCausesTest, Success) {
+  EXPECT_WRITE32(SYSRST_CTRL_KEY_INTR_STATUS_REG_OFFSET, 0xff);
+  EXPECT_DIF_OK(
+      dif_sysrst_ctrl_input_change_irq_clear_causes(&sysrst_ctrl_, 0xff));
+}
+
 class UlpWakeupGetStatusTest : public SysrstCtrlTest {};
 
 TEST_F(UlpWakeupGetStatusTest, NullArgs) {