|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|