ble: ap807: Switch to PLL mode and update CPU frequency

- Update CPU frequency on AP807 to 2GHz for SAR 0x0.
- Increase AVS to 0.88V for 2GHz clock

Change-Id: Ic945b682ab2f8543e34294bfc56c3eae2c5e0c8e
Signed-off-by: Christine Gharzuzi <chrisg@marvell.com>
Signed-off-by: Konstantin Porotchkin <kostap@marvell.com>
diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c
new file mode 100644
index 0000000..841e6ae
--- /dev/null
+++ b/drivers/marvell/ap807_clocks_init.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <aro.h>
+#include <delay_timer.h>
+#include <mmio.h>
+
+/* Notify bootloader on DRAM setup */
+#define AP807_CPU_ARO_CTRL(cluster)	\
+			(MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster)))
+
+/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
+#define AP807_CPU_ARO_CLK_EN_OFFSET	0
+#define AP807_CPU_ARO_CLK_EN_MASK	(0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
+
+/* 0 - ARO is the clock source, 1 - PLL is the clock source */
+#define AP807_CPU_ARO_SEL_PLL_OFFSET	5
+#define AP807_CPU_ARO_SEL_PLL_MASK	(0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
+
+/* AP807 clusters count */
+#define AP807_CLUSTER_NUM		2
+
+/* PLL frequency values */
+#define PLL_FREQ_1200			0x2AE5F002 /* 1200 */
+#define PLL_FREQ_2000			0x2FC9F002 /* 2000 */
+#define PLL_FREQ_2200			0x2AC57001 /* 2200 */
+#define PLL_FREQ_2400			0x2AE5F001 /* 2400 */
+
+/* CPU PLL control registers */
+#define AP807_CPU_PLL_CTRL(cluster)	\
+			(MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster)))
+
+#define AP807_CPU_PLL_PARAM(cluster)	AP807_CPU_PLL_CTRL(cluster)
+#define AP807_CPU_PLL_CFG(cluster)	(AP807_CPU_PLL_CTRL(cluster) + 0x4)
+#define AP807_CPU_PLL_CFG_BYPASS_MODE	(0x1)
+#define AP807_CPU_PLL_CFG_USE_REG_FILE	(0x1 << 9)
+
+static void pll_set_freq(unsigned int freq_val)
+{
+	int i;
+
+	for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE);
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE |
+			      AP807_CPU_PLL_CFG_BYPASS_MODE);
+		mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE);
+	}
+}
+
+/* Switch to ARO from PLL in ap807 */
+static void aro_to_pll(void)
+{
+	unsigned int reg;
+	int i;
+
+	for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+		/* switch from ARO to PLL */
+		reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+		reg |= AP807_CPU_ARO_SEL_PLL_MASK;
+		mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+
+		mdelay(100);
+
+		/* disable ARO clk driver */
+		reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+		reg |= (AP807_CPU_ARO_CLK_EN_MASK);
+		mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+	}
+}
+
+/* switch from ARO to PLL
+ * in case of default frequency option, configure PLL registers
+ * to be aligned with new default frequency.
+ */
+void ap807_clocks_init(unsigned int freq_option)
+{
+	/* Switch from ARO to PLL */
+	aro_to_pll();
+
+	/* Modifications in frequency table:
+	 * 0x0: 764x: change to 2000 MHz.
+	 * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
+	 * 0x3: 3900/744x/764x change to 1200 MHz.
+	 */
+	switch (freq_option) {
+	case CPU_2000_DDR_1200_RCLK_1200:
+		pll_set_freq(PLL_FREQ_2000);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/include/drivers/marvell/ap807_clocks_init.h b/include/drivers/marvell/ap807_clocks_init.h
new file mode 100644
index 0000000..4353b83
--- /dev/null
+++ b/include/drivers/marvell/ap807_clocks_init.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef AP807_INIT_CLOCKS_H
+#define AP807_INIT_CLOCKS_H
+
+void ap807_clocks_init(unsigned int freq_option);
+
+#endif /* AP807_INIT_CLOCKS_H */
+
diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk
index 6136a1f..6b2b353 100644
--- a/plat/marvell/a8k/common/a8k_common.mk
+++ b/plat/marvell/a8k/common/a8k_common.mk
@@ -60,14 +60,15 @@
 
 MARVELL_MOCHI_DRV	+=	$(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
-BLE_SOURCES		:=	drivers/mentor/i2c/mi2cv.c			\
-				$(PLAT_COMMON_BASE)/plat_ble_setup.c		\
-				$(MARVELL_MOCHI_DRV)			       \
-				$(PLAT_COMMON_BASE)/plat_pm.c		 	\
-				$(MARVELL_DRV_BASE)/thermal.c			\
-				$(PLAT_COMMON_BASE)/plat_thermal.c		\
-				$(BLE_PORTING_SOURCES)				\
-				$(MARVELL_DRV_BASE)/ccu.c			\
+BLE_SOURCES		:=	drivers/mentor/i2c/mi2cv.c		\
+				$(PLAT_COMMON_BASE)/plat_ble_setup.c	\
+				$(MARVELL_MOCHI_DRV)			\
+				$(PLAT_COMMON_BASE)/plat_pm.c		\
+				$(MARVELL_DRV_BASE)/ap807_clocks_init.c	\
+				$(MARVELL_DRV_BASE)/thermal.c		\
+				$(PLAT_COMMON_BASE)/plat_thermal.c	\
+				$(BLE_PORTING_SOURCES)			\
+				$(MARVELL_DRV_BASE)/ccu.c		\
 				$(MARVELL_DRV_BASE)/io_win.c
 
 BL1_SOURCES		+=	$(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
diff --git a/plat/marvell/a8k/common/plat_ble_setup.c b/plat/marvell/a8k/common/plat_ble_setup.c
index 7438f69..07d6cad 100644
--- a/plat/marvell/a8k/common/plat_ble_setup.c
+++ b/plat/marvell/a8k/common/plat_ble_setup.c
@@ -15,14 +15,15 @@
 #include <mv_ddr_if.h>
 #include <mvebu_def.h>
 #include <plat_marvell.h>
+#include "ap807_clocks_init.h"
 
 /* Register for skip image use */
 #define SCRATCH_PAD_REG2		0xF06F00A8
 #define SCRATCH_PAD_SKIP_VAL		0x01
 #define NUM_OF_GPIO_PER_REG 32
 
-#define MMAP_SAVE_AND_CONFIG	0
-#define MMAP_RESTORE_SAVED	1
+#define MMAP_SAVE_AND_CONFIG		0
+#define MMAP_RESTORE_SAVED		1
 
 /* SAR clock settings */
 #define MVEBU_AP_GEN_MGMT_BASE		(MVEBU_RFU_BASE + 0x8000)
@@ -77,22 +78,17 @@
 					 (0x2c2 << 3) | \
 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
 					 (0x1 << AVS_ENABLE_OFFSET))
+/* VDD is 0.88V for 2GHz clock */
+#define AVS_A3900_HIGH_CLK_VALUE	((0x80 << 24) | \
+					 (0x2f5 << 13) | \
+					 (0x2f5 << 3) | \
+					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
+					 (0x1 << AVS_ENABLE_OFFSET))
 
 #define MVEBU_AP_EFUSE_SRV_CTRL_REG	(MVEBU_AP_GEN_MGMT_BASE + 0x8)
 #define EFUSE_SRV_CTRL_LD_SELECT_OFFS	6
 #define EFUSE_SRV_CTRL_LD_SEL_USER_MASK	(1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
 
-/* Notify bootloader on DRAM setup */
-#define AP807_CPU_ARO_0_CTRL_0		(MVEBU_RFU_BASE + 0x82A8)
-#define AP807_CPU_ARO_1_CTRL_0		(MVEBU_RFU_BASE + 0x8D00)
-
-/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
-#define AP807_CPU_ARO_CLK_EN_OFFSET	0
-#define AP807_CPU_ARO_CLK_EN_MASK	(0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
-
-/* 0 - ARO is the clock source, 1 - PLL is the clock source */
-#define AP807_CPU_ARO_SEL_PLL_OFFSET	5
-#define AP807_CPU_ARO_SEL_PLL_MASK	(0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
 
 /*
  * - Identification information in the LD-0 eFuse:
@@ -143,9 +139,9 @@
 	#define EFUSE_AP_LD0_WP_MASK		0x3FF
 #endif
 
-#define EFUSE_AP_LD0_SVC4_OFFS		42		/* LD0[112:105] */
+#define EFUSE_AP_LD0_SVC4_OFFS			42	/* LD0[112:105] */
 
-#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS	4
+#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS		4
 
 /* Return the AP revision of the chip */
 static unsigned int ble_get_ap_type(void)
@@ -207,37 +203,44 @@
  */
 static void ble_plat_avs_config(void)
 {
-	uint32_t reg_val, device_id;
+	uint32_t freq_mode, device_id;
+	uint32_t avs_val = 0;
 
+	freq_mode =
+		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+						 FREQ_MODE_AP_SAR_REG_NUM)));
 	/* Check which SoC is running and act accordingly */
 	if (ble_get_ap_type() == CHIP_ID_AP807) {
-		VERBOSE("AVS: Setting AP807 AVS CTRL to 0x%x\n",
-			AVS_A3900_CLK_VALUE);
-		mmio_write_32(AVS_EN_CTRL_REG, AVS_A3900_CLK_VALUE);
-		return;
+		/* Increase CPU voltage for higher CPU clock */
+		if (freq_mode == CPU_2000_DDR_1200_RCLK_1200)
+			avs_val = AVS_A3900_HIGH_CLK_VALUE;
+		else
+			avs_val = AVS_A3900_CLK_VALUE;
+	} else {
+		/* Check which SoC is running and act accordingly */
+		device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+		switch (device_id) {
+		case MVEBU_80X0_DEV_ID:
+		case MVEBU_80X0_CP115_DEV_ID:
+			/* Always fix the default AVS value on A80x0 */
+			avs_val = AVS_A8K_CLK_VALUE;
+			break;
+		case MVEBU_70X0_DEV_ID:
+		case MVEBU_70X0_CP115_DEV_ID:
+			/* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
+			if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
+			    (freq_mode < CPU_DDR_RCLK_INVALID))
+				avs_val = AVS_A7K_LOW_CLK_VALUE;
+			break;
+		default:
+			ERROR("Unsupported Device ID 0x%x\n", device_id);
+			return;
+		}
 	}
 
-	/* Check which SoC is running and act accordingly */
-	device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
-	switch (device_id) {
-	case MVEBU_80X0_DEV_ID:
-	case MVEBU_80X0_CP115_DEV_ID:
-		/* Set the new AVS value - fix the default one on A80x0 */
-		mmio_write_32(AVS_EN_CTRL_REG, AVS_A8K_CLK_VALUE);
-		break;
-	case MVEBU_70X0_DEV_ID:
-	case MVEBU_70X0_CP115_DEV_ID:
-		/* Only fix AVS for CPU clocks lower than 1600MHz on A70x0 */
-		reg_val = mmio_read_32(MVEBU_AP_SAR_REG_BASE(
-						FREQ_MODE_AP_SAR_REG_NUM));
-		reg_val &= SAR_CLOCK_FREQ_MODE_MASK;
-		reg_val >>= SAR_CLOCK_FREQ_MODE_OFFSET;
-		if ((reg_val > CPU_1600_DDR_900_RCLK_900_2) &&
-		    (reg_val < CPU_DDR_RCLK_INVALID))
-			mmio_write_32(AVS_EN_CTRL_REG, AVS_A7K_LOW_CLK_VALUE);
-		break;
-	default:
-		ERROR("Unsupported Device ID 0x%x\n", device_id);
+	if (avs_val) {
+		VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
+		mmio_write_32(AVS_EN_CTRL_REG, avs_val);
 	}
 }
 
@@ -543,35 +546,11 @@
 }
 #endif
 
-/* Switch to ARO from PLL in ap807 */
-static void aro_to_pll(void)
-{
-	unsigned int reg;
-
-	/* switch from ARO to PLL */
-	reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-	reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-	mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-	reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-	reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-	mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-
-	mdelay(1000);
-
-	/* disable ARO clk driver */
-	reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-	reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-	mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-	reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-	reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-	mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-}
 
 int ble_plat_setup(int *skip)
 {
 	int ret;
+	unsigned int freq_mode;
 
 	/* Power down unused CPUs */
 	plat_marvell_early_cpu_powerdown();
@@ -598,9 +577,14 @@
 	/* Setup AVS */
 	ble_plat_svc_config();
 
+	/* read clk option from sampled-at-reset register */
+	freq_mode =
+		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+						 FREQ_MODE_AP_SAR_REG_NUM)));
+
 	/* work with PLL clock driver in AP807 */
 	if (ble_get_ap_type() == CHIP_ID_AP807)
-		aro_to_pll();
+		ap807_clocks_init(freq_mode);
 
 	/* Do required AP setups for BLE stage */
 	ap_ble_init();