diff options
| -rw-r--r-- | CHANGELOG | 10 | ||||
| -rw-r--r-- | drivers/pci_auto.c | 58 | ||||
| -rw-r--r-- | include/pci.h | 4 | 
3 files changed, 61 insertions, 11 deletions
@@ -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 3302457a3..15f74328f 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 8f1999755..f78a769bb 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);  |