summaryrefslogtreecommitdiff
path: root/plat/marvell/common/marvell_gicv2.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/marvell/common/marvell_gicv2.c')
-rw-r--r--plat/marvell/common/marvell_gicv2.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/plat/marvell/common/marvell_gicv2.c b/plat/marvell/common/marvell_gicv2.c
index ba8e4096..52518546 100644
--- a/plat/marvell/common/marvell_gicv2.c
+++ b/plat/marvell/common/marvell_gicv2.c
@@ -5,7 +5,11 @@
* https://spdx.org/licenses
*/
+#include <bakery_lock.h>
+#include <debug.h>
#include <gicv2.h>
+#include <interrupt_mgmt.h>
+#include <mmio.h>
#include <plat_marvell.h>
#include <platform.h>
#include <platform_def.h>
@@ -17,6 +21,21 @@
#pragma weak plat_marvell_gic_driver_init
#pragma weak plat_marvell_gic_init
+#define A7K8K_PIC_CAUSE_REG 0xf03f0100
+#define A7K8K_PIC0_MASK_REG 0xf03f0108
+
+#define A7K8K_PIC_PMUOF_IRQ_MASK (1 << 17)
+
+#define A7K8K_PIC_MAX_IRQS 32
+#define A7K8K_PIC_MAX_IRQ_MASK ((1UL << A7K8K_PIC_MAX_IRQS) - 1)
+
+#define A7K8K_ODMIN_SET_REG 0xf0300040
+#define A7K8K_ODMI_PMU_IRQ(idx) ((2 + idx) << 12)
+
+#define A7K8K_ODMI_PMU_GIC_IRQ(idx) (130 + idx)
+
+static DEFINE_BAKERY_LOCK(a7k8k_irq_lock);
+
/*
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
* interrupts.
@@ -50,6 +69,69 @@ void plat_marvell_gic_driver_init(void)
gicv2_driver_init(&marvell_gic_data);
}
+static uint64_t a7k8k_pmu_interrupt_handler(uint32_t id,
+ uint32_t flags,
+ void *handle,
+ void *cookie)
+{
+ unsigned int idx = plat_my_core_pos();
+ uint32_t irq;
+
+ bakery_lock_get(&a7k8k_irq_lock);
+
+ /* Acknowledge IRQ */
+ irq = plat_ic_acknowledge_interrupt();
+
+ plat_ic_end_of_interrupt(irq);
+
+ if (irq != MARVELL_IRQ_PIC0) {
+ bakery_lock_release(&a7k8k_irq_lock);
+ return 0;
+ }
+
+ /* Acknowledge PMU overflow IRQ in PIC0 */
+ mmio_setbits_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+
+ /* Trigger ODMI Frame IRQ as edge triggered */
+ gicv2_interrupt_set_edge_triggered(A7K8K_ODMI_PMU_GIC_IRQ(idx));
+ mmio_write_32(A7K8K_ODMIN_SET_REG, A7K8K_ODMI_PMU_IRQ(idx));
+
+ bakery_lock_release(&a7k8k_irq_lock);
+
+ return 0;
+}
+
+void mvebu_pmu_interrupt_enable(void)
+{
+ uint32_t flags;
+ int32_t rc;
+
+ /* Reset PIC */
+ mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
+ /* Unmask PMU overflow IRQ in PIC0 */
+ mmio_clrbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+
+ /*
+ * Register IRQ handler as INTR_TYPE_S_EL1 as its the only valid type
+ * for GICv2 in ARM-TF.
+ */
+ flags = 0U;
+ set_interrupt_rm_flag((flags), (NON_SECURE));
+ rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+ a7k8k_pmu_interrupt_handler,
+ flags);
+ if (rc != 0)
+ panic();
+}
+
+void mvebu_pmu_interrupt_disable(void)
+{
+ /* Reset PIC */
+ mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
+ /* Mask PMU overflow IRQ in PIC0 */
+ mmio_setbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+}
+
void plat_marvell_gic_init(void)
{
gicv2_distif_init();