aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/marvell/comphy/phy-comphy-common.h25
-rw-r--r--drivers/marvell/comphy/phy-comphy-cp110.c49
-rw-r--r--drivers/marvell/comphy/phy-comphy-cp110.h2
-rw-r--r--plat/marvell/common/mrvl_sip_svc.c2
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 */