03fdaf3eef99e4a3f403b2437e447bba01bdb240
[openwrt/staging/luka.git] / target / linux / ipq806x / patches / 0014-ARM-qcom-Add-SMP-support-for-KPSSv2.patch
1 From eb07c23d45ddf10fa89296e6c6c6aed553d8bbf5 Mon Sep 17 00:00:00 2001
2 From: Rohit Vaswani <rvaswani@codeaurora.org>
3 Date: Fri, 21 Jun 2013 17:09:13 -0700
4 Subject: [PATCH 014/182] ARM: qcom: Add SMP support for KPSSv2
5
6 Implement support for the Krait CPU release sequence when the
7 CPUs are part of the second version of the Krait processor
8 subsystem.
9
10 Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
11 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
12 Signed-off-by: Kumar Gala <galak@codeaurora.org>
13 ---
14 arch/arm/mach-qcom/platsmp.c | 123 ++++++++++++++++++++++++++++++++++++++++++
15 1 file changed, 123 insertions(+)
16
17 diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
18 index cb0783f..d690856 100644
19 --- a/arch/arm/mach-qcom/platsmp.c
20 +++ b/arch/arm/mach-qcom/platsmp.c
21 @@ -34,7 +34,15 @@
22 #define L2DT_SLP BIT(3)
23 #define CLAMP BIT(0)
24
25 +#define APC_PWR_GATE_CTL 0x14
26 +#define BHS_CNT_SHIFT 24
27 +#define LDO_PWR_DWN_SHIFT 16
28 +#define LDO_BYP_SHIFT 8
29 +#define BHS_SEG_SHIFT 1
30 +#define BHS_EN BIT(0)
31 +
32 #define APCS_SAW2_VCTL 0x14
33 +#define APCS_SAW2_2_VCTL 0x1c
34
35 extern void secondary_startup(void);
36
37 @@ -160,6 +168,106 @@ out_acc:
38 return ret;
39 }
40
41 +static int kpssv2_release_secondary(unsigned int cpu)
42 +{
43 + void __iomem *reg;
44 + struct device_node *cpu_node, *l2_node, *acc_node, *saw_node;
45 + void __iomem *l2_saw_base;
46 + unsigned reg_val;
47 + int ret;
48 +
49 + cpu_node = of_get_cpu_node(cpu, NULL);
50 + if (!cpu_node)
51 + return -ENODEV;
52 +
53 + acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
54 + if (!acc_node) {
55 + ret = -ENODEV;
56 + goto out_acc;
57 + }
58 +
59 + l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
60 + if (!l2_node) {
61 + ret = -ENODEV;
62 + goto out_l2;
63 + }
64 +
65 + saw_node = of_parse_phandle(l2_node, "qcom,saw", 0);
66 + if (!saw_node) {
67 + ret = -ENODEV;
68 + goto out_saw;
69 + }
70 +
71 + reg = of_iomap(acc_node, 0);
72 + if (!reg) {
73 + ret = -ENOMEM;
74 + goto out_map;
75 + }
76 +
77 + l2_saw_base = of_iomap(saw_node, 0);
78 + if (!l2_saw_base) {
79 + ret = -ENOMEM;
80 + goto out_saw_map;
81 + }
82 +
83 + /* Turn on the BHS, turn off LDO Bypass and power down LDO */
84 + reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN;
85 + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
86 + mb();
87 + /* wait for the BHS to settle */
88 + udelay(1);
89 +
90 + /* Turn on BHS segments */
91 + reg_val |= 0x3f << BHS_SEG_SHIFT;
92 + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
93 + mb();
94 + /* wait for the BHS to settle */
95 + udelay(1);
96 +
97 + /* Finally turn on the bypass so that BHS supplies power */
98 + reg_val |= 0x3f << LDO_BYP_SHIFT;
99 + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
100 +
101 + /* enable max phases */
102 + writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL);
103 + mb();
104 + udelay(50);
105 +
106 + reg_val = COREPOR_RST | CLAMP;
107 + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
108 + mb();
109 + udelay(2);
110 +
111 + reg_val &= ~CLAMP;
112 + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
113 + mb();
114 + udelay(2);
115 +
116 + reg_val &= ~COREPOR_RST;
117 + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
118 + mb();
119 +
120 + reg_val |= CORE_PWRD_UP;
121 + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
122 + mb();
123 +
124 + ret = 0;
125 +
126 + iounmap(l2_saw_base);
127 +out_saw_map:
128 + iounmap(reg);
129 +out_map:
130 + of_node_put(saw_node);
131 +out_saw:
132 + of_node_put(l2_node);
133 +out_l2:
134 + of_node_put(acc_node);
135 +out_acc:
136 + of_node_put(cpu_node);
137 +
138 + return ret;
139 +}
140 +
141 static DEFINE_PER_CPU(int, cold_boot_done);
142
143 static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
144 @@ -204,6 +312,11 @@ static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle)
145 return qcom_boot_secondary(cpu, kpssv1_release_secondary);
146 }
147
148 +static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
149 +{
150 + return qcom_boot_secondary(cpu, kpssv2_release_secondary);
151 +}
152 +
153 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
154 {
155 int cpu, map;
156 @@ -253,3 +366,13 @@ static struct smp_operations qcom_smp_kpssv1_ops __initdata = {
157 #endif
158 };
159 CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops);
160 +
161 +static struct smp_operations qcom_smp_kpssv2_ops __initdata = {
162 + .smp_prepare_cpus = qcom_smp_prepare_cpus,
163 + .smp_secondary_init = qcom_secondary_init,
164 + .smp_boot_secondary = kpssv2_boot_secondary,
165 +#ifdef CONFIG_HOTPLUG_CPU
166 + .cpu_die = qcom_cpu_die,
167 +#endif
168 +};
169 +CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops);
170 --
171 1.7.10.4
172