| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // clang-format off |
| // |
| // ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// |
| // PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND: |
| // util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson |
| // -o hw/top_earlgrey |
| #include <limits.h> |
| |
| #include "sw/device/lib/base/csr.h" |
| #include "sw/device/lib/base/mmio.h" |
| #include "sw/device/lib/dif/dif_adc_ctrl.h" |
| #include "sw/device/lib/dif/dif_alert_handler.h" |
| #include "sw/device/lib/dif/dif_aon_timer.h" |
| #include "sw/device/lib/dif/dif_csrng.h" |
| #include "sw/device/lib/dif/dif_edn.h" |
| #include "sw/device/lib/dif/dif_entropy_src.h" |
| #include "sw/device/lib/dif/dif_flash_ctrl.h" |
| #include "sw/device/lib/dif/dif_gpio.h" |
| #include "sw/device/lib/dif/dif_hmac.h" |
| #include "sw/device/lib/dif/dif_i2c.h" |
| #include "sw/device/lib/dif/dif_keymgr.h" |
| #include "sw/device/lib/dif/dif_kmac.h" |
| #include "sw/device/lib/dif/dif_otbn.h" |
| #include "sw/device/lib/dif/dif_otp_ctrl.h" |
| #include "sw/device/lib/dif/dif_pattgen.h" |
| #include "sw/device/lib/dif/dif_pwrmgr.h" |
| #include "sw/device/lib/dif/dif_rv_plic.h" |
| #include "sw/device/lib/dif/dif_rv_timer.h" |
| #include "sw/device/lib/dif/dif_sensor_ctrl.h" |
| #include "sw/device/lib/dif/dif_spi_device.h" |
| #include "sw/device/lib/dif/dif_spi_host.h" |
| #include "sw/device/lib/dif/dif_sysrst_ctrl.h" |
| #include "sw/device/lib/dif/dif_uart.h" |
| #include "sw/device/lib/dif/dif_usbdev.h" |
| #include "sw/device/lib/runtime/ibex.h" |
| #include "sw/device/lib/runtime/irq.h" |
| #include "sw/device/lib/runtime/log.h" |
| #include "sw/device/lib/testing/test_framework/check.h" |
| #include "sw/device/lib/testing/rv_plic_testutils.h" |
| #include "sw/device/lib/testing/test_framework/ottf_main.h" |
| #include "sw/device/lib/testing/test_framework/status.h" |
| #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" |
| |
| static dif_adc_ctrl_t adc_ctrl_aon; |
| static dif_alert_handler_t alert_handler; |
| static dif_aon_timer_t aon_timer_aon; |
| static dif_csrng_t csrng; |
| static dif_edn_t edn0; |
| static dif_edn_t edn1; |
| static dif_entropy_src_t entropy_src; |
| static dif_flash_ctrl_t flash_ctrl; |
| static dif_gpio_t gpio; |
| static dif_hmac_t hmac; |
| static dif_i2c_t i2c0; |
| static dif_i2c_t i2c1; |
| static dif_i2c_t i2c2; |
| static dif_keymgr_t keymgr; |
| static dif_kmac_t kmac; |
| static dif_otbn_t otbn; |
| static dif_otp_ctrl_t otp_ctrl; |
| static dif_pattgen_t pattgen; |
| static dif_pwrmgr_t pwrmgr_aon; |
| static dif_rv_timer_t rv_timer; |
| static dif_sensor_ctrl_t sensor_ctrl; |
| static dif_spi_device_t spi_device; |
| static dif_spi_host_t spi_host0; |
| static dif_spi_host_t spi_host1; |
| static dif_sysrst_ctrl_t sysrst_ctrl_aon; |
| static dif_uart_t uart0; |
| static dif_uart_t uart1; |
| static dif_uart_t uart2; |
| static dif_uart_t uart3; |
| static dif_usbdev_t usbdev; |
| static dif_rv_plic_t plic; |
| static const top_earlgrey_plic_target_t kHart = kTopEarlgreyPlicTargetIbex0; |
| |
| /** |
| * Flag indicating which peripheral is under test. |
| * |
| * Declared volatile because it is referenced in the main program flow as well |
| * as the ISR. |
| */ |
| static volatile top_earlgrey_plic_peripheral_t peripheral_expected; |
| |
| /** |
| * Flags indicating the IRQ expected to have triggered and serviced within the |
| * peripheral. |
| * |
| * Declared volatile because it is referenced in the main program flow as well |
| * as the ISR. |
| */ |
| static volatile dif_adc_ctrl_irq_t adc_ctrl_irq_expected; |
| static volatile dif_adc_ctrl_irq_t adc_ctrl_irq_serviced; |
| static volatile dif_alert_handler_irq_t alert_handler_irq_expected; |
| static volatile dif_alert_handler_irq_t alert_handler_irq_serviced; |
| static volatile dif_aon_timer_irq_t aon_timer_irq_expected; |
| static volatile dif_aon_timer_irq_t aon_timer_irq_serviced; |
| static volatile dif_csrng_irq_t csrng_irq_expected; |
| static volatile dif_csrng_irq_t csrng_irq_serviced; |
| static volatile dif_edn_irq_t edn_irq_expected; |
| static volatile dif_edn_irq_t edn_irq_serviced; |
| static volatile dif_entropy_src_irq_t entropy_src_irq_expected; |
| static volatile dif_entropy_src_irq_t entropy_src_irq_serviced; |
| static volatile dif_flash_ctrl_irq_t flash_ctrl_irq_expected; |
| static volatile dif_flash_ctrl_irq_t flash_ctrl_irq_serviced; |
| static volatile dif_gpio_irq_t gpio_irq_expected; |
| static volatile dif_gpio_irq_t gpio_irq_serviced; |
| static volatile dif_hmac_irq_t hmac_irq_expected; |
| static volatile dif_hmac_irq_t hmac_irq_serviced; |
| static volatile dif_i2c_irq_t i2c_irq_expected; |
| static volatile dif_i2c_irq_t i2c_irq_serviced; |
| static volatile dif_keymgr_irq_t keymgr_irq_expected; |
| static volatile dif_keymgr_irq_t keymgr_irq_serviced; |
| static volatile dif_kmac_irq_t kmac_irq_expected; |
| static volatile dif_kmac_irq_t kmac_irq_serviced; |
| static volatile dif_otbn_irq_t otbn_irq_expected; |
| static volatile dif_otbn_irq_t otbn_irq_serviced; |
| static volatile dif_otp_ctrl_irq_t otp_ctrl_irq_expected; |
| static volatile dif_otp_ctrl_irq_t otp_ctrl_irq_serviced; |
| static volatile dif_pattgen_irq_t pattgen_irq_expected; |
| static volatile dif_pattgen_irq_t pattgen_irq_serviced; |
| static volatile dif_pwrmgr_irq_t pwrmgr_irq_expected; |
| static volatile dif_pwrmgr_irq_t pwrmgr_irq_serviced; |
| static volatile dif_rv_timer_irq_t rv_timer_irq_expected; |
| static volatile dif_rv_timer_irq_t rv_timer_irq_serviced; |
| static volatile dif_sensor_ctrl_irq_t sensor_ctrl_irq_expected; |
| static volatile dif_sensor_ctrl_irq_t sensor_ctrl_irq_serviced; |
| static volatile dif_spi_device_irq_t spi_device_irq_expected; |
| static volatile dif_spi_device_irq_t spi_device_irq_serviced; |
| static volatile dif_spi_host_irq_t spi_host_irq_expected; |
| static volatile dif_spi_host_irq_t spi_host_irq_serviced; |
| static volatile dif_sysrst_ctrl_irq_t sysrst_ctrl_irq_expected; |
| static volatile dif_sysrst_ctrl_irq_t sysrst_ctrl_irq_serviced; |
| static volatile dif_uart_irq_t uart_irq_expected; |
| static volatile dif_uart_irq_t uart_irq_serviced; |
| static volatile dif_usbdev_irq_t usbdev_irq_expected; |
| static volatile dif_usbdev_irq_t usbdev_irq_serviced; |
| |
| /** |
| * Provides external IRQ handling for this test. |
| * |
| * This function overrides the default OTTF external ISR. |
| * |
| * For each IRQ, it performs the following: |
| * 1. Claims the IRQ fired (finds PLIC IRQ index). |
| * 2. Checks that the index belongs to the expected peripheral. |
| * 3. Checks that the correct and the only IRQ from the expected peripheral |
| * triggered. |
| * 4. Clears the IRQ at the peripheral. |
| * 5. Completes the IRQ service at PLIC. |
| */ |
| void ottf_external_isr(void) { |
| dif_rv_plic_irq_id_t plic_irq_id; |
| CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kHart, &plic_irq_id)); |
| |
| top_earlgrey_plic_peripheral_t peripheral = (top_earlgrey_plic_peripheral_t) |
| top_earlgrey_plic_interrupt_for_peripheral[plic_irq_id]; |
| CHECK(peripheral == peripheral_expected, |
| "Interrupt from incorrect peripheral: exp = %d, obs = %d", |
| peripheral_expected, peripheral); |
| |
| switch (peripheral) { |
| case kTopEarlgreyPlicPeripheralAdcCtrlAon: { |
| dif_adc_ctrl_irq_t irq = (dif_adc_ctrl_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdAdcCtrlAonMatchDone); |
| CHECK(irq == adc_ctrl_irq_expected, |
| "Incorrect adc_ctrl_aon IRQ triggered: exp = %d, obs = %d", |
| adc_ctrl_irq_expected, irq); |
| adc_ctrl_irq_serviced = irq; |
| |
| dif_adc_ctrl_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_adc_ctrl_irq_get_state(&adc_ctrl_aon, &snapshot)); |
| CHECK(snapshot == (dif_adc_ctrl_irq_state_snapshot_t)(1 << irq), |
| "Only adc_ctrl_aon IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_adc_ctrl_irq_force(&adc_ctrl_aon, irq, false)); |
| CHECK_DIF_OK(dif_adc_ctrl_irq_acknowledge(&adc_ctrl_aon, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralAlertHandler: { |
| dif_alert_handler_irq_t irq = (dif_alert_handler_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdAlertHandlerClassa); |
| CHECK(irq == alert_handler_irq_expected, |
| "Incorrect alert_handler IRQ triggered: exp = %d, obs = %d", |
| alert_handler_irq_expected, irq); |
| alert_handler_irq_serviced = irq; |
| |
| dif_alert_handler_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_alert_handler_irq_get_state(&alert_handler, &snapshot)); |
| CHECK(snapshot == (dif_alert_handler_irq_state_snapshot_t)(1 << irq), |
| "Only alert_handler IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_alert_handler_irq_force(&alert_handler, irq, false)); |
| CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralAonTimerAon: { |
| dif_aon_timer_irq_t irq = (dif_aon_timer_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdAonTimerAonWkupTimerExpired); |
| CHECK(irq == aon_timer_irq_expected, |
| "Incorrect aon_timer_aon IRQ triggered: exp = %d, obs = %d", |
| aon_timer_irq_expected, irq); |
| aon_timer_irq_serviced = irq; |
| |
| dif_aon_timer_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_aon_timer_irq_get_state(&aon_timer_aon, &snapshot)); |
| CHECK(snapshot == (dif_aon_timer_irq_state_snapshot_t)(1 << irq), |
| "Only aon_timer_aon IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_aon_timer_irq_force(&aon_timer_aon, irq, false)); |
| CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer_aon, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralCsrng: { |
| dif_csrng_irq_t irq = (dif_csrng_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdCsrngCsCmdReqDone); |
| CHECK(irq == csrng_irq_expected, |
| "Incorrect csrng IRQ triggered: exp = %d, obs = %d", |
| csrng_irq_expected, irq); |
| csrng_irq_serviced = irq; |
| |
| dif_csrng_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_csrng_irq_get_state(&csrng, &snapshot)); |
| CHECK(snapshot == (dif_csrng_irq_state_snapshot_t)(1 << irq), |
| "Only csrng IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_csrng_irq_force(&csrng, irq, false)); |
| CHECK_DIF_OK(dif_csrng_irq_acknowledge(&csrng, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralEdn0: { |
| dif_edn_irq_t irq = (dif_edn_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdEdn0EdnCmdReqDone); |
| CHECK(irq == edn_irq_expected, |
| "Incorrect edn0 IRQ triggered: exp = %d, obs = %d", |
| edn_irq_expected, irq); |
| edn_irq_serviced = irq; |
| |
| dif_edn_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_edn_irq_get_state(&edn0, &snapshot)); |
| CHECK(snapshot == (dif_edn_irq_state_snapshot_t)(1 << irq), |
| "Only edn0 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_edn_irq_force(&edn0, irq, false)); |
| CHECK_DIF_OK(dif_edn_irq_acknowledge(&edn0, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralEdn1: { |
| dif_edn_irq_t irq = (dif_edn_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdEdn1EdnCmdReqDone); |
| CHECK(irq == edn_irq_expected, |
| "Incorrect edn1 IRQ triggered: exp = %d, obs = %d", |
| edn_irq_expected, irq); |
| edn_irq_serviced = irq; |
| |
| dif_edn_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_edn_irq_get_state(&edn1, &snapshot)); |
| CHECK(snapshot == (dif_edn_irq_state_snapshot_t)(1 << irq), |
| "Only edn1 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_edn_irq_force(&edn1, irq, false)); |
| CHECK_DIF_OK(dif_edn_irq_acknowledge(&edn1, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralEntropySrc: { |
| dif_entropy_src_irq_t irq = (dif_entropy_src_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdEntropySrcEsEntropyValid); |
| CHECK(irq == entropy_src_irq_expected, |
| "Incorrect entropy_src IRQ triggered: exp = %d, obs = %d", |
| entropy_src_irq_expected, irq); |
| entropy_src_irq_serviced = irq; |
| |
| dif_entropy_src_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_entropy_src_irq_get_state(&entropy_src, &snapshot)); |
| CHECK(snapshot == (dif_entropy_src_irq_state_snapshot_t)(1 << irq), |
| "Only entropy_src IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_entropy_src_irq_force(&entropy_src, irq, false)); |
| CHECK_DIF_OK(dif_entropy_src_irq_acknowledge(&entropy_src, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralFlashCtrl: { |
| dif_flash_ctrl_irq_t irq = (dif_flash_ctrl_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdFlashCtrlProgEmpty); |
| CHECK(irq == flash_ctrl_irq_expected, |
| "Incorrect flash_ctrl IRQ triggered: exp = %d, obs = %d", |
| flash_ctrl_irq_expected, irq); |
| flash_ctrl_irq_serviced = irq; |
| |
| dif_flash_ctrl_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_flash_ctrl_irq_get_state(&flash_ctrl, &snapshot)); |
| CHECK(snapshot == (dif_flash_ctrl_irq_state_snapshot_t)(1 << irq), |
| "Only flash_ctrl IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_flash_ctrl_irq_force(&flash_ctrl, irq, false)); |
| CHECK_DIF_OK(dif_flash_ctrl_irq_acknowledge(&flash_ctrl, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralGpio: { |
| dif_gpio_irq_t irq = (dif_gpio_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdGpioGpio0); |
| CHECK(irq == gpio_irq_expected, |
| "Incorrect gpio IRQ triggered: exp = %d, obs = %d", |
| gpio_irq_expected, irq); |
| gpio_irq_serviced = irq; |
| |
| dif_gpio_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_gpio_irq_get_state(&gpio, &snapshot)); |
| CHECK(snapshot == (dif_gpio_irq_state_snapshot_t)(1 << irq), |
| "Only gpio IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_gpio_irq_force(&gpio, irq, false)); |
| CHECK_DIF_OK(dif_gpio_irq_acknowledge(&gpio, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralHmac: { |
| dif_hmac_irq_t irq = (dif_hmac_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdHmacHmacDone); |
| CHECK(irq == hmac_irq_expected, |
| "Incorrect hmac IRQ triggered: exp = %d, obs = %d", |
| hmac_irq_expected, irq); |
| hmac_irq_serviced = irq; |
| |
| dif_hmac_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_hmac_irq_get_state(&hmac, &snapshot)); |
| CHECK(snapshot == (dif_hmac_irq_state_snapshot_t)(1 << irq), |
| "Only hmac IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_hmac_irq_force(&hmac, irq, false)); |
| CHECK_DIF_OK(dif_hmac_irq_acknowledge(&hmac, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralI2c0: { |
| dif_i2c_irq_t irq = (dif_i2c_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdI2c0FmtThreshold); |
| CHECK(irq == i2c_irq_expected, |
| "Incorrect i2c0 IRQ triggered: exp = %d, obs = %d", |
| i2c_irq_expected, irq); |
| i2c_irq_serviced = irq; |
| |
| dif_i2c_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_i2c_irq_get_state(&i2c0, &snapshot)); |
| CHECK(snapshot == (dif_i2c_irq_state_snapshot_t)(1 << irq), |
| "Only i2c0 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c0, irq, false)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge(&i2c0, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralI2c1: { |
| dif_i2c_irq_t irq = (dif_i2c_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdI2c1FmtThreshold); |
| CHECK(irq == i2c_irq_expected, |
| "Incorrect i2c1 IRQ triggered: exp = %d, obs = %d", |
| i2c_irq_expected, irq); |
| i2c_irq_serviced = irq; |
| |
| dif_i2c_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_i2c_irq_get_state(&i2c1, &snapshot)); |
| CHECK(snapshot == (dif_i2c_irq_state_snapshot_t)(1 << irq), |
| "Only i2c1 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c1, irq, false)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge(&i2c1, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralI2c2: { |
| dif_i2c_irq_t irq = (dif_i2c_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdI2c2FmtThreshold); |
| CHECK(irq == i2c_irq_expected, |
| "Incorrect i2c2 IRQ triggered: exp = %d, obs = %d", |
| i2c_irq_expected, irq); |
| i2c_irq_serviced = irq; |
| |
| dif_i2c_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_i2c_irq_get_state(&i2c2, &snapshot)); |
| CHECK(snapshot == (dif_i2c_irq_state_snapshot_t)(1 << irq), |
| "Only i2c2 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c2, irq, false)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge(&i2c2, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralKeymgr: { |
| dif_keymgr_irq_t irq = (dif_keymgr_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdKeymgrOpDone); |
| CHECK(irq == keymgr_irq_expected, |
| "Incorrect keymgr IRQ triggered: exp = %d, obs = %d", |
| keymgr_irq_expected, irq); |
| keymgr_irq_serviced = irq; |
| |
| dif_keymgr_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_keymgr_irq_get_state(&keymgr, &snapshot)); |
| CHECK(snapshot == (dif_keymgr_irq_state_snapshot_t)(1 << irq), |
| "Only keymgr IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_keymgr_irq_force(&keymgr, irq, false)); |
| CHECK_DIF_OK(dif_keymgr_irq_acknowledge(&keymgr, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralKmac: { |
| dif_kmac_irq_t irq = (dif_kmac_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdKmacKmacDone); |
| CHECK(irq == kmac_irq_expected, |
| "Incorrect kmac IRQ triggered: exp = %d, obs = %d", |
| kmac_irq_expected, irq); |
| kmac_irq_serviced = irq; |
| |
| dif_kmac_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_kmac_irq_get_state(&kmac, &snapshot)); |
| CHECK(snapshot == (dif_kmac_irq_state_snapshot_t)(1 << irq), |
| "Only kmac IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_kmac_irq_force(&kmac, irq, false)); |
| CHECK_DIF_OK(dif_kmac_irq_acknowledge(&kmac, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralOtbn: { |
| dif_otbn_irq_t irq = (dif_otbn_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdOtbnDone); |
| CHECK(irq == otbn_irq_expected, |
| "Incorrect otbn IRQ triggered: exp = %d, obs = %d", |
| otbn_irq_expected, irq); |
| otbn_irq_serviced = irq; |
| |
| dif_otbn_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_otbn_irq_get_state(&otbn, &snapshot)); |
| CHECK(snapshot == (dif_otbn_irq_state_snapshot_t)(1 << irq), |
| "Only otbn IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_otbn_irq_force(&otbn, irq, false)); |
| CHECK_DIF_OK(dif_otbn_irq_acknowledge(&otbn, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralOtpCtrl: { |
| dif_otp_ctrl_irq_t irq = (dif_otp_ctrl_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdOtpCtrlOtpOperationDone); |
| CHECK(irq == otp_ctrl_irq_expected, |
| "Incorrect otp_ctrl IRQ triggered: exp = %d, obs = %d", |
| otp_ctrl_irq_expected, irq); |
| otp_ctrl_irq_serviced = irq; |
| |
| dif_otp_ctrl_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_otp_ctrl_irq_get_state(&otp_ctrl, &snapshot)); |
| CHECK(snapshot == (dif_otp_ctrl_irq_state_snapshot_t)(1 << irq), |
| "Only otp_ctrl IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_otp_ctrl_irq_force(&otp_ctrl, irq, false)); |
| CHECK_DIF_OK(dif_otp_ctrl_irq_acknowledge(&otp_ctrl, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralPattgen: { |
| dif_pattgen_irq_t irq = (dif_pattgen_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdPattgenDoneCh0); |
| CHECK(irq == pattgen_irq_expected, |
| "Incorrect pattgen IRQ triggered: exp = %d, obs = %d", |
| pattgen_irq_expected, irq); |
| pattgen_irq_serviced = irq; |
| |
| dif_pattgen_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_pattgen_irq_get_state(&pattgen, &snapshot)); |
| CHECK(snapshot == (dif_pattgen_irq_state_snapshot_t)(1 << irq), |
| "Only pattgen IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_pattgen_irq_force(&pattgen, irq, false)); |
| CHECK_DIF_OK(dif_pattgen_irq_acknowledge(&pattgen, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralPwrmgrAon: { |
| dif_pwrmgr_irq_t irq = (dif_pwrmgr_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdPwrmgrAonWakeup); |
| CHECK(irq == pwrmgr_irq_expected, |
| "Incorrect pwrmgr_aon IRQ triggered: exp = %d, obs = %d", |
| pwrmgr_irq_expected, irq); |
| pwrmgr_irq_serviced = irq; |
| |
| dif_pwrmgr_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_pwrmgr_irq_get_state(&pwrmgr_aon, &snapshot)); |
| CHECK(snapshot == (dif_pwrmgr_irq_state_snapshot_t)(1 << irq), |
| "Only pwrmgr_aon IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_pwrmgr_irq_force(&pwrmgr_aon, irq, false)); |
| CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge(&pwrmgr_aon, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralRvTimer: { |
| dif_rv_timer_irq_t irq = (dif_rv_timer_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdRvTimerTimerExpiredHart0Timer0); |
| CHECK(irq == rv_timer_irq_expected, |
| "Incorrect rv_timer IRQ triggered: exp = %d, obs = %d", |
| rv_timer_irq_expected, irq); |
| rv_timer_irq_serviced = irq; |
| |
| dif_rv_timer_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_rv_timer_irq_get_state(&rv_timer, kHart, &snapshot)); |
| CHECK(snapshot == (dif_rv_timer_irq_state_snapshot_t)(1 << irq), |
| "Only rv_timer IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_rv_timer_irq_force(&rv_timer, irq, false)); |
| CHECK_DIF_OK(dif_rv_timer_irq_acknowledge(&rv_timer, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralSensorCtrl: { |
| dif_sensor_ctrl_irq_t irq = (dif_sensor_ctrl_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdSensorCtrlIoStatusChange); |
| CHECK(irq == sensor_ctrl_irq_expected, |
| "Incorrect sensor_ctrl IRQ triggered: exp = %d, obs = %d", |
| sensor_ctrl_irq_expected, irq); |
| sensor_ctrl_irq_serviced = irq; |
| |
| dif_sensor_ctrl_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_sensor_ctrl_irq_get_state(&sensor_ctrl, &snapshot)); |
| CHECK(snapshot == (dif_sensor_ctrl_irq_state_snapshot_t)(1 << irq), |
| "Only sensor_ctrl IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_sensor_ctrl_irq_force(&sensor_ctrl, irq, false)); |
| CHECK_DIF_OK(dif_sensor_ctrl_irq_acknowledge(&sensor_ctrl, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralSpiDevice: { |
| dif_spi_device_irq_t irq = (dif_spi_device_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdSpiDeviceGenericRxFull); |
| CHECK(irq == spi_device_irq_expected, |
| "Incorrect spi_device IRQ triggered: exp = %d, obs = %d", |
| spi_device_irq_expected, irq); |
| spi_device_irq_serviced = irq; |
| |
| dif_spi_device_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_spi_device_irq_get_state(&spi_device, &snapshot)); |
| CHECK(snapshot == (dif_spi_device_irq_state_snapshot_t)(1 << irq), |
| "Only spi_device IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_spi_device_irq_force(&spi_device, irq, false)); |
| CHECK_DIF_OK(dif_spi_device_irq_acknowledge(&spi_device, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralSpiHost0: { |
| dif_spi_host_irq_t irq = (dif_spi_host_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdSpiHost0Error); |
| CHECK(irq == spi_host_irq_expected, |
| "Incorrect spi_host0 IRQ triggered: exp = %d, obs = %d", |
| spi_host_irq_expected, irq); |
| spi_host_irq_serviced = irq; |
| |
| dif_spi_host_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_spi_host_irq_get_state(&spi_host0, &snapshot)); |
| CHECK(snapshot == (dif_spi_host_irq_state_snapshot_t)(1 << irq), |
| "Only spi_host0 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_spi_host_irq_force(&spi_host0, irq, false)); |
| CHECK_DIF_OK(dif_spi_host_irq_acknowledge(&spi_host0, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralSpiHost1: { |
| dif_spi_host_irq_t irq = (dif_spi_host_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdSpiHost1Error); |
| CHECK(irq == spi_host_irq_expected, |
| "Incorrect spi_host1 IRQ triggered: exp = %d, obs = %d", |
| spi_host_irq_expected, irq); |
| spi_host_irq_serviced = irq; |
| |
| dif_spi_host_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_spi_host_irq_get_state(&spi_host1, &snapshot)); |
| CHECK(snapshot == (dif_spi_host_irq_state_snapshot_t)(1 << irq), |
| "Only spi_host1 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_spi_host_irq_force(&spi_host1, irq, false)); |
| CHECK_DIF_OK(dif_spi_host_irq_acknowledge(&spi_host1, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralSysrstCtrlAon: { |
| dif_sysrst_ctrl_irq_t irq = (dif_sysrst_ctrl_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdSysrstCtrlAonEventDetected); |
| CHECK(irq == sysrst_ctrl_irq_expected, |
| "Incorrect sysrst_ctrl_aon IRQ triggered: exp = %d, obs = %d", |
| sysrst_ctrl_irq_expected, irq); |
| sysrst_ctrl_irq_serviced = irq; |
| |
| dif_sysrst_ctrl_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_sysrst_ctrl_irq_get_state(&sysrst_ctrl_aon, &snapshot)); |
| CHECK(snapshot == (dif_sysrst_ctrl_irq_state_snapshot_t)(1 << irq), |
| "Only sysrst_ctrl_aon IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_sysrst_ctrl_irq_force(&sysrst_ctrl_aon, irq, false)); |
| CHECK_DIF_OK(dif_sysrst_ctrl_irq_acknowledge(&sysrst_ctrl_aon, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralUart0: { |
| dif_uart_irq_t irq = (dif_uart_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdUart0TxWatermark); |
| CHECK(irq == uart_irq_expected, |
| "Incorrect uart0 IRQ triggered: exp = %d, obs = %d", |
| uart_irq_expected, irq); |
| uart_irq_serviced = irq; |
| |
| dif_uart_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_uart_irq_get_state(&uart0, &snapshot)); |
| CHECK(snapshot == (dif_uart_irq_state_snapshot_t)(1 << irq), |
| "Only uart0 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_uart_irq_force(&uart0, irq, false)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart0, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralUart1: { |
| dif_uart_irq_t irq = (dif_uart_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdUart1TxWatermark); |
| CHECK(irq == uart_irq_expected, |
| "Incorrect uart1 IRQ triggered: exp = %d, obs = %d", |
| uart_irq_expected, irq); |
| uart_irq_serviced = irq; |
| |
| dif_uart_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_uart_irq_get_state(&uart1, &snapshot)); |
| CHECK(snapshot == (dif_uart_irq_state_snapshot_t)(1 << irq), |
| "Only uart1 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_uart_irq_force(&uart1, irq, false)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart1, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralUart2: { |
| dif_uart_irq_t irq = (dif_uart_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdUart2TxWatermark); |
| CHECK(irq == uart_irq_expected, |
| "Incorrect uart2 IRQ triggered: exp = %d, obs = %d", |
| uart_irq_expected, irq); |
| uart_irq_serviced = irq; |
| |
| dif_uart_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_uart_irq_get_state(&uart2, &snapshot)); |
| CHECK(snapshot == (dif_uart_irq_state_snapshot_t)(1 << irq), |
| "Only uart2 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_uart_irq_force(&uart2, irq, false)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart2, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralUart3: { |
| dif_uart_irq_t irq = (dif_uart_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdUart3TxWatermark); |
| CHECK(irq == uart_irq_expected, |
| "Incorrect uart3 IRQ triggered: exp = %d, obs = %d", |
| uart_irq_expected, irq); |
| uart_irq_serviced = irq; |
| |
| dif_uart_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_uart_irq_get_state(&uart3, &snapshot)); |
| CHECK(snapshot == (dif_uart_irq_state_snapshot_t)(1 << irq), |
| "Only uart3 IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_uart_irq_force(&uart3, irq, false)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart3, irq)); |
| break; |
| } |
| |
| case kTopEarlgreyPlicPeripheralUsbdev: { |
| dif_usbdev_irq_t irq = (dif_usbdev_irq_t)( |
| plic_irq_id - |
| (dif_rv_plic_irq_id_t)kTopEarlgreyPlicIrqIdUsbdevPktReceived); |
| CHECK(irq == usbdev_irq_expected, |
| "Incorrect usbdev IRQ triggered: exp = %d, obs = %d", |
| usbdev_irq_expected, irq); |
| usbdev_irq_serviced = irq; |
| |
| dif_usbdev_irq_state_snapshot_t snapshot; |
| CHECK_DIF_OK(dif_usbdev_irq_get_state(&usbdev, &snapshot)); |
| CHECK(snapshot == (dif_usbdev_irq_state_snapshot_t)(1 << irq), |
| "Only usbdev IRQ %d expected to fire. Actual interrupt " |
| "status = %x", |
| irq, snapshot); |
| |
| // TODO: Check Interrupt type then clear INTR_TEST if needed. |
| CHECK_DIF_OK(dif_usbdev_irq_force(&usbdev, irq, false)); |
| CHECK_DIF_OK(dif_usbdev_irq_acknowledge(&usbdev, irq)); |
| break; |
| } |
| |
| default: |
| LOG_FATAL("ISR is not implemented!"); |
| test_status_set(kTestStatusFailed); |
| } |
| |
| // Complete the IRQ at PLIC. |
| CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kHart, plic_irq_id)); |
| } |
| |
| /** |
| * Initializes the handles to all peripherals. |
| */ |
| static void peripherals_init(void) { |
| mmio_region_t base_addr; |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_ADC_CTRL_AON_BASE_ADDR); |
| CHECK_DIF_OK(dif_adc_ctrl_init(base_addr, &adc_ctrl_aon)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_ALERT_HANDLER_BASE_ADDR); |
| CHECK_DIF_OK(dif_alert_handler_init(base_addr, &alert_handler)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR); |
| CHECK_DIF_OK(dif_aon_timer_init(base_addr, &aon_timer_aon)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_CSRNG_BASE_ADDR); |
| CHECK_DIF_OK(dif_csrng_init(base_addr, &csrng)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_EDN0_BASE_ADDR); |
| CHECK_DIF_OK(dif_edn_init(base_addr, &edn0)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_EDN1_BASE_ADDR); |
| CHECK_DIF_OK(dif_edn_init(base_addr, &edn1)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR); |
| CHECK_DIF_OK(dif_entropy_src_init(base_addr, &entropy_src)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR); |
| CHECK_DIF_OK(dif_flash_ctrl_init(base_addr, &flash_ctrl)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_GPIO_BASE_ADDR); |
| CHECK_DIF_OK(dif_gpio_init(base_addr, &gpio)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR); |
| CHECK_DIF_OK(dif_hmac_init(base_addr, &hmac)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_I2C0_BASE_ADDR); |
| CHECK_DIF_OK(dif_i2c_init(base_addr, &i2c0)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_I2C1_BASE_ADDR); |
| CHECK_DIF_OK(dif_i2c_init(base_addr, &i2c1)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_I2C2_BASE_ADDR); |
| CHECK_DIF_OK(dif_i2c_init(base_addr, &i2c2)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR); |
| CHECK_DIF_OK(dif_keymgr_init(base_addr, &keymgr)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR); |
| CHECK_DIF_OK(dif_kmac_init(base_addr, &kmac)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR); |
| CHECK_DIF_OK(dif_otbn_init(base_addr, &otbn)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR); |
| CHECK_DIF_OK(dif_otp_ctrl_init(base_addr, &otp_ctrl)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_PATTGEN_BASE_ADDR); |
| CHECK_DIF_OK(dif_pattgen_init(base_addr, &pattgen)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR); |
| CHECK_DIF_OK(dif_pwrmgr_init(base_addr, &pwrmgr_aon)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_RV_TIMER_BASE_ADDR); |
| CHECK_DIF_OK(dif_rv_timer_init(base_addr, &rv_timer)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_SENSOR_CTRL_BASE_ADDR); |
| CHECK_DIF_OK(dif_sensor_ctrl_init(base_addr, &sensor_ctrl)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_SPI_DEVICE_BASE_ADDR); |
| CHECK_DIF_OK(dif_spi_device_init(base_addr, &spi_device)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_SPI_HOST0_BASE_ADDR); |
| CHECK_DIF_OK(dif_spi_host_init(base_addr, &spi_host0)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_SPI_HOST1_BASE_ADDR); |
| CHECK_DIF_OK(dif_spi_host_init(base_addr, &spi_host1)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_SYSRST_CTRL_AON_BASE_ADDR); |
| CHECK_DIF_OK(dif_sysrst_ctrl_init(base_addr, &sysrst_ctrl_aon)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_UART0_BASE_ADDR); |
| CHECK_DIF_OK(dif_uart_init(base_addr, &uart0)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_UART1_BASE_ADDR); |
| CHECK_DIF_OK(dif_uart_init(base_addr, &uart1)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_UART2_BASE_ADDR); |
| CHECK_DIF_OK(dif_uart_init(base_addr, &uart2)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_UART3_BASE_ADDR); |
| CHECK_DIF_OK(dif_uart_init(base_addr, &uart3)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_USBDEV_BASE_ADDR); |
| CHECK_DIF_OK(dif_usbdev_init(base_addr, &usbdev)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_RV_PLIC_BASE_ADDR); |
| CHECK_DIF_OK(dif_rv_plic_init(base_addr, &plic)); |
| } |
| |
| /** |
| * Clears pending IRQs in all peripherals. |
| */ |
| static void peripheral_irqs_clear(void) { |
| CHECK_DIF_OK(dif_adc_ctrl_irq_acknowledge_all(&adc_ctrl_aon)); |
| CHECK_DIF_OK(dif_alert_handler_irq_acknowledge_all(&alert_handler)); |
| CHECK_DIF_OK(dif_aon_timer_irq_acknowledge_all(&aon_timer_aon)); |
| CHECK_DIF_OK(dif_csrng_irq_acknowledge_all(&csrng)); |
| CHECK_DIF_OK(dif_edn_irq_acknowledge_all(&edn0)); |
| CHECK_DIF_OK(dif_edn_irq_acknowledge_all(&edn1)); |
| CHECK_DIF_OK(dif_entropy_src_irq_acknowledge_all(&entropy_src)); |
| CHECK_DIF_OK(dif_flash_ctrl_irq_acknowledge_all(&flash_ctrl)); |
| CHECK_DIF_OK(dif_gpio_irq_acknowledge_all(&gpio)); |
| CHECK_DIF_OK(dif_hmac_irq_acknowledge_all(&hmac)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge_all(&i2c0)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge_all(&i2c1)); |
| CHECK_DIF_OK(dif_i2c_irq_acknowledge_all(&i2c2)); |
| CHECK_DIF_OK(dif_keymgr_irq_acknowledge_all(&keymgr)); |
| CHECK_DIF_OK(dif_kmac_irq_acknowledge_all(&kmac)); |
| CHECK_DIF_OK(dif_otbn_irq_acknowledge_all(&otbn)); |
| CHECK_DIF_OK(dif_otp_ctrl_irq_acknowledge_all(&otp_ctrl)); |
| CHECK_DIF_OK(dif_pattgen_irq_acknowledge_all(&pattgen)); |
| CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge_all(&pwrmgr_aon)); |
| CHECK_DIF_OK(dif_rv_timer_irq_acknowledge_all(&rv_timer, kHart)); |
| CHECK_DIF_OK(dif_sensor_ctrl_irq_acknowledge_all(&sensor_ctrl)); |
| CHECK_DIF_OK(dif_spi_device_irq_acknowledge_all(&spi_device)); |
| CHECK_DIF_OK(dif_spi_host_irq_acknowledge_all(&spi_host0)); |
| CHECK_DIF_OK(dif_spi_host_irq_acknowledge_all(&spi_host1)); |
| CHECK_DIF_OK(dif_sysrst_ctrl_irq_acknowledge_all(&sysrst_ctrl_aon)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge_all(&uart0)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge_all(&uart1)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge_all(&uart2)); |
| CHECK_DIF_OK(dif_uart_irq_acknowledge_all(&uart3)); |
| CHECK_DIF_OK(dif_usbdev_irq_acknowledge_all(&usbdev)); |
| } |
| |
| /** |
| * Enables all IRQs in all peripherals. |
| */ |
| static void peripheral_irqs_enable(void) { |
| dif_adc_ctrl_irq_state_snapshot_t adc_ctrl_irqs = |
| (dif_adc_ctrl_irq_state_snapshot_t)UINT_MAX; |
| dif_alert_handler_irq_state_snapshot_t alert_handler_irqs = |
| (dif_alert_handler_irq_state_snapshot_t)UINT_MAX; |
| dif_csrng_irq_state_snapshot_t csrng_irqs = |
| (dif_csrng_irq_state_snapshot_t)UINT_MAX; |
| dif_edn_irq_state_snapshot_t edn_irqs = |
| (dif_edn_irq_state_snapshot_t)UINT_MAX; |
| dif_entropy_src_irq_state_snapshot_t entropy_src_irqs = |
| (dif_entropy_src_irq_state_snapshot_t)UINT_MAX; |
| dif_flash_ctrl_irq_state_snapshot_t flash_ctrl_irqs = |
| (dif_flash_ctrl_irq_state_snapshot_t)UINT_MAX; |
| dif_gpio_irq_state_snapshot_t gpio_irqs = |
| (dif_gpio_irq_state_snapshot_t)UINT_MAX; |
| dif_hmac_irq_state_snapshot_t hmac_irqs = |
| (dif_hmac_irq_state_snapshot_t)UINT_MAX; |
| dif_i2c_irq_state_snapshot_t i2c_irqs = |
| (dif_i2c_irq_state_snapshot_t)UINT_MAX; |
| dif_keymgr_irq_state_snapshot_t keymgr_irqs = |
| (dif_keymgr_irq_state_snapshot_t)UINT_MAX; |
| dif_kmac_irq_state_snapshot_t kmac_irqs = |
| (dif_kmac_irq_state_snapshot_t)UINT_MAX; |
| dif_otbn_irq_state_snapshot_t otbn_irqs = |
| (dif_otbn_irq_state_snapshot_t)UINT_MAX; |
| dif_otp_ctrl_irq_state_snapshot_t otp_ctrl_irqs = |
| (dif_otp_ctrl_irq_state_snapshot_t)UINT_MAX; |
| dif_pattgen_irq_state_snapshot_t pattgen_irqs = |
| (dif_pattgen_irq_state_snapshot_t)UINT_MAX; |
| dif_pwrmgr_irq_state_snapshot_t pwrmgr_irqs = |
| (dif_pwrmgr_irq_state_snapshot_t)UINT_MAX; |
| dif_rv_timer_irq_state_snapshot_t rv_timer_irqs = |
| (dif_rv_timer_irq_state_snapshot_t)UINT_MAX; |
| dif_sensor_ctrl_irq_state_snapshot_t sensor_ctrl_irqs = |
| (dif_sensor_ctrl_irq_state_snapshot_t)UINT_MAX; |
| dif_spi_device_irq_state_snapshot_t spi_device_irqs = |
| (dif_spi_device_irq_state_snapshot_t)UINT_MAX; |
| dif_spi_host_irq_state_snapshot_t spi_host_irqs = |
| (dif_spi_host_irq_state_snapshot_t)UINT_MAX; |
| dif_sysrst_ctrl_irq_state_snapshot_t sysrst_ctrl_irqs = |
| (dif_sysrst_ctrl_irq_state_snapshot_t)UINT_MAX; |
| dif_uart_irq_state_snapshot_t uart_irqs = |
| (dif_uart_irq_state_snapshot_t)UINT_MAX; |
| dif_usbdev_irq_state_snapshot_t usbdev_irqs = |
| (dif_usbdev_irq_state_snapshot_t)UINT_MAX; |
| |
| CHECK_DIF_OK( |
| dif_adc_ctrl_irq_restore_all(&adc_ctrl_aon, &adc_ctrl_irqs)); |
| CHECK_DIF_OK( |
| dif_alert_handler_irq_restore_all(&alert_handler, &alert_handler_irqs)); |
| CHECK_DIF_OK( |
| dif_csrng_irq_restore_all(&csrng, &csrng_irqs)); |
| CHECK_DIF_OK( |
| dif_edn_irq_restore_all(&edn0, &edn_irqs)); |
| CHECK_DIF_OK( |
| dif_edn_irq_restore_all(&edn1, &edn_irqs)); |
| CHECK_DIF_OK( |
| dif_entropy_src_irq_restore_all(&entropy_src, &entropy_src_irqs)); |
| CHECK_DIF_OK( |
| dif_flash_ctrl_irq_restore_all(&flash_ctrl, &flash_ctrl_irqs)); |
| CHECK_DIF_OK( |
| dif_gpio_irq_restore_all(&gpio, &gpio_irqs)); |
| CHECK_DIF_OK( |
| dif_hmac_irq_restore_all(&hmac, &hmac_irqs)); |
| CHECK_DIF_OK( |
| dif_i2c_irq_restore_all(&i2c0, &i2c_irqs)); |
| CHECK_DIF_OK( |
| dif_i2c_irq_restore_all(&i2c1, &i2c_irqs)); |
| CHECK_DIF_OK( |
| dif_i2c_irq_restore_all(&i2c2, &i2c_irqs)); |
| CHECK_DIF_OK( |
| dif_keymgr_irq_restore_all(&keymgr, &keymgr_irqs)); |
| CHECK_DIF_OK( |
| dif_kmac_irq_restore_all(&kmac, &kmac_irqs)); |
| CHECK_DIF_OK( |
| dif_otbn_irq_restore_all(&otbn, &otbn_irqs)); |
| CHECK_DIF_OK( |
| dif_otp_ctrl_irq_restore_all(&otp_ctrl, &otp_ctrl_irqs)); |
| CHECK_DIF_OK( |
| dif_pattgen_irq_restore_all(&pattgen, &pattgen_irqs)); |
| CHECK_DIF_OK( |
| dif_pwrmgr_irq_restore_all(&pwrmgr_aon, &pwrmgr_irqs)); |
| CHECK_DIF_OK( |
| dif_rv_timer_irq_restore_all(&rv_timer, kHart, &rv_timer_irqs)); |
| CHECK_DIF_OK( |
| dif_sensor_ctrl_irq_restore_all(&sensor_ctrl, &sensor_ctrl_irqs)); |
| CHECK_DIF_OK( |
| dif_spi_device_irq_restore_all(&spi_device, &spi_device_irqs)); |
| CHECK_DIF_OK( |
| dif_spi_host_irq_restore_all(&spi_host0, &spi_host_irqs)); |
| CHECK_DIF_OK( |
| dif_spi_host_irq_restore_all(&spi_host1, &spi_host_irqs)); |
| CHECK_DIF_OK( |
| dif_sysrst_ctrl_irq_restore_all(&sysrst_ctrl_aon, &sysrst_ctrl_irqs)); |
| // lowrisc/opentitan#8656: Skip UART0 in non-DV setups due to interference |
| // from the logging facility. |
| if (kDeviceType == kDeviceSimDV) { |
| CHECK_DIF_OK( |
| dif_uart_irq_restore_all(&uart0, &uart_irqs)); |
| } |
| CHECK_DIF_OK( |
| dif_uart_irq_restore_all(&uart1, &uart_irqs)); |
| CHECK_DIF_OK( |
| dif_uart_irq_restore_all(&uart2, &uart_irqs)); |
| CHECK_DIF_OK( |
| dif_uart_irq_restore_all(&uart3, &uart_irqs)); |
| CHECK_DIF_OK( |
| dif_usbdev_irq_restore_all(&usbdev, &usbdev_irqs)); |
| } |
| |
| /** |
| * Triggers all IRQs in all peripherals one by one. |
| * |
| * Walks through all instances of all peripherals and triggers an interrupt one |
| * by one, by forcing with the `intr_test` CSR. On trigger, the CPU instantly |
| * jumps into the ISR. The main flow of execution thus proceeds to check that |
| * the correct IRQ was serviced immediately. The ISR, in turn checks if the |
| * expected IRQ from the expected peripheral triggered. |
| */ |
| static void peripheral_irqs_trigger(void) { |
| peripheral_expected = kTopEarlgreyPlicPeripheralAdcCtrlAon; |
| for (dif_adc_ctrl_irq_t irq = kDifAdcCtrlIrqMatchDone; |
| irq <= kDifAdcCtrlIrqMatchDone; ++irq) { |
| adc_ctrl_irq_expected = irq; |
| LOG_INFO("Triggering adc_ctrl_aon IRQ %d.", irq); |
| CHECK_DIF_OK(dif_adc_ctrl_irq_force(&adc_ctrl_aon, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(adc_ctrl_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from adc_ctrl_aon is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralAlertHandler; |
| for (dif_alert_handler_irq_t irq = kDifAlertHandlerIrqClassa; |
| irq <= kDifAlertHandlerIrqClassd; ++irq) { |
| alert_handler_irq_expected = irq; |
| LOG_INFO("Triggering alert_handler IRQ %d.", irq); |
| CHECK_DIF_OK(dif_alert_handler_irq_force(&alert_handler, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(alert_handler_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from alert_handler is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralAonTimerAon; |
| for (dif_aon_timer_irq_t irq = kDifAonTimerIrqWkupTimerExpired; |
| irq <= kDifAonTimerIrqWdogTimerBark; ++irq) { |
| aon_timer_irq_expected = irq; |
| LOG_INFO("Triggering aon_timer_aon IRQ %d.", irq); |
| CHECK_DIF_OK(dif_aon_timer_irq_force(&aon_timer_aon, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(aon_timer_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from aon_timer_aon is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralCsrng; |
| for (dif_csrng_irq_t irq = kDifCsrngIrqCsCmdReqDone; |
| irq <= kDifCsrngIrqCsFatalErr; ++irq) { |
| csrng_irq_expected = irq; |
| LOG_INFO("Triggering csrng IRQ %d.", irq); |
| CHECK_DIF_OK(dif_csrng_irq_force(&csrng, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(csrng_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from csrng is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralEdn0; |
| for (dif_edn_irq_t irq = kDifEdnIrqEdnCmdReqDone; |
| irq <= kDifEdnIrqEdnFatalErr; ++irq) { |
| edn_irq_expected = irq; |
| LOG_INFO("Triggering edn0 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_edn_irq_force(&edn0, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(edn_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from edn0 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralEdn1; |
| for (dif_edn_irq_t irq = kDifEdnIrqEdnCmdReqDone; |
| irq <= kDifEdnIrqEdnFatalErr; ++irq) { |
| edn_irq_expected = irq; |
| LOG_INFO("Triggering edn1 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_edn_irq_force(&edn1, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(edn_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from edn1 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralEntropySrc; |
| for (dif_entropy_src_irq_t irq = kDifEntropySrcIrqEsEntropyValid; |
| irq <= kDifEntropySrcIrqEsFatalErr; ++irq) { |
| entropy_src_irq_expected = irq; |
| LOG_INFO("Triggering entropy_src IRQ %d.", irq); |
| CHECK_DIF_OK(dif_entropy_src_irq_force(&entropy_src, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(entropy_src_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from entropy_src is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralFlashCtrl; |
| for (dif_flash_ctrl_irq_t irq = kDifFlashCtrlIrqProgEmpty; |
| irq <= kDifFlashCtrlIrqCorrErr; ++irq) { |
| flash_ctrl_irq_expected = irq; |
| LOG_INFO("Triggering flash_ctrl IRQ %d.", irq); |
| CHECK_DIF_OK(dif_flash_ctrl_irq_force(&flash_ctrl, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(flash_ctrl_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from flash_ctrl is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralGpio; |
| for (dif_gpio_irq_t irq = kDifGpioIrqGpio0; |
| irq <= kDifGpioIrqGpio31; ++irq) { |
| gpio_irq_expected = irq; |
| LOG_INFO("Triggering gpio IRQ %d.", irq); |
| CHECK_DIF_OK(dif_gpio_irq_force(&gpio, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(gpio_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from gpio is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralHmac; |
| for (dif_hmac_irq_t irq = kDifHmacIrqHmacDone; |
| irq <= kDifHmacIrqHmacErr; ++irq) { |
| hmac_irq_expected = irq; |
| LOG_INFO("Triggering hmac IRQ %d.", irq); |
| CHECK_DIF_OK(dif_hmac_irq_force(&hmac, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(hmac_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from hmac is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralI2c0; |
| for (dif_i2c_irq_t irq = kDifI2cIrqFmtThreshold; |
| irq <= kDifI2cIrqHostTimeout; ++irq) { |
| i2c_irq_expected = irq; |
| LOG_INFO("Triggering i2c0 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c0, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(i2c_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from i2c0 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralI2c1; |
| for (dif_i2c_irq_t irq = kDifI2cIrqFmtThreshold; |
| irq <= kDifI2cIrqHostTimeout; ++irq) { |
| i2c_irq_expected = irq; |
| LOG_INFO("Triggering i2c1 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c1, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(i2c_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from i2c1 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralI2c2; |
| for (dif_i2c_irq_t irq = kDifI2cIrqFmtThreshold; |
| irq <= kDifI2cIrqHostTimeout; ++irq) { |
| i2c_irq_expected = irq; |
| LOG_INFO("Triggering i2c2 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_i2c_irq_force(&i2c2, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(i2c_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from i2c2 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralKeymgr; |
| for (dif_keymgr_irq_t irq = kDifKeymgrIrqOpDone; |
| irq <= kDifKeymgrIrqOpDone; ++irq) { |
| keymgr_irq_expected = irq; |
| LOG_INFO("Triggering keymgr IRQ %d.", irq); |
| CHECK_DIF_OK(dif_keymgr_irq_force(&keymgr, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(keymgr_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from keymgr is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralKmac; |
| for (dif_kmac_irq_t irq = kDifKmacIrqKmacDone; |
| irq <= kDifKmacIrqKmacErr; ++irq) { |
| kmac_irq_expected = irq; |
| LOG_INFO("Triggering kmac IRQ %d.", irq); |
| CHECK_DIF_OK(dif_kmac_irq_force(&kmac, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(kmac_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from kmac is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralOtbn; |
| for (dif_otbn_irq_t irq = kDifOtbnIrqDone; |
| irq <= kDifOtbnIrqDone; ++irq) { |
| otbn_irq_expected = irq; |
| LOG_INFO("Triggering otbn IRQ %d.", irq); |
| CHECK_DIF_OK(dif_otbn_irq_force(&otbn, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(otbn_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from otbn is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralOtpCtrl; |
| for (dif_otp_ctrl_irq_t irq = kDifOtpCtrlIrqOtpOperationDone; |
| irq <= kDifOtpCtrlIrqOtpError; ++irq) { |
| otp_ctrl_irq_expected = irq; |
| LOG_INFO("Triggering otp_ctrl IRQ %d.", irq); |
| CHECK_DIF_OK(dif_otp_ctrl_irq_force(&otp_ctrl, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(otp_ctrl_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from otp_ctrl is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralPattgen; |
| for (dif_pattgen_irq_t irq = kDifPattgenIrqDoneCh0; |
| irq <= kDifPattgenIrqDoneCh1; ++irq) { |
| pattgen_irq_expected = irq; |
| LOG_INFO("Triggering pattgen IRQ %d.", irq); |
| CHECK_DIF_OK(dif_pattgen_irq_force(&pattgen, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(pattgen_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from pattgen is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralPwrmgrAon; |
| for (dif_pwrmgr_irq_t irq = kDifPwrmgrIrqWakeup; |
| irq <= kDifPwrmgrIrqWakeup; ++irq) { |
| pwrmgr_irq_expected = irq; |
| LOG_INFO("Triggering pwrmgr_aon IRQ %d.", irq); |
| CHECK_DIF_OK(dif_pwrmgr_irq_force(&pwrmgr_aon, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(pwrmgr_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from pwrmgr_aon is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralRvTimer; |
| for (dif_rv_timer_irq_t irq = kDifRvTimerIrqTimerExpiredHart0Timer0; |
| irq <= kDifRvTimerIrqTimerExpiredHart0Timer0; ++irq) { |
| rv_timer_irq_expected = irq; |
| LOG_INFO("Triggering rv_timer IRQ %d.", irq); |
| CHECK_DIF_OK(dif_rv_timer_irq_force(&rv_timer, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(rv_timer_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from rv_timer is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralSensorCtrl; |
| for (dif_sensor_ctrl_irq_t irq = kDifSensorCtrlIrqIoStatusChange; |
| irq <= kDifSensorCtrlIrqInitStatusChange; ++irq) { |
| sensor_ctrl_irq_expected = irq; |
| LOG_INFO("Triggering sensor_ctrl IRQ %d.", irq); |
| CHECK_DIF_OK(dif_sensor_ctrl_irq_force(&sensor_ctrl, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(sensor_ctrl_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from sensor_ctrl is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralSpiDevice; |
| for (dif_spi_device_irq_t irq = kDifSpiDeviceIrqGenericRxFull; |
| irq <= kDifSpiDeviceIrqTpmHeaderNotEmpty; ++irq) { |
| spi_device_irq_expected = irq; |
| LOG_INFO("Triggering spi_device IRQ %d.", irq); |
| CHECK_DIF_OK(dif_spi_device_irq_force(&spi_device, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(spi_device_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from spi_device is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralSpiHost0; |
| for (dif_spi_host_irq_t irq = kDifSpiHostIrqError; |
| irq <= kDifSpiHostIrqSpiEvent; ++irq) { |
| spi_host_irq_expected = irq; |
| LOG_INFO("Triggering spi_host0 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_spi_host_irq_force(&spi_host0, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(spi_host_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from spi_host0 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralSpiHost1; |
| for (dif_spi_host_irq_t irq = kDifSpiHostIrqError; |
| irq <= kDifSpiHostIrqSpiEvent; ++irq) { |
| spi_host_irq_expected = irq; |
| LOG_INFO("Triggering spi_host1 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_spi_host_irq_force(&spi_host1, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(spi_host_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from spi_host1 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralSysrstCtrlAon; |
| for (dif_sysrst_ctrl_irq_t irq = kDifSysrstCtrlIrqEventDetected; |
| irq <= kDifSysrstCtrlIrqEventDetected; ++irq) { |
| sysrst_ctrl_irq_expected = irq; |
| LOG_INFO("Triggering sysrst_ctrl_aon IRQ %d.", irq); |
| CHECK_DIF_OK(dif_sysrst_ctrl_irq_force(&sysrst_ctrl_aon, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(sysrst_ctrl_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from sysrst_ctrl_aon is serviced.", irq); |
| } |
| |
| // lowrisc/opentitan#8656: Skip UART0 in non-DV setups due to interference |
| // from the logging facility. |
| if (kDeviceType == kDeviceSimDV) { |
| peripheral_expected = kTopEarlgreyPlicPeripheralUart0; |
| for (dif_uart_irq_t irq = kDifUartIrqTxWatermark; |
| irq <= kDifUartIrqRxParityErr; ++irq) { |
| uart_irq_expected = irq; |
| LOG_INFO("Triggering uart0 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_uart_irq_force(&uart0, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(uart_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from uart0 is serviced.", irq); |
| } |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralUart1; |
| for (dif_uart_irq_t irq = kDifUartIrqTxWatermark; |
| irq <= kDifUartIrqRxParityErr; ++irq) { |
| uart_irq_expected = irq; |
| LOG_INFO("Triggering uart1 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_uart_irq_force(&uart1, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(uart_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from uart1 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralUart2; |
| for (dif_uart_irq_t irq = kDifUartIrqTxWatermark; |
| irq <= kDifUartIrqRxParityErr; ++irq) { |
| uart_irq_expected = irq; |
| LOG_INFO("Triggering uart2 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_uart_irq_force(&uart2, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(uart_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from uart2 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralUart3; |
| for (dif_uart_irq_t irq = kDifUartIrqTxWatermark; |
| irq <= kDifUartIrqRxParityErr; ++irq) { |
| uart_irq_expected = irq; |
| LOG_INFO("Triggering uart3 IRQ %d.", irq); |
| CHECK_DIF_OK(dif_uart_irq_force(&uart3, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(uart_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from uart3 is serviced.", irq); |
| } |
| |
| peripheral_expected = kTopEarlgreyPlicPeripheralUsbdev; |
| for (dif_usbdev_irq_t irq = kDifUsbdevIrqPktReceived; |
| irq <= kDifUsbdevIrqLinkOutErr; ++irq) { |
| usbdev_irq_expected = irq; |
| LOG_INFO("Triggering usbdev IRQ %d.", irq); |
| CHECK_DIF_OK(dif_usbdev_irq_force(&usbdev, irq, true)); |
| |
| // This avoids a race where *irq_serviced is read before |
| // entering the ISR. |
| IBEX_SPIN_FOR(usbdev_irq_serviced == irq, 1); |
| LOG_INFO("IRQ %d from usbdev is serviced.", irq); |
| } |
| } |
| |
| /** |
| * Checks that the target ID corresponds to the ID of the hart on which |
| * this test is executed on. This check is meant to be used in a |
| * single-hart system only. |
| */ |
| static void check_hart_id(uint32_t exp_hart_id) { |
| uint32_t act_hart_id; |
| CSR_READ(CSR_REG_MHARTID, &act_hart_id); |
| CHECK(act_hart_id == exp_hart_id, "Processor has unexpected HART ID."); |
| } |
| |
| OTTF_DEFINE_TEST_CONFIG(); |
| |
| bool test_main(void) { |
| irq_global_ctrl(true); |
| irq_external_ctrl(true); |
| peripherals_init(); |
| check_hart_id((uint32_t)kHart); |
| rv_plic_testutils_irq_range_enable( |
| &plic, kHart, kTopEarlgreyPlicIrqIdNone + 1, kTopEarlgreyPlicIrqIdLast); |
| peripheral_irqs_clear(); |
| peripheral_irqs_enable(); |
| peripheral_irqs_trigger(); |
| return true; |
| } |
| |
| // clang-format on |