Merge with git://git.kernel.org/pub/scm/boot/u-boot/u-boot.git#pci

This commit is contained in:
Wolfgang Denk 2006-03-12 21:31:38 +01:00
commit 7b230f61db
5 changed files with 86 additions and 11 deletions

View File

@ -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 helper function for generic flat device tree fixups for mpc83xx
Patch by Kumar Gala, 11 Jan 2006

View File

@ -459,6 +459,7 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus)
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);

View File

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

View File

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

View File

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