OK, let's go through the v2 for this a bit. It's interesting because, well, I bet few people have bothered with it and I know I forgot.
Here we go.
chip southbridge/amd/amd8111 # this "device pci 0.0" is the parent the next one # PCI bridge device pci 0.0 on device pci 0.0 on end device pci 0.1 on end device pci 0.2 off end device pci 1.0 off end end device pci 1.0 on
So what happens here? The amd8111 is a chip, and it has kids, and it has this function: struct chip_operations southbridge_amd_amd8111_ops = { CHIP_NAME("AMD-8111 Southbridge") /* This only called when this device is listed in the * static device tree. */ .enable_dev = amd8111_enable, };
enable, and the first code in the enable is this:
void amd8111_enable(device_t dev) { device_t lpc_dev; device_t bus_dev; unsigned index; unsigned reg_old, reg;
/* See if we are on the behind the amd8111 pci bridge */ bus_dev = dev->bus->dev; if ((bus_dev->vendor == PCI_VENDOR_ID_AMD) && (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) { unsigned devfn; devfn = bus_dev->path.u.pci.devfn + (1 << 3); lpc_dev = dev_find_slot(bus_dev->bus->secondary, devfn); index = ((dev->path.u.pci.devfn & ~7) >> 3) + 8; if (dev->path.u.pci.devfn == 2) { /* EHCI */ index = 16; } } else { unsigned devfn; devfn = (dev->path.u.pci.devfn) & ~7; lpc_dev = dev_find_slot(dev->bus->secondary, devfn); index = dev->path.u.pci.devfn & 7; }
At this point you might be saying, uh, what? What is this? It's the kind of code that tends to send people running for the exits.
The entity is a chip, not a device. Recall that a chip can have multiple devices but there are common chip-level registers that might need to be set to enable or control devices. If we look at static.c for v2,
struct device _dev15 = { .ops = 0, .bus = &_dev8.link[0], .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .devfn = PCI_DEVFN(0x0,0)}}}, .enabled = 1, .on_mainboard = 1, .link = { [0] = { .link = 0, .dev = &_dev15, .children = &_dev16, }, }, .links = 1, .sibling = &_dev20, .chip_ops = &southbridge_amd_amd8111_ops, .chip_info = &southbridge_amd_amd8111_info_14, .next=&_dev16 }; note that in addition to chip_info we have chip_ops.
What is chip_ops? It has one struct member, and it looks like this:
/* Run the magice enable sequence for the device */ if (dev->chip_ops && dev->chip_ops->enable_dev) { dev->chip_ops->enable_dev(dev); }
So the amd8111 enable will be called for each device in this tree under the amd81111. That's why it has to check its own bus -- it has to figure out which of its devices it is being called for, then enable or disable that device.
Now, the pci device is the hardware that supports actual scanning. But note that structure above:
chip southbridge/amd/amd8111 # this "device pci 0.0" is the parent the next one # PCI bridge device pci 0.0 on device pci 0.0 on end device pci 0.1 on end device pci 0.2 off end device pci 1.0 off end end device pci 1.0 on
The pci 0.0 is the bridge, but the devices it refers to follow it.
What should this look like in dts?
Well, I made several mistakes.
First, the amd8111.c should not have a device struct. It should have nothing. It's just a function. In v3 we put support for functions like amd8111_enable right into the device struct: struct device_operations amd8111_lpc = { .id = {.type = DEVICE_ID_PCI, {.pci = {.vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD_8111_ISA}}}, .constructor = default_device_constructor, .phase3_scan = scan_static_bus, .phase4_enable_disable = amd8111_enable, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So the 'chip' keyword is gone as it did not fit well with dts.
So dts becomes this: pci@0,0 { /config/("southbridge/amd/amd8111/pci.dts"); pci{ /config/("southbridge/amd/amd8111/nic.dts"); }; };
because it's the pci device that is a bridge.
Hope this short writeup helps; I am testing this now.
ron