diff --git a/CHANGELOG b/CHANGELOG
index c1da98fc510ff38ad2ab83cdfd3b759848990631..60d29aca79d72bca42096b6682c5b7c0c0e52249 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,16 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Added support for PCI prefetchable region and BARs
+  If a host controller sets up a region as prefetchable and
+  a device's BAR denotes it as prefetchable, allocate the
+  BAR into the prefetch region.
+
+  If a BAR is prefetchable and no prefetchable region has
+  been setup by the controller we fall back to allocating
+  the BAR into the normally memory region.
+  Patch by Kumar Gala 11 Jan 2006
+
 * Add support for 28F256J3A flah (=> 64 MB) on PM520 board
 
 * Fix compiler problem with at91rm9200dk board.
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
index 3302457a3909dc1590d4a8961ddeb6a8c9200be0..15f74328f0a6a011c58cd425c56cb3a561dd1c98 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci_auto.c
@@ -77,6 +77,7 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned
 void pciauto_setup_device(struct pci_controller *hose,
 			  pci_dev_t dev, int bars_num,
 			  struct pci_region *mem,
+			  struct pci_region *prefetch,
 			  struct pci_region *io)
 {
 	unsigned int bar_value, bar_response, bar_size;
@@ -111,7 +112,10 @@ void pciauto_setup_device(struct pci_controller *hose,
 				found_mem64 = 1;
 
 			bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1;
-			bar_res = mem;
+			if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH))
+				bar_res = prefetch;
+			else
+				bar_res = mem;
 
 			DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size);
 		}
@@ -148,6 +152,7 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 					 pci_dev_t dev, int sub_bus)
 {
 	struct pci_region *pci_mem = hose->pci_mem;
+	struct pci_region *pci_prefetch = hose->pci_prefetch;
 	struct pci_region *pci_io = hose->pci_io;
 	unsigned int cmdstat;
 
@@ -169,6 +174,21 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 		cmdstat |= PCI_COMMAND_MEMORY;
 	}
 
+	if (pci_prefetch) {
+		/* Round memory allocator to 1MB boundary */
+		pciauto_region_align(pci_prefetch, 0x100000);
+
+		/* Set up memory and I/O filter limits, assume 32-bit I/O space */
+		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
+					(pci_prefetch->bus_lower & 0xfff00000) >> 16);
+
+		cmdstat |= PCI_COMMAND_MEMORY;
+	} else {
+		/* We don't support prefetchable memory for now, so disable */
+		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
+		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000);
+	}
+
 	if (pci_io) {
 		/* Round I/O allocator to 4KB boundary */
 		pciauto_region_align(pci_io, 0x1000);
@@ -181,10 +201,6 @@ static void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 		cmdstat |= PCI_COMMAND_IO;
 	}
 
-	/* We don't support prefetchable memory for now, so disable */
-	pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
-	pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000);
-
 	/* Enable memory and I/O accesses, enable bus master */
 	pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER);
 }
@@ -193,6 +209,7 @@ static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
 					  pci_dev_t dev, int sub_bus)
 {
 	struct pci_region *pci_mem = hose->pci_mem;
+	struct pci_region *pci_prefetch = hose->pci_prefetch;
 	struct pci_region *pci_io = hose->pci_io;
 
 	/* Configure bus number registers */
@@ -206,6 +223,14 @@ static void pciauto_postscan_setup_bridge(struct pci_controller *hose,
 					(pci_mem->bus_lower-1) >> 16);
 	}
 
+	if (pci_prefetch) {
+		/* Round memory allocator to 1MB boundary */
+		pciauto_region_align(pci_prefetch, 0x100000);
+
+		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
+					(pci_prefetch->bus_lower-1) >> 16);
+	}
+
 	if (pci_io) {
 		/* Round I/O allocator to 4KB boundary */
 		pciauto_region_align(pci_io, 0x1000);
@@ -239,6 +264,11 @@ void pciauto_config_init(struct pci_controller *hose)
 			    hose->pci_mem->size < hose->regions[i].size)
 				hose->pci_mem = hose->regions + i;
 			break;
+		case (PCI_REGION_MEM | PCI_REGION_PREFETCH):
+			if (!hose->pci_prefetch ||
+			    hose->pci_prefetch->size < hose->regions[i].size)
+				hose->pci_prefetch = hose->regions + i;
+			break;
 		}
 	}
 
@@ -251,6 +281,14 @@ void pciauto_config_init(struct pci_controller *hose)
 		    hose->pci_mem->bus_start + hose->pci_mem->size - 1);
 	}
 
+	if (hose->pci_prefetch) {
+		pciauto_region_init(hose->pci_prefetch);
+
+		DEBUGF("PCI Autoconfig: Prefetchable Memory region: [%lx-%lx]\n",
+		    hose->pci_prefetch->bus_start,
+		    hose->pci_prefetch->bus_start + hose->pci_prefetch->size - 1);
+	}
+
 	if (hose->pci_io) {
 		pciauto_region_init(hose->pci_io);
 
@@ -275,7 +313,7 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
 	switch(class) {
 	case PCI_CLASS_BRIDGE_PCI:
 		hose->current_busno++;
-		pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);
+		pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
 
 		DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));
 
@@ -301,12 +339,12 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
 			return sub_bus;
 		}
 
-		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
 		break;
 
 	case PCI_CLASS_BRIDGE_CARDBUS:
 		/* just do a minimal setup of the bridge, let the OS take care of the rest */
-		pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io);
+		pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
 
 		DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n", PCI_DEV(dev));
 
@@ -328,11 +366,11 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
 		 * the PIMMR window to be allocated (BAR0 - 1MB size)
 		 */
 		DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n");
-		pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io);
+		pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
 		break;
 #endif
 	default:
-		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
 		break;
 	}
 
diff --git a/include/pci.h b/include/pci.h
index 8f19997559228d61b25dd84a883fd78fba635cfb..f78a769bb1f9e4f4f3dae0f9a8c418eabcad3767 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -309,6 +309,7 @@ struct pci_region {
 #define PCI_REGION_MEM		0x00000000	/* PCI memory space */
 #define PCI_REGION_IO		0x00000001	/* PCI IO space */
 #define PCI_REGION_TYPE		0x00000001
+#define PCI_REGION_PREFETCH	0x00000008	/* prefetchable PCI memory */
 
 #define PCI_REGION_MEMORY	0x00000100	/* System memory */
 #define PCI_REGION_RO		0x00000200	/* Read-only memory */
@@ -386,7 +387,7 @@ struct pci_controller {
 	int (*write_dword)(struct pci_controller*, pci_dev_t, int where, u32);
 
 	/* Used by auto config */
-	struct pci_region *pci_mem, *pci_io;
+	struct pci_region *pci_mem, *pci_io, *pci_prefetch;
 
 	/* Used by ppc405 autoconfig*/
 	struct pci_region *pci_fb;
@@ -472,6 +473,7 @@ extern int pciauto_region_allocate(struct pci_region* res, unsigned int size, un
 extern void pciauto_setup_device(struct pci_controller *hose,
 				 pci_dev_t dev, int bars_num,
 				 struct pci_region *mem,
+				 struct pci_region *prefetch,
 				 struct pci_region *io);
 int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);