PageRenderTime 23ms CodeModel.GetById 13ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/arm/mach-exynos/hotplug.c

https://github.com/AICP/kernel_google_msm
C | 135 lines | 72 code | 19 blank | 44 comment | 7 complexity | 249247458558acf0cc4f0b539ad06397 MD5 | raw file
  1/* linux arch/arm/mach-exynos4/hotplug.c
  2 *
  3 *  Cloned from linux/arch/arm/mach-realview/hotplug.c
  4 *
  5 *  Copyright (C) 2002 ARM Ltd.
  6 *  All Rights Reserved
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License version 2 as
 10 * published by the Free Software Foundation.
 11*/
 12
 13#include <linux/kernel.h>
 14#include <linux/errno.h>
 15#include <linux/smp.h>
 16#include <linux/io.h>
 17
 18#include <asm/cacheflush.h>
 19#include <asm/cp15.h>
 20#include <asm/smp_plat.h>
 21
 22#include <mach/regs-pmu.h>
 23
 24extern volatile int pen_release;
 25
 26static inline void cpu_enter_lowpower(void)
 27{
 28	unsigned int v;
 29
 30	flush_cache_all();
 31	asm volatile(
 32	"	mcr	p15, 0, %1, c7, c5, 0\n"
 33	"	mcr	p15, 0, %1, c7, c10, 4\n"
 34	/*
 35	 * Turn off coherency
 36	 */
 37	"	mrc	p15, 0, %0, c1, c0, 1\n"
 38	"	bic	%0, %0, %3\n"
 39	"	mcr	p15, 0, %0, c1, c0, 1\n"
 40	"	mrc	p15, 0, %0, c1, c0, 0\n"
 41	"	bic	%0, %0, %2\n"
 42	"	mcr	p15, 0, %0, c1, c0, 0\n"
 43	  : "=&r" (v)
 44	  : "r" (0), "Ir" (CR_C), "Ir" (0x40)
 45	  : "cc");
 46}
 47
 48static inline void cpu_leave_lowpower(void)
 49{
 50	unsigned int v;
 51
 52	asm volatile(
 53	"mrc	p15, 0, %0, c1, c0, 0\n"
 54	"	orr	%0, %0, %1\n"
 55	"	mcr	p15, 0, %0, c1, c0, 0\n"
 56	"	mrc	p15, 0, %0, c1, c0, 1\n"
 57	"	orr	%0, %0, %2\n"
 58	"	mcr	p15, 0, %0, c1, c0, 1\n"
 59	  : "=&r" (v)
 60	  : "Ir" (CR_C), "Ir" (0x40)
 61	  : "cc");
 62}
 63
 64static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 65{
 66	for (;;) {
 67
 68		/* make cpu1 to be turned off at next WFI command */
 69		if (cpu == 1)
 70			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
 71
 72		/*
 73		 * here's the WFI
 74		 */
 75		asm(".word	0xe320f003\n"
 76		    :
 77		    :
 78		    : "memory", "cc");
 79
 80		if (pen_release == cpu_logical_map(cpu)) {
 81			/*
 82			 * OK, proper wakeup, we're done
 83			 */
 84			break;
 85		}
 86
 87		/*
 88		 * Getting here, means that we have come out of WFI without
 89		 * having been woken up - this shouldn't happen
 90		 *
 91		 * Just note it happening - when we're woken, we can report
 92		 * its occurrence.
 93		 */
 94		(*spurious)++;
 95	}
 96}
 97
 98int platform_cpu_kill(unsigned int cpu)
 99{
100	return 1;
101}
102
103/*
104 * platform-specific code to shutdown a CPU
105 *
106 * Called with IRQs disabled
107 */
108void platform_cpu_die(unsigned int cpu)
109{
110	int spurious = 0;
111
112	/*
113	 * we're ready for shutdown now, so do it
114	 */
115	cpu_enter_lowpower();
116	platform_do_lowpower(cpu, &spurious);
117
118	/*
119	 * bring this CPU back into the world of cache
120	 * coherency, and then restore interrupts
121	 */
122	cpu_leave_lowpower();
123
124	if (spurious)
125		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
126}
127
128int platform_cpu_disable(unsigned int cpu)
129{
130	/*
131	 * we don't allow CPU 0 to be shutdown (it is still too special
132	 * e.g. clock tick interrupts)
133	 */
134	return cpu == 0 ? -EPERM : 0;
135}