{
struct pci_controller *phb = data;
u32 *regs;
+ char *device_type = get_property(dn, "device_type", NULL);
+ char *model;
dn->phb = phb;
- regs = (u32 *)get_property(dn, "reg", NULL);
- if (regs) {
- /* First register entry is addr (00BBSS00) */
- dn->busno = (regs[0] >> 16) & 0xff;
- dn->devfn = (regs[0] >> 8) & 0xff;
+ if (device_type && (strcmp(device_type, "pci") == 0) &&
+ (get_property(dn, "class-code", NULL) == 0)) {
+ /* special case for PHB's. Sigh. */
+ regs = (u32 *)get_property(dn, "bus-range", NULL);
+ dn->busno = regs[0];
+
+ model = (char *)get_property(dn, "model", NULL);
+
+ if (strstr(model, "U3"))
+ dn->devfn = -1;
+ else
+ dn->devfn = 0; /* assumption */
+ } else {
+ regs = (u32 *)get_property(dn, "reg", NULL);
+ if (regs) {
+ /* First register entry is addr (00BBSS00) */
+ dn->busno = (regs[0] >> 16) & 0xff;
+ dn->devfn = (regs[0] >> 8) & 0xff;
+ }
}
return NULL;
}
struct device_node *dn, *nextdn;
void *ret;
- /* We started with a phb, iterate all childs */
+ if (pre && ((ret = pre(start, data)) != NULL))
+ return ret;
for (dn = start->child; dn; dn = nextdn) {
- u32 *classp, class;
-
nextdn = NULL;
- classp = (u32 *)get_property(dn, "class-code", NULL);
- class = classp ? *classp : 0;
-
- if (pre && ((ret = pre(dn, data)) != NULL))
- return ret;
-
- /* If we are a PCI bridge, go down */
- if (dn->child && ((class >> 8) == PCI_CLASS_BRIDGE_PCI ||
- (class >> 8) == PCI_CLASS_BRIDGE_CARDBUS))
- /* Depth first...do children */
- nextdn = dn->child;
- else if (dn->sibling)
- /* ok, try next sibling instead. */
- nextdn = dn->sibling;
+ if (get_property(dn, "class-code", NULL)) {
+ if (pre && ((ret = pre(dn, data)) != NULL))
+ return ret;
+ if (dn->child)
+ /* Depth first...do children */
+ nextdn = dn->child;
+ else if (dn->sibling)
+ /* ok, try next sibling instead. */
+ nextdn = dn->sibling;
+ }
if (!nextdn) {
/* Walk up to next valid sibling. */
do {
return NULL;
}
-void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
+/*
+ * Same as traverse_pci_devices except this does it for all phbs.
+ */
+static void *traverse_all_pci_devices(traverse_func pre)
{
- struct device_node * dn = (struct device_node *) phb->arch_data;
+ struct pci_controller *phb, *tmp;
+ void *ret;
- /* PHB nodes themselves must not match */
- dn->devfn = dn->busno = -1;
- dn->phb = phb;
+ list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
+ if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
+ != NULL)
+ return ret;
+ return NULL;
+}
+void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
+{
/* Update dn->phb ptrs for new phb and children devices */
- traverse_pci_devices(dn, update_dn_pci_info, phb);
+ traverse_pci_devices((struct device_node *)phb->arch_data,
+ update_dn_pci_info, phb);
}
/*
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xff;
-
return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
}
phb_dn = phb->arch_data;
dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
- if (dn)
+ if (dn) {
dev->sysdata = dn;
+ /* ToDo: call some device init hook here */
+ }
return dn;
}
EXPORT_SYMBOL(fetch_dev_dn);
*/
void __init pci_devs_phb_init(void)
{
- struct pci_controller *phb, *tmp;
-
/* This must be done first so the device nodes have valid pci info! */
- list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
- pci_devs_phb_init_dynamic(phb);
+ traverse_all_pci_devices(update_dn_pci_info);
}
static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list)
{
+ struct list_head *ln;
struct pci_bus *bus;
- list_for_each_entry(bus, bus_list, node) {
+ for (ln = bus_list->next; ln != bus_list; ln = ln->next) {
+ bus = pci_bus_b(ln);
if (bus->self)
bus->sysdata = bus->self->sysdata;
pci_fixup_bus_sysdata_list(&bus->children);