summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/plat/marvell/a8k/common/marvell_def.h1
-rw-r--r--include/plat/marvell/a8k/common/plat_marvell.h8
-rw-r--r--plat/marvell/a8k/common/include/platform_def.h4
-rw-r--r--plat/marvell/common/marvell_gicv2.c82
-rw-r--r--plat/marvell/common/mrvl_sip_svc.c11
5 files changed, 106 insertions, 0 deletions
diff --git a/include/plat/marvell/a8k/common/marvell_def.h b/include/plat/marvell/a8k/common/marvell_def.h
index 538209e8..2870a3e7 100644
--- a/include/plat/marvell/a8k/common/marvell_def.h
+++ b/include/plat/marvell/a8k/common/marvell_def.h
@@ -63,6 +63,7 @@
#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \
MARVELL_DRAM_SIZE - 1)
+#define MARVELL_IRQ_PIC0 28
#define MARVELL_IRQ_SEC_PHY_TIMER 29
#define MARVELL_IRQ_SEC_SGI_0 8
diff --git a/include/plat/marvell/a8k/common/plat_marvell.h b/include/plat/marvell/a8k/common/plat_marvell.h
index 265f33c4..2be0c113 100644
--- a/include/plat/marvell/a8k/common/plat_marvell.h
+++ b/include/plat/marvell/a8k/common/plat_marvell.h
@@ -92,6 +92,14 @@ void marvell_psci_arch_init(int ap_idx);
void plat_marvell_system_reset(void);
/*
+ * Miscellaneous platform SMC routines
+ */
+#ifdef MVEBU_PMU_IRQ_WA
+void mvebu_pmu_interrupt_enable(void);
+void mvebu_pmu_interrupt_disable(void);
+#endif
+
+/*
* Optional functions required in Marvell standard platforms
*/
void plat_marvell_io_setup(void);
diff --git a/plat/marvell/a8k/common/include/platform_def.h b/plat/marvell/a8k/common/include/platform_def.h
index 66edf1bf..0ec49e57 100644
--- a/plat/marvell/a8k/common/include/platform_def.h
+++ b/plat/marvell/a8k/common/include/platform_def.h
@@ -134,6 +134,8 @@
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_PIC0, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL)
#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
@@ -212,4 +214,6 @@
#define OVERRIDE_SERROR_HANDLER
#endif
+#define MVEBU_PMU_IRQ_WA
+
#endif /* __PLATFORM_DEF_H__ */
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();
diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c
index 499e096e..da694c66 100644
--- a/plat/marvell/common/mrvl_sip_svc.c
+++ b/plat/marvell/common/mrvl_sip_svc.c
@@ -9,6 +9,7 @@
#include <cache_llc.h>
#include <debug.h>
#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
#include <runtime_svc.h>
#include <smcc.h>
#include "comphy/phy-comphy-cp110.h"
@@ -30,6 +31,8 @@
/* Miscellaneous FID's' */
#define MV_SIP_DRAM_SIZE 0x82000010
#define MV_SIP_LLC_ENABLE 0x82000011
+#define MV_SIP_PMU_IRQ_ENABLE 0x82000012
+#define MV_SIP_PMU_IRQ_DISABLE 0x82000013
#define MAX_LANE_NR 6
#define MVEBU_COMPHY_OFFSET 0x441000
@@ -109,6 +112,14 @@ uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
llc_runtime_enable(i);
SMC_RET1(handle, 0);
+#ifdef MVEBU_PMU_IRQ_WA
+ case MV_SIP_PMU_IRQ_ENABLE:
+ mvebu_pmu_interrupt_enable();
+ SMC_RET1(handle, 0);
+ case MV_SIP_PMU_IRQ_DISABLE:
+ mvebu_pmu_interrupt_disable();
+ SMC_RET1(handle, 0);
+#endif
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);