bsp/qoriq: Support message signaled interrupts

This commit is contained in:
Sebastian Huber
2022-12-20 11:08:18 +01:00
parent 62932ec0cc
commit ad454d1c63
2 changed files with 244 additions and 17 deletions

View File

@@ -363,7 +363,23 @@ extern "C" {
#define QORIQ_IRQ_GT_B_2 (QORIQ_IRQ_GT_BASE + 6)
#define QORIQ_IRQ_GT_B_3 (QORIQ_IRQ_GT_BASE + 7)
#define BSP_INTERRUPT_VECTOR_COUNT (QORIQ_IRQ_GT_B_3 + 1)
#define QORIQ_INTERRUPT_SOURCE_COUNT (QORIQ_IRQ_GT_B_3 + 1)
#define QORIQ_IS_INTERRUPT_SOURCE(vector) \
(((rtems_vector_number) (vector)) < QORIQ_INTERRUPT_SOURCE_COUNT)
#define QORIQ_IRQ_MSI_MULTIPLEX_BASE QORIQ_INTERRUPT_SOURCE_COUNT
#define QORIQ_IRQ_MSI_COUNT 256
#define QORIQ_IRQ_MSI_INDEX(vector) ((vector) - QORIQ_IRQ_MSI_MULTIPLEX_BASE)
#define QORIQ_IRQ_MSI_VECTOR(index) (QORIQ_IRQ_MSI_MULTIPLEX_BASE + (index))
#define QORIQ_IRQ_IS_MSI(vector) \
(QORIQ_IRQ_MSI_INDEX(vector) < QORIQ_IRQ_MSI_COUNT)
#define BSP_INTERRUPT_VECTOR_COUNT QORIQ_IRQ_MSI_VECTOR(QORIQ_IRQ_MSI_COUNT)
/** @} */
@@ -403,6 +419,16 @@ rtems_status_code bsp_interrupt_get_affinity(
Processor_mask *affinity
);
rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector);
rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector);
rtems_status_code qoriq_pic_msi_map(
rtems_vector_number vector,
uint64_t *addr,
uint32_t *data
);
/** @} */
#ifdef __cplusplus

View File

@@ -34,6 +34,7 @@
*/
#include <sys/param.h>
#include <sys/bitset.h>
#include <rtems.h>
@@ -307,6 +308,10 @@ rtems_status_code qoriq_pic_set_priority(
rtems_status_code sc = RTEMS_SUCCESSFUL;
uint32_t old_vpr = 0;
if (QORIQ_IRQ_IS_MSI(vector)) {
return RTEMS_UNSATISFIED;
}
if (bsp_interrupt_is_valid_vector(vector)) {
volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
@@ -344,6 +349,10 @@ rtems_status_code bsp_interrupt_set_affinity(
return RTEMS_UNSATISFIED;
}
if (QORIQ_IRQ_IS_MSI(vector)) {
return RTEMS_UNSATISFIED;
}
src_cfg = get_src_cfg(vector);
src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
return RTEMS_SUCCESSFUL;
@@ -360,22 +369,34 @@ rtems_status_code bsp_interrupt_get_affinity(
return RTEMS_UNSATISFIED;
}
if (QORIQ_IRQ_IS_MSI(vector)) {
return RTEMS_UNSATISFIED;
}
src_cfg = get_src_cfg(vector);
_Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
return RTEMS_SUCCESSFUL;
}
static void pic_vector_enable(rtems_vector_number vector, uint32_t msk)
static rtems_status_code pic_vector_set_mask(
rtems_vector_number vector,
uint32_t msk
)
{
volatile qoriq_pic_src_cfg *src_cfg;
rtems_interrupt_lock_context lock_context;
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
if (QORIQ_IRQ_IS_MSI(vector)) {
return RTEMS_UNSATISFIED;
}
src_cfg = get_src_cfg(vector);
rtems_interrupt_lock_acquire(&lock, &lock_context);
src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
rtems_interrupt_lock_release(&lock, &lock_context);
return RTEMS_SUCCESSFUL;
}
rtems_status_code bsp_interrupt_get_attributes(
@@ -383,17 +404,25 @@ rtems_status_code bsp_interrupt_get_attributes(
rtems_interrupt_attributes *attributes
)
{
bool vector_is_ipi = pic_is_ipi(vector);
bool is_ipi = pic_is_ipi(vector);
bool is_msi = QORIQ_IRQ_IS_MSI(vector);
attributes->is_maskable = true;
attributes->can_enable = true;
attributes->maybe_enable = true;
attributes->can_disable = true;
attributes->maybe_disable = true;
attributes->can_enable = !is_msi;
attributes->maybe_enable = !is_msi;
attributes->can_disable = !is_msi;
attributes->maybe_disable = !is_msi;
attributes->cleared_by_acknowledge = true;
attributes->can_get_affinity = !vector_is_ipi;
attributes->can_set_affinity = !vector_is_ipi;
attributes->can_raise = vector_is_ipi;
attributes->can_raise_on = vector_is_ipi;
attributes->can_get_affinity = !(is_ipi || is_msi);
attributes->can_set_affinity = !(is_ipi || is_msi);
attributes->can_raise = is_ipi;
attributes->can_raise_on = is_ipi;
if (is_msi) {
attributes->can_be_triggered_by_message = true;
attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
}
return RTEMS_SUCCESSFUL;
}
@@ -407,6 +436,11 @@ rtems_status_code bsp_interrupt_is_pending(
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
bsp_interrupt_assert(pending != NULL);
if (QORIQ_IRQ_IS_MSI(vector)) {
*pending = false;
return RTEMS_SUCCESSFUL;
}
src_cfg = get_src_cfg(vector);
*pending = (src_cfg->vpr & VPR_A) != 0;
return RTEMS_SUCCESSFUL;
@@ -463,6 +497,10 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
bsp_interrupt_assert(enabled != NULL);
if (QORIQ_IRQ_IS_MSI(vector)) {
vector = QORIQ_IRQ_MSI_0 + QORIQ_IRQ_MSI_INDEX(vector) / 32;
}
src_cfg = get_src_cfg(vector);
*enabled = (src_cfg->vpr & VPR_MSK) == 0;
return RTEMS_SUCCESSFUL;
@@ -470,14 +508,12 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
{
pic_vector_enable(vector, 0);
return RTEMS_SUCCESSFUL;
return pic_vector_set_mask(vector, 0);
}
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
{
pic_vector_enable(vector, VPR_MSK);
return RTEMS_SUCCESSFUL;
return pic_vector_set_mask(vector, VPR_MSK);
}
void bsp_interrupt_dispatch(uintptr_t exception_number)
@@ -529,7 +565,7 @@ void bsp_interrupt_facility_initialize(void)
pic_reset();
for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
src_cfg->vpr = VPR_MSK | VPR_P
@@ -555,11 +591,176 @@ void bsp_interrupt_facility_initialize(void)
qoriq.pic.ctpr = 0;
for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
qoriq.pic.iack;
qoriq.pic.eoi = 0;
qoriq.pic.whoami;
}
}
typedef __BITSET_DEFINE(pic_msi_bitset, QORIQ_IRQ_MSI_COUNT) pic_msi_bitset;
static pic_msi_bitset pic_msi_available =
__BITSET_T_INITIALIZER(__BITSET_FSET(__bitset_words(QORIQ_IRQ_MSI_COUNT)));
static uint32_t pic_msi_bitset_to_uint32_t(
const pic_msi_bitset *bitset,
uint32_t index
)
{
long bits = bitset->__bits[index / _BITSET_BITS];
return (uint32_t) (bits >> (32 * ((index % _BITSET_BITS) / 32)));
}
static void pic_msi_dispatch(void *arg)
{
uintptr_t reg = (uintptr_t) arg;
uint32_t msir = qoriq.pic.msir[reg].reg;
while (msir != 0) {
uint32_t index = 31 - __builtin_clz(msir);
const rtems_interrupt_entry *entry;
msir &= ~(UINT32_C(1) << index);
entry = bsp_interrupt_entry_load_first(
QORIQ_IRQ_MSI_VECTOR(32 * reg + index)
);
if (entry != NULL) {
bsp_interrupt_dispatch_entries(entry);
}
}
}
static rtems_status_code pic_msi_allocate(rtems_vector_number *vector)
{
pic_msi_bitset *available = &pic_msi_available;
long found = __BIT_FFS(QORIQ_IRQ_MSI_COUNT, available);
rtems_vector_number index;
uint32_t subset;
if (found == 0) {
return RTEMS_UNSATISFIED;
}
index = (rtems_vector_number) found - 1;
subset = pic_msi_bitset_to_uint32_t(available, index);
if (subset == 0xffffffff) {
uintptr_t reg = index / 32;
rtems_status_code sc;
sc = rtems_interrupt_handler_install(
QORIQ_IRQ_MSI_0 + reg,
"MSI",
RTEMS_INTERRUPT_UNIQUE,
pic_msi_dispatch,
(void *) reg
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
}
__BIT_CLR(QORIQ_IRQ_MSI_COUNT, index, available);
*vector = QORIQ_IRQ_MSI_VECTOR(index);
return RTEMS_SUCCESSFUL;
}
static rtems_status_code pic_msi_free(rtems_vector_number vector)
{
pic_msi_bitset *available = &pic_msi_available;
rtems_vector_number index = QORIQ_IRQ_MSI_INDEX(vector);
uint32_t subset;
if (__BIT_ISSET(QORIQ_IRQ_MSI_COUNT, index, available)) {
return RTEMS_NOT_DEFINED;
}
__BIT_SET(QORIQ_IRQ_MSI_COUNT, index, available);
subset = pic_msi_bitset_to_uint32_t(available, index);
if (subset == 0xffffffff) {
uintptr_t reg = index / 32;
return rtems_interrupt_handler_remove(
QORIQ_IRQ_MSI_0 + reg,
pic_msi_dispatch,
(void *) reg
);
}
return RTEMS_SUCCESSFUL;
}
rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector)
{
rtems_status_code sc;
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INCORRECT_STATE;
}
if (vector == NULL) {
return RTEMS_INVALID_ADDRESS;
}
if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
bsp_interrupt_lock();
sc = pic_msi_allocate(vector);
bsp_interrupt_unlock();
return sc;
}
rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector)
{
rtems_status_code sc;
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INCORRECT_STATE;
}
if (!QORIQ_IRQ_IS_MSI(vector) ) {
return RTEMS_INVALID_ID;
}
if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
bsp_interrupt_lock();
sc = pic_msi_free(vector);
bsp_interrupt_unlock();
return sc;
}
rtems_status_code qoriq_pic_msi_map(
rtems_vector_number vector,
uint64_t *addr,
uint32_t *data
)
{
if (addr == NULL) {
return RTEMS_INVALID_ADDRESS;
}
if (data == NULL) {
return RTEMS_INVALID_ADDRESS;
}
if (!QORIQ_IRQ_IS_MSI(vector) ) {
return RTEMS_INVALID_ID;
}
*addr = (uint64_t)(uintptr_t) &qoriq.pic.msiir;
*data = QORIQ_IRQ_MSI_INDEX(vector) << 24;
return RTEMS_SUCCESSFUL;
}
#endif /* QORIQ_IS_HYPERVISOR_GUEST */