11c51ed4fSMagnus Damm /* 21c51ed4fSMagnus Damm * SMP support for R-Mobile / SH-Mobile 31c51ed4fSMagnus Damm * 41c51ed4fSMagnus Damm * Copyright (C) 2010 Magnus Damm 51c51ed4fSMagnus Damm * 61c51ed4fSMagnus Damm * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved 71c51ed4fSMagnus Damm * 81c51ed4fSMagnus Damm * This program is free software; you can redistribute it and/or modify 91c51ed4fSMagnus Damm * it under the terms of the GNU General Public License version 2 as 101c51ed4fSMagnus Damm * published by the Free Software Foundation. 111c51ed4fSMagnus Damm */ 121c51ed4fSMagnus Damm #include <linux/init.h> 131c51ed4fSMagnus Damm #include <linux/errno.h> 141c51ed4fSMagnus Damm #include <linux/delay.h> 151c51ed4fSMagnus Damm #include <linux/device.h> 161c51ed4fSMagnus Damm #include <linux/smp.h> 171c51ed4fSMagnus Damm #include <linux/io.h> 181c51ed4fSMagnus Damm #include <asm/localtimer.h> 1972f4d579SMagnus Damm #include <asm/mach-types.h> 2072f4d579SMagnus Damm #include <mach/common.h> 211c51ed4fSMagnus Damm 221c51ed4fSMagnus Damm static unsigned int __init shmobile_smp_get_core_count(void) 231c51ed4fSMagnus Damm { 2472f4d579SMagnus Damm if (machine_is_ag5evm()) 2572f4d579SMagnus Damm return sh73a0_get_core_count(); 2672f4d579SMagnus Damm 271c51ed4fSMagnus Damm return 1; 281c51ed4fSMagnus Damm } 291c51ed4fSMagnus Damm 301c51ed4fSMagnus Damm static void __init shmobile_smp_prepare_cpus(void) 311c51ed4fSMagnus Damm { 3272f4d579SMagnus Damm if (machine_is_ag5evm()) 3372f4d579SMagnus Damm sh73a0_smp_prepare_cpus(); 341c51ed4fSMagnus Damm } 351c51ed4fSMagnus Damm 361c51ed4fSMagnus Damm 371c51ed4fSMagnus Damm void __cpuinit platform_secondary_init(unsigned int cpu) 381c51ed4fSMagnus Damm { 391c51ed4fSMagnus Damm trace_hardirqs_off(); 4072f4d579SMagnus Damm 4172f4d579SMagnus Damm if (machine_is_ag5evm()) 4272f4d579SMagnus Damm sh73a0_secondary_init(cpu); 431c51ed4fSMagnus Damm } 441c51ed4fSMagnus Damm 451c51ed4fSMagnus Damm int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) 461c51ed4fSMagnus Damm { 4772f4d579SMagnus Damm if (machine_is_ag5evm()) 4872f4d579SMagnus Damm return sh73a0_boot_secondary(cpu); 4972f4d579SMagnus Damm 501c51ed4fSMagnus Damm return -ENOSYS; 511c51ed4fSMagnus Damm } 521c51ed4fSMagnus Damm 531c51ed4fSMagnus Damm void __init smp_init_cpus(void) 541c51ed4fSMagnus Damm { 551c51ed4fSMagnus Damm unsigned int ncores = shmobile_smp_get_core_count(); 561c51ed4fSMagnus Damm unsigned int i; 571c51ed4fSMagnus Damm 581c51ed4fSMagnus Damm for (i = 0; i < ncores; i++) 591c51ed4fSMagnus Damm set_cpu_possible(i, true); 601c51ed4fSMagnus Damm } 611c51ed4fSMagnus Damm 621c51ed4fSMagnus Damm void __init smp_prepare_cpus(unsigned int max_cpus) 631c51ed4fSMagnus Damm { 641c51ed4fSMagnus Damm unsigned int ncores = shmobile_smp_get_core_count(); 651c51ed4fSMagnus Damm unsigned int cpu = smp_processor_id(); 661c51ed4fSMagnus Damm int i; 671c51ed4fSMagnus Damm 681c51ed4fSMagnus Damm smp_store_cpu_info(cpu); 691c51ed4fSMagnus Damm 701c51ed4fSMagnus Damm if (max_cpus > ncores) 711c51ed4fSMagnus Damm max_cpus = ncores; 721c51ed4fSMagnus Damm 731c51ed4fSMagnus Damm for (i = 0; i < max_cpus; i++) 741c51ed4fSMagnus Damm set_cpu_present(i, true); 751c51ed4fSMagnus Damm 761c51ed4fSMagnus Damm if (max_cpus > 1) { 771c51ed4fSMagnus Damm shmobile_smp_prepare_cpus(); 781c51ed4fSMagnus Damm 791c51ed4fSMagnus Damm /* 801c51ed4fSMagnus Damm * Enable the local timer or broadcast device for the 811c51ed4fSMagnus Damm * boot CPU, but only if we have more than one CPU. 821c51ed4fSMagnus Damm */ 831c51ed4fSMagnus Damm percpu_timer_setup(); 841c51ed4fSMagnus Damm } 851c51ed4fSMagnus Damm } 86