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/hardware/gic.h> 18 #include <asm/mach-types.h> 19 #include <asm/smp_scu.h> 20 21 #include <mach/board-eb.h> 22 #include <mach/board-pb11mp.h> 23 #include <mach/board-pbx.h> 24 25 #include "core.h" 26 27 extern void versatile_secondary_startup(void); 28 scu_base_addr(void)29static void __iomem *scu_base_addr(void) 30 { 31 if (machine_is_realview_eb_mp()) 32 return __io_address(REALVIEW_EB11MP_SCU_BASE); 33 else if (machine_is_realview_pb11mp()) 34 return __io_address(REALVIEW_TC11MP_SCU_BASE); 35 else if (machine_is_realview_pbx() && 36 (core_tile_pbx11mp() || core_tile_pbxa9mp())) 37 return __io_address(REALVIEW_PBX_TILE_SCU_BASE); 38 else 39 return (void __iomem *)0; 40 } 41 42 /* 43 * Initialise the CPU possible map early - this describes the CPUs 44 * which may be present or become present in the system. 45 */ smp_init_cpus(void)46void __init smp_init_cpus(void) 47 { 48 void __iomem *scu_base = scu_base_addr(); 49 unsigned int i, ncores; 50 51 ncores = scu_base ? scu_get_core_count(scu_base) : 1; 52 53 /* sanity check */ 54 if (ncores > nr_cpu_ids) { 55 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", 56 ncores, nr_cpu_ids); 57 ncores = nr_cpu_ids; 58 } 59 60 for (i = 0; i < ncores; i++) 61 set_cpu_possible(i, true); 62 63 set_smp_cross_call(gic_raise_softirq); 64 } 65 platform_smp_prepare_cpus(unsigned int max_cpus)66void __init platform_smp_prepare_cpus(unsigned int max_cpus) 67 { 68 69 scu_enable(scu_base_addr()); 70 71 /* 72 * Write the address of secondary startup into the 73 * system-wide flags register. The BootMonitor waits 74 * until it receives a soft interrupt, and then the 75 * secondary CPU branches to this address. 76 */ 77 __raw_writel(virt_to_phys(versatile_secondary_startup), 78 __io_address(REALVIEW_SYS_FLAGSSET)); 79 } 80