arm64: configs: synchronize with other 3399 config for 3399 linux
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / hotplug.c
1 /*
2  * Copyright (C) 2012-2014 ROCKCHIP, Inc.
3  * Copyright (C) 2002 ARM Ltd.
4  * All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/smp.h>
14 #include <linux/delay.h>
15 #include <linux/rockchip/common.h>
16 #include <linux/rockchip/pmu.h>
17
18 #include <asm/cacheflush.h>
19 #include <asm/cp15.h>
20 #include <asm/smp_plat.h>
21 #include <asm/system.h>
22
23
24 static cpumask_t dead_cpus;
25
26 int rockchip_cpu_kill(unsigned int cpu)
27 {
28         int k;
29
30         /* this function is running on another CPU than the offline target,
31          * here we need wait for shutdown code in platform_cpu_die() to
32          * finish before asking SoC-specific code to power off the CPU core.
33          */
34         for (k = 0; k < 1000; k++) {
35                 if (cpumask_test_cpu(cpu, &dead_cpus)) {
36                         mdelay(1);
37                         rockchip_pmu_ops.set_power_domain(PD_CPU_0 + cpu, false);
38                         return 1;
39                 }
40
41                 mdelay(1);
42         }
43
44         return 0;
45 }
46
47 /*
48  * platform-specific code to shutdown a CPU
49  *
50  * Called with IRQs disabled
51  */
52 void rockchip_cpu_die_a9(unsigned int cpu)
53 {
54         unsigned int v;
55
56         /* hardware shutdown code running on the CPU that is being offlined */
57         flush_cache_all();
58         dsb();
59
60         /* notify platform_cpu_kill() that hardware shutdown is finished */
61         cpumask_set_cpu(cpu, &dead_cpus);
62         flush_cache_louis();
63
64         asm volatile(
65         "       mcr     p15, 0, %1, c7, c5, 0\n"
66         "       mcr     p15, 0, %1, c7, c10, 4\n"
67         /*
68          * Turn off coherency
69          */
70         "       mrc     p15, 0, %0, c1, c0, 1\n"
71         "       bic     %0, %0, %3\n"           // clear ACTLR.SMP | ACTLR.FW
72         "       mcr     p15, 0, %0, c1, c0, 1\n"
73         "       mrc     p15, 0, %0, c1, c0, 0\n"
74         "       bic     %0, %0, %2\n"
75         "       mcr     p15, 0, %0, c1, c0, 0\n"
76           : "=&r" (v)
77           : "r" (0), "Ir" (CR_C), "Ir" ((1 << 6) | (1 << 0))
78           : "cc");
79
80         /* wait for SoC code in platform_cpu_kill() to shut off CPU core
81          * power. CPU bring up starts from the reset vector.
82          */
83         while (1) {
84                 dsb();
85                 wfi();
86         }
87 }
88
89 void rockchip_cpu_die(unsigned int cpu)
90 {
91         /* notify platform_cpu_kill() that hardware shutdown is finished */
92         cpumask_set_cpu(cpu, &dead_cpus);
93         flush_cache_louis();
94
95         v7_exit_coherency_flush(louis);
96
97         while (1) {
98                 dsb();
99                 wfi();
100         }
101 }
102
103 int rockchip_cpu_disable(unsigned int cpu)
104 {
105         cpumask_clear_cpu(cpu, &dead_cpus);
106         /*
107          * we don't allow CPU 0 to be shutdown (it is still too special
108          * e.g. clock tick interrupts)
109          */
110         return cpu == 0 ? -EPERM : 0;
111 }