| Jeff Ohlstein | 9f1890a | 2010-12-02 12:11:27 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  *  Copyright (C) 2002 ARM Ltd. | 
 | 3 |  *  All Rights Reserved | 
 | 4 |  * | 
 | 5 |  * This program is free software; you can redistribute it and/or modify | 
 | 6 |  * it under the terms of the GNU General Public License version 2 as | 
 | 7 |  * published by the Free Software Foundation. | 
 | 8 |  */ | 
 | 9 | #include <linux/kernel.h> | 
 | 10 | #include <linux/errno.h> | 
 | 11 | #include <linux/smp.h> | 
 | 12 |  | 
 | 13 | #include <asm/cacheflush.h> | 
 | 14 |  | 
 | 15 | extern volatile int pen_release; | 
 | 16 |  | 
 | 17 | static inline void cpu_enter_lowpower(void) | 
 | 18 | { | 
 | 19 | 	/* Just flush the cache. Changing the coherency is not yet | 
 | 20 | 	 * available on msm. */ | 
 | 21 | 	flush_cache_all(); | 
 | 22 | } | 
 | 23 |  | 
 | 24 | static inline void cpu_leave_lowpower(void) | 
 | 25 | { | 
 | 26 | } | 
 | 27 |  | 
 | 28 | static inline void platform_do_lowpower(unsigned int cpu) | 
 | 29 | { | 
 | 30 | 	/* Just enter wfi for now. TODO: Properly shut off the cpu. */ | 
 | 31 | 	for (;;) { | 
 | 32 | 		/* | 
 | 33 | 		 * here's the WFI | 
 | 34 | 		 */ | 
 | 35 | 		asm("wfi" | 
 | 36 | 		    : | 
 | 37 | 		    : | 
 | 38 | 		    : "memory", "cc"); | 
 | 39 |  | 
| Will Deacon | 1d3cfb3 | 2011-08-09 12:02:27 +0100 | [diff] [blame] | 40 | 		if (pen_release == cpu_logical_map(cpu)) { | 
| Jeff Ohlstein | 9f1890a | 2010-12-02 12:11:27 -0800 | [diff] [blame] | 41 | 			/* | 
 | 42 | 			 * OK, proper wakeup, we're done | 
 | 43 | 			 */ | 
 | 44 | 			break; | 
 | 45 | 		} | 
 | 46 |  | 
 | 47 | 		/* | 
 | 48 | 		 * getting here, means that we have come out of WFI without | 
 | 49 | 		 * having been woken up - this shouldn't happen | 
 | 50 | 		 * | 
 | 51 | 		 * The trouble is, letting people know about this is not really | 
 | 52 | 		 * possible, since we are currently running incoherently, and | 
 | 53 | 		 * therefore cannot safely call printk() or anything else | 
 | 54 | 		 */ | 
 | 55 | 		pr_debug("CPU%u: spurious wakeup call\n", cpu); | 
 | 56 | 	} | 
 | 57 | } | 
 | 58 |  | 
 | 59 | int platform_cpu_kill(unsigned int cpu) | 
 | 60 | { | 
 | 61 | 	return 1; | 
 | 62 | } | 
 | 63 |  | 
 | 64 | /* | 
 | 65 |  * platform-specific code to shutdown a CPU | 
 | 66 |  * | 
 | 67 |  * Called with IRQs disabled | 
 | 68 |  */ | 
 | 69 | void platform_cpu_die(unsigned int cpu) | 
 | 70 | { | 
 | 71 | 	/* | 
 | 72 | 	 * we're ready for shutdown now, so do it | 
 | 73 | 	 */ | 
 | 74 | 	cpu_enter_lowpower(); | 
 | 75 | 	platform_do_lowpower(cpu); | 
 | 76 |  | 
 | 77 | 	/* | 
 | 78 | 	 * bring this CPU back into the world of cache | 
 | 79 | 	 * coherency, and then restore interrupts | 
 | 80 | 	 */ | 
 | 81 | 	cpu_leave_lowpower(); | 
 | 82 | } | 
 | 83 |  | 
 | 84 | int platform_cpu_disable(unsigned int cpu) | 
 | 85 | { | 
 | 86 | 	/* | 
 | 87 | 	 * we don't allow CPU 0 to be shutdown (it is still too special | 
 | 88 | 	 * e.g. clock tick interrupts) | 
 | 89 | 	 */ | 
 | 90 | 	return cpu == 0 ? -EPERM : 0; | 
 | 91 | } |