blob: 340061337259e0c18c3504394f59185445a01200 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
<%doc>
This file is the "auto-generated DIF library implementation template", which
provides implementations of some mandatory DIFs that are similar across all
IPs. When rendered, this template implements the DIFs defined in the
auto-generated DIF header file (see util/make_new_dif/dif_autogen.inc.tpl).
Note, this template requires the following Python objects to be passed:
1. ip: See util/make_new_dif.py for the definition of the `ip` obj.
2. list[irq]: See util/make_new_dif.py for the definition of the `irq` obj.
</%doc>
<%def name="mmio_region_read32(intr_reg_upper)">mmio_region_read32(
${ip.name_snake}->base_addr,
${ip.name_upper}_INTR_${intr_reg_upper}_REG_OFFSET);
</%def>
<%def name="mmio_region_write32(intr_reg_upper, value)">mmio_region_write32(
${ip.name_snake}->base_addr,
${ip.name_upper}_INTR_${intr_reg_upper}_REG_OFFSET,
${value});
</%def>
// This file is auto-generated.
#include "sw/device/lib/dif/dif_${ip.name_snake}.h"
#include "${ip.name_snake}_regs.h" // Generated.
% if len(irqs) > 0:
/**
* Get the corresponding interrupt register bit offset. INTR_STATE,
* INTR_ENABLE and INTR_TEST registers have the same bit offsets, so this
* routine can be reused.
*/
static bool ${ip.name_snake}_get_irq_bit_index(
dif_${ip.name_snake}_irq_t irq,
bitfield_bit32_index_t *index_out) {
switch (irq) {
% for irq in irqs:
## This handles the GPIO IP case where there is a multi-bit interrupt.
% if irq.width > 1:
% for irq_idx in range(irq.width):
case kDif${ip.name_camel}Irq${irq.name_camel}${irq_idx}:
*index_out = ${irq_idx};
break;
% endfor
## This handles all other IPs.
% else:
case kDif${ip.name_camel}Irq${irq.name_camel}:
*index_out = ${ip.name_upper}_INTR_STATE_${irq.name_upper}_BIT;
break;
% endif
% endfor
default:
return false;
}
return true;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_get_state(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_state_snapshot_t *snapshot) {
if (${ip.name_snake} == NULL || snapshot == NULL) {
return kDifBadArg;
}
*snapshot = ${mmio_region_read32("STATE")}
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_is_pending(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_t irq,
bool *is_pending) {
if (${ip.name_snake} == NULL || is_pending == NULL) {
return kDifBadArg;
}
bitfield_bit32_index_t index;
if (!${ip.name_snake}_get_irq_bit_index(irq, &index)) {
return kDifBadArg;
}
uint32_t intr_state_reg = ${mmio_region_read32("STATE")}
*is_pending = bitfield_bit32_read(intr_state_reg, index);
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_acknowledge(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_t irq) {
if (${ip.name_snake} == NULL) {
return kDifBadArg;
}
bitfield_bit32_index_t index;
if (!${ip.name_snake}_get_irq_bit_index(irq, &index)) {
return kDifBadArg;
}
// Writing to the register clears the corresponding bits (Write-one clear).
uint32_t intr_state_reg = bitfield_bit32_write(0, index, true);
${mmio_region_write32("STATE", "intr_state_reg")}
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_force(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_t irq) {
if (${ip.name_snake} == NULL) {
return kDifBadArg;
}
bitfield_bit32_index_t index;
if (!${ip.name_snake}_get_irq_bit_index(irq, &index)) {
return kDifBadArg;
}
uint32_t intr_test_reg = bitfield_bit32_write(0, index, true);
${mmio_region_write32("TEST", "intr_test_reg")}
return kDifOk;
}
% if ip.name_snake != "aon_timer":
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_get_enabled(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_t irq,
dif_toggle_t *state) {
if (${ip.name_snake} == NULL || state == NULL) {
return kDifBadArg;
}
bitfield_bit32_index_t index;
if (!${ip.name_snake}_get_irq_bit_index(irq, &index)) {
return kDifBadArg;
}
uint32_t intr_enable_reg = ${mmio_region_read32("ENABLE")}
bool is_enabled = bitfield_bit32_read(intr_enable_reg, index);
*state = is_enabled ?
kDifToggleEnabled : kDifToggleDisabled;
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_set_enabled(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_t irq,
dif_toggle_t state) {
if (${ip.name_snake} == NULL) {
return kDifBadArg;
}
bitfield_bit32_index_t index;
if (!${ip.name_snake}_get_irq_bit_index(irq, &index)) {
return kDifBadArg;
}
uint32_t intr_enable_reg = ${mmio_region_read32("ENABLE")}
bool enable_bit = (state == kDifToggleEnabled) ? true : false;
intr_enable_reg = bitfield_bit32_write(intr_enable_reg, index, enable_bit);
${mmio_region_write32("ENABLE", "intr_enable_reg")}
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_disable_all(
const dif_${ip.name_snake}_t *${ip.name_snake},
dif_${ip.name_snake}_irq_enable_snapshot_t *snapshot) {
if (${ip.name_snake} == NULL) {
return kDifBadArg;
}
// Pass the current interrupt state to the caller, if requested.
if (snapshot != NULL) {
*snapshot = ${mmio_region_read32("ENABLE")}
}
// Disable all interrupts.
${mmio_region_write32("ENABLE", "0u")}
return kDifOk;
}
OT_WARN_UNUSED_RESULT
dif_result_t dif_${ip.name_snake}_irq_restore_all(
const dif_${ip.name_snake}_t *${ip.name_snake},
const dif_${ip.name_snake}_irq_enable_snapshot_t *snapshot) {
if (${ip.name_snake} == NULL || snapshot == NULL) {
return kDifBadArg;
}
${mmio_region_write32("ENABLE", "*snapshot")}
return kDifOk;
}
% endif
% endif