2002-11-03 00:24:07 +00:00
|
|
|
/*
|
2010-04-15 14:07:28 +00:00
|
|
|
* arch/powerpc/kernel/pci_auto.c
|
2002-11-03 00:24:07 +00:00
|
|
|
*
|
|
|
|
* PCI autoconfiguration library
|
|
|
|
*
|
|
|
|
* Author: Matt Porter <mporter@mvista.com>
|
|
|
|
*
|
|
|
|
* Copyright 2000 MontaVista Software Inc.
|
|
|
|
*
|
2013-07-08 07:37:19 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
2002-11-03 00:24:07 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
2015-01-15 04:37:04 +00:00
|
|
|
#include <errno.h>
|
2002-11-03 00:24:07 +00:00
|
|
|
#include <pci.h>
|
|
|
|
|
2008-10-16 13:01:15 +00:00
|
|
|
/* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */
|
|
|
|
#ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE
|
|
|
|
#define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8
|
2007-08-31 13:21:46 +00:00
|
|
|
#endif
|
|
|
|
|
2002-11-03 00:24:07 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
void pciauto_region_init(struct pci_region *res)
|
2002-11-03 00:24:07 +00:00
|
|
|
{
|
2007-04-23 13:30:39 +00:00
|
|
|
/*
|
|
|
|
* Avoid allocating PCI resources from address 0 -- this is illegal
|
|
|
|
* according to PCI 2.1 and moreover, this is known to cause Linux IDE
|
|
|
|
* drivers to fail. Use a reasonable starting value of 0x1000 instead.
|
|
|
|
*/
|
|
|
|
res->bus_lower = res->bus_start ? res->bus_start : 0x1000;
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2008-10-21 13:36:08 +00:00
|
|
|
void pciauto_region_align(struct pci_region *res, pci_size_t size)
|
2002-11-03 00:24:07 +00:00
|
|
|
{
|
|
|
|
res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1;
|
|
|
|
}
|
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
int pciauto_region_allocate(struct pci_region *res, pci_size_t size,
|
|
|
|
pci_addr_t *bar)
|
2002-11-03 00:24:07 +00:00
|
|
|
{
|
2008-10-21 13:36:08 +00:00
|
|
|
pci_addr_t addr;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (!res) {
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("No resource");
|
2002-11-03 00:24:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr = ((res->bus_lower - 1) | (size - 1)) + 1;
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (addr - res->bus_start + size > res->size) {
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("No room in resource");
|
2002-11-03 00:24:07 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
res->bus_lower = addr + size;
|
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("address=0x%llx bus_lower=0x%llx", (unsigned long long)addr,
|
|
|
|
(unsigned long long)res->bus_lower);
|
2002-11-03 00:24:07 +00:00
|
|
|
|
|
|
|
*bar = addr;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2008-10-21 13:36:08 +00:00
|
|
|
*bar = (pci_addr_t)-1;
|
2002-11-03 00:24:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
void pciauto_setup_device(struct pci_controller *hose,
|
|
|
|
pci_dev_t dev, int bars_num,
|
|
|
|
struct pci_region *mem,
|
2006-01-11 19:24:15 +00:00
|
|
|
struct pci_region *prefetch,
|
2002-11-03 00:24:07 +00:00
|
|
|
struct pci_region *io)
|
|
|
|
{
|
2012-09-19 04:47:36 +00:00
|
|
|
u32 bar_response;
|
2008-10-21 13:36:08 +00:00
|
|
|
pci_size_t bar_size;
|
2012-08-01 12:27:16 +00:00
|
|
|
u16 cmdstat = 0;
|
2002-11-03 00:24:07 +00:00
|
|
|
int bar, bar_nr = 0;
|
2015-07-31 15:31:34 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2015-07-08 05:06:40 +00:00
|
|
|
u8 header_type;
|
|
|
|
int rom_addr;
|
2012-08-29 14:16:32 +00:00
|
|
|
pci_addr_t bar_value;
|
|
|
|
struct pci_region *bar_res;
|
2002-11-03 00:24:07 +00:00
|
|
|
int found_mem64 = 0;
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2012-08-01 12:27:16 +00:00
|
|
|
pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
|
2002-11-03 00:24:07 +00:00
|
|
|
cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
|
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
for (bar = PCI_BASE_ADDRESS_0;
|
|
|
|
bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Tickle the BAR and get the response */
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_read_config_dword(hose, dev, bar, &bar_response);
|
|
|
|
|
|
|
|
/* If BAR is not implemented go to the next BAR */
|
|
|
|
if (!bar_response)
|
|
|
|
continue;
|
|
|
|
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2002-11-03 00:24:07 +00:00
|
|
|
found_mem64 = 0;
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
|
|
|
/* Check the BAR type and set our address mask */
|
2004-02-22 23:46:08 +00:00
|
|
|
if (bar_response & PCI_BASE_ADDRESS_SPACE) {
|
2006-06-27 10:12:02 +00:00
|
|
|
bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
|
|
|
|
& 0xffff) + 1;
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2002-11-03 00:24:07 +00:00
|
|
|
bar_res = io;
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
|
|
|
|
bar_nr, (unsigned long long)bar_size);
|
2004-02-22 23:46:08 +00:00
|
|
|
} else {
|
2012-08-29 14:16:29 +00:00
|
|
|
if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
|
2008-10-21 13:36:08 +00:00
|
|
|
PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
|
|
|
u32 bar_response_upper;
|
|
|
|
u64 bar64;
|
2012-08-29 14:16:32 +00:00
|
|
|
|
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2012-08-29 14:16:29 +00:00
|
|
|
pci_hose_write_config_dword(hose, dev, bar + 4,
|
|
|
|
0xffffffff);
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2012-08-29 14:16:29 +00:00
|
|
|
pci_hose_read_config_dword(hose, dev, bar + 4,
|
|
|
|
&bar_response_upper);
|
2008-10-21 13:36:08 +00:00
|
|
|
|
|
|
|
bar64 = ((u64)bar_response_upper << 32) | bar_response;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2008-10-21 13:36:08 +00:00
|
|
|
bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2008-10-21 13:36:08 +00:00
|
|
|
found_mem64 = 1;
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2008-10-21 13:36:08 +00:00
|
|
|
} else {
|
|
|
|
bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
|
|
|
|
}
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2006-01-11 19:24:15 +00:00
|
|
|
if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH))
|
|
|
|
bar_res = prefetch;
|
|
|
|
else
|
|
|
|
bar_res = mem;
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2015-07-27 21:47:18 +00:00
|
|
|
debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
|
|
|
|
bar_nr, bar_res == prefetch ? "Prf" : "Mem",
|
|
|
|
(unsigned long long)bar_size);
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2012-08-29 14:16:32 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2004-02-22 23:46:08 +00:00
|
|
|
if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Write it out and update our limit */
|
2008-10-21 13:36:08 +00:00
|
|
|
pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value);
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (found_mem64) {
|
2002-11-03 00:24:07 +00:00
|
|
|
bar += 4;
|
2008-10-21 13:36:08 +00:00
|
|
|
#ifdef CONFIG_SYS_PCI_64BIT
|
|
|
|
pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* If we are a 64-bit decoder then increment to the
|
|
|
|
* upper 32 bits of the bar and force it to locate
|
|
|
|
* in the lower 4GB of memory.
|
|
|
|
*/
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
|
2008-10-21 13:36:08 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2012-08-29 14:16:32 +00:00
|
|
|
#endif
|
|
|
|
cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
|
|
|
|
PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("\n");
|
2002-11-03 00:24:07 +00:00
|
|
|
|
|
|
|
bar_nr++;
|
|
|
|
}
|
|
|
|
|
2015-07-31 15:31:34 +00:00
|
|
|
#ifndef CONFIG_PCI_ENUM_ONLY
|
2015-07-08 05:06:40 +00:00
|
|
|
/* Configure the expansion ROM address */
|
|
|
|
pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
|
|
|
|
if (header_type != PCI_HEADER_TYPE_CARDBUS) {
|
|
|
|
rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
|
|
|
|
PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
|
|
|
|
pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
|
|
|
|
pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
|
|
|
|
if (bar_response) {
|
|
|
|
bar_size = -(bar_response & ~1);
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: ROM, size=%#x, ",
|
|
|
|
(unsigned int)bar_size);
|
2015-07-08 05:06:40 +00:00
|
|
|
if (pciauto_region_allocate(mem, bar_size,
|
|
|
|
&bar_value) == 0) {
|
|
|
|
pci_hose_write_config_dword(hose, dev, rom_addr,
|
|
|
|
bar_value);
|
|
|
|
}
|
|
|
|
cmdstat |= PCI_COMMAND_MEMORY;
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("\n");
|
2015-07-08 05:06:40 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-31 15:31:34 +00:00
|
|
|
#endif
|
2015-07-08 05:06:40 +00:00
|
|
|
|
2012-08-01 12:27:16 +00:00
|
|
|
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
|
2007-08-31 13:21:46 +00:00
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
|
2008-10-16 13:01:15 +00:00
|
|
|
CONFIG_SYS_PCI_CACHE_LINE_SIZE);
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
|
|
|
|
}
|
|
|
|
|
2007-07-11 19:51:48 +00:00
|
|
|
void pciauto_prescan_setup_bridge(struct pci_controller *hose,
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_dev_t dev, int sub_bus)
|
|
|
|
{
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
struct pci_region *pci_mem;
|
|
|
|
struct pci_region *pci_prefetch;
|
|
|
|
struct pci_region *pci_io;
|
2015-02-02 08:53:13 +00:00
|
|
|
u16 cmdstat, prefechable_64;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
/* The root controller has the region information */
|
|
|
|
struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
|
|
|
|
|
|
|
|
pci_mem = ctlr_hose->pci_mem;
|
|
|
|
pci_prefetch = ctlr_hose->pci_prefetch;
|
|
|
|
pci_io = ctlr_hose->pci_io;
|
|
|
|
#else
|
|
|
|
pci_mem = hose->pci_mem;
|
|
|
|
pci_prefetch = hose->pci_prefetch;
|
|
|
|
pci_io = hose->pci_io;
|
|
|
|
#endif
|
|
|
|
|
2012-08-01 12:27:16 +00:00
|
|
|
pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
|
2015-02-02 08:53:13 +00:00
|
|
|
pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
|
|
|
|
&prefechable_64);
|
|
|
|
prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
|
|
|
/* Configure bus number registers */
|
2015-07-18 16:20:03 +00:00
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev));
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus);
|
|
|
|
#else
|
2007-07-11 19:52:08 +00:00
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
|
|
|
|
PCI_BUS(dev) - hose->first_busno);
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS,
|
|
|
|
sub_bus - hose->first_busno);
|
2015-07-18 16:20:03 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (pci_mem) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Round memory allocator to 1MB boundary */
|
|
|
|
pciauto_region_align(pci_mem, 0x100000);
|
|
|
|
|
|
|
|
/* Set up memory and I/O filter limits, assume 32-bit I/O space */
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE,
|
|
|
|
(pci_mem->bus_lower & 0xfff00000) >> 16);
|
|
|
|
|
|
|
|
cmdstat |= PCI_COMMAND_MEMORY;
|
|
|
|
}
|
|
|
|
|
2006-01-11 19:24:15 +00:00
|
|
|
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);
|
2015-02-02 08:53:13 +00:00
|
|
|
if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
|
|
|
|
#ifdef CONFIG_SYS_PCI_64BIT
|
|
|
|
pci_hose_write_config_dword(hose, dev,
|
|
|
|
PCI_PREF_BASE_UPPER32,
|
|
|
|
pci_prefetch->bus_lower >> 32);
|
|
|
|
#else
|
|
|
|
pci_hose_write_config_dword(hose, dev,
|
|
|
|
PCI_PREF_BASE_UPPER32,
|
|
|
|
0x0);
|
|
|
|
#endif
|
2006-01-11 19:24:15 +00:00
|
|
|
|
|
|
|
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);
|
2006-06-28 15:44:23 +00:00
|
|
|
pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0);
|
2015-02-02 08:53:13 +00:00
|
|
|
if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) {
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0);
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0);
|
|
|
|
}
|
2006-01-11 19:24:15 +00:00
|
|
|
}
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (pci_io) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Round I/O allocator to 4KB boundary */
|
|
|
|
pciauto_region_align(pci_io, 0x1000);
|
|
|
|
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_IO_BASE,
|
|
|
|
(pci_io->bus_lower & 0x0000f000) >> 8);
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16,
|
|
|
|
(pci_io->bus_lower & 0xffff0000) >> 16);
|
|
|
|
|
|
|
|
cmdstat |= PCI_COMMAND_IO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable memory and I/O accesses, enable bus master */
|
2012-08-01 12:27:16 +00:00
|
|
|
pci_hose_write_config_word(hose, dev, PCI_COMMAND,
|
|
|
|
cmdstat | PCI_COMMAND_MASTER);
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2007-07-11 19:51:48 +00:00
|
|
|
void pciauto_postscan_setup_bridge(struct pci_controller *hose,
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_dev_t dev, int sub_bus)
|
|
|
|
{
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
struct pci_region *pci_mem;
|
|
|
|
struct pci_region *pci_prefetch;
|
|
|
|
struct pci_region *pci_io;
|
|
|
|
|
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
/* The root controller has the region information */
|
|
|
|
struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
|
|
|
|
|
|
|
|
pci_mem = ctlr_hose->pci_mem;
|
|
|
|
pci_prefetch = ctlr_hose->pci_prefetch;
|
|
|
|
pci_io = ctlr_hose->pci_io;
|
|
|
|
#else
|
|
|
|
pci_mem = hose->pci_mem;
|
|
|
|
pci_prefetch = hose->pci_prefetch;
|
|
|
|
pci_io = hose->pci_io;
|
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
|
|
|
/* Configure bus number registers */
|
2015-07-18 16:20:03 +00:00
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus);
|
|
|
|
#else
|
2007-07-11 19:52:08 +00:00
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS,
|
|
|
|
sub_bus - hose->first_busno);
|
2015-07-18 16:20:03 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (pci_mem) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Round memory allocator to 1MB boundary */
|
|
|
|
pciauto_region_align(pci_mem, 0x100000);
|
|
|
|
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT,
|
2012-08-29 14:16:29 +00:00
|
|
|
(pci_mem->bus_lower - 1) >> 16);
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2006-01-11 19:24:15 +00:00
|
|
|
if (pci_prefetch) {
|
2015-02-02 08:53:13 +00:00
|
|
|
u16 prefechable_64;
|
|
|
|
|
|
|
|
pci_hose_read_config_word(hose, dev,
|
|
|
|
PCI_PREF_MEMORY_LIMIT,
|
|
|
|
&prefechable_64);
|
|
|
|
prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
|
|
|
|
|
2006-01-11 19:24:15 +00:00
|
|
|
/* Round memory allocator to 1MB boundary */
|
|
|
|
pciauto_region_align(pci_prefetch, 0x100000);
|
|
|
|
|
|
|
|
pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
|
2012-08-29 14:16:29 +00:00
|
|
|
(pci_prefetch->bus_lower - 1) >> 16);
|
2015-02-02 08:53:13 +00:00
|
|
|
if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
|
|
|
|
#ifdef CONFIG_SYS_PCI_64BIT
|
|
|
|
pci_hose_write_config_dword(hose, dev,
|
|
|
|
PCI_PREF_LIMIT_UPPER32,
|
|
|
|
(pci_prefetch->bus_lower - 1) >> 32);
|
|
|
|
#else
|
|
|
|
pci_hose_write_config_dword(hose, dev,
|
|
|
|
PCI_PREF_LIMIT_UPPER32,
|
|
|
|
0x0);
|
|
|
|
#endif
|
2006-01-11 19:24:15 +00:00
|
|
|
}
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (pci_io) {
|
2002-11-03 00:24:07 +00:00
|
|
|
/* Round I/O allocator to 4KB boundary */
|
|
|
|
pciauto_region_align(pci_io, 0x1000);
|
|
|
|
|
|
|
|
pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT,
|
2012-08-29 14:16:29 +00:00
|
|
|
((pci_io->bus_lower - 1) & 0x0000f000) >> 8);
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16,
|
2012-08-29 14:16:29 +00:00
|
|
|
((pci_io->bus_lower - 1) & 0xffff0000) >> 16);
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
void pciauto_config_init(struct pci_controller *hose)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2013-09-20 13:50:50 +00:00
|
|
|
hose->pci_io = hose->pci_mem = hose->pci_prefetch = NULL;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
for (i = 0; i < hose->region_count; i++) {
|
2004-02-22 23:46:08 +00:00
|
|
|
switch(hose->regions[i].flags) {
|
2002-11-03 00:24:07 +00:00
|
|
|
case PCI_REGION_IO:
|
|
|
|
if (!hose->pci_io ||
|
|
|
|
hose->pci_io->size < hose->regions[i].size)
|
|
|
|
hose->pci_io = hose->regions + i;
|
|
|
|
break;
|
|
|
|
case PCI_REGION_MEM:
|
|
|
|
if (!hose->pci_mem ||
|
|
|
|
hose->pci_mem->size < hose->regions[i].size)
|
|
|
|
hose->pci_mem = hose->regions + i;
|
|
|
|
break;
|
2006-01-11 19:24:15 +00:00
|
|
|
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;
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (hose->pci_mem) {
|
2002-11-03 00:24:07 +00:00
|
|
|
pciauto_region_init(hose->pci_mem);
|
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n"
|
2008-10-21 13:36:08 +00:00
|
|
|
"\t\tPhysical Memory [%llx-%llxx]\n",
|
|
|
|
(u64)hose->pci_mem->bus_start,
|
|
|
|
(u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1),
|
|
|
|
(u64)hose->pci_mem->phys_start,
|
|
|
|
(u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1));
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2006-01-11 19:24:15 +00:00
|
|
|
if (hose->pci_prefetch) {
|
|
|
|
pciauto_region_init(hose->pci_prefetch);
|
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n"
|
2008-10-21 13:36:08 +00:00
|
|
|
"\t\tPhysical Memory [%llx-%llx]\n",
|
|
|
|
(u64)hose->pci_prefetch->bus_start,
|
|
|
|
(u64)(hose->pci_prefetch->bus_start +
|
|
|
|
hose->pci_prefetch->size - 1),
|
|
|
|
(u64)hose->pci_prefetch->phys_start,
|
|
|
|
(u64)(hose->pci_prefetch->phys_start +
|
|
|
|
hose->pci_prefetch->size - 1));
|
2006-01-11 19:24:15 +00:00
|
|
|
}
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
if (hose->pci_io) {
|
2002-11-03 00:24:07 +00:00
|
|
|
pciauto_region_init(hose->pci_io);
|
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n"
|
2008-10-21 13:36:08 +00:00
|
|
|
"\t\tPhysical Memory: [%llx-%llx]\n",
|
|
|
|
(u64)hose->pci_io->bus_start,
|
|
|
|
(u64)(hose->pci_io->bus_start + hose->pci_io->size - 1),
|
|
|
|
(u64)hose->pci_io->phys_start,
|
|
|
|
(u64)(hose->pci_io->phys_start + hose->pci_io->size - 1));
|
2007-07-11 19:51:48 +00:00
|
|
|
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
/*
|
|
|
|
* HJF: Changed this to return int. I think this is required
|
2002-11-19 11:04:11 +00:00
|
|
|
* to get the correct result when scanning bridges
|
|
|
|
*/
|
|
|
|
int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
|
2002-11-03 00:24:07 +00:00
|
|
|
{
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
struct pci_region *pci_mem;
|
|
|
|
struct pci_region *pci_prefetch;
|
|
|
|
struct pci_region *pci_io;
|
2002-11-19 11:04:11 +00:00
|
|
|
unsigned int sub_bus = PCI_BUS(dev);
|
2002-11-03 00:24:07 +00:00
|
|
|
unsigned short class;
|
2004-02-08 22:55:38 +00:00
|
|
|
int n;
|
2002-11-03 00:24:07 +00:00
|
|
|
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
/* The root controller has the region information */
|
|
|
|
struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
|
|
|
|
|
|
|
|
pci_mem = ctlr_hose->pci_mem;
|
|
|
|
pci_prefetch = ctlr_hose->pci_prefetch;
|
|
|
|
pci_io = ctlr_hose->pci_io;
|
|
|
|
#else
|
|
|
|
pci_mem = hose->pci_mem;
|
|
|
|
pci_prefetch = hose->pci_prefetch;
|
|
|
|
pci_io = hose->pci_io;
|
|
|
|
#endif
|
|
|
|
|
2002-11-03 00:24:07 +00:00
|
|
|
pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
|
|
|
|
|
2012-08-29 14:16:29 +00:00
|
|
|
switch (class) {
|
2002-11-03 00:24:07 +00:00
|
|
|
case PCI_CLASS_BRIDGE_PCI:
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Found P2P bridge, device %d\n",
|
|
|
|
PCI_DEV(dev));
|
2015-03-05 19:25:25 +00:00
|
|
|
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
pciauto_setup_device(hose, dev, 2, pci_mem,
|
|
|
|
pci_prefetch, pci_io);
|
2002-11-03 00:24:07 +00:00
|
|
|
|
2015-03-05 19:25:25 +00:00
|
|
|
#ifdef CONFIG_DM_PCI
|
|
|
|
n = dm_pci_hose_probe_bus(hose, dev);
|
|
|
|
if (n < 0)
|
|
|
|
return n;
|
|
|
|
sub_bus = (unsigned int)n;
|
|
|
|
#else
|
2004-02-22 23:46:08 +00:00
|
|
|
/* Passing in current_busno allows for sibling P2P bridges */
|
2015-03-05 19:25:25 +00:00
|
|
|
hose->current_busno++;
|
2004-02-08 22:55:38 +00:00
|
|
|
pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
|
2004-02-10 00:03:41 +00:00
|
|
|
/*
|
2004-02-22 23:46:08 +00:00
|
|
|
* need to figure out if this is a subordinate bridge on the bus
|
2004-02-08 22:55:38 +00:00
|
|
|
* to be able to properly set the pri/sec/sub bridge registers.
|
|
|
|
*/
|
|
|
|
n = pci_hose_scan_bus(hose, hose->current_busno);
|
|
|
|
|
2004-02-22 23:46:08 +00:00
|
|
|
/* figure out the deepest we've gone for this leg */
|
linux/kernel.h: sync min, max, min3, max3 macros with Linux
U-Boot has never cared about the type when we get max/min of two
values, but Linux Kernel does. This commit gets min, max, min3, max3
macros synced with the kernel introducing type checks.
Many of references of those macros must be fixed to suppress warnings.
We have two options:
- Use min, max, min3, max3 only when the arguments have the same type
(or add casts to the arguments)
- Use min_t/max_t instead with the appropriate type for the first
argument
Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Pavel Machek <pavel@denx.de>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
[trini: Fixup arch/blackfin/lib/string.c]
Signed-off-by: Tom Rini <trini@ti.com>
2014-11-06 18:03:31 +00:00
|
|
|
sub_bus = max((unsigned int)n, sub_bus);
|
2003-03-06 00:58:30 +00:00
|
|
|
pciauto_postscan_setup_bridge(hose, dev, sub_bus);
|
2004-02-08 22:55:38 +00:00
|
|
|
|
2003-03-06 00:58:30 +00:00
|
|
|
sub_bus = hose->current_busno;
|
2015-03-05 19:25:25 +00:00
|
|
|
#endif
|
2002-11-03 00:24:07 +00:00
|
|
|
break;
|
|
|
|
|
2003-03-06 21:55:29 +00:00
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS:
|
2012-08-29 14:16:29 +00:00
|
|
|
/*
|
|
|
|
* just do a minimal setup of the bridge,
|
|
|
|
* let the OS take care of the rest
|
|
|
|
*/
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
pciauto_setup_device(hose, dev, 0, pci_mem,
|
|
|
|
pci_prefetch, pci_io);
|
2003-03-06 21:55:29 +00:00
|
|
|
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n",
|
|
|
|
PCI_DEV(dev));
|
2003-03-06 21:55:29 +00:00
|
|
|
|
2015-03-05 19:25:25 +00:00
|
|
|
#ifndef CONFIG_DM_PCI
|
2003-03-06 21:55:29 +00:00
|
|
|
hose->current_busno++;
|
2015-03-05 19:25:25 +00:00
|
|
|
#endif
|
2003-03-06 21:55:29 +00:00
|
|
|
break;
|
|
|
|
|
2008-03-30 06:19:06 +00:00
|
|
|
#if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE)
|
2003-08-17 18:55:18 +00:00
|
|
|
case PCI_CLASS_BRIDGE_OTHER:
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Skipping bridge device %d\n",
|
|
|
|
PCI_DEV(dev));
|
2003-08-17 18:55:18 +00:00
|
|
|
break;
|
|
|
|
#endif
|
2009-07-25 04:19:12 +00:00
|
|
|
#if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349)
|
2005-10-17 00:39:53 +00:00
|
|
|
case PCI_CLASS_BRIDGE_OTHER:
|
|
|
|
/*
|
|
|
|
* The host/PCI bridge 1 seems broken in 8349 - it presents
|
|
|
|
* itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_
|
|
|
|
* device claiming resources io/mem/irq.. we only allow for
|
|
|
|
* the PIMMR window to be allocated (BAR0 - 1MB size)
|
|
|
|
*/
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI Autoconfig: Broken bridge found, only minimal config\n");
|
2012-08-29 14:16:29 +00:00
|
|
|
pciauto_setup_device(hose, dev, 0, hose->pci_mem,
|
|
|
|
hose->pci_prefetch, hose->pci_io);
|
2005-10-17 00:39:53 +00:00
|
|
|
break;
|
|
|
|
#endif
|
2012-08-29 14:16:32 +00:00
|
|
|
|
|
|
|
case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
|
2015-07-31 15:31:33 +00:00
|
|
|
debug("PCI AutoConfig: Found PowerPC device\n");
|
2012-08-29 14:16:32 +00:00
|
|
|
|
2002-11-03 00:24:07 +00:00
|
|
|
default:
|
dm: pci: Support bridge device configuration correctly
Commit aec241d "dm: pci: Use the correct hose when configuring devices"
was an attempt to fix pci bridge device configuration, but unfortunately
that does not work 100%. In pciauto_config_devices(), the fix tried to
call pciauto_config_device() with a ctlr_hose which is supposed to be
the root controller hose, however when walking through a pci topology
with 2 or more pci bridges this logic simply fails.
The call chain is: pciauto_config_devices()->pciauto_config_device()
->dm_pci_hose_probe_bus(). Here the call to dm_pci_hose_probe_bus()
does not make any sense as the given hose is not the bridge device's
hose, instead it is either the root controller's hose (case#1: if it
is the 2nd pci bridge), or the bridge's parent bridge's hose (case#2:
if it is the 3rd pci bridge). In both cases the logic is wrong.
For example, for failing case#1 if the bridge device to config has the
same devfn as one of the devices under the root controller, the call
to pci_bus_find_devfn() will return the udevice of that pci device
under the root controller as the bus, but this is wrong as the udevice
is not a bus which does not contain all the necessary bits associated
with the udevice which causes further failures.
To correctly support pci bridge device configuration, we should still
call pciauto_config_device() with the pci bridge's hose directly.
In order to access valid pci region information, we need to refer to
the root controller simply by a call to pci_bus_to_hose(0) and get the
region information there in the pciauto_prescan_setup_bridge(),
pciauto_postscan_setup_bridge() and pciauto_config_device().
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
2015-07-18 16:20:06 +00:00
|
|
|
pciauto_setup_device(hose, dev, 6, pci_mem,
|
|
|
|
pci_prefetch, pci_io);
|
2002-11-03 00:24:07 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-11-19 11:04:11 +00:00
|
|
|
|
|
|
|
return sub_bus;
|
2002-11-03 00:24:07 +00:00
|
|
|
}
|