xref: /openbmc/linux/arch/arm/mach-shmobile/platsmp.c (revision 72f4d579)
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