blob: 3005de31c4f1027aa0c7ec17fb59eae26bc67023 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
${autogen_banner}
#include "sw/device/lib/testing/autogen/isr_testutils.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
% for ip in ips_with_difs:
% if ip.irqs:
#include "sw/device/lib/dif/dif_${ip.name_snake}.h"
% endif
% endfor
#include "sw/device/lib/testing/test_framework/check.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
% for ip in ips_with_difs:
% if ip.irqs:
void isr_testutils_${ip.name_snake}_isr(
plic_isr_ctx_t plic_ctx,
${ip.name_snake}_isr_ctx_t ${ip.name_snake}_ctx,
top_earlgrey_plic_peripheral_t *peripheral_serviced,
dif_${ip.name_snake}_irq_t *irq_serviced) {
// Claim the IRQ at the PLIC.
dif_rv_plic_irq_id_t plic_irq_id;
CHECK_DIF_OK(dif_rv_plic_irq_claim(
plic_ctx.rv_plic,
plic_ctx.hart_id,
&plic_irq_id));
// Get the peripheral the IRQ belongs to.
*peripheral_serviced = (top_earlgrey_plic_peripheral_t)
top_earlgrey_plic_interrupt_for_peripheral[plic_irq_id];
// Get the IRQ that was fired from the PLIC IRQ ID.
dif_${ip.name_snake}_irq_t irq = (dif_${ip.name_snake}_irq_t)(plic_irq_id -
${ip.name_snake}_ctx.plic_${ip.name_snake}_start_irq_id);
*irq_serviced = irq;
// Check if it is supposed to be the only IRQ fired.
if (${ip.name_snake}_ctx.is_only_irq) {
dif_${ip.name_snake}_irq_state_snapshot_t snapshot;
CHECK_DIF_OK(dif_${ip.name_snake}_irq_get_state(
${ip.name_snake}_ctx.${ip.name_snake},
% if ip.name_snake == "rv_timer":
plic_ctx.hart_id,
% endif
&snapshot));
CHECK(snapshot == (dif_${ip.name_snake}_irq_state_snapshot_t)(1 << irq),
"Only ${ip.name_snake} IRQ %d expected to fire. Actual IRQ state = %x",
irq, snapshot);
}
% if ip.name_snake == "adc_ctrl":
// TODO(lowRISC/opentitan:#11354): future releases of the ADC Controller HW should hide
// the need to also clear the cause CSRs. At which point, this can be removed.
CHECK_DIF_OK(dif_${ip.name_snake}_irq_clear_causes(
${ip.name_snake}_ctx.${ip.name_snake},
kDifAdcCtrlIrqCauseAll));
% endif
// Acknowledge the IRQ at the peripheral if IRQ is of the event type.
dif_irq_type_t type;
CHECK_DIF_OK(dif_${ip.name_snake}_irq_get_type(
${ip.name_snake}_ctx.${ip.name_snake}, irq, &type));
if (type == kDifIrqTypeEvent) {
CHECK_DIF_OK(dif_${ip.name_snake}_irq_acknowledge(
${ip.name_snake}_ctx.${ip.name_snake},
irq));
}
// Complete the IRQ at the PLIC.
CHECK_DIF_OK(dif_rv_plic_irq_complete(
plic_ctx.rv_plic,
plic_ctx.hart_id,
plic_irq_id));
}
% endif
% endfor