summaryrefslogtreecommitdiff
path: root/target/linux/ipq806x/patches/0013-ARM-qcom-Add-SMP-support-for-KPSSv1.patch
blob: e1d9ae1ac68fedf9836f1cc3b60fc4cb4cbc857c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
From 8e843640b3c4a43b963332fdc7b233948ad25a5b Mon Sep 17 00:00:00 2001
From: Rohit Vaswani <rvaswani@codeaurora.org>
Date: Tue, 21 May 2013 19:13:50 -0700
Subject: [PATCH 013/182] ARM: qcom: Add SMP support for KPSSv1

Implement support for the Krait CPU release sequence when the
CPUs are part of the first version of the krait processor
subsystem.

Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
---
 arch/arm/mach-qcom/platsmp.c  |  106 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-qcom/scm-boot.h |    8 ++--
 2 files changed, 111 insertions(+), 3 deletions(-)

--- a/arch/arm/mach-qcom/platsmp.c
+++ b/arch/arm/mach-qcom/platsmp.c
@@ -26,6 +26,16 @@
 #define SCSS_CPU1CORE_RESET		0x2d80
 #define SCSS_DBG_STATUS_CORE_PWRDUP	0x2e64
 
+#define APCS_CPU_PWR_CTL	0x04
+#define PLL_CLAMP		BIT(8)
+#define CORE_PWRD_UP		BIT(7)
+#define COREPOR_RST		BIT(5)
+#define CORE_RST		BIT(4)
+#define L2DT_SLP		BIT(3)
+#define CLAMP			BIT(0)
+
+#define APCS_SAW2_VCTL		0x14
+
 extern void secondary_startup(void);
 
 static DEFINE_SPINLOCK(boot_lock);
@@ -71,6 +81,85 @@ static int scss_release_secondary(unsign
 	return 0;
 }
 
+static int kpssv1_release_secondary(unsigned int cpu)
+{
+	int ret = 0;
+	void __iomem *reg, *saw_reg;
+	struct device_node *cpu_node, *acc_node, *saw_node;
+	u32 val;
+
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		return -ENODEV;
+
+	acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
+	if (!acc_node) {
+		ret = -ENODEV;
+		goto out_acc;
+	}
+
+	saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
+	if (!saw_node) {
+		ret = -ENODEV;
+		goto out_saw;
+	}
+
+	reg = of_iomap(acc_node, 0);
+	if (!reg) {
+		ret = -ENOMEM;
+		goto out_acc_map;
+	}
+
+	saw_reg = of_iomap(saw_node, 0);
+	if (!saw_reg) {
+		ret = -ENOMEM;
+		goto out_saw_map;
+	}
+
+	/* Turn on CPU rail */
+	writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL);
+	mb();
+	udelay(512);
+
+	/* Krait bring-up sequence */
+	val = PLL_CLAMP | L2DT_SLP | CLAMP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	val &= ~L2DT_SLP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	ndelay(300);
+
+	val |= COREPOR_RST;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	val &= ~CLAMP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(2);
+
+	val &= ~COREPOR_RST;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+	udelay(100);
+
+	val |= CORE_PWRD_UP;
+	writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
+	mb();
+
+	iounmap(saw_reg);
+out_saw_map:
+	iounmap(reg);
+out_acc_map:
+	of_node_put(saw_node);
+out_saw:
+	of_node_put(acc_node);
+out_acc:
+	of_node_put(cpu_node);
+	return ret;
+}
+
 static DEFINE_PER_CPU(int, cold_boot_done);
 
 static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
@@ -110,6 +199,11 @@ static int msm8660_boot_secondary(unsign
 	return qcom_boot_secondary(cpu, scss_release_secondary);
 }
 
+static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	return qcom_boot_secondary(cpu, kpssv1_release_secondary);
+}
+
 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int cpu, map;
@@ -117,6 +211,8 @@ static void __init qcom_smp_prepare_cpus
 	static const int cold_boot_flags[] = {
 		0,
 		SCM_FLAG_COLDBOOT_CPU1,
+		SCM_FLAG_COLDBOOT_CPU2,
+		SCM_FLAG_COLDBOOT_CPU3,
 	};
 
 	for_each_present_cpu(cpu) {
@@ -147,3 +243,13 @@ static struct smp_operations smp_msm8660
 #endif
 };
 CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops);
+
+static struct smp_operations qcom_smp_kpssv1_ops __initdata = {
+	.smp_prepare_cpus	= qcom_smp_prepare_cpus,
+	.smp_secondary_init	= qcom_secondary_init,
+	.smp_boot_secondary	= kpssv1_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= qcom_cpu_die,
+#endif
+};
+CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops);
--- a/arch/arm/mach-qcom/scm-boot.h
+++ b/arch/arm/mach-qcom/scm-boot.h
@@ -13,9 +13,11 @@
 #define __MACH_SCM_BOOT_H
 
 #define SCM_BOOT_ADDR			0x1
-#define SCM_FLAG_COLDBOOT_CPU1		0x1
-#define SCM_FLAG_WARMBOOT_CPU1		0x2
-#define SCM_FLAG_WARMBOOT_CPU0		0x4
+#define SCM_FLAG_COLDBOOT_CPU1		0x01
+#define SCM_FLAG_COLDBOOT_CPU2		0x08
+#define SCM_FLAG_COLDBOOT_CPU3		0x20
+#define SCM_FLAG_WARMBOOT_CPU0		0x04
+#define SCM_FLAG_WARMBOOT_CPU1		0x02
 
 int scm_set_boot_addr(phys_addr_t addr, int flags);