plat: marvell: ap806: implement workaround for errata-id FE-4265711

ERRATA ID: FE-4265711 - Incorrect CNTVAL reading

CNTVAL reflects the global system counter value in binary format.
Due to this erratum, the CNTVAL value presented to the processor
may be incorrect for several clock cycles.

Workaround: Override the default value of AP Register Device General
control 20 [19:16] and AP Register Device General Control 21 [11:8]
to the value of 0x3.

Change-Id: I1705608d08acd9631ab98d6f7ceada34d6b8336f
Signed-off-by: Stefan Chulski <stefanc@marvell.com>
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
diff --git a/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
index 9facdbc..d576514 100644
--- a/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
+++ b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
@@ -15,6 +15,13 @@
 #define MVEBU_IO_AFFINITY		(0xF00)
 #define MVEBU_SF_REG			(MVEBU_REGS_BASE + 0x40)
 #define MVEBU_SF_EN			BIT(8)
+#define MVEBU_DFX_REG(cluster_id)	(MVEBU_REGS_BASE + 0x6F82A0 + \
+					(cluster_id) * 0x4)
+#define MVEBU_DFX_CLK_EN_POS		0x3
+#define MVEBU_DFX_CL0_CLK_OFFS		16
+#define MVEBU_DFX_CL0_CLK_MASK		(0xF << MVEBU_DFX_CL0_CLK_OFFS)
+#define MVEBU_DFX_CL1_CLK_OFFS		8
+#define MVEBU_DFX_CL1_CLK_MASK		(0xF << MVEBU_DFX_CL1_CLK_OFFS)
 
 #ifdef MVEBU_SOC_AP807
 static void plat_enable_snoop_filter(void)
@@ -29,6 +36,29 @@
 }
 #endif
 
+#ifndef MVEBU_SOC_AP807
+static void plat_config_dfx_clock(void)
+{
+	int cluster_id = plat_my_core_pos();
+	uint32_t val;
+
+	/* DFX clock needs to be configured once per cluster */
+	if ((cluster_id % PLAT_MAX_CPUS_PER_CLUSTER) != 0) {
+		return;
+	}
+
+	val = mmio_read_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER));
+	if (cluster_id == 0) {
+		val &= ~MVEBU_DFX_CL0_CLK_MASK;
+		val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL0_CLK_OFFS);
+	} else {
+		val &= ~MVEBU_DFX_CL1_CLK_MASK;
+		val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL1_CLK_OFFS);
+	}
+	mmio_write_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER), val);
+}
+#endif
+
 static void plat_enable_affinity(void)
 {
 	int cluster_id;
@@ -59,5 +89,7 @@
 
 #ifdef MVEBU_SOC_AP807
 	plat_enable_snoop_filter();
+#else
+	plat_config_dfx_clock();
 #endif
 }