summaryrefslogtreecommitdiff
path: root/plat/marvell/common/marvell_gicv2.c
diff options
context:
space:
mode:
authorMarcin Wojtas <mw@semihalf.com>2018-03-21 09:59:59 +0100
committerKonstantin Porotchkin <kostap@marvell.com>2018-09-03 14:51:26 +0300
commit9cfa6fc3e8976ca2b0514f7ff276b37416d0f1f0 (patch)
treee698aefd579469705dc2baa3a6fbbec2369cfc37 /plat/marvell/common/marvell_gicv2.c
parent9a5f0375db9b8fbc88ba37fab655a4e068bcea42 (diff)
plat: a8k: enable PMU overflow interrupt handler
This patch enables handling PMU overflow IRQ by GIC SPI's directly in EL3. Also implement additional SMC routine, which can disable the solution on demand in runtime. Change-Id: Ie76aa62ccc4fd7cabfec9e3d5ed9970ada1c1b2a Signed-off-by: Marcin Wojtas <mw@semihalf.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/58304 Reviewed-by: Kostya Porotchkin <kostap@marvell.com> Tested-by: Kostya Porotchkin <kostap@marvell.com>
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();