diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h index 12a112dd0ae0..ea909a56a3ee 100644 --- a/arch/mips/bcm47xx/bcm47xx_private.h +++ b/arch/mips/bcm47xx/bcm47xx_private.h @@ -15,6 +15,9 @@ int __init bcm47xx_buttons_register(void); /* leds.c */ void __init bcm47xx_leds_register(void); +/* setup.c */ +void __init bcm47xx_bus_setup(void); + /* workarounds.c */ void __init bcm47xx_workarounds(void); diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c index e0585b76ec19..21b4497f09be 100644 --- a/arch/mips/bcm47xx/irq.c +++ b/arch/mips/bcm47xx/irq.c @@ -22,6 +22,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "bcm47xx_private.h" + #include #include #include @@ -65,6 +67,12 @@ DEFINE_HWx_IRQDISPATCH(7) void __init arch_init_irq(void) { + /* + * This is the first arch callback after mm_init (we can use kmalloc), + * so let's finish bus initialization now. + */ + bcm47xx_bus_setup(); + #ifdef CONFIG_BCM47XX_BCMA if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 444c65a09970..e43b5046cb30 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -156,15 +156,14 @@ static void __init bcm47xx_register_bcma(void) err = bcma_host_soc_register(&bcm47xx_bus.bcma); if (err) panic("Failed to register BCMA bus (err %d)", err); - - err = bcma_host_soc_init(&bcm47xx_bus.bcma); - if (err) - panic("Failed to initialize BCMA bus (err %d)", err); - - bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL); } #endif +/* + * Memory setup is done in the early part of MIPS's arch_mem_init. It's supposed + * to detect memory and record it with add_memory_region. + * Any extra initializaion performed here must not use kmalloc or bootmem. + */ void __init plat_mem_setup(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -193,6 +192,28 @@ void __init plat_mem_setup(void) _machine_restart = bcm47xx_machine_restart; _machine_halt = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt; +} + +/* + * This finishes bus initialization doing things that were not possible without + * kmalloc. Make sure to call it late enough (after mm_init). + */ +void __init bcm47xx_bus_setup(void) +{ +#ifdef CONFIG_BCM47XX_BCMA + if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { + int err; + + err = bcma_host_soc_init(&bcm47xx_bus.bcma); + if (err) + panic("Failed to initialize BCMA bus (err %d)", err); + + bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, + NULL); + } +#endif + + /* With bus initialized we can access NVRAM and detect the board */ bcm47xx_board_detect(); mips_set_machine_name(bcm47xx_board_get_name()); }