bin_hdr: a38x: add SERDES PCIe By 4 support

Change-Id: I9b26a5174c66c205acb0cf43971df389d1dd424b
Signed-off-by: Neta Zur <neta@marvell.com>
Reviewed-on: http://vgitil04.il.marvell.com:8080/5224
Tested-by: Star_Automation <star@marvell.com>
Reviewed-by: Omri Itach <omrii@marvell.com>
Reviewed-by: Eli Nidam <elini@marvell.com>
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
diff --git a/tools/marvell/bin_hdr/src_phy_a38x/mvBHboardEnvSpec.c b/tools/marvell/bin_hdr/src_phy_a38x/mvBHboardEnvSpec.c
index 4d3e697..04f6a68 100644
--- a/tools/marvell/bin_hdr/src_phy_a38x/mvBHboardEnvSpec.c
+++ b/tools/marvell/bin_hdr/src_phy_a38x/mvBHboardEnvSpec.c
@@ -171,9 +171,9 @@
 SERDES_MAP DbConfigSLM1363_D[MAX_SERDES_LANES] =
 {
 	{ PEX0,		  __5Gbps,		PEX_ROOT_COMPLEX_x4		   },
-	{ DEFAULT_SERDES, LAST_SERDES_SPEED,	SERDES_DEFAULT_MODE		   },
-	{ DEFAULT_SERDES, LAST_SERDES_SPEED,	SERDES_DEFAULT_MODE		   },
-	{ DEFAULT_SERDES, LAST_SERDES_SPEED,	SERDES_DEFAULT_MODE		   },
+	{ PEX1,		  __5Gbps,		PEX_ROOT_COMPLEX_x4		   },
+	{ PEX2,		  __5Gbps,		PEX_ROOT_COMPLEX_x4		   },
+	{ PEX3,		  __5Gbps,		PEX_ROOT_COMPLEX_x4		   },
 	{ SATA1,	  __3Gbps,		SERDES_DEFAULT_MODE		   },
 	{ SATA2,	  __3Gbps,		SERDES_DEFAULT_MODE		   }
 };
diff --git a/tools/marvell/bin_hdr/src_phy_a38x/mvCtrlPex.c b/tools/marvell/bin_hdr/src_phy_a38x/mvCtrlPex.c
index 11d8d6c..6935d64 100644
--- a/tools/marvell/bin_hdr/src_phy_a38x/mvCtrlPex.c
+++ b/tools/marvell/bin_hdr/src_phy_a38x/mvCtrlPex.c
@@ -189,6 +189,14 @@
 		if ((serdesType != PEX0) && (serdesType != PEX1) && (serdesType != PEX2) && (serdesType != PEX3))
 			continue;
 
+		if ((serdesType != PEX0) &&
+				((serdesMap[serdesIdx].serdesMode == PEX_ROOT_COMPLEX_x4) ||
+				 (serdesMap[serdesIdx].serdesMode == PEX_END_POINT_x4)))
+		{
+			/* for PEX by4 - relevant for the first port only */
+			continue;
+		}
+
 		pexIdx = serdesType - PEX0;
 		tmp = MV_REG_READ(PEX_CAPABILITIES_REG(pexIdx));
 		tmp &= ~(0xf << 20);
@@ -201,6 +209,13 @@
 
 	for (serdesIdx = 0; serdesIdx < MAX_SERDES_LANES; serdesIdx++) {
 		serdesType = serdesMap[serdesIdx].serdesType;
+		if ((serdesType != PEX0) &&
+				((serdesMap[serdesIdx].serdesMode == PEX_ROOT_COMPLEX_x4) ||
+				 (serdesMap[serdesIdx].serdesMode == PEX_END_POINT_x4)))
+		{
+			/* for PEX by4 - relevant for the first port only */
+			continue;
+		}
 		switch (serdesType) {
 		case PEX0:
 			tmp |= 0x1 << PCIE0_ENABLE_OFFS;
@@ -241,6 +256,14 @@
 		if ((serdesType != PEX0) && (serdesType != PEX1) && (serdesType != PEX2) && (serdesType != PEX3))
 			continue;
 
+		if ((serdesType != PEX0) &&
+				((serdesMap[serdesIdx].serdesMode == PEX_ROOT_COMPLEX_x4) ||
+				 (serdesMap[serdesIdx].serdesMode == PEX_END_POINT_x4)))
+		{
+			/* for PEX by4 - relevant for the first port only */
+			continue;
+		}
+
 		pexIdx = serdesType - PEX0;
 		tmp = MV_REG_READ(PEX_DBG_STATUS_REG(pexIdx));
 
@@ -312,6 +335,14 @@
 		if ((serdesType != PEX0) && (serdesType != PEX1) && (serdesType != PEX2) && (serdesType != PEX3))
 			continue;
 
+		if ((serdesType != PEX0) &&
+				((serdesMap[serdesIdx].serdesMode == PEX_ROOT_COMPLEX_x4) ||
+				 (serdesMap[serdesIdx].serdesMode == PEX_END_POINT_x4)))
+		{
+			/* for PEX by4 - relevant for the first port only */
+			continue;
+		}
+
 		pexIdx = serdesType - PEX0;
 		devId = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIdx, PEX_DEVICE_AND_VENDOR_ID));
 		devId &= 0xFFFF;
