I think I see the problem. The mainboard.c code is called during the chip_operations enable_dev stage very early before the static tree is setup with the device function pointers. The reason for this is to do chip device setup before the devices are scanned. For example the device may need to be enabled in the southbridge before it will be found in the normal scan or it may need to be hidden etc.
If you look at static.c you will see that the .ops = 0 for all the devices. That field gets updated in set_pci_ops() (or other device ops setup functions) which happens later in the device scan, after the chip enable_dev.
That is why we need to use the direct access pci functions and not the static tree pointer functions. I think that the fix is to add a comment explaining why you need to use the direct access functions at in the enable_dev function.
I hope that was clear. It is a bit easier to understand in V3 where the stages/phases are numbered.
Marc