bcma_unregister_cores(bus);
 }
 
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+                                  struct bcma_device *core_cc,
+                                  struct bcma_device *core_mips)
+{
+       int err;
+       struct bcma_device *core;
+       struct bcma_device_id match;
+
+       bcma_init_bus(bus);
+
+       match.manuf = BCMA_MANUF_BCM;
+       match.id = BCMA_CORE_CHIPCOMMON;
+       match.class = BCMA_CL_SIM;
+       match.rev = BCMA_ANY_REV;
+
+       /* Scan for chip common core */
+       err = bcma_bus_scan_early(bus, &match, core_cc);
+       if (err) {
+               pr_err("Failed to scan for common core: %d\n", err);
+               return -1;
+       }
+
+       match.manuf = BCMA_MANUF_MIPS;
+       match.id = BCMA_CORE_MIPS_74K;
+       match.class = BCMA_CL_SIM;
+       match.rev = BCMA_ANY_REV;
+
+       /* Scan for mips core */
+       err = bcma_bus_scan_early(bus, &match, core_mips);
+       if (err) {
+               pr_err("Failed to scan for mips core: %d\n", err);
+               return -1;
+       }
+
+       /* Init CC core */
+       core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+       if (core) {
+               bus->drv_cc.core = core;
+               bcma_core_chipcommon_init(&bus->drv_cc);
+       }
+
+       pr_info("Early bus registered\n");
+
+       return 0;
+}
+
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
        drv->drv.name = drv->name;
 
        return addrl;
 }
 
+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
+                                                  u16 index)
+{
+       struct bcma_device *core;
+
+       list_for_each_entry(core, &bus->cores, list) {
+               if (core->core_index == index)
+                       return core;
+       }
+       return NULL;
+}
+
 static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+                             struct bcma_device_id *match, int core_num,
                              struct bcma_device *core)
 {
        s32 tmp;
                return -ENXIO;
        }
 
+       if (bcma_find_core_by_index(bus, core_num)) {
+               bcma_erom_skip_component(bus, eromptr);
+               return -ENODEV;
+       }
+
+       if (match && ((match->manuf != BCMA_ANY_MANUF &&
+             match->manuf != core->id.manuf) ||
+            (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
+            (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
+            (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
+           )) {
+               bcma_erom_skip_component(bus, eromptr);
+               return -ENODEV;
+       }
+
        /* get & parse master ports */
        for (i = 0; i < ports[0]; i++) {
                u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
        return 0;
 }
 
-static void bcma_init_bus(struct bcma_bus *bus)
+void bcma_init_bus(struct bcma_bus *bus)
 {
        s32 tmp;
 
+       if (bus->init_done)
+               return;
+
        INIT_LIST_HEAD(&bus->cores);
        bus->nr_cores = 0;
 
        bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
        bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
        bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+       bus->init_done = true;
 }
 
 int bcma_bus_scan(struct bcma_bus *bus)
        u32 erombase;
        u32 __iomem *eromptr, *eromend;
 
-       int err;
+       int err, core_num = 0;
 
        bcma_init_bus(bus);
 
                INIT_LIST_HEAD(&core->list);
                core->bus = bus;
 
-               err = bcma_get_next_core(bus, &eromptr, core);
-               if (err == -ENXIO)
+               err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
+               if (err == -ENODEV) {
+                       core_num++;
+                       continue;
+               } else if (err == -ENXIO)
                        continue;
                else if (err == -ESPIPE)
                        break;
                else if (err < 0)
                        return err;
 
+               core->core_index = core_num++;
+               bus->nr_cores++;
+
                pr_info("Core %d found: %s "
                        "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-                       bus->nr_cores, bcma_device_name(&core->id),
+                       core->core_index, bcma_device_name(&core->id),
                        core->id.manuf, core->id.id, core->id.rev,
                        core->id.class);
 
-               core->core_index = bus->nr_cores++;
                list_add(&core->list, &bus->cores);
        }
 
        return 0;
 }
+
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+                              struct bcma_device_id *match,
+                              struct bcma_device *core)
+{
+       u32 erombase;
+       u32 __iomem *eromptr, *eromend;
+
+       int err, core_num = 0;
+
+       erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
+       eromptr = bus->mmio;
+       eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
+
+       bcma_scan_switch_core(bus, erombase);
+
+       while (eromptr < eromend) {
+               memset(core, 0, sizeof(*core));
+               INIT_LIST_HEAD(&core->list);
+               core->bus = bus;
+
+               err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
+               if (err == -ENODEV) {
+                       core_num++;
+                       continue;
+               } else if (err == -ENXIO)
+                       continue;
+               else if (err == -ESPIPE)
+                       break;
+               else if (err < 0)
+                       return err;
+
+               core->core_index = core_num++;
+               bus->nr_cores++;
+               pr_info("Core %d found: %s "
+                       "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+                       core->core_index, bcma_device_name(&core->id),
+                       core->id.manuf, core->id.id, core->id.rev,
+                       core->id.class);
+
+               list_add(&core->list, &bus->cores);
+               return 0;
+       }
+
+       return -ENODEV;
+}