diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
index fdf2d6dbdc84..ff0ad7a9c7fd 100644
--- a/arch/arm/dts/armada-375.dtsi
+++ b/arch/arm/dts/armada-375.dtsi
@@ -617,6 +617,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -635,6 +636,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/dts/armada-380.dtsi b/arch/arm/dts/armada-380.dtsi
index cff1269f3fbf..f3d7f4b27ddb 100644
--- a/arch/arm/dts/armada-380.dtsi
+++ b/arch/arm/dts/armada-380.dtsi
@@ -73,6 +73,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -92,6 +93,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -111,6 +113,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi
index f0022d10c715..581a7d9beac3 100644
--- a/arch/arm/dts/armada-385.dtsi
+++ b/arch/arm/dts/armada-385.dtsi
@@ -78,6 +78,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -97,6 +98,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -116,6 +118,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 
@@ -138,6 +141,7 @@
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 3>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi
index 8369de79afa2..1a48ff3c6162 100644
--- a/arch/arm/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -85,6 +85,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78230.dtsi b/arch/arm/dts/armada-xp-mv78230.dtsi
index 8558bf6bb54c..63d7f48cf456 100644
--- a/arch/arm/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/dts/armada-xp-mv78230.dtsi
@@ -92,6 +92,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -110,6 +111,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -128,6 +130,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -146,6 +149,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -164,6 +168,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78260.dtsi b/arch/arm/dts/armada-xp-mv78260.dtsi
index 2d85fe8ac327..5dc413dd14be 100644
--- a/arch/arm/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/dts/armada-xp-mv78260.dtsi
@@ -107,6 +107,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -125,6 +126,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -143,6 +145,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -161,6 +164,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -179,6 +183,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -197,6 +202,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 10>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -215,6 +221,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 11>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -233,6 +240,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 12>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -251,6 +259,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 26>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78460.dtsi b/arch/arm/dts/armada-xp-mv78460.dtsi
index 230a3fd36b30..6fbd0ce215ff 100644
--- a/arch/arm/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/dts/armada-xp-mv78460.dtsi
@@ -128,6 +128,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -146,6 +147,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -164,6 +166,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -182,6 +185,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -200,6 +204,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -218,6 +223,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 10>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -236,6 +242,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 11>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -254,6 +261,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 12>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -272,6 +280,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 26>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 
@@ -290,6 +299,7 @@
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 27>;
+				resets = <&systemc 0 3>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts
index 861967cd7e87..35909e3c69c6 100644
--- a/arch/arm/dts/armada-xp-synology-ds414.dts
+++ b/arch/arm/dts/armada-xp-synology-ds414.dts
@@ -187,6 +187,7 @@
 	pcie@1,0 {
 		/* Port 0, Lane 0 */
 		status = "okay";
+		num-lanes = <4>;
 	};
 
 	/*
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index 24cc1cc5278e..a06a65af1587 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -214,5 +214,6 @@
 	pcie@9,0 {
 		/* Port 2, Lane 0 */
 		status = "okay";
+		num-lanes = <4>;
 	};
 };
diff --git a/arch/arm/mach-mvebu/serdes/a38x/Makefile b/arch/arm/mach-mvebu/serdes/a38x/Makefile
index 917fc1350ce5..5a70b3759667 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/Makefile
+++ b/arch/arm/mach-mvebu/serdes/a38x/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-obj-$(CONFIG_SPL_BUILD)	= ctrl_pex.o
 obj-$(CONFIG_SPL_BUILD)	+= high_speed_env_spec.o
 obj-$(CONFIG_SPL_BUILD)	+= high_speed_env_spec-38x.o
 obj-$(CONFIG_SPL_BUILD)	+= seq_exec.o
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
deleted file mode 100644
index b3cbddf6a2f0..000000000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#include <common.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/soc.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#include "ctrl_pex.h"
-#include "sys_env_lib.h"
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
-{
-	enum serdes_type serdes_type;
-	u32 idx, tmp;
-
-	DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
-
-	tmp = reg_read(SOC_CONTROL_REG1);
-	tmp &= ~0x03;
-
-	for (idx = 0; idx < count; idx++) {
-		serdes_type = serdes_map[idx].serdes_type;
-		if ((serdes_type != PEX0) &&
-		    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
-		     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
-			/* for PEX by4 - relevant for the first port only */
-			continue;
-		}
-
-		switch (serdes_type) {
-		case PEX0:
-			tmp |= 0x1 << PCIE0_ENABLE_OFFS;
-			break;
-		case PEX1:
-			tmp |= 0x1 << PCIE1_ENABLE_OFFS;
-			break;
-		case PEX2:
-			tmp |= 0x1 << PCIE2_ENABLE_OFFS;
-			break;
-		case PEX3:
-			tmp |= 0x1 << PCIE3_ENABLE_OFFS;
-			break;
-		default:
-			break;
-		}
-	}
-
-	reg_write(SOC_CONTROL_REG1, tmp);
-
-	return MV_OK;
-}
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
deleted file mode 100644
index abdbe3c66045..000000000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#ifndef _CTRL_PEX_H
-#define _CTRL_PEX_H
-
-#include <pci.h>
-#include "high_speed_env_spec.h"
-
-/* Direct access to PEX0 Root Port's PCIe Capability structure */
-#define PEX0_RP_PCIE_CFG_OFFSET		(0x00080000 + 0x60)
-
-/* SOC_CONTROL_REG1 fields */
-#define PCIE0_ENABLE_OFFS		0
-#define PCIE0_ENABLE_MASK		(0x1 << PCIE0_ENABLE_OFFS)
-#define PCIE1_ENABLE_OFFS		1
-#define PCIE1_ENABLE_MASK		(0x1 << PCIE1_ENABLE_OFFS)
-#define PCIE2_ENABLE_OFFS		2
-#define PCIE2_ENABLE_MASK		(0x1 << PCIE2_ENABLE_OFFS)
-#define PCIE3_ENABLE_OFFS		3
-#define PCIE4_ENABLE_MASK		(0x1 << PCIE3_ENABLE_OFFS)
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
-
-#endif
diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
index 9ba60b57aac8..2e467b546d5f 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
@@ -12,7 +12,6 @@
 
 #include "high_speed_env_spec.h"
 #include "sys_env_lib.h"
-#include "ctrl_pex.h"
 
 /*
  * serdes_seq_db - holds all serdes sequences, their size and the
@@ -1555,9 +1554,6 @@ int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count)
 		   After finish the Power_up sequence for all lanes,
 		   the lanes should be released from reset state.       */
 		CHECK_STATUS(hws_pex_tx_config_seq(serdes_map, count));
-
-		/* PEX configuration */
-		CHECK_STATUS(hws_pex_config(serdes_map, count));
 	}
 
 	/* USB2 configuration */
@@ -1743,21 +1739,6 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
 				else
 					reg_data &= ~0x4000;
 				reg_write(SOC_CONTROL_REG1, reg_data);
-
-				/*
-				 * Set Maximum Link Width to X1 or X4 in Root
-				 * Port's PCIe Link Capability register.
-				 * This register is read-only but if is not set
-				 * correctly then access to PCI config space of
-				 * endpoint card behind this Root Port does not
-				 * work.
-				 */
-				reg_data = reg_read(PEX0_RP_PCIE_CFG_OFFSET +
-						    PCI_EXP_LNKCAP);
-				reg_data &= ~PCI_EXP_LNKCAP_MLW;
-				reg_data |= (is_pex_by1 ? 1 : 4) << 4;
-				reg_write(PEX0_RP_PCIE_CFG_OFFSET +
-					  PCI_EXP_LNKCAP, reg_data);
 			}
 
 			CHECK_STATUS(mv_seq_exec(serdes_num, PEX_POWER_UP_SEQ));
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index cc139af6cb57..ba0d334e2009 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -259,6 +259,7 @@ config PCI_MVEBU
 	bool "Enable Armada XP/38x PCIe driver"
 	depends on ARCH_MVEBU
 	select MISC
+	select DM_RESET
 	help
 	  Say Y here if you want to enable PCIe controller support on
 	  Armada XP/38x SoCs.
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index b5b0897b2124..84b8ab4fb4d6 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -18,6 +18,7 @@
 #include <dm/lists.h>
 #include <dm/of_access.h>
 #include <pci.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
@@ -83,6 +84,7 @@ struct mvebu_pcie {
 	u32 intregs;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	u32 lane_mask;
 	int first_busno;
@@ -388,7 +390,30 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
 /* Only enable PCIe link, do not setup it */
 static int mvebu_pcie_enable_link(struct mvebu_pcie *pcie, ofnode node)
 {
-	/* PCIe link is currently automatically enabled in SerDes code */
+	struct reset_ctl rst;
+	int ret;
+
+	ret = reset_get_by_index_nodev(node, 0, &rst);
+	if (ret == -ENOENT) {
+		return 0;
+	} else if (ret < 0) {
+		printf("%s: cannot get reset controller: %d\n", pcie->name, ret);
+		return ret;
+	}
+
+	ret = reset_request(&rst);
+	if (ret) {
+		printf("%s: cannot request reset controller: %d\n", pcie->name, ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&rst);
+	reset_free(&rst);
+	if (ret) {
+		printf("%s: cannot enable PCIe port: %d\n", pcie->name, ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -401,6 +426,18 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
 	reg = readl(pcie->base + PCIE_CTRL_OFF);
 	reg |= PCIE_CTRL_RC_MODE;
 	writel(reg, pcie->base + PCIE_CTRL_OFF);
+
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	reg = readl(pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
+	reg &= ~PCI_EXP_LNKCAP_MLW;
+	reg |= (pcie->is_x4 ? 4 : 1) << 4;
+	writel(reg, pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
 }
 
 static int mvebu_pcie_probe(struct udevice *dev)
@@ -591,6 +628,7 @@ static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pci
 {
 	struct fdt_pci_addr pci_addr;
 	const u32 *addr;
+	u32 num_lanes;
 	int ret = 0;
 	int len;
 
@@ -606,6 +644,9 @@ static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pci
 
 	sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane);
 
+	if (!ofnode_read_u32(node, "num-lanes", &num_lanes) && num_lanes == 4)
+		pcie->is_x4 = true;
+
 	/* devfn is in bits [15:8], see PCI_DEV usage */
 	ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", &pci_addr);
 	if (ret < 0) {
