diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 75b9208a33e39975bd4298a3f5f83e423e7f9a4e..8db07081ff26fe306aed58be2af6890273c042e0 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -6,6 +6,7 @@ config TEGRA_COMMON
 	select DM_GPIO
 	select DM_I2C
 	select DM_KEYBOARD
+	select DM_PCI
 	select DM_SERIAL
 	select DM_SPI
 	select DM_SPI_FLASH
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 8ba143d996caed61ceb613383acf283d72838b6b..a650abd731adb78ae30dd0d03bdf5d16d3757e56 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -377,6 +377,10 @@ void dram_init_banksize(void)
 	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
 	gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
 
+#ifdef CONFIG_PCI
+	gd->pci_ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+#endif
+
 #ifdef CONFIG_PHYS_64BIT
 	if (gd->ram_size > SZ_2G) {
 		gd->bd->bi_dram[1].start = 0x100000000;
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index 690896f9f57183f4651553a5b614c951386479de..5a7fefed5e1525e6d942a8e36a9d21b70e4dd3a1 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -10,10 +10,10 @@
  * SPDX-License-Identifier:	GPL-2.0
  */
 
-#define DEBUG
 #define pr_fmt(fmt) "tegra-pcie: " fmt
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
@@ -177,7 +177,12 @@ DECLARE_GLOBAL_DATA_PTR;
 #define  RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE	0x20000000
 #define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK	0x3fff0000
 
-struct tegra_pcie;
+enum tegra_pci_id {
+	TEGRA20_PCIE,
+	TEGRA30_PCIE,
+	TEGRA124_PCIE,
+	TEGRA210_PCIE,
+};
 
 struct tegra_pcie_port {
 	struct tegra_pcie *pcie;
@@ -207,10 +212,6 @@ struct tegra_pcie {
 	struct fdt_resource afi;
 	struct fdt_resource cs;
 
-	struct fdt_resource prefetch;
-	struct fdt_resource mem;
-	struct fdt_resource io;
-
 	struct list_head ports;
 	unsigned long xbar;
 
@@ -218,11 +219,6 @@ struct tegra_pcie {
 	struct tegra_xusb_phy *phy;
 };
 
-static inline struct tegra_pcie *to_tegra_pcie(struct pci_controller *hose)
-{
-	return container_of(hose, struct tegra_pcie, hose);
-}
-
 static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
 		       unsigned long offset)
 {
@@ -284,46 +280,54 @@ static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf,
 		return 0;
 	}
 
-	return -1;
+	return -EFAULT;
 }
 
-static int tegra_pcie_read_conf(struct pci_controller *hose, pci_dev_t bdf,
-				int where, u32 *value)
+static int pci_tegra_read_config(struct udevice *bus, pci_dev_t bdf,
+				 uint offset, ulong *valuep,
+				 enum pci_size_t size)
 {
-	struct tegra_pcie *pcie = to_tegra_pcie(hose);
-	unsigned long address;
+	struct tegra_pcie *pcie = dev_get_priv(bus);
+	unsigned long address, value;
 	int err;
 
-	err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+	err = tegra_pcie_conf_address(pcie, bdf, offset, &address);
 	if (err < 0) {
-		*value = 0xffffffff;
-		return 1;
+		value = 0xffffffff;
+		goto done;
 	}
 
-	*value = readl(address);
+	value = readl(address);
 
 	/* fixup root port class */
 	if (PCI_BUS(bdf) == 0) {
-		if (where == PCI_CLASS_REVISION) {
-			*value &= ~0x00ff0000;
-			*value |= PCI_CLASS_BRIDGE_PCI << 16;
+		if (offset == PCI_CLASS_REVISION) {
+			value &= ~0x00ff0000;
+			value |= PCI_CLASS_BRIDGE_PCI << 16;
 		}
 	}
 
+done:
+	*valuep = pci_conv_32_to_size(value, offset, size);
+
 	return 0;
 }
 
-static int tegra_pcie_write_conf(struct pci_controller *hose, pci_dev_t bdf,
-				 int where, u32 value)
+static int pci_tegra_write_config(struct udevice *bus, pci_dev_t bdf,
+				  uint offset, ulong value,
+				  enum pci_size_t size)
 {
-	struct tegra_pcie *pcie = to_tegra_pcie(hose);
+	struct tegra_pcie *pcie = dev_get_priv(bus);
 	unsigned long address;
+	ulong old;
 	int err;
 
-	err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+	err = tegra_pcie_conf_address(pcie, bdf, offset, &address);
 	if (err < 0)
-		return 1;
+		return 0;
 
+	old = readl(address);
+	value = pci_conv_size_to_32(old, value, offset, size);
 	writel(value, address);
 
 	return 0;
@@ -348,12 +352,10 @@ static int tegra_pcie_port_parse_dt(const void *fdt, int node,
 }
 
 static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
-				      unsigned long *xbar)
+				      enum tegra_pci_id id, unsigned long *xbar)
 {
-	enum fdt_compat_id id = fdtdec_lookup(fdt, node);
-
 	switch (id) {
-	case COMPAT_NVIDIA_TEGRA20_PCIE:
+	case TEGRA20_PCIE:
 		switch (lanes) {
 		case 0x00000004:
 			debug("single-mode configuration\n");
@@ -366,8 +368,7 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
 			return 0;
 		}
 		break;
-
-	case COMPAT_NVIDIA_TEGRA30_PCIE:
+	case TEGRA30_PCIE:
 		switch (lanes) {
 		case 0x00000204:
 			debug("4x1, 2x1 configuration\n");
@@ -385,9 +386,8 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
 			return 0;
 		}
 		break;
-
-	case COMPAT_NVIDIA_TEGRA124_PCIE:
-	case COMPAT_NVIDIA_TEGRA210_PCIE:
+	case TEGRA124_PCIE:
+	case TEGRA210_PCIE:
 		switch (lanes) {
 		case 0x0000104:
 			debug("4x1, 1x1 configuration\n");
@@ -400,7 +400,6 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
 			return 0;
 		}
 		break;
-
 	default:
 		break;
 	}
@@ -408,84 +407,6 @@ static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
 	return -FDT_ERR_NOTFOUND;
 }
 
-static int tegra_pcie_parse_dt_ranges(const void *fdt, int node,
-				      struct tegra_pcie *pcie)
-{
-	int parent, na_parent, na_pcie, ns_pcie;
-	const u32 *ptr, *end;
-	int len;
-
-	parent = fdt_parent_offset(fdt, node);
-	if (parent < 0) {
-		error("Can't find PCI parent node\n");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	na_parent = fdt_address_cells(fdt, parent);
-	if (na_parent < 1) {
-		error("bad #address-cells for PCIE parent\n");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	na_pcie = fdt_address_cells(fdt, node);
-	if (na_pcie < 1) {
-		error("bad #address-cells for PCIE\n");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	ns_pcie = fdt_size_cells(fdt, node);
-	if (ns_pcie < 1) {
-		error("bad #size-cells for PCIE\n");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	ptr = fdt_getprop(fdt, node, "ranges", &len);
-	if (!ptr) {
-		error("missing \"ranges\" property");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	end = ptr + len / 4;
-
-	while (ptr < end) {
-		struct fdt_resource *res = NULL;
-		u32 space = fdt32_to_cpu(*ptr);
-
-		switch ((space >> 24) & 0x3) {
-		case 0x01:
-			res = &pcie->io;
-			break;
-
-		case 0x02: /* 32 bit */
-		case 0x03: /* 64 bit */
-			if (space & (1 << 30))
-				res = &pcie->prefetch;
-			else
-				res = &pcie->mem;
-
-			break;
-		}
-
-		if (res) {
-			int start_low = na_pcie + (na_parent - 1);
-			int size_low = na_pcie + na_parent + (ns_pcie - 1);
-			res->start = fdt32_to_cpu(ptr[start_low]);
-			res->end = res->start + fdt32_to_cpu(ptr[size_low]);
-		}
-
-		ptr += na_pcie + na_parent + ns_pcie;
-	}
-
-	debug("PCI regions:\n");
-	debug("  I/O: %pa-%pa\n", &pcie->io.start, &pcie->io.end);
-	debug("  non-prefetchable memory: %pa-%pa\n", &pcie->mem.start,
-	      &pcie->mem.end);
-	debug("  prefetchable memory: %pa-%pa\n", &pcie->prefetch.start,
-	      &pcie->prefetch.end);
-
-	return 0;
-}
-
 static int tegra_pcie_parse_port_info(const void *fdt, int node,
 				      unsigned int *index,
 				      unsigned int *lanes)
@@ -512,7 +433,12 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
 	return 0;
 }
 
-static int tegra_pcie_parse_dt(const void *fdt, int node,
+int __weak tegra_pcie_board_init(void)
+{
+	return 0;
+}
+
+static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
 			       struct tegra_pcie *pcie)
 {
 	int err, subnode;
@@ -539,6 +465,8 @@ static int tegra_pcie_parse_dt(const void *fdt, int node,
 		return err;
 	}
 
+	tegra_pcie_board_init();
+
 	pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
 	if (pcie->phy) {
 		err = tegra_xusb_phy_prepare(pcie->phy);
@@ -548,12 +476,6 @@ static int tegra_pcie_parse_dt(const void *fdt, int node,
 		}
 	}
 
-	err = tegra_pcie_parse_dt_ranges(fdt, node, pcie);
-	if (err < 0) {
-		error("failed to parse \"ranges\" property");
-		return err;
-	}
-
 	fdt_for_each_subnode(fdt, subnode, node) {
 		unsigned int index = 0, num_lanes = 0;
 		struct tegra_pcie_port *port;
@@ -588,7 +510,7 @@ static int tegra_pcie_parse_dt(const void *fdt, int node,
 		port->pcie = pcie;
 	}
 
-	err = tegra_pcie_get_xbar_config(fdt, node, lanes, &pcie->xbar);
+	err = tegra_pcie_get_xbar_config(fdt, node, lanes, id, &pcie->xbar);
 	if (err < 0) {
 		error("invalid lane configuration");
 		return err;
@@ -597,11 +519,6 @@ static int tegra_pcie_parse_dt(const void *fdt, int node,
 	return 0;
 }
 
-int __weak tegra_pcie_board_init(void)
-{
-	return 0;
-}
-
 static int tegra_pcie_power_on(struct tegra_pcie *pcie)
 {
 	const struct tegra_pcie_soc *soc = pcie->soc;
@@ -788,9 +705,12 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
 	return 0;
 }
 
-static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
+static int tegra_pcie_setup_translations(struct udevice *bus)
 {
+	struct tegra_pcie *pcie = dev_get_priv(bus);
 	unsigned long fpci, axi, size;
+	struct pci_region *io, *mem, *pref;
+	int count;
 
 	/* BAR 0: type 1 extended configuration space */
 	fpci = 0xfe100000;
@@ -801,28 +721,32 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ);
 	afi_writel(pcie, fpci, AFI_FPCI_BAR0);
 
+	count = pci_get_regions(bus, &io, &mem, &pref);
+	if (count != 3)
+		return -EINVAL;
+
 	/* BAR 1: downstream I/O */
 	fpci = 0xfdfc0000;
-	size = fdt_resource_size(&pcie->io);
-	axi = pcie->io.start;
+	size = io->size;
+	axi = io->phys_start;
 
 	afi_writel(pcie, axi, AFI_AXI_BAR1_START);
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
 	afi_writel(pcie, fpci, AFI_FPCI_BAR1);
 
 	/* BAR 2: prefetchable memory */
-	fpci = (((pcie->prefetch.start >> 12) & 0x0fffffff) << 4) | 0x1;
-	size = fdt_resource_size(&pcie->prefetch);
-	axi = pcie->prefetch.start;
+	fpci = (((pref->phys_start >> 12) & 0x0fffffff) << 4) | 0x1;
+	size = pref->size;
+	axi = pref->phys_start;
 
 	afi_writel(pcie, axi, AFI_AXI_BAR2_START);
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ);
 	afi_writel(pcie, fpci, AFI_FPCI_BAR2);
 
 	/* BAR 3: non-prefetchable memory */
-	fpci = (((pcie->mem.start >> 12) & 0x0fffffff) << 4) | 0x1;
-	size = fdt_resource_size(&pcie->mem);
-	axi = pcie->mem.start;
+	fpci = (((mem->phys_start >> 12) & 0x0fffffff) << 4) | 0x1;
+	size = mem->size;
+	axi = mem->phys_start;
 
 	afi_writel(pcie, axi, AFI_AXI_BAR3_START);
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ);
@@ -848,6 +772,8 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 	afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
 	afi_writel(pcie, 0, AFI_MSI_AXI_BAR_ST);
 	afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
+
+	return 0;
 }
 
 static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
@@ -1001,209 +927,116 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie)
 	return 0;
 }
 
-static const struct tegra_pcie_soc tegra20_pcie_soc = {
-	.num_ports = 2,
-	.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
-	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
-	.has_pex_clkreq_en = false,
-	.has_pex_bias_ctrl = false,
-	.has_cml_clk = false,
-	.has_gen2 = false,
-	.force_pca_enable = false,
-};
-
-static const struct tegra_pcie_soc tegra30_pcie_soc = {
-	.num_ports = 3,
-	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
-	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
-	.has_pex_clkreq_en = true,
-	.has_pex_bias_ctrl = true,
-	.has_cml_clk = true,
-	.has_gen2 = false,
-	.force_pca_enable = false,
-};
-
-static const struct tegra_pcie_soc tegra124_pcie_soc = {
-	.num_ports = 2,
-	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
-	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
-	.has_pex_clkreq_en = true,
-	.has_pex_bias_ctrl = true,
-	.has_cml_clk = true,
-	.has_gen2 = true,
-	.force_pca_enable = false,
-};
-
-static const struct tegra_pcie_soc tegra210_pcie_soc = {
-	.num_ports = 2,
-	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
-	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
-	.has_pex_clkreq_en = true,
-	.has_pex_bias_ctrl = true,
-	.has_cml_clk = true,
-	.has_gen2 = true,
-	.force_pca_enable = true,
+static const struct tegra_pcie_soc pci_tegra_soc[] = {
+	[TEGRA20_PCIE] = {
+		.num_ports = 2,
+		.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
+		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
+		.has_pex_clkreq_en = false,
+		.has_pex_bias_ctrl = false,
+		.has_cml_clk = false,
+		.has_gen2 = false,
+	},
+	[TEGRA30_PCIE] = {
+		.num_ports = 3,
+		.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+		.has_pex_clkreq_en = true,
+		.has_pex_bias_ctrl = true,
+		.has_cml_clk = true,
+		.has_gen2 = false,
+	},
+	[TEGRA124_PCIE] = {
+		.num_ports = 2,
+		.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+		.has_pex_clkreq_en = true,
+		.has_pex_bias_ctrl = true,
+		.has_cml_clk = true,
+		.has_gen2 = true,
+	},
+	[TEGRA210_PCIE] = {
+		.num_ports = 2,
+		.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+		.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+		.has_pex_clkreq_en = true,
+		.has_pex_bias_ctrl = true,
+		.has_cml_clk = true,
+		.has_gen2 = true,
+		.force_pca_enable = true,
+	}
 };
 
-static int process_nodes(const void *fdt, int nodes[], unsigned int count)
+static int pci_tegra_ofdata_to_platdata(struct udevice *dev)
 {
-	unsigned int i;
-	uint64_t dram_end;
-	uint32_t pci_dram_size;
-
-	/* Clip PCI-accessible DRAM to 32-bits */
-	dram_end = ((uint64_t)NV_PA_SDRAM_BASE) + gd->ram_size;
-	if (dram_end > 0x100000000)
-		dram_end = 0x100000000;
-	pci_dram_size = dram_end - NV_PA_SDRAM_BASE;
-
-	for (i = 0; i < count; i++) {
-		const struct tegra_pcie_soc *soc;
-		struct tegra_pcie *pcie;
-		enum fdt_compat_id id;
-		int err;
-
-		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
-			continue;
-
-		id = fdtdec_lookup(fdt, nodes[i]);
-		switch (id) {
-		case COMPAT_NVIDIA_TEGRA20_PCIE:
-			soc = &tegra20_pcie_soc;
-			break;
-
-		case COMPAT_NVIDIA_TEGRA30_PCIE:
-			soc = &tegra30_pcie_soc;
-			break;
-
-		case COMPAT_NVIDIA_TEGRA124_PCIE:
-			soc = &tegra124_pcie_soc;
-			break;
-
-		case COMPAT_NVIDIA_TEGRA210_PCIE:
-			soc = &tegra210_pcie_soc;
-			break;
-
-		default:
-			error("unsupported compatible: %s",
-			      fdtdec_get_compatible(id));
-			continue;
-		}
-
-		pcie = malloc(sizeof(*pcie));
-		if (!pcie) {
-			error("failed to allocate controller");
-			continue;
-		}
-
-		memset(pcie, 0, sizeof(*pcie));
-		pcie->soc = soc;
-
-		INIT_LIST_HEAD(&pcie->ports);
-
-		err = tegra_pcie_parse_dt(fdt, nodes[i], pcie);
-		if (err < 0) {
-			free(pcie);
-			continue;
-		}
-
-		err = tegra_pcie_power_on(pcie);
-		if (err < 0) {
-			error("failed to power on");
-			continue;
-		}
+	struct tegra_pcie *pcie = dev_get_priv(dev);
+	enum tegra_pci_id id;
 
-		err = tegra_pcie_enable_controller(pcie);
-		if (err < 0) {
-			error("failed to enable controller");
-			continue;
-		}
-
-		tegra_pcie_setup_translations(pcie);
-
-		err = tegra_pcie_enable(pcie);
-		if (err < 0) {
-			error("failed to enable PCIe");
-			continue;
-		}
+	id = dev_get_driver_data(dev);
+	pcie->soc = &pci_tegra_soc[id];
 
-		pcie->hose.first_busno = 0;
-		pcie->hose.current_busno = 0;
-		pcie->hose.last_busno = 0;
+	INIT_LIST_HEAD(&pcie->ports);
 
-		pci_set_region(&pcie->hose.regions[0], NV_PA_SDRAM_BASE,
-			       NV_PA_SDRAM_BASE, pci_dram_size,
-			       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+	if (tegra_pcie_parse_dt(gd->fdt_blob, dev->of_offset, id, pcie))
+		return -EINVAL;
 
-		pci_set_region(&pcie->hose.regions[1], pcie->io.start,
-			       pcie->io.start, fdt_resource_size(&pcie->io),
-			       PCI_REGION_IO);
-
-		pci_set_region(&pcie->hose.regions[2], pcie->mem.start,
-			       pcie->mem.start, fdt_resource_size(&pcie->mem),
-			       PCI_REGION_MEM);
-
-		pci_set_region(&pcie->hose.regions[3], pcie->prefetch.start,
-			       pcie->prefetch.start,
-			       fdt_resource_size(&pcie->prefetch),
-			       PCI_REGION_MEM | PCI_REGION_PREFETCH);
+	return 0;
+}
 
-		pcie->hose.region_count = 4;
+static int pci_tegra_probe(struct udevice *dev)
+{
+	struct tegra_pcie *pcie = dev_get_priv(dev);
+	int err;
 
-		pci_set_ops(&pcie->hose,
-			    pci_hose_read_config_byte_via_dword,
-			    pci_hose_read_config_word_via_dword,
-			    tegra_pcie_read_conf,
-			    pci_hose_write_config_byte_via_dword,
-			    pci_hose_write_config_word_via_dword,
-			    tegra_pcie_write_conf);
+	err = tegra_pcie_power_on(pcie);
+	if (err < 0) {
+		error("failed to power on");
+		return err;
+	}
 
-		pci_register_hose(&pcie->hose);
+	err = tegra_pcie_enable_controller(pcie);
+	if (err < 0) {
+		error("failed to enable controller");
+		return err;
+	}
 
-#ifdef CONFIG_PCI_SCAN_SHOW
-		printf("PCI: Enumerating devices...\n");
-		printf("---------------------------------------\n");
-		printf("  Device        ID          Description\n");
-		printf("  ------        --          -----------\n");
-#endif
+	err = tegra_pcie_setup_translations(dev);
+	if (err < 0) {
+		error("failed to decode ranges");
+		return err;
+	}
 
-		pcie->hose.last_busno = pci_hose_scan(&pcie->hose);
+	err = tegra_pcie_enable(pcie);
+	if (err < 0) {
+		error("failed to enable PCIe");
+		return err;
 	}
 
 	return 0;
 }
 
-void pci_init_board(void)
-{
-	const void *fdt = gd->fdt_blob;
-	int count, nodes[1];
+static const struct dm_pci_ops pci_tegra_ops = {
+	.read_config	= pci_tegra_read_config,
+	.write_config	= pci_tegra_write_config,
+};
 
-	tegra_pcie_board_init();
+static const struct udevice_id pci_tegra_ids[] = {
+	{ .compatible = "nvidia,tegra20-pcie", .data = TEGRA20_PCIE },
+	{ .compatible = "nvidia,tegra30-pcie", .data = TEGRA30_PCIE },
+	{ .compatible = "nvidia,tegra124-pcie", .data = TEGRA124_PCIE },
+	{ .compatible = "nvidia,tegra210-pcie", .data = TEGRA210_PCIE },
+	{ }
+};
 
-	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
-					   COMPAT_NVIDIA_TEGRA210_PCIE,
-					   nodes, ARRAY_SIZE(nodes));
-	if (process_nodes(fdt, nodes, count))
-		return;
-
-	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
-					   COMPAT_NVIDIA_TEGRA124_PCIE,
-					   nodes, ARRAY_SIZE(nodes));
-	if (process_nodes(fdt, nodes, count))
-		return;
-
-	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
-					   COMPAT_NVIDIA_TEGRA30_PCIE,
-					   nodes, ARRAY_SIZE(nodes));
-	if (process_nodes(fdt, nodes, count))
-		return;
-
-	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
-					   COMPAT_NVIDIA_TEGRA20_PCIE,
-					   nodes, ARRAY_SIZE(nodes));
-	if (process_nodes(fdt, nodes, count))
-		return;
-}
+U_BOOT_DRIVER(pci_tegra) = {
+	.name	= "pci_tegra",
+	.id	= UCLASS_PCI,
+	.of_match = pci_tegra_ids,
+	.ops	= &pci_tegra_ops,
+	.ofdata_to_platdata = pci_tegra_ofdata_to_platdata,
+	.probe	= pci_tegra_probe,
+	.priv_auto_alloc_size = sizeof(struct tegra_pcie),
+};
 
 int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
 {
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 79826d78fad2244b6a517f5db5a5291ad6316652..7fe657d0a0cdbad0d14fb810abfeff8af8fe0893 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -128,10 +128,6 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA124_SDMMC,	/* Tegra124 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA30_SDMMC,	/* Tegra30 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA20_SDMMC,	/* Tegra20 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA124_PCIE,	/* Tegra 124 PCIe controller */
-	COMPAT_NVIDIA_TEGRA210_PCIE,	/* Tegra 210 PCIe controller */
-	COMPAT_NVIDIA_TEGRA30_PCIE,	/* Tegra 30 PCIe controller */
-	COMPAT_NVIDIA_TEGRA20_PCIE,	/* Tegra 20 PCIe controller */
 	COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
 					/* Tegra124 XUSB pad controller */
 	COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index e0e6bb48fa40424c2cd278e67ea7c3c000a8329b..82d0090f8acf115509b4697d0f23536743cf6c11 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -34,10 +34,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
 	COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
 	COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
-	COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
-	COMPAT(NVIDIA_TEGRA210_PCIE, "nvidia,tegra210-pcie"),
-	COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
-	COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
 	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),