summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgal Liberman <igall@marvell.com>2018-11-15 16:13:11 +0200
committerKostya Porotchkin <kostap@marvell.com>2018-11-21 16:11:14 +0200
commit4db85ae088a5e2f51e9a5a671f531cb80a632067 (patch)
tree5b7099c569c173353c6777cc08baf80395a62d62
parent7bb4c104eaf97001693a896173201d4e409bf156 (diff)
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 <igall@marvell.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/60959 Tested-by: iSoC Platform CI <ykjenk@marvell.com> Reviewed-by: Grzegorz Jaszczyk <jaz@semihalf.com> Reviewed-by: Kostya Porotchkin <kostap@marvell.com>
-rw-r--r--drivers/marvell/comphy/phy-comphy-common.h15
-rw-r--r--drivers/marvell/comphy/phy-comphy-cp110.c49
-rw-r--r--drivers/marvell/comphy/phy-comphy-cp110.h3
-rw-r--r--plat/marvell/common/mrvl_sip_svc.c2
4 files changed, 64 insertions, 5 deletions
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index 4245a757..8cc7dcd6 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -23,8 +23,10 @@
* - 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 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 a73542a7..8aa9829c 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -1165,6 +1165,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);
@@ -2312,14 +2328,45 @@ int mvebu_cp110_comphy_power_on(uint64_t comphy_base, uint8_t comphy_index, uint
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 3cb07b0a..ff53045a 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.h
+++ b/drivers/marvell/comphy/phy-comphy-cp110.h
@@ -80,7 +80,8 @@ 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);
+int mvebu_cp110_comphy_power_off(uint64_t comphy_base, 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, uint8_t comphy_index);
int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, uint8_t comphy_index,
diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c
index da694c66..10a36c10 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 */