/* * linux/arch/arm/mach-realview/platsmp.c * * Copyright (C) 2002 ARM Ltd. * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include #include "core.h" static void __iomem *scu_base_addr(void) { if (machine_is_realview_eb_mp()) return __io_address(REALVIEW_EB11MP_SCU_BASE); else if (machine_is_realview_pb11mp()) return __io_address(REALVIEW_TC11MP_SCU_BASE); else if (machine_is_realview_pbx() && (core_tile_pbx11mp() || core_tile_pbxa9mp())) return __io_address(REALVIEW_PBX_TILE_SCU_BASE); else return (void __iomem *)0; } /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init realview_smp_init_cpus(void) { void __iomem *scu_base = scu_base_addr(); unsigned int i, ncores; ncores = scu_base ? scu_get_core_count(scu_base) : 1; /* sanity check */ if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", ncores, nr_cpu_ids); ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); } static void __init realview_smp_prepare_cpus(unsigned int max_cpus) { scu_enable(scu_base_addr()); /* * Write the address of secondary startup into the * system-wide flags register. The BootMonitor waits * until it receives a soft interrupt, and then the * secondary CPU branches to this address. */ __raw_writel(virt_to_phys(versatile_secondary_startup), __io_address(REALVIEW_SYS_FLAGSSET)); } struct smp_operations realview_smp_ops __initdata = { .smp_init_cpus = realview_smp_init_cpus, .smp_prepare_cpus = realview_smp_prepare_cpus, .smp_secondary_init = versatile_secondary_init, .smp_boot_secondary = versatile_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = realview_cpu_die, #endif };