diff --git a/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvLib.c b/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvLib.c
index a4ac66c..7ffa3dc 100644
--- a/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvLib.c
+++ b/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvLib.c
@@ -243,6 +243,13 @@
 	{ 0x0,		   0x0,						    0x0,	     { 0x0,   0x0   }, 10,	   0			  } /* 10ms delay */
 };
 
+/* PEX by 4 config seq */
+MV_OP_PARAMS pexBy4ConfigParams[] =
+{
+	/* unitunitBaseReg  unitOffset   mask    data                   waitTime   numOfLoops */
+	{ 0xa0710,	    0x800,       0x7,	 { 0x5, 0x0, 0x0, 0x2 },  0,	        0}
+};
+
 /* USB3 device donfig seq */
 MV_OP_PARAMS usb3DeviceConfigParams[] =
 {
@@ -373,6 +380,11 @@
 	serdesSeqDb[PEX_TX_CONFIG_SEQ].cfgSeqSize =  sizeof(pexAndUsb3TxConfigParams) / sizeof(MV_OP_PARAMS);
 	serdesSeqDb[PEX_TX_CONFIG_SEQ].dataArrIdx = PEX;
 
+	/* PEX_BY_4_CONFIG_SEQ sequence init */
+	serdesSeqDb[PEX_BY_4_CONFIG_SEQ].opParamsPtr = pexBy4ConfigParams;
+	serdesSeqDb[PEX_BY_4_CONFIG_SEQ].cfgSeqSize =  sizeof(pexBy4ConfigParams) / sizeof(MV_OP_PARAMS);
+	serdesSeqDb[PEX_BY_4_CONFIG_SEQ].dataArrIdx = PEX;
+
 	/* USB3_POWER_UP_SEQ sequence init */
 	serdesSeqDb[USB3_POWER_UP_SEQ].opParamsPtr = pexAndUsb3PowerUpParams;
 	serdesSeqDb[USB3_POWER_UP_SEQ].cfgSeqSize =  sizeof(pexAndUsb3PowerUpParams) / sizeof(MV_OP_PARAMS);
@@ -571,6 +583,7 @@
 	REF_CLOCK refClock;
 	SERDES_TYPE serdesType;
 	SERDES_SPEED serdesSpeed;
+	SERDES_MODE  serdesMode;
 
 	DEBUG_INIT_FULL_S("\n### powerUpSerdesLanes ###\n");
 
@@ -586,6 +599,7 @@
 
 		serdesType = serdesConfigMap[serdesLaneNum].serdesType;
 		serdesSpeed = serdesConfigMap[serdesLaneNum].serdesSpeed;
+		serdesMode = serdesConfigMap[serdesLaneNum].serdesMode;
 
 		/* serdes lane is not in use */
 		if (serdesType == DEFAULT_SERDES)
@@ -600,6 +614,7 @@
 						 MV_TRUE,
 						 serdesType,
 						 serdesSpeed,
+						 serdesMode,
 						 refClock));
 	}
 
@@ -631,6 +646,7 @@
 	MV_BOOL serdesPowerUp,
 	SERDES_TYPE serdesType,
 	SERDES_SPEED baudRate,
+	SERDES_MODE  serdesMode,
 	REF_CLOCK refClock
 )
 {
@@ -640,6 +656,7 @@
 	int sataIdx, pexIdx;
 	SERDES_SEQ speedSeqId;
 	MV_U32 regData;
+	MV_BOOL isPexBy1;
 
 	DEBUG_INIT_FULL_S("\n### mvSerdesPowerUpCtrl ###\n");
 
@@ -663,28 +680,51 @@
 		case PEX1:
 		case PEX2:
 		case PEX3:
-			regData = MV_REG_READ(SOC_CONTROL_REG1);
-			regData |= 0x4000;
-			MV_REG_WRITE(SOC_CONTROL_REG1, regData);
 
+			isPexBy1 = (serdesMode == PEX_ROOT_COMPLEX_x1) ||
+				(serdesMode == PEX_ROOT_COMPLEX_x1);
 			pexIdx = serdesType - PEX0;
 
-			regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c));
-			regData &= ~0x3F0;
-			regData |= 0x10;
-			MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c), regData);
+			if ((isPexBy1 == MV_TRUE) || (serdesType == PEX0))
+			{
+				/* For PEX by 4, init only the PEX 0 */
+				regData = MV_REG_READ(SOC_CONTROL_REG1);
+				if (isPexBy1 == MV_TRUE) {
+					regData |= 0x4000;
+				}
+				else{
+					regData &= ~0x4000;
+				}
+				MV_REG_WRITE(SOC_CONTROL_REG1, regData);
 
-			regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c));
-			regData &= ~0xF;
-			regData |= 0x2;
-			MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c), regData);
+				regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c));
+				regData &= ~0x3F0;
+				if (isPexBy1 == MV_TRUE) {
+					regData |= 0x10;
+				}
+				else {
+					regData |= 0x40;
+				}
+				MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c), regData);
 
-			regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x70));
-			regData &= ~0x40;
-			regData |= 0x40;
-			MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x70), regData);
+				regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c));
+				regData &= ~0xF;
+				regData |= 0x2;
+				MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x6c), regData);
+
+				regData = MV_REG_READ(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x70));
+				regData &= ~0x40;
+				regData |= 0x40;
+				MV_REG_WRITE(((MV_PEX_IF_REGS_BASE(pexIdx)) + 0x70), regData);
+			}
 
 			CHECK_STATUS(mvSeqExec(serdesNum, PEX_POWER_UP_SEQ));
+			if (isPexBy1 == MV_FALSE) {
+				/* for PEX by 4 - use the PEX index as the seq array index */
+				serdesSeqDb[PEX_BY_4_CONFIG_SEQ].dataArrIdx = pexIdx;
+				CHECK_STATUS(mvSeqExec(serdesNum, PEX_BY_4_CONFIG_SEQ));
+			}
+
 			CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
 			CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
 			CHECK_STATUS(mvSeqExec(serdesNum, PEX_TX_CONFIG_SEQ));
@@ -858,12 +898,18 @@
 			return MV_BAD_PARAM;
 		}
 
+		/* Checking if the board topology configuration includes PEXx4 - for the next step */
+		if ((serdesMode == PEX_END_POINT_x4) || (serdesMode == PEX_ROOT_COMPLEX_x4)) {
+			if (serdesType == PEX0) {
+				isPEXx4 = MV_TRUE;
+			} else {
+				/* update lane data to the 3 next SERDES lanes */
+				laneData = 2;
+			}
+		}
+
 		/* Updating the data that will be written to COMMON_PHYS_SELECTORS_REG */
 		regData |= (laneData << (3 * serdesIdx));
-
-		/* Checking if the board topology configuration includes PEXx4 - for the next step */
-		if ((serdesMode == PEX_END_POINT_x4) || (serdesMode == PEX_ROOT_COMPLEX_x4))
-			isPEXx4 = MV_TRUE;
 	}
 
 	/* Updating the 18th bit in the COMMON PHYS SELECTORS register in case there is PEXx4 */
diff --git a/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvSpec.h b/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvSpec.h
index b96a1f3..df4a7f6 100644
--- a/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvSpec.h
+++ b/tools/marvell/bin_hdr/src_phy_a38x/mvHighSpeedEnvSpec.h
@@ -168,6 +168,7 @@
 	PEX__2_5_SPEED_CONFIG_SEQ,
 	PEX__5_SPEED_CONFIG_SEQ,
 	PEX_TX_CONFIG_SEQ,
+	PEX_BY_4_CONFIG_SEQ,
 
 	USB3_POWER_UP_SEQ,
 	USB3__HOST_SPEED_CONFIG_SEQ,
@@ -337,6 +338,7 @@
  *                       serdesType      -   PEX, SATA, SGMII
  *                                           or USB3 (host or device)
  *                       baudRate        -   serdes speed
+ *                       serdesMode      -   serdes mode
  *                       refClock        -   ref clock (25 or 100)
  * OUTPUT:               None.
  * RETURNS:              MV_OK           -   for success
@@ -345,6 +347,7 @@
 			      MV_BOOL serdesPowerUp,
 			      SERDES_TYPE serdesType,
 			      SERDES_SPEED baudRate,
+			      SERDES_MODE  serdesMode,
 			      REF_CLOCK refClock);
 
 #endif /* _MV_HIGHSPEED_ENV_SPEC_H */