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 +#include +#include +#include + +/* 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 #include #include +#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();