diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index aafd766..c673e6c 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -26,7 +26,15 @@
 
 #include "pcie-designware.h"
 
-/* Synopsis specific PCIE configuration registers */
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES		10
+#define LINK_WAIT_MAX_ATU_RETRIES	5
+#define LINK_WAIT_USLEEP_MIN		90000
+#define LINK_WAIT_USLEEP_MAX		100000
+#define LINK_WAIT_IATU_MIN		9000
+#define LINK_WAIT_IATU_MAX		10000
+
+/* Synopsys specific PCIE configuration registers */
 #define PCIE_PORT_LINK_CONTROL		0x710
 #define PORT_LINK_MODE_MASK		(0x3f << 16)
 #define PORT_LINK_MODE_1_LANES		(0x1 << 16)
@@ -58,6 +66,7 @@
 #define PCIE_ATU_TYPE_IO		(0x2 << 0)
 #define PCIE_ATU_TYPE_CFG0		(0x4 << 0)
 #define PCIE_ATU_TYPE_CFG1		(0x5 << 0)
+
 #define PCIE_ATU_CR2			0x908
 #define PCIE_ATU_ENABLE			(0x1 << 31)
 #define PCIE_ATU_BAR_MODE_ENABLE	(0x1 << 30)
@@ -75,6 +84,37 @@
 #define PCIE_PHY_DEBUG_R1		(PLR_OFFSET + 0x2c)
 #define PCIE_PHY_DEBUG_R1_LINK_UP	0x00000010
 
+/*
+ * iatu unroll specific registers and definitions
+ * From 4.80 Core version the address translation will be made by unroll
+ */
+
+/* Registers */
+#define PCIE_ATU_UNR_REGION_CTRL1	0x00
+#define PCIE_ATU_UNR_REGION_CTRL2	0x01
+#define PCIE_ATU_UNR_LOWER_BASE		0x02
+#define PCIE_ATU_UNR_UPPER_BASE		0x03
+#define PCIE_ATU_UNR_LIMIT		0x04
+#define PCIE_ATU_UNR_LOWER_TARGET	0x05
+#define PCIE_ATU_UNR_UPPER_TARGET	0x06
+#define PCIE_ATU_UNR_REGION_CTRL3	0x07
+#define PCIE_ATU_UNR_UPPR_LIMIT		0x08
+
+/* register address builder */
+#define PCIE_GET_ATU_INB_UNR_REG_ADDR ((region, register)		\
+					(0x3 << 20) | (region << 9) |	\
+					(0x1 << 8) | (register << 2))
+
+#define PCIE_GET_ATU_OUTB_UNR_REG_ADDR ((region, register)		\
+					(0x3 << 20) | (region << 9) |	\
+					(register << 2))
+
+/* translation types */
+#define PCIE_TRANSL_INB			0x1
+#define PCIE_TRANSL_OUTB		0x2
+
+/* end of Unroll specific */
+
 static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
@@ -131,6 +171,38 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
 		writel(val, pp->dbi_base + reg);
 }
 
+static inline void dw_pcie_readl_unroll(struct pcie_port *pp, u32 type,
+						u32 index, u32 reg, u32 *val)
+{
+	u32 reg_addr = 0;
+
+	if (type == PCIE_TRANSL_OUTB)
+		reg_addr = PCIE_GET_ATU_OUTB_UNR_REG_ADDR(index, reg);
+	else if  (type == PCIE_TRANSL_INB)
+		reg_addr = PCIE_GET_ATU_INB_UNR_REG_ADDR(index, reg);
+
+	if (pp->ops->readl_rc)
+		pp->ops->readl_rc(pp, pp->va_unroll_base + reg_addr, val);
+	else
+		*val = readl(pp->va_unroll_base + reg_addr);
+}
+
+static inline void dw_pcie_writel_unroll(struct pcie_port *pp, u32 type,
+						u32 index, u32 val, u32 reg)
+{
+	u32 reg_addr = 0;
+
+	if (type == PCIE_TRANSL_OUTB)
+		reg_addr = PCIE_GET_ATU_OUTB_UNR_REG_ADDR(index, reg);
+	else if  (type == PCIE_TRANSL_INB)
+		reg_addr = PCIE_GET_ATU_INB_UNR_REG_ADDR(index, reg);
+
+	if (pp->ops->writel_rc)
+		pp->ops->writel_rc(pp, val, pp->va_unroll_base + reg_addr);
+	else
+		writel(val, pp->va_unroll_base + reg_addr);
+}
+
 static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
 			       u32 *val)
 {
@@ -152,24 +224,66 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
 static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
 		int type, u64 cpu_addr, u64 pci_addr, u32 size)
 {
-	u32 val;
-
-	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
-			  PCIE_ATU_VIEWPORT);
-	dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE);
-	dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE);
-	dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
-			  PCIE_ATU_LIMIT);
-	dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET);
-	dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET);
-	dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
-	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+	u32 val = 0;
+	u32 retries = 0;
+
+	if (pp->iatu_unroll_status) {
+		/* outbound translation using Unroll feature*/
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			lower_32_bits(cpu_addr), PCIE_ATU_UNR_LOWER_BASE);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			upper_32_bits(cpu_addr), PCIE_ATU_UNR_UPPER_BASE);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			lower_32_bits(cpu_addr + size - 1), PCIE_ATU_UNR_LIMIT);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			lower_32_bits(pci_addr), PCIE_ATU_UNR_LOWER_TARGET);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			upper_32_bits(pci_addr), PCIE_ATU_UNR_UPPER_TARGET);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			type, PCIE_ATU_UNR_REGION_CTRL1);
+		dw_pcie_writel_unroll(pp, PCIE_TRANSL_OUTB, index,
+			PCIE_ATU_ENABLE, PCIE_ATU_UNR_REGION_CTRL2);
+		dw_pcie_readl_unroll(pp, PCIE_TRANSL_OUTB, index,
+			PCIE_ATU_UNR_REGION_CTRL2, &val);
+	} else {
+		/* outbound translation using legacy mechanism */
+		dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
+						PCIE_ATU_VIEWPORT);
+		dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr),
+						PCIE_ATU_LOWER_BASE);
+		dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr),
+						PCIE_ATU_UPPER_BASE);
+		dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
+						PCIE_ATU_LIMIT);
+		dw_pcie_writel_rc(pp, lower_32_bits(pci_addr),
+						PCIE_ATU_LOWER_TARGET);
+		dw_pcie_writel_rc(pp, upper_32_bits(pci_addr),
+						PCIE_ATU_UPPER_TARGET);
+		dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
+		dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+		dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val);
+	}
 
 	/*
 	 * Make sure ATU enable takes effect before any subsequent config
 	 * and I/O accesses.
 	 */
-	dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val);
+	for (retries = 0; retries < LINK_WAIT_MAX_ATU_RETRIES; retries++) {
+
+		if (val == PCIE_ATU_ENABLE)
+			break;
+
+		usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+
+		if (pp->iatu_unroll_status) {
+			dw_pcie_readl_unroll(pp, PCIE_TRANSL_OUTB, index,
+				PCIE_ATU_UNR_REGION_CTRL2, &val);
+		} else {
+			dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val);
+		}
+	}
+
+	dev_dbg(pp->dev, "iATU is not being enabled\n");
 }
 
 static struct irq_chip dw_msi_irq_chip = {
@@ -428,6 +542,18 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
+static void dw_pcie_get_atu_mode(struct pcie_port *pp)
+{
+	u32 val = 0;
+
+	/* Check if the iATU unroll is enabled or not */
+	dw_pcie_readl_rc(pp, PCIE_ATU_VIEWPORT, &val);
+
+	pp->iatu_unroll_status = 0; /* disabled - legacy is used */
+	if (val == 0xFFFFFFFF)
+		pp->iatu_unroll_status = 1; /* enabled */
+}
+
 int dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
@@ -540,6 +666,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		}
 	}
 
+	/* get ATU mode */
+	dw_pcie_get_atu_mode(pp);
+
 	if (pp->ops->host_init)
 		pp->ops->host_init(pp);
 
@@ -570,6 +699,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pcie_bus_configure_settings(child);
 
 	pci_bus_add_devices(bus);
+
 	return 0;
 }
 
@@ -603,6 +733,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  type, cpu_addr,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
+
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
 				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
@@ -640,6 +771,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  type, cpu_addr,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
+
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
 				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index f437f9b..354a981 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -22,11 +22,6 @@
 #define MAX_MSI_IRQS			32
 #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
 
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES		10
-#define LINK_WAIT_USLEEP_MIN		90000
-#define LINK_WAIT_USLEEP_MAX		100000
-
 struct pcie_port {
 	struct device		*dev;
 	u8			root_bus_nr;
@@ -53,6 +48,7 @@ struct pcie_port {
 	int			msi_irq;
 	struct irq_domain	*irq_domain;
 	unsigned long		msi_data;
+	u8			iatu_unroll_status;
 	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
 
