#include #include #include #include #include #include static int of_soc_create_device_name(struct device_node *node, char *name) { const u32 *reg; u64 addr; reg = get_property(node, "dcr-reg", NULL); if (reg) { addr = of_translate_dcr_address(node, reg); if (addr != OF_BAD_ADDR) goto found_dcr; } reg = get_property(node, "reg", NULL); if (reg) { addr = of_translate_address(node, reg); if (addr != OF_BAD_ADDR) goto found; } return -EINVAL; found_dcr: sprintf(name, "D%lx.%s", addr, node->name); return 0; found: sprintf(name, "%lx.%s", addr, node->name); return 0; } static int of_soc_device_create(struct device_node *node, struct device *parent) { char name[BUS_ID_SIZE]; int ret; ret = of_soc_create_device_name(node, name); if (ret) return ret; of_platform_device_create(node, name, parent); return 0; } static int of_soc_bus_probe(struct of_device *dev, const struct of_device_id *match) { struct device_node *child; int ret = -ENODEV; for (child = NULL; (child = of_get_next_child(dev->node, child)); ) { if (strcmp(child->type, "soc") == 0) { ret = of_soc_device_create(child, &dev->dev); if (ret) break; } } return ret; } static struct of_device_id of_soc_ids[] = { { .type = "soc", }, {}, }; static struct of_platform_driver of_soc_driver = { .name = "soc", .match_table = of_soc_ids, .probe = of_soc_bus_probe, }; static int of_pci_bus_probe(struct of_device *dev, const struct of_device_id *match) { struct pci_controller *phb; phb = pcibios_alloc_controller(dev->node); if (!phb) return -ENODEV; setup_phb(dev->node, phb); pci_process_bridge_OF_ranges(phb, dev->node, 0); pci_setup_phb_io(phb, 0); return 0; } static struct of_device_id of_pci_ids[] = { { .type = "pci", }, { .type = "pcie", }, { .type = "pciex", }, { .type = "ht", }, { .compatible = "pci", }, { .compatible = "pcie", }, { .compatible = "pciex", }, { .compatible = "ht", }, }; static struct of_platform_driver of_pci_driver = { .name = "pci", .match_table = of_pci_ids, .probe = of_pci_bus_probe, }; static int of_soc_probe(void) { struct device_node *root, *child; int ret; root = of_find_node_by_name(NULL, "/"); ret = of_register_driver(&of_soc_driver); if (ret) goto out; ret = of_register_driver(&of_pci_driver); if (ret) goto out2; for (child = NULL; (child = of_get_next_child(root, child)); ) { if (strcmp(child->type, "soc") == 0) { ret = of_soc_device_create(child, NULL); if (ret) goto out3; } } return 0; out3: of_unregister_driver(&of_soc_driver); out2: of_unregister_driver(&of_pci_driver); out: return ret; } __initcall(of_soc_probe);