1/* 2 * linux/arch/arm/mach-realview/platsmp.c 3 * 4 * Copyright (C) 2002 ARM Ltd. 5 * All Rights Reserved 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11#include <linux/init.h> 12#include <linux/errno.h> 13#include <linux/smp.h> 14#include <linux/io.h> 15 16#include <mach/hardware.h> 17#include <asm/mach-types.h> 18#include <asm/smp_scu.h> 19 20#include <mach/board-eb.h> 21#include <mach/board-pb11mp.h> 22#include <mach/board-pbx.h> 23 24#include <plat/platsmp.h> 25 26#include "core.h" 27 28static void __iomem *scu_base_addr(void) 29{ 30 if (machine_is_realview_eb_mp()) 31 return __io_address(REALVIEW_EB11MP_SCU_BASE); 32 else if (machine_is_realview_pb11mp()) 33 return __io_address(REALVIEW_TC11MP_SCU_BASE); 34 else if (machine_is_realview_pbx() && 35 (core_tile_pbx11mp() || core_tile_pbxa9mp())) 36 return __io_address(REALVIEW_PBX_TILE_SCU_BASE); 37 else 38 return (void __iomem *)0; 39} 40 41/* 42 * Initialise the CPU possible map early - this describes the CPUs 43 * which may be present or become present in the system. 44 */ 45static void __init realview_smp_init_cpus(void) 46{ 47 void __iomem *scu_base = scu_base_addr(); 48 unsigned int i, ncores; 49 50 ncores = scu_base ? scu_get_core_count(scu_base) : 1; 51 52 /* sanity check */ 53 if (ncores > nr_cpu_ids) { 54 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", 55 ncores, nr_cpu_ids); 56 ncores = nr_cpu_ids; 57 } 58 59 for (i = 0; i < ncores; i++) 60 set_cpu_possible(i, true); 61} 62 63static void __init realview_smp_prepare_cpus(unsigned int max_cpus) 64{ 65 66 scu_enable(scu_base_addr()); 67 68 /* 69 * Write the address of secondary startup into the 70 * system-wide flags register. The BootMonitor waits 71 * until it receives a soft interrupt, and then the 72 * secondary CPU branches to this address. 73 */ 74 __raw_writel(virt_to_phys(versatile_secondary_startup), 75 __io_address(REALVIEW_SYS_FLAGSSET)); 76} 77 78struct smp_operations realview_smp_ops __initdata = { 79 .smp_init_cpus = realview_smp_init_cpus, 80 .smp_prepare_cpus = realview_smp_prepare_cpus, 81 .smp_secondary_init = versatile_secondary_init, 82 .smp_boot_secondary = versatile_boot_secondary, 83#ifdef CONFIG_HOTPLUG_CPU 84 .cpu_die = realview_cpu_die, 85#endif 86}; 87