lineage_kernel_xcoverpro/drivers/misc/samsung/scsc/pcie_mbox_intgen.c

141 lines
4.0 KiB
C
Executable File

/****************************************************************************
*
* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved
*
* Maxwell Mailbox Interrupt Generator Emulation (Implementation)
*
****************************************************************************/
/* Implements */
#include "pcie_mbox_intgen.h"
/* Uses */
#include "pcie_mbox_intgen_shared_data.h"
#include "functor.h"
#include <scsc/scsc_logring.h>
/* Private Functions */
/**
* Trigger the hardware interrupt associated with this Interrupt Generator.
*/
static void pcie_mbox_intgen_trigger_interrupt(struct pcie_mbox_intgen *intgen)
{
/* Implementation is abstracted to hide the differences from this module */
functor_call(intgen->trigger_interrupt_fn);
}
/* Public Functions */
void pcie_mbox_intgen_init(
struct pcie_mbox_intgen *intgen,
const char *name,
struct pcie_mbox_intgen_shared_data *shared_data,
struct functor *trigger_interrupt_fn
)
{
strncpy(intgen->name, name, sizeof(intgen->name));
intgen->shared_data = shared_data;
intgen->trigger_interrupt_fn = trigger_interrupt_fn;
}
u32 pcie_mbox_intgen_get_masked_bitmask(const struct pcie_mbox_intgen *intgen)
{
/* Compile bitmask from the emulation's separate source mask fields */
u32 masked_bitmask = 0;
int source_num;
for (source_num = 0; source_num < PCIE_MIF_MBOX_NUM_INTR_SOURCES; ++source_num)
if (intgen->shared_data->mask[source_num])
masked_bitmask |= (1 << source_num);
return masked_bitmask;
}
bool pcie_mbox_intgen_is_source_pending(const struct pcie_mbox_intgen *intgen, int source_num)
{
return intgen->shared_data->status[source_num] && !intgen->shared_data->mask[source_num];
}
u32 pcie_mbox_intgen_get_pending_bitmask(const struct pcie_mbox_intgen *intgen)
{
/* Compile bitmask from the emulation's separate source status and mask fields */
u32 pending_bitmask = 0;
int source_num;
for (source_num = 0; source_num < PCIE_MIF_MBOX_NUM_INTR_SOURCES; ++source_num)
if (pcie_mbox_intgen_is_source_pending(intgen, source_num))
pending_bitmask |= (1 << source_num);
return pending_bitmask;
}
void pcie_mbox_intgen_set_source(struct pcie_mbox_intgen *intgen, int source_num)
{
if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) {
SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num);
return;
}
SCSC_TAG_DEBUG(PCIE_MIF, "Set source %s:%d. (P %08x, M %08x)\n",
intgen->name, source_num,
pcie_mbox_intgen_get_pending_bitmask(intgen),
pcie_mbox_intgen_get_masked_bitmask(intgen)
);
intgen->shared_data->status[source_num] = 1;
pcie_mbox_shared_data_wmb();
if (!intgen->shared_data->mask[source_num])
pcie_mbox_intgen_trigger_interrupt(intgen);
}
void pcie_mbox_intgen_clear_source(struct pcie_mbox_intgen *intgen, int source_num)
{
if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) {
SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num);
return;
}
SCSC_TAG_DEBUG(PCIE_MIF, "Clear source %s:%d. (P %08x, M %08x)\n",
intgen->name, source_num,
pcie_mbox_intgen_get_pending_bitmask(intgen),
pcie_mbox_intgen_get_masked_bitmask(intgen)
);
intgen->shared_data->status[source_num] = 0;
pcie_mbox_shared_data_wmb();
}
void pcie_mbox_intgen_mask_source(struct pcie_mbox_intgen *intgen, int source_num)
{
if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) {
SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num);
return;
}
SCSC_TAG_DEBUG(PCIE_MIF, "Mask source %s:%d.\n", intgen->name, source_num);
intgen->shared_data->mask[source_num] = 1;
pcie_mbox_shared_data_wmb();
}
void pcie_mbox_intgen_unmask_source(struct pcie_mbox_intgen *intgen, int source_num)
{
if (source_num >= PCIE_MIF_MBOX_NUM_INTR_SOURCES) {
SCSC_TAG_ERR(PCIE_MIF, "Invalid intgen source %d\n", source_num);
return;
}
SCSC_TAG_DEBUG(PCIE_MIF, "UnMask source %s:%d.\n", intgen->name, source_num);
intgen->shared_data->mask[source_num] = 0;
pcie_mbox_shared_data_wmb();
if (intgen->shared_data->status[source_num])
pcie_mbox_intgen_trigger_interrupt(intgen);
}