106 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			106 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * MSP71xx Platform-specific hooks for SMP operation | ||
|  |  */ | ||
|  | #include <linux/irq.h>
 | ||
|  | #include <linux/init.h>
 | ||
|  | 
 | ||
|  | #include <asm/mipsmtregs.h>
 | ||
|  | #include <asm/mipsregs.h>
 | ||
|  | #include <asm/smtc.h>
 | ||
|  | #include <asm/smtc_ipi.h>
 | ||
|  | 
 | ||
|  | /* VPE/SMP Prototype implements platform interfaces directly */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Cause the specified action to be performed on a targeted "CPU" | ||
|  |  */ | ||
|  | 
 | ||
|  | static void msp_smtc_send_ipi_single(int cpu, unsigned int action) | ||
|  | { | ||
|  | 	/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ | ||
|  | 	smtc_send_ipi(cpu, LINUX_SMP_IPI, action); | ||
|  | } | ||
|  | 
 | ||
|  | static void msp_smtc_send_ipi_mask(const struct cpumask *mask, | ||
|  | 						unsigned int action) | ||
|  | { | ||
|  | 	unsigned int i; | ||
|  | 
 | ||
|  | 	for_each_cpu(i, mask) | ||
|  | 		msp_smtc_send_ipi_single(i, action); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Post-config but pre-boot cleanup entry point | ||
|  |  */ | ||
|  | static void __cpuinit msp_smtc_init_secondary(void) | ||
|  | { | ||
|  | 	int myvpe; | ||
|  | 
 | ||
|  | 	/* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ | ||
|  | 	myvpe = read_c0_tcbind() & TCBIND_CURVPE; | ||
|  | 	if (myvpe > 0) | ||
|  | 		change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 | | ||
|  | 				STATUSF_IP6 | STATUSF_IP7); | ||
|  | 	smtc_init_secondary(); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Platform "CPU" startup hook | ||
|  |  */ | ||
|  | static void __cpuinit msp_smtc_boot_secondary(int cpu, | ||
|  | 					struct task_struct *idle) | ||
|  | { | ||
|  | 	smtc_boot_secondary(cpu, idle); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * SMP initialization finalization entry point | ||
|  |  */ | ||
|  | static void __cpuinit msp_smtc_smp_finish(void) | ||
|  | { | ||
|  | 	smtc_smp_finish(); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Hook for after all CPUs are online | ||
|  |  */ | ||
|  | 
 | ||
|  | static void msp_smtc_cpus_done(void) | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Platform SMP pre-initialization | ||
|  |  * | ||
|  |  * As noted above, we can assume a single CPU for now | ||
|  |  * but it may be multithreaded. | ||
|  |  */ | ||
|  | 
 | ||
|  | static void __init msp_smtc_smp_setup(void) | ||
|  | { | ||
|  | 	/*
 | ||
|  | 	 * we won't get the definitive value until | ||
|  | 	 * we've run smtc_prepare_cpus later, but | ||
|  | 	 */ | ||
|  | 
 | ||
|  | 	if (read_c0_config3() & (1 << 2)) | ||
|  | 		smp_num_siblings = smtc_build_cpu_map(0); | ||
|  | } | ||
|  | 
 | ||
|  | static void __init msp_smtc_prepare_cpus(unsigned int max_cpus) | ||
|  | { | ||
|  | 	smtc_prepare_cpus(max_cpus); | ||
|  | } | ||
|  | 
 | ||
|  | struct plat_smp_ops msp_smtc_smp_ops = { | ||
|  | 	.send_ipi_single	= msp_smtc_send_ipi_single, | ||
|  | 	.send_ipi_mask		= msp_smtc_send_ipi_mask, | ||
|  | 	.init_secondary		= msp_smtc_init_secondary, | ||
|  | 	.smp_finish		= msp_smtc_smp_finish, | ||
|  | 	.cpus_done		= msp_smtc_cpus_done, | ||
|  | 	.boot_secondary		= msp_smtc_boot_secondary, | ||
|  | 	.smp_setup		= msp_smtc_smp_setup, | ||
|  | 	.prepare_cpus		= msp_smtc_prepare_cpus, | ||
|  | }; |