From 0529106c4bb7e6e14247b3cca98b7c12009b42f0 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 19 Oct 2018 15:30:02 +0200 Subject: [PATCH 01/10] mvebu: cp110: fix phy selector configuration for XFI1 Extended phy selector configuration about XFI1 mode. Change-Id: I1309770bbb5fdbfb0127b6f12ee78974d1d6b19f Signed-off-by: Grzegorz Jaszczyk Reviewed-by: Kostya Porotchkin --- drivers/marvell/comphy/phy-comphy-cp110.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c index 25893a98f..897a0b0dd 100644 --- a/drivers/marvell/comphy/phy-comphy-cp110.c +++ b/drivers/marvell/comphy/phy-comphy-cp110.c @@ -208,8 +208,8 @@ static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, */ if ((mode == COMPHY_SGMII_MODE || mode == COMPHY_HS_SGMII_MODE || - mode == COMPHY_SFI_MODE) && - COMPHY_GET_ID(comphy_mode) == 1) + mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE) + && COMPHY_GET_ID(comphy_mode) == 1) reg |= COMMON_SELECTOR_COMPHY4_PORT1 << comphy_offset; else From 9cb6751d5988fe62d10b809469d4f6ec082730c6 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Wed, 14 Nov 2018 18:47:35 +0100 Subject: [PATCH 02/10] plat: marvell: a3700: do not power off cpu due to errata ref #13 Do not power off the CPU1 since there is no way to wake it up (wake-up is causing CPU0 reset as well duo to HW bug). Quote from errata Ref #13 [In power saving mode, both cores must be powered off]: "When Core 0 is on and Core 1 is in power-off state, a Core 1 wake-up resets Core 0 as well and puts Core 0 back to ROM". To overcome described HW bug instead of powering the CPU off, let it reach WFI instruction, which is invoked by generic psci_do_cpu_off function after platform handler finishes. This will put the core in low power state and give a chance to wake it up. Before this change, after running secondary kernel via kexec, only one core was up, now both cores are up. Change-Id: I87f144867550728055d9b8a2edb84a14539acab7 Signed-off-by: Grzegorz Jaszczyk Reviewed-by: Kostya Porotchkin --- plat/marvell/a3700/common/plat_pm.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plat/marvell/a3700/common/plat_pm.c b/plat/marvell/a3700/common/plat_pm.c index 5cebc9222..dce484168 100644 --- a/plat/marvell/a3700/common/plat_pm.c +++ b/plat/marvell/a3700/common/plat_pm.c @@ -288,18 +288,9 @@ int a3700_validate_ns_entrypoint(uintptr_t entrypoint) */ void a3700_pwr_domain_off(const psci_power_state_t *target_state) { - uint32_t cpu_idx = plat_my_core_pos(); - /* Prevent interrupts from spuriously waking up this cpu */ plat_marvell_gic_cpuif_disable(); - /* - * Enable Core VDD OFF, core is supposed to be powered - * off by PMU when WFI command is issued. - */ - mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG + 4 * cpu_idx, - MVEBU_PM_CORE_PD); - /* Core can not be powered down with pending IRQ, * acknowledge all the pending IRQ */ From 55df84f974ea37abbb4f93f000f101f70cda5303 Mon Sep 17 00:00:00 2001 From: Igal Liberman Date: Thu, 15 Nov 2018 16:13:11 +0200 Subject: [PATCH 03/10] mvebu: cp110: avoid pcie power on/off sequence when called from Linux In Armada 8K DB boards, PCIe initialization can be executed only once because PCIe reset performed during chip power on and it cannot be executed via GPIO later. This means that power on can be executed only once, when it's called from the bootloader. Power on: Read bit 21 of the mode, it marks if the caller is the bootloader or the Linux Kernel. Power off: Check if the comphy was already configured to PCIe, if yes, check if the caller is bootloader, if both conditions are true (PCIe mode and called by Linux) - skip the power-off. In addition, fix incorrect documentation describing mode fields - PCIe width is 3 bits, not 2. NOTE: with this patch, please use LK4.14.76 (LK4.4.120 may not work with it). Change-Id: I4b929011f97a0a1869a51ba378687e78b3eca4ff Signed-off-by: Igal Liberman Reviewed-by: Grzegorz Jaszczyk Reviewed-by: Kostya Porotchkin --- drivers/marvell/comphy/phy-comphy-common.h | 25 +++++++---- drivers/marvell/comphy/phy-comphy-cp110.c | 49 +++++++++++++++++++++- drivers/marvell/comphy/phy-comphy-cp110.h | 2 +- plat/marvell/common/mrvl_sip_svc.c | 2 +- 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h index 78c7a38fc..e3b430a91 100644 --- a/drivers/marvell/comphy/phy-comphy-common.h +++ b/drivers/marvell/comphy/phy-comphy-common.h @@ -18,13 +18,15 @@ #endif /* A lane is described by 4 fields: - * - bit 1~0 represent comphy polarity invert - * - bit 7~2 represent comphy speed - * - bit 11~8 represent unit index - * - bit 16~12 represent mode - * - bit 17 represent comphy indication of clock source - * - bit 19-18 represents pcie width (in case of pcie comphy config.) - * - bit 31~20 reserved + * - bit 1~0 represent comphy polarity invert + * - bit 7~2 represent comphy speed + * - bit 11~8 represent unit index + * - bit 16~12 represent mode + * - bit 17 represent comphy indication of clock source + * - bit 20~18 represents pcie width (in case of pcie comphy config.) + * - bit 21 represents the source of the request (Linux/Bootloader), + * (reguired only for PCIe!) + * - bit 31~22 reserved */ #define COMPHY_INVERT_OFFSET 0 @@ -50,6 +52,11 @@ #define COMPHY_PCI_WIDTH_LEN 3 #define COMPHY_PCI_WIDTH_MASK COMPHY_MASK(COMPHY_PCI_WIDTH_OFFSET, \ COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_OFFSET \ + (COMPHY_PCI_WIDTH_OFFSET + COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_LEN 1 +#define COMPHY_PCI_CALLER_MASK COMPHY_MASK(COMPHY_PCI_CALLER_OFFSET, \ + COMPHY_PCI_CALLER_LEN) #define COMPHY_MASK(offset, len) (((1 << (len)) - 1) << (offset)) @@ -69,6 +76,10 @@ #define COMPHY_GET_PCIE_WIDTH(x) (((x) & COMPHY_PCI_WIDTH_MASK) >> \ COMPHY_PCI_WIDTH_OFFSET) +/* Macro which extracts the caller for pcie power on from lane description */ +#define COMPHY_GET_CALLER(x) (((x) & COMPHY_PCI_CALLER_MASK) >> \ + COMPHY_PCI_CALLER_OFFSET) + /* Macro which extracts the polarity invert from lane description */ #define COMPHY_GET_POLARITY_INVERT(x) (((x) & COMPHY_INVERT_MASK) >> \ COMPHY_INVERT_OFFSET) diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c index 897a0b0dd..86e5f1c68 100644 --- a/drivers/marvell/comphy/phy-comphy-cp110.c +++ b/drivers/marvell/comphy/phy-comphy-cp110.c @@ -1205,6 +1205,22 @@ static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base, uint32_t clk_dir; uintptr_t hpipe_addr, comphy_addr, addr; _Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode); + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); + + /* In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later). + * This means that power on can be executed only once, so let's + * mark if the caller is bootloader or Linux. + * If bootloader -> run power on. + * If Linux -> exit. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-on by Linux. + */ + if (!called_from_uboot) + return ret; hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), comphy_index); @@ -2366,14 +2382,45 @@ int mvebu_cp110_comphy_power_on(uint64_t comphy_base, uint8_t comphy_index, return err; } -int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index) +int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index, + uint64_t comphy_mode) { uintptr_t sd_ip_addr, comphy_ip_addr; uint32_t mask, data; uint8_t ap_nr, cp_nr; + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); debug_enter(); + /* Power-off might happen because of 2 things: + * 1. Bootloader turns off unconnected lanes + * 2. Linux turns off all lanes during boot + * (and then reconfigure it). + * + * For PCIe, there's a problem: + * In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later) so a lane configured to + * PCIe should not be powered off by Linux. + * + * So, check 2 things: + * 1. Is Linux called for power-off? + * 2. Is the comphy configured to PCIe? + * If the answer is YES for both 1 and 2, skip the power-off. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-off. + */ + if (!called_from_uboot) { + data = mmio_read_32(comphy_base + + COMMON_SELECTOR_PIPE_REG_OFFSET); + data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index); + data &= COMMON_SELECTOR_COMPHY_MASK; + if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE) + return 0; + } + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) { diff --git a/drivers/marvell/comphy/phy-comphy-cp110.h b/drivers/marvell/comphy/phy-comphy-cp110.h index 70dbfbfce..407909bf7 100644 --- a/drivers/marvell/comphy/phy-comphy-cp110.h +++ b/drivers/marvell/comphy/phy-comphy-cp110.h @@ -82,7 +82,7 @@ struct sata_params { int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, uint8_t comphy_index); int mvebu_cp110_comphy_power_off(uint64_t comphy_base, - uint8_t comphy_index); + uint8_t comphy_index, uint64_t comphy_mode); int mvebu_cp110_comphy_power_on(uint64_t comphy_base, uint8_t comphy_index, uint64_t comphy_mode); int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base, diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c index 8bc633b14..bc4b62113 100644 --- a/plat/marvell/common/mrvl_sip_svc.c +++ b/plat/marvell/common/mrvl_sip_svc.c @@ -87,7 +87,7 @@ uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid, SMC_RET1(handle, ret); case MV_SIP_COMPHY_POWER_OFF: /* x1: comphy_base, x2: comphy_index */ - ret = mvebu_cp110_comphy_power_off(x1, x2); + ret = mvebu_cp110_comphy_power_off(x1, x2, x3); SMC_RET1(handle, ret); case MV_SIP_COMPHY_PLL_LOCK: /* x1: comphy_base, x2: comphy_index */ From 1020e0d3264887fb642b02d47d1d1dcb4783fdba Mon Sep 17 00:00:00 2001 From: Christine Gharzuzi Date: Mon, 25 Jun 2018 13:39:37 +0300 Subject: [PATCH 04/10] 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 Signed-off-by: Konstantin Porotchkin --- drivers/marvell/ap807_clocks_init.c | 101 +++++++++++++++++ include/drivers/marvell/ap807_clocks_init.h | 14 +++ plat/marvell/a8k/common/a8k_common.mk | 17 +-- plat/marvell/a8k/common/plat_ble_setup.c | 118 +++++++++----------- 4 files changed, 175 insertions(+), 75 deletions(-) create mode 100644 drivers/marvell/ap807_clocks_init.c create mode 100644 include/drivers/marvell/ap807_clocks_init.h diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c new file mode 100644 index 000000000..841e6aeb4 --- /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 000000000..4353b83e8 --- /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 6136a1f59..6b2b35358 100644 --- a/plat/marvell/a8k/common/a8k_common.mk +++ b/plat/marvell/a8k/common/a8k_common.mk @@ -60,14 +60,15 @@ BLE_PORTING_SOURCES := $(PLAT_FAMILY_BASE)/$(PLAT)/board/dram_port.c \ 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 7438f69cc..07d6cad9b 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_mmap_config(int restore) */ 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 @@ static int ble_skip_current_image(void) } #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 @@ int ble_plat_setup(int *skip) /* 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(); From c35442690cbf4316151c039fb0ccdac2a39ad40a Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Tue, 6 Nov 2018 12:25:38 +0200 Subject: [PATCH 05/10] svc: Update the EEPROM AVS values processing Add support for SVC test builds for tuning AVS values. Update the SVC procedure and add EEPROM access. Add support for AP807 AVS values (10 bits wide). Signed-off-by: Konstantin Porotchkin --- plat/marvell/a8k/common/a8k_common.mk | 3 + plat/marvell/a8k/common/plat_ble_setup.c | 134 ++++++++++++++++++++++- 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk index 6b2b35358..88d931115 100644 --- a/plat/marvell/a8k/common/a8k_common.mk +++ b/plat/marvell/a8k/common/a8k_common.mk @@ -13,6 +13,9 @@ PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common MARVELL_DRV_BASE := drivers/marvell MARVELL_COMMON_BASE := plat/marvell/common +MARVELL_SVC_TEST := 0 +$(eval $(call add_define,MARVELL_SVC_TEST)) + ERRATA_A72_859971 := 1 # Enable MSS support for a8k family diff --git a/plat/marvell/a8k/common/plat_ble_setup.c b/plat/marvell/a8k/common/plat_ble_setup.c index 07d6cad9b..dbadeb768 100644 --- a/plat/marvell/a8k/common/plat_ble_setup.c +++ b/plat/marvell/a8k/common/plat_ble_setup.c @@ -41,6 +41,7 @@ #define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \ SAR_CLOCK_FREQ_MODE_OFFSET) +#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */ #define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130) #define AVS_ENABLE_OFFSET (0) #define AVS_SOFT_RESET_OFFSET (2) @@ -72,7 +73,9 @@ (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \ (0x1 << AVS_SOFT_RESET_OFFSET) | \ (0x1 << AVS_ENABLE_OFFSET)) - +/* VDD limit is 0.82V for all A3900 devices + * AVS offsets are not the same as in A70x0 + */ #define AVS_A3900_CLK_VALUE ((0x80 << 24) | \ (0x2c2 << 13) | \ (0x2c2 << 3) | \ @@ -143,6 +146,13 @@ #define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4 +#if MARVELL_SVC_TEST +#define MVEBU_CP_MPP_CTRL37_OFFS 20 +#define MVEBU_CP_MPP_CTRL38_OFFS 24 +#define MVEBU_CP_MPP_I2C_FUNC 2 +#define MVEBU_MPP_CTRL_MASK 0xf +#endif + /* Return the AP revision of the chip */ static unsigned int ble_get_ap_type(void) { @@ -201,6 +211,7 @@ static void ble_plat_mmap_config(int restore) * Setup Adaptive Voltage Switching - this is required for some platforms **************************************************************************** */ +#if !MARVELL_SVC_TEST static void ble_plat_avs_config(void) { uint32_t freq_mode, device_id; @@ -243,6 +254,113 @@ static void ble_plat_avs_config(void) mmio_write_32(AVS_EN_CTRL_REG, avs_val); } } +#endif +/****************************************************************************** + * Update or override current AVS work point value using data stored in EEPROM + * This is only required by QA/validation flows and activated by + * MARVELL_SVC_TEST flag. + * + * The function is expected to be called twice. + * + * First time with AVS value of 0 for testing if the EEPROM requests completely + * override the AVS value and bypass the eFuse test + * + * Second time - with non-zero AVS value obtained from eFuses as an input. + * In this case the EEPROM may contain AVS correction value (either positive + * or negative) that is added to the input AVS value and returned back for + * further processing. + ****************************************************************************** + */ +static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint) +{ + uint32_t new_wp = avs_workpoint; +#if MARVELL_SVC_TEST + /* --------------------------------------------------------------------- + * EEPROM | Data description (avs_step) + * address | + * --------------------------------------------------------------------- + * 0x120 | AVS workpoint correction value + * | if not 0 and not 0xff, correct the AVS taken from eFuse + * | by the number of steps indicated by bit[6:0] + * | bit[7] defines correction direction. + * | If bit[7]=1, add the value from bit[6:0] to AVS workpoint, + * | othervise substruct this value from AVS workpoint. + * --------------------------------------------------------------------- + * 0x121 | AVS workpoint override value + * | Override the AVS workpoint with the value stored in this + * | byte. When running on AP806, the AVS workpoint is 7 bits + * | wide and override value is valid when bit[6:0] holds + * | value greater than zero and smaller than 0x33. + * | When running on AP807, the AVS workpoint is 10 bits wide. + * | Additional 2 MSB bits are supplied by EEPROM byte 0x122. + * | AVS override value is valid when byte @ 0x121 and bit[1:0] + * | of byte @ 0x122 combined have non-zero value. + * --------------------------------------------------------------------- + * 0x122 | Extended AVS workpoint override value + * | Valid only for AP807 platforms and must be less than 0x4 + * --------------------------------------------------------------------- + */ + static uint8_t avs_step[3] = {0}; + uintptr_t reg; + uint32_t val; + unsigned int ap_type = ble_get_ap_type(); + + /* Always happens on second call to this function */ + if (avs_workpoint != 0) { + /* Get correction steps from the EEPROM */ + if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) { + NOTICE("AVS request to step %s by 0x%x from old 0x%x\n", + avs_step[0] & 0x80 ? "DOWN" : "UP", + avs_step[0] & 0x7f, new_wp); + if (avs_step[0] & 0x80) + new_wp -= avs_step[0] & 0x7f; + else + new_wp += avs_step[0] & 0x7f; + } + + return new_wp; + } + + /* AVS values are located in EEPROM + * at CP0 i2c bus #0, device 0x57 offset 0x120 + * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2. + */ + reg = MVEBU_CP_MPP_REGS(0, 4); + val = mmio_read_32(reg); + val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); + val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) | + (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS); + mmio_write_32(reg, val); + + /* Init CP0 i2c-0 */ + i2c_init((void *)(MVEBU_CP0_I2C_BASE)); + + /* Read EEPROM only once at the fist call! */ + i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3); + NOTICE("== SVC test build ==\n"); + NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n", + avs_step[0], avs_step[1], avs_step[2]); + + /* Override the AVS value? */ + if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) { + /* AP806 - AVS is 7 bits */ + new_wp = avs_step[1]; + + } else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) { + /* AP807 - AVS is 10 bits */ + new_wp = avs_step[2]; + new_wp <<= 8; + new_wp |= avs_step[1]; + } + + if (new_wp == 0) + NOTICE("Ignore BAD AVS Override value in EEPROM!\n"); + else + NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp); +#endif /* MARVELL_SVC_TEST */ + return new_wp; +} /**************************************************************************** * SVC flow - v0.10 @@ -264,6 +382,11 @@ static void ble_plat_svc_config(void) uint16_t svc[4], perr[4], i, sw_ver; unsigned int ap_type; + /* Set access to LD0 */ + avs_workpoint = avs_update_from_eeprom(0); + if (avs_workpoint) + goto set_aws_wp; + /* Set access to LD0 */ reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG); reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_OFFS; @@ -282,7 +405,12 @@ static void ble_plat_svc_config(void) sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK; if (sw_ver < 1) { NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver); +#if MARVELL_SVC_TEST + NOTICE("SVC_TEST: AVS bypassed\n"); + +#else ble_plat_avs_config(); +#endif return; } @@ -450,6 +578,10 @@ static void ble_plat_svc_config(void) if (ap_type != CHIP_ID_AP807) avs_workpoint &= 0x7F; + /* Update WP from EEPROM if needed */ + avs_workpoint = avs_update_from_eeprom(avs_workpoint); + +set_aws_wp: reg_val = mmio_read_32(AVS_EN_CTRL_REG); NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n", (reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET, From 5cf6fafe223da89c60e2323c242ea188b17e98c3 Mon Sep 17 00:00:00 2001 From: Christine Gharzuzi Date: Wed, 25 Jul 2018 16:06:10 +0300 Subject: [PATCH 06/10] fix: a3900: pm: fix number of CPU power switches. - Number of open power switches for CPUs should be three and now two. - This patch updates the value of open power switches from 0xfd (two power-switches) to 0xfc (three power-switches). Change-Id: I2783ab7f04bbbb6da78eeedcabe4636f9a774512 Signed-off-by: Christine Gharzuzi Reviewed-by: Kostya Porotchkin --- plat/marvell/a8k/common/plat_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/a8k/common/plat_pm.c index 1b68d0767..285441691 100644 --- a/plat/marvell/a8k/common/plat_pm.c +++ b/plat/marvell/a8k/common/plat_pm.c @@ -79,7 +79,7 @@ enum CPU_ID { #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1 #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0 #else -#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0 + #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0 #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31 #endif @@ -106,7 +106,7 @@ enum CPU_ID { #define AP807_PWRC_LDO_CR0_OFFSET 16 #define AP807_PWRC_LDO_CR0_MASK \ (0xff << AP807_PWRC_LDO_CR0_OFFSET) -#define AP807_PWRC_LDO_CR0_VAL 0xfd +#define AP807_PWRC_LDO_CR0_VAL 0xfc /* * Power down CPU: From d03f7a312274e9e61f42943be17d65d5385e2db6 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Sun, 25 Nov 2018 16:18:06 +0200 Subject: [PATCH 07/10] doc: marvell: Update build manual with new memory layouts Add description for memory layouts used by EspressoBin v7 (DDR4) Change-Id: I199d8b52580b26e560f14b503a6e99d32de4f284 Signed-off-by: Konstantin Porotchkin Reviewed-on: http://vgitil04.il.marvell.com:8080/61279 Reviewed-by: Stefan Chulski Tested-by: iSoC Platform CI --- docs/marvell/build.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/marvell/build.txt b/docs/marvell/build.txt index 8a669c100..0682b77d3 100644 --- a/docs/marvell/build.txt +++ b/docs/marvell/build.txt @@ -78,9 +78,11 @@ Build Instructions Supported Options: - DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB) - DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB) - - DDR3 2CS (2): EspressoBIN (1GB) + - DDR3 2CS (2): EspressoBIN V3-V5 (1GB) - DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB) - DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB) + - DDR4 1CS (5): EspressoBin V7 (1GB) + - DDR4 2CS (6): EspressoBin V7 (2GB) - CUSTOMER (CUST): Customer board, DDR3 1CS 512MB - CLOCKSPRESET: For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency, From 5a9f00f707e9a560ed598dece9711a8640c8e55f Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Sun, 21 Oct 2018 16:48:33 +0300 Subject: [PATCH 08/10] plat/marvell: comphy: Add support for SFI on Lane 4 Add static configuration for SFI+ 10Gbps interface on SERDES Lane 4. This is just a copy of Lane 2 static values, not optimized. Board-to-board iperf test shows up to 6Gbps transfer speed. Change-Id: I024d2ac132f7fa6c342a64367f3dca2123a27e97 Signed-off-by: Konstantin Porotchkin Reviewed-by: Igal Liberman --- .../a8k/a80x0/board/phy-porting-layer.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h index 38497fb53..abd85b5d2 100644 --- a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h +++ b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h @@ -27,7 +27,14 @@ static const struct xfi_params .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, .valid = 0x1 }, /* Comphy2 */ { 0 }, /* Comphy3 */ - { 0 }, /* Comphy4 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy4 */ { 0 }, /* Comphy5 */ }, @@ -44,7 +51,14 @@ static const struct xfi_params .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, .valid = 0x1 }, /* Comphy2 */ { 0 }, /* Comphy3 */ - { 0 }, /* Comphy4 */ + { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, + .align90 = 0x5f, + .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe, + .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, + .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0, + .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0, + .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2, + .valid = 0x1 }, /* Comphy4 */ { 0 }, /* Comphy5 */ }, }, From ff82813af89a528ac87d3e6b02a4d11269bfc05c Mon Sep 17 00:00:00 2001 From: Igal Liberman Date: Mon, 3 Sep 2018 10:40:21 +0300 Subject: [PATCH 09/10] a8k: pm: extend MSS_TRIGGER_TIMEOUT Very rarely, during cpuidle operations the following error is seen: "PM MSG Trigger Timeout". This is caused by slow handling of message interrutps in the PM FW running on CM3 (under heavy PM operation load). This is not a real issue, so we extend the timeout to avoid the error prints. Change-Id: I92fd6f2ff1ddf208b216c123880ded28a00b6e0e Signed-off-by: Igal Liberman Reviewed-on: http://vgitil04.il.marvell.com:8080/59670 Reviewed-by: Kostya Porotchkin Tested-by: iSoC Platform CI --- plat/marvell/a8k/common/mss/mss_pm_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/a8k/common/mss/mss_pm_ipc.c index 6ff4abcca..d1297b07b 100644 --- a/plat/marvell/a8k/common/mss/mss_pm_ipc.c +++ b/plat/marvell/a8k/common/mss/mss_pm_ipc.c @@ -26,7 +26,7 @@ #define MSS_MSG_INT_MASK (0x80000000) #define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110) -#define MSS_TRIGGER_TIMEOUT (1000) +#define MSS_TRIGGER_TIMEOUT (2000) /***************************************************************************** * mss_pm_ipc_msg_send From f32f3899f81742a89973176167d977ee4eddbc77 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Thu, 29 Nov 2018 15:04:10 +0200 Subject: [PATCH 10/10] plat/marvell: update platform LSP version to 18.12.0 Sync the platform code version with current Marvell LSP. Signed-off-by: Konstantin Porotchkin --- plat/marvell/version.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/marvell/version.mk b/plat/marvell/version.mk index 16b0a16aa..e072e12d5 100644 --- a/plat/marvell/version.mk +++ b/plat/marvell/version.mk @@ -1 +1 @@ -SUBVERSION = devel-18.09.1 +SUBVERSION = devel-18.12.0