[U-Boot-Users] [git patch] pci

Kumar Gala galak at gate.crashing.org
Tue Jan 24 00:45:13 CET 2006


Please pull from 'pci' branch of
git.kernel.org:/pub/scm/boot/u-boot/u-boot.git

to receive the following updates:

 CHANGELOG              |   18 +++++++++++++++
 drivers/pci.c          |    1 
 drivers/pci_auto.c     |   58 ++++++++++++++++++++++++++++++++++++++++---------
 drivers/pci_indirect.c |   16 +++++++++++++
 include/pci.h          |    4 ++-
 5 files changed, 86 insertions(+), 11 deletions(-)

Kumar Gala:
      Added support for PCI prefetchable region and BARs
      Report back PCI bus when doing table based device config
      Fixed PCI indirect config ops to handle multiple PCI controllers

diff --git a/CHANGELOG b/CHANGELOG
index c1da98f..9ed9dff 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,24 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Fixed PCI indirect config ops to handle multiple PCI controllers
+  We need to adjust the bus number we are trying to access based
+  on which PCI controller its on
+  Patch by Kumar Gala 12 Jan 2006
+
+* Report back PCI bus when doing table based device config
+  Patch by Kumar Gala 11 Jan 2006
+
+* 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.c b/drivers/pci.c
index 5360030..3c24b99 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -459,6 +459,7 @@ int pci_hose_scan_bus(struct pci_control
 					      PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
 			if (cfg) {
 				cfg->config_device(hose, dev, cfg);
+				sub_bus = max(sub_bus, hose->current_busno);
 #ifdef CONFIG_PCI_PNP
 			} else {
 				int n = pciauto_config_device(hose, dev);
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
index 3302457..15f7432 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci_auto.c
@@ -77,6 +77,7 @@ int pciauto_region_allocate(struct pci_r
 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_con
 				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
 					 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
 		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
 		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_bridg
 					  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_bridg
 					(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_cont
 			    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_cont
 		    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_con
 	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_con
 			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_con
 		 * 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/drivers/pci_indirect.c b/drivers/pci_indirect.c
index e8f19f5..f0c4a1c 100644
--- a/drivers/pci_indirect.c
+++ b/drivers/pci_indirect.c
@@ -36,6 +36,10 @@ static int								 \
 indirect_##rw##_config_##size(struct pci_controller *hose, 		 \
 			      pci_dev_t dev, int offset, type val)	 \
 {									 \
+	u32 b, d,f;							 \
+	b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev);		 \
+	b = b - hose->first_busno;					 \
+	dev = PCI_BDF(b, d, f);						 \
 	out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); 	 \
 	sync();								 \
 	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \
@@ -47,6 +51,10 @@ static int                              
 indirect_##rw##_config_##size(struct pci_controller *hose,               \
 			      pci_dev_t dev, int offset, type val)       \
 {                                                                        \
+	u32 b, d,f;							 \
+	b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev);		 \
+	b = b - hose->first_busno;					 \
+	dev = PCI_BDF(b, d, f);						 \
 	*(hose->cfg_addr) = dev | (offset & 0xfc) | 0x80000000;          \
 	sync();                                                          \
 	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);       \
@@ -58,6 +66,10 @@ static int								 \
 indirect_##rw##_config_##size(struct pci_controller *hose, 		 \
 			      pci_dev_t dev, int offset, type val)	 \
 {									 \
+	u32 b, d,f;							 \
+	b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev);		 \
+	b = b - hose->first_busno;					 \
+	dev = PCI_BDF(b, d, f);						 \
 	if (PCI_BUS(dev) > 0)                                            \
 		out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000001); \
 	else                                                             \
@@ -71,6 +83,10 @@ static int								 \
 indirect_##rw##_config_##size(struct pci_controller *hose, 		 \
 			      pci_dev_t dev, int offset, type val)	 \
 {									 \
+	u32 b, d,f;							 \
+	b = PCI_BUS(dev); d = PCI_DEV(dev); f = PCI_FUNC(dev);		 \
+	b = b - hose->first_busno;					 \
+	dev = PCI_BDF(b, d, f);						 \
 	out_le32(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); 	 \
 	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \
 	return 0;    					 		 \
diff --git a/include/pci.h b/include/pci.h
index 8f19997..f78a769 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(struc
 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);
 





More information about the U-Boot mailing list