ipq806x: Add support for IPQ806x chip family
[openwrt/openwrt.git] / target / linux / ipq806x / patches / 0005-ARM-qcom-Split-Qualcomm-support-into-legacy-and-mult.patch
1 From 8c2a00c0129d6f718245f7a613c2bb28976b7973 Mon Sep 17 00:00:00 2001
2 From: Kumar Gala <galak@codeaurora.org>
3 Date: Tue, 21 Jan 2014 17:14:10 -0600
4 Subject: [PATCH 005/182] ARM: qcom: Split Qualcomm support into legacy and
5 multiplatform
6
7 Introduce a new mach-qcom that will support SoCs that intend to be
8 multiplatform compatible while keeping mach-msm to legacy SoC/board
9 support that will not transition over to multiplatform.
10
11 As part of this, we move support for MSM8X60, MSM8960 and MSM8974 over
12 to mach-qcom.
13
14 Signed-off-by: Kumar Gala <galak@codeaurora.org>
15 ---
16 MAINTAINERS | 8 ++
17 arch/arm/Kconfig | 7 +-
18 arch/arm/Kconfig.debug | 2 +-
19 arch/arm/Makefile | 1 +
20 arch/arm/boot/dts/Makefile | 6 +-
21 arch/arm/mach-msm/Kconfig | 45 +------
22 arch/arm/mach-msm/Makefile | 6 -
23 arch/arm/mach-msm/board-dt.c | 41 ------
24 arch/arm/mach-msm/platsmp.c | 137 -------------------
25 arch/arm/mach-msm/scm-boot.c | 39 ------
26 arch/arm/mach-msm/scm-boot.h | 22 ---
27 arch/arm/mach-msm/scm.c | 299 -----------------------------------------
28 arch/arm/mach-msm/scm.h | 25 ----
29 arch/arm/mach-qcom/Kconfig | 33 +++++
30 arch/arm/mach-qcom/Makefile | 5 +
31 arch/arm/mach-qcom/board.c | 40 ++++++
32 arch/arm/mach-qcom/platsmp.c | 137 +++++++++++++++++++
33 arch/arm/mach-qcom/scm-boot.c | 39 ++++++
34 arch/arm/mach-qcom/scm-boot.h | 22 +++
35 arch/arm/mach-qcom/scm.c | 299 +++++++++++++++++++++++++++++++++++++++++
36 arch/arm/mach-qcom/scm.h | 25 ++++
37 21 files changed, 619 insertions(+), 619 deletions(-)
38 delete mode 100644 arch/arm/mach-msm/board-dt.c
39 delete mode 100644 arch/arm/mach-msm/platsmp.c
40 delete mode 100644 arch/arm/mach-msm/scm-boot.c
41 delete mode 100644 arch/arm/mach-msm/scm-boot.h
42 delete mode 100644 arch/arm/mach-msm/scm.c
43 delete mode 100644 arch/arm/mach-msm/scm.h
44 create mode 100644 arch/arm/mach-qcom/Kconfig
45 create mode 100644 arch/arm/mach-qcom/Makefile
46 create mode 100644 arch/arm/mach-qcom/board.c
47 create mode 100644 arch/arm/mach-qcom/platsmp.c
48 create mode 100644 arch/arm/mach-qcom/scm-boot.c
49 create mode 100644 arch/arm/mach-qcom/scm-boot.h
50 create mode 100644 arch/arm/mach-qcom/scm.c
51 create mode 100644 arch/arm/mach-qcom/scm.h
52
53 diff --git a/MAINTAINERS b/MAINTAINERS
54 index 900d98e..7d23402 100644
55 --- a/MAINTAINERS
56 +++ b/MAINTAINERS
57 @@ -1168,6 +1168,14 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
58 W: http://www.arm.linux.org.uk/
59 S: Maintained
60
61 +ARM/QUALCOMM SUPPORT
62 +M: Kumar Gala <galak@codeaurora.org>
63 +M: David Brown <davidb@codeaurora.org>
64 +L: linux-arm-msm@vger.kernel.org
65 +S: Maintained
66 +F: arch/arm/mach-qcom/
67 +T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
68 +
69 ARM/RADISYS ENP2611 MACHINE SUPPORT
70 M: Lennert Buytenhek <kernel@wantstofly.org>
71 L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
72 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
73 index 1594945..d02ce70 100644
74 --- a/arch/arm/Kconfig
75 +++ b/arch/arm/Kconfig
76 @@ -657,9 +657,8 @@ config ARCH_PXA
77 help
78 Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
79
80 -config ARCH_MSM_NODT
81 - bool "Qualcomm MSM"
82 - select ARCH_MSM
83 +config ARCH_MSM
84 + bool "Qualcomm MSM (non-multiplatform)"
85 select ARCH_REQUIRE_GPIOLIB
86 select COMMON_CLK
87 select GENERIC_CLOCKEVENTS
88 @@ -1005,6 +1004,8 @@ source "arch/arm/plat-pxa/Kconfig"
89
90 source "arch/arm/mach-mmp/Kconfig"
91
92 +source "arch/arm/mach-qcom/Kconfig"
93 +
94 source "arch/arm/mach-realview/Kconfig"
95
96 source "arch/arm/mach-rockchip/Kconfig"
97 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
98 index 0531da8..4491c7b 100644
99 --- a/arch/arm/Kconfig.debug
100 +++ b/arch/arm/Kconfig.debug
101 @@ -956,7 +956,7 @@ config DEBUG_STI_UART
102
103 config DEBUG_MSM_UART
104 bool
105 - depends on ARCH_MSM
106 + depends on ARCH_MSM || ARCH_QCOM
107
108 config DEBUG_LL_INCLUDE
109 string
110 diff --git a/arch/arm/Makefile b/arch/arm/Makefile
111 index 08a9ef5..51e5bed 100644
112 --- a/arch/arm/Makefile
113 +++ b/arch/arm/Makefile
114 @@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
115 machine-$(CONFIG_ARCH_ORION5X) += orion5x
116 machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell
117 machine-$(CONFIG_ARCH_PXA) += pxa
118 +machine-$(CONFIG_ARCH_QCOM) += qcom
119 machine-$(CONFIG_ARCH_REALVIEW) += realview
120 machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip
121 machine-$(CONFIG_ARCH_RPC) += rpc
122 diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
123 index 0320303..4a89023 100644
124 --- a/arch/arm/boot/dts/Makefile
125 +++ b/arch/arm/boot/dts/Makefile
126 @@ -119,9 +119,6 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
127 kirkwood-ts219-6282.dtb
128 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
129 dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
130 -dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \
131 - qcom-msm8960-cdp.dtb \
132 - qcom-apq8074-dragonboard.dtb
133 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
134 armada-370-mirabox.dtb \
135 armada-370-netgear-rn102.dtb \
136 @@ -234,6 +231,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
137 dra7-evm.dtb
138 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
139 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
140 +dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \
141 + qcom-msm8960-cdp.dtb \
142 + qcom-apq8074-dragonboard.dtb
143 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
144 ste-hrefprev60-stuib.dtb \
145 ste-hrefprev60-tvk.dtb \
146 diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
147 index 3c4eca7..a7f959e 100644
148 --- a/arch/arm/mach-msm/Kconfig
149 +++ b/arch/arm/mach-msm/Kconfig
150 @@ -1,50 +1,9 @@
151 -config ARCH_MSM
152 - bool
153 -
154 -config ARCH_MSM_DT
155 - bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7
156 - select ARCH_MSM
157 - select ARCH_REQUIRE_GPIOLIB
158 - select CLKSRC_OF
159 - select GENERIC_CLOCKEVENTS
160 - help
161 - Support for Qualcomm's devicetree based MSM systems.
162 -
163 if ARCH_MSM
164
165 -menu "Qualcomm MSM SoC Selection"
166 - depends on ARCH_MSM_DT
167 -
168 -config ARCH_MSM8X60
169 - bool "Enable support for MSM8X60"
170 - select ARM_GIC
171 - select CPU_V7
172 - select HAVE_SMP
173 - select MSM_SCM if SMP
174 - select CLKSRC_QCOM
175 -
176 -config ARCH_MSM8960
177 - bool "Enable support for MSM8960"
178 - select ARM_GIC
179 - select CPU_V7
180 - select HAVE_SMP
181 - select MSM_SCM if SMP
182 - select CLKSRC_QCOM
183 -
184 -config ARCH_MSM8974
185 - bool "Enable support for MSM8974"
186 - select ARM_GIC
187 - select CPU_V7
188 - select HAVE_ARM_ARCH_TIMER
189 - select HAVE_SMP
190 - select MSM_SCM if SMP
191 -
192 -endmenu
193 -
194 choice
195 prompt "Qualcomm MSM SoC Type"
196 default ARCH_MSM7X00A
197 - depends on ARCH_MSM_NODT
198 + depends on ARCH_MSM
199
200 config ARCH_MSM7X00A
201 bool "MSM7x00A / MSM7x01A"
202 @@ -99,7 +58,7 @@ config MSM_VIC
203 bool
204
205 menu "Qualcomm MSM Board Type"
206 - depends on ARCH_MSM_NODT
207 + depends on ARCH_MSM
208
209 config MACH_HALIBUT
210 depends on ARCH_MSM
211 diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
212 index 04b1bee..27c078a 100644
213 --- a/arch/arm/mach-msm/Makefile
214 +++ b/arch/arm/mach-msm/Makefile
215 @@ -13,17 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
216
217 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
218 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
219 -obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
220 -
221 -CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
222 -
223 -obj-$(CONFIG_SMP) += platsmp.o
224
225 obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
226 obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
227 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
228 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
229 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
230 -obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o
231 obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
232 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
233 diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
234 deleted file mode 100644
235 index 1f11d93..0000000
236 --- a/arch/arm/mach-msm/board-dt.c
237 +++ /dev/null
238 @@ -1,41 +0,0 @@
239 -/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved.
240 - *
241 - * This program is free software; you can redistribute it and/or modify
242 - * it under the terms of the GNU General Public License version 2 and
243 - * only version 2 as published by the Free Software Foundation.
244 - *
245 - * This program is distributed in the hope that it will be useful,
246 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
247 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
248 - * GNU General Public License for more details.
249 - */
250 -
251 -#include <linux/init.h>
252 -#include <linux/of.h>
253 -#include <linux/of_platform.h>
254 -
255 -#include <asm/mach/arch.h>
256 -#include <asm/mach/map.h>
257 -
258 -#include "common.h"
259 -
260 -static const char * const msm_dt_match[] __initconst = {
261 - "qcom,msm8660-fluid",
262 - "qcom,msm8660-surf",
263 - "qcom,msm8960-cdp",
264 - NULL
265 -};
266 -
267 -static const char * const apq8074_dt_match[] __initconst = {
268 - "qcom,apq8074-dragonboard",
269 - NULL
270 -};
271 -
272 -DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
273 - .smp = smp_ops(msm_smp_ops),
274 - .dt_compat = msm_dt_match,
275 -MACHINE_END
276 -
277 -DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)")
278 - .dt_compat = apq8074_dt_match,
279 -MACHINE_END
280 diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
281 deleted file mode 100644
282 index 251a91e..0000000
283 --- a/arch/arm/mach-msm/platsmp.c
284 +++ /dev/null
285 @@ -1,137 +0,0 @@
286 -/*
287 - * Copyright (C) 2002 ARM Ltd.
288 - * All Rights Reserved
289 - * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
290 - *
291 - * This program is free software; you can redistribute it and/or modify
292 - * it under the terms of the GNU General Public License version 2 as
293 - * published by the Free Software Foundation.
294 - */
295 -
296 -#include <linux/init.h>
297 -#include <linux/errno.h>
298 -#include <linux/delay.h>
299 -#include <linux/device.h>
300 -#include <linux/smp.h>
301 -#include <linux/io.h>
302 -
303 -#include <asm/cputype.h>
304 -#include <asm/smp_plat.h>
305 -
306 -#include "scm-boot.h"
307 -#include "common.h"
308 -
309 -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
310 -#define SCSS_CPU1CORE_RESET 0xD80
311 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
312 -
313 -extern void secondary_startup(void);
314 -
315 -static DEFINE_SPINLOCK(boot_lock);
316 -
317 -#ifdef CONFIG_HOTPLUG_CPU
318 -static void __ref msm_cpu_die(unsigned int cpu)
319 -{
320 - wfi();
321 -}
322 -#endif
323 -
324 -static inline int get_core_count(void)
325 -{
326 - /* 1 + the PART[1:0] field of MIDR */
327 - return ((read_cpuid_id() >> 4) & 3) + 1;
328 -}
329 -
330 -static void msm_secondary_init(unsigned int cpu)
331 -{
332 - /*
333 - * Synchronise with the boot thread.
334 - */
335 - spin_lock(&boot_lock);
336 - spin_unlock(&boot_lock);
337 -}
338 -
339 -static void prepare_cold_cpu(unsigned int cpu)
340 -{
341 - int ret;
342 - ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
343 - SCM_FLAG_COLDBOOT_CPU1);
344 - if (ret == 0) {
345 - void __iomem *sc1_base_ptr;
346 - sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
347 - if (sc1_base_ptr) {
348 - writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
349 - writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
350 - writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
351 - iounmap(sc1_base_ptr);
352 - }
353 - } else
354 - printk(KERN_DEBUG "Failed to set secondary core boot "
355 - "address\n");
356 -}
357 -
358 -static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
359 -{
360 - static int cold_boot_done;
361 -
362 - /* Only need to bring cpu out of reset this way once */
363 - if (cold_boot_done == false) {
364 - prepare_cold_cpu(cpu);
365 - cold_boot_done = true;
366 - }
367 -
368 - /*
369 - * set synchronisation state between this boot processor
370 - * and the secondary one
371 - */
372 - spin_lock(&boot_lock);
373 -
374 - /*
375 - * Send the secondary CPU a soft interrupt, thereby causing
376 - * the boot monitor to read the system wide flags register,
377 - * and branch to the address found there.
378 - */
379 - arch_send_wakeup_ipi_mask(cpumask_of(cpu));
380 -
381 - /*
382 - * now the secondary core is starting up let it run its
383 - * calibrations, then wait for it to finish
384 - */
385 - spin_unlock(&boot_lock);
386 -
387 - return 0;
388 -}
389 -
390 -/*
391 - * Initialise the CPU possible map early - this describes the CPUs
392 - * which may be present or become present in the system. The msm8x60
393 - * does not support the ARM SCU, so just set the possible cpu mask to
394 - * NR_CPUS.
395 - */
396 -static void __init msm_smp_init_cpus(void)
397 -{
398 - unsigned int i, ncores = get_core_count();
399 -
400 - if (ncores > nr_cpu_ids) {
401 - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
402 - ncores, nr_cpu_ids);
403 - ncores = nr_cpu_ids;
404 - }
405 -
406 - for (i = 0; i < ncores; i++)
407 - set_cpu_possible(i, true);
408 -}
409 -
410 -static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
411 -{
412 -}
413 -
414 -struct smp_operations msm_smp_ops __initdata = {
415 - .smp_init_cpus = msm_smp_init_cpus,
416 - .smp_prepare_cpus = msm_smp_prepare_cpus,
417 - .smp_secondary_init = msm_secondary_init,
418 - .smp_boot_secondary = msm_boot_secondary,
419 -#ifdef CONFIG_HOTPLUG_CPU
420 - .cpu_die = msm_cpu_die,
421 -#endif
422 -};
423 diff --git a/arch/arm/mach-msm/scm-boot.c b/arch/arm/mach-msm/scm-boot.c
424 deleted file mode 100644
425 index 45cee3e..0000000
426 --- a/arch/arm/mach-msm/scm-boot.c
427 +++ /dev/null
428 @@ -1,39 +0,0 @@
429 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
430 - *
431 - * This program is free software; you can redistribute it and/or modify
432 - * it under the terms of the GNU General Public License version 2 and
433 - * only version 2 as published by the Free Software Foundation.
434 - *
435 - * This program is distributed in the hope that it will be useful,
436 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
437 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
438 - * GNU General Public License for more details.
439 - *
440 - * You should have received a copy of the GNU General Public License
441 - * along with this program; if not, write to the Free Software
442 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
443 - * 02110-1301, USA.
444 - */
445 -
446 -#include <linux/module.h>
447 -#include <linux/slab.h>
448 -
449 -#include "scm.h"
450 -#include "scm-boot.h"
451 -
452 -/*
453 - * Set the cold/warm boot address for one of the CPU cores.
454 - */
455 -int scm_set_boot_addr(phys_addr_t addr, int flags)
456 -{
457 - struct {
458 - unsigned int flags;
459 - phys_addr_t addr;
460 - } cmd;
461 -
462 - cmd.addr = addr;
463 - cmd.flags = flags;
464 - return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
465 - &cmd, sizeof(cmd), NULL, 0);
466 -}
467 -EXPORT_SYMBOL(scm_set_boot_addr);
468 diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h
469 deleted file mode 100644
470 index 7be32ff..0000000
471 --- a/arch/arm/mach-msm/scm-boot.h
472 +++ /dev/null
473 @@ -1,22 +0,0 @@
474 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
475 - *
476 - * This program is free software; you can redistribute it and/or modify
477 - * it under the terms of the GNU General Public License version 2 and
478 - * only version 2 as published by the Free Software Foundation.
479 - *
480 - * This program is distributed in the hope that it will be useful,
481 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
482 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
483 - * GNU General Public License for more details.
484 - */
485 -#ifndef __MACH_SCM_BOOT_H
486 -#define __MACH_SCM_BOOT_H
487 -
488 -#define SCM_BOOT_ADDR 0x1
489 -#define SCM_FLAG_COLDBOOT_CPU1 0x1
490 -#define SCM_FLAG_WARMBOOT_CPU1 0x2
491 -#define SCM_FLAG_WARMBOOT_CPU0 0x4
492 -
493 -int scm_set_boot_addr(phys_addr_t addr, int flags);
494 -
495 -#endif
496 diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
497 deleted file mode 100644
498 index c536fd6..0000000
499 --- a/arch/arm/mach-msm/scm.c
500 +++ /dev/null
501 @@ -1,299 +0,0 @@
502 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
503 - *
504 - * This program is free software; you can redistribute it and/or modify
505 - * it under the terms of the GNU General Public License version 2 and
506 - * only version 2 as published by the Free Software Foundation.
507 - *
508 - * This program is distributed in the hope that it will be useful,
509 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
510 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
511 - * GNU General Public License for more details.
512 - *
513 - * You should have received a copy of the GNU General Public License
514 - * along with this program; if not, write to the Free Software
515 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
516 - * 02110-1301, USA.
517 - */
518 -
519 -#include <linux/slab.h>
520 -#include <linux/io.h>
521 -#include <linux/module.h>
522 -#include <linux/mutex.h>
523 -#include <linux/errno.h>
524 -#include <linux/err.h>
525 -
526 -#include <asm/cacheflush.h>
527 -
528 -#include "scm.h"
529 -
530 -/* Cache line size for msm8x60 */
531 -#define CACHELINESIZE 32
532 -
533 -#define SCM_ENOMEM -5
534 -#define SCM_EOPNOTSUPP -4
535 -#define SCM_EINVAL_ADDR -3
536 -#define SCM_EINVAL_ARG -2
537 -#define SCM_ERROR -1
538 -#define SCM_INTERRUPTED 1
539 -
540 -static DEFINE_MUTEX(scm_lock);
541 -
542 -/**
543 - * struct scm_command - one SCM command buffer
544 - * @len: total available memory for command and response
545 - * @buf_offset: start of command buffer
546 - * @resp_hdr_offset: start of response buffer
547 - * @id: command to be executed
548 - * @buf: buffer returned from scm_get_command_buffer()
549 - *
550 - * An SCM command is laid out in memory as follows:
551 - *
552 - * ------------------- <--- struct scm_command
553 - * | command header |
554 - * ------------------- <--- scm_get_command_buffer()
555 - * | command buffer |
556 - * ------------------- <--- struct scm_response and
557 - * | response header | scm_command_to_response()
558 - * ------------------- <--- scm_get_response_buffer()
559 - * | response buffer |
560 - * -------------------
561 - *
562 - * There can be arbitrary padding between the headers and buffers so
563 - * you should always use the appropriate scm_get_*_buffer() routines
564 - * to access the buffers in a safe manner.
565 - */
566 -struct scm_command {
567 - u32 len;
568 - u32 buf_offset;
569 - u32 resp_hdr_offset;
570 - u32 id;
571 - u32 buf[0];
572 -};
573 -
574 -/**
575 - * struct scm_response - one SCM response buffer
576 - * @len: total available memory for response
577 - * @buf_offset: start of response data relative to start of scm_response
578 - * @is_complete: indicates if the command has finished processing
579 - */
580 -struct scm_response {
581 - u32 len;
582 - u32 buf_offset;
583 - u32 is_complete;
584 -};
585 -
586 -/**
587 - * alloc_scm_command() - Allocate an SCM command
588 - * @cmd_size: size of the command buffer
589 - * @resp_size: size of the response buffer
590 - *
591 - * Allocate an SCM command, including enough room for the command
592 - * and response headers as well as the command and response buffers.
593 - *
594 - * Returns a valid &scm_command on success or %NULL if the allocation fails.
595 - */
596 -static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
597 -{
598 - struct scm_command *cmd;
599 - size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
600 - resp_size;
601 -
602 - cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
603 - if (cmd) {
604 - cmd->len = len;
605 - cmd->buf_offset = offsetof(struct scm_command, buf);
606 - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
607 - }
608 - return cmd;
609 -}
610 -
611 -/**
612 - * free_scm_command() - Free an SCM command
613 - * @cmd: command to free
614 - *
615 - * Free an SCM command.
616 - */
617 -static inline void free_scm_command(struct scm_command *cmd)
618 -{
619 - kfree(cmd);
620 -}
621 -
622 -/**
623 - * scm_command_to_response() - Get a pointer to a scm_response
624 - * @cmd: command
625 - *
626 - * Returns a pointer to a response for a command.
627 - */
628 -static inline struct scm_response *scm_command_to_response(
629 - const struct scm_command *cmd)
630 -{
631 - return (void *)cmd + cmd->resp_hdr_offset;
632 -}
633 -
634 -/**
635 - * scm_get_command_buffer() - Get a pointer to a command buffer
636 - * @cmd: command
637 - *
638 - * Returns a pointer to the command buffer of a command.
639 - */
640 -static inline void *scm_get_command_buffer(const struct scm_command *cmd)
641 -{
642 - return (void *)cmd->buf;
643 -}
644 -
645 -/**
646 - * scm_get_response_buffer() - Get a pointer to a response buffer
647 - * @rsp: response
648 - *
649 - * Returns a pointer to a response buffer of a response.
650 - */
651 -static inline void *scm_get_response_buffer(const struct scm_response *rsp)
652 -{
653 - return (void *)rsp + rsp->buf_offset;
654 -}
655 -
656 -static int scm_remap_error(int err)
657 -{
658 - switch (err) {
659 - case SCM_ERROR:
660 - return -EIO;
661 - case SCM_EINVAL_ADDR:
662 - case SCM_EINVAL_ARG:
663 - return -EINVAL;
664 - case SCM_EOPNOTSUPP:
665 - return -EOPNOTSUPP;
666 - case SCM_ENOMEM:
667 - return -ENOMEM;
668 - }
669 - return -EINVAL;
670 -}
671 -
672 -static u32 smc(u32 cmd_addr)
673 -{
674 - int context_id;
675 - register u32 r0 asm("r0") = 1;
676 - register u32 r1 asm("r1") = (u32)&context_id;
677 - register u32 r2 asm("r2") = cmd_addr;
678 - do {
679 - asm volatile(
680 - __asmeq("%0", "r0")
681 - __asmeq("%1", "r0")
682 - __asmeq("%2", "r1")
683 - __asmeq("%3", "r2")
684 -#ifdef REQUIRES_SEC
685 - ".arch_extension sec\n"
686 -#endif
687 - "smc #0 @ switch to secure world\n"
688 - : "=r" (r0)
689 - : "r" (r0), "r" (r1), "r" (r2)
690 - : "r3");
691 - } while (r0 == SCM_INTERRUPTED);
692 -
693 - return r0;
694 -}
695 -
696 -static int __scm_call(const struct scm_command *cmd)
697 -{
698 - int ret;
699 - u32 cmd_addr = virt_to_phys(cmd);
700 -
701 - /*
702 - * Flush the entire cache here so callers don't have to remember
703 - * to flush the cache when passing physical addresses to the secure
704 - * side in the buffer.
705 - */
706 - flush_cache_all();
707 - ret = smc(cmd_addr);
708 - if (ret < 0)
709 - ret = scm_remap_error(ret);
710 -
711 - return ret;
712 -}
713 -
714 -/**
715 - * scm_call() - Send an SCM command
716 - * @svc_id: service identifier
717 - * @cmd_id: command identifier
718 - * @cmd_buf: command buffer
719 - * @cmd_len: length of the command buffer
720 - * @resp_buf: response buffer
721 - * @resp_len: length of the response buffer
722 - *
723 - * Sends a command to the SCM and waits for the command to finish processing.
724 - */
725 -int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
726 - void *resp_buf, size_t resp_len)
727 -{
728 - int ret;
729 - struct scm_command *cmd;
730 - struct scm_response *rsp;
731 -
732 - cmd = alloc_scm_command(cmd_len, resp_len);
733 - if (!cmd)
734 - return -ENOMEM;
735 -
736 - cmd->id = (svc_id << 10) | cmd_id;
737 - if (cmd_buf)
738 - memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
739 -
740 - mutex_lock(&scm_lock);
741 - ret = __scm_call(cmd);
742 - mutex_unlock(&scm_lock);
743 - if (ret)
744 - goto out;
745 -
746 - rsp = scm_command_to_response(cmd);
747 - do {
748 - u32 start = (u32)rsp;
749 - u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
750 - start &= ~(CACHELINESIZE - 1);
751 - while (start < end) {
752 - asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
753 - : "memory");
754 - start += CACHELINESIZE;
755 - }
756 - } while (!rsp->is_complete);
757 -
758 - if (resp_buf)
759 - memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
760 -out:
761 - free_scm_command(cmd);
762 - return ret;
763 -}
764 -EXPORT_SYMBOL(scm_call);
765 -
766 -u32 scm_get_version(void)
767 -{
768 - int context_id;
769 - static u32 version = -1;
770 - register u32 r0 asm("r0");
771 - register u32 r1 asm("r1");
772 -
773 - if (version != -1)
774 - return version;
775 -
776 - mutex_lock(&scm_lock);
777 -
778 - r0 = 0x1 << 8;
779 - r1 = (u32)&context_id;
780 - do {
781 - asm volatile(
782 - __asmeq("%0", "r0")
783 - __asmeq("%1", "r1")
784 - __asmeq("%2", "r0")
785 - __asmeq("%3", "r1")
786 -#ifdef REQUIRES_SEC
787 - ".arch_extension sec\n"
788 -#endif
789 - "smc #0 @ switch to secure world\n"
790 - : "=r" (r0), "=r" (r1)
791 - : "r" (r0), "r" (r1)
792 - : "r2", "r3");
793 - } while (r0 == SCM_INTERRUPTED);
794 -
795 - version = r1;
796 - mutex_unlock(&scm_lock);
797 -
798 - return version;
799 -}
800 -EXPORT_SYMBOL(scm_get_version);
801 diff --git a/arch/arm/mach-msm/scm.h b/arch/arm/mach-msm/scm.h
802 deleted file mode 100644
803 index 00b31ea..0000000
804 --- a/arch/arm/mach-msm/scm.h
805 +++ /dev/null
806 @@ -1,25 +0,0 @@
807 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
808 - *
809 - * This program is free software; you can redistribute it and/or modify
810 - * it under the terms of the GNU General Public License version 2 and
811 - * only version 2 as published by the Free Software Foundation.
812 - *
813 - * This program is distributed in the hope that it will be useful,
814 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
815 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
816 - * GNU General Public License for more details.
817 - */
818 -#ifndef __MACH_SCM_H
819 -#define __MACH_SCM_H
820 -
821 -#define SCM_SVC_BOOT 0x1
822 -#define SCM_SVC_PIL 0x2
823 -
824 -extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
825 - void *resp_buf, size_t resp_len);
826 -
827 -#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
828 -
829 -extern u32 scm_get_version(void);
830 -
831 -#endif
832 diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
833 new file mode 100644
834 index 0000000..a028be2
835 --- /dev/null
836 +++ b/arch/arm/mach-qcom/Kconfig
837 @@ -0,0 +1,33 @@
838 +config ARCH_QCOM
839 + bool "Qualcomm Support" if ARCH_MULTI_V7
840 + select ARCH_REQUIRE_GPIOLIB
841 + select ARM_GIC
842 + select CLKSRC_OF
843 + select GENERIC_CLOCKEVENTS
844 + select HAVE_SMP
845 + select QCOM_SCM if SMP
846 + help
847 + Support for Qualcomm's devicetree based systems.
848 +
849 +if ARCH_QCOM
850 +
851 +menu "Qualcomm SoC Selection"
852 +
853 +config ARCH_MSM8X60
854 + bool "Enable support for MSM8X60"
855 + select CLKSRC_QCOM
856 +
857 +config ARCH_MSM8960
858 + bool "Enable support for MSM8960"
859 + select CLKSRC_QCOM
860 +
861 +config ARCH_MSM8974
862 + bool "Enable support for MSM8974"
863 + select HAVE_ARM_ARCH_TIMER
864 +
865 +endmenu
866 +
867 +config QCOM_SCM
868 + bool
869 +
870 +endif
871 diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
872 new file mode 100644
873 index 0000000..8f756ae
874 --- /dev/null
875 +++ b/arch/arm/mach-qcom/Makefile
876 @@ -0,0 +1,5 @@
877 +obj-y := board.o
878 +obj-$(CONFIG_SMP) += platsmp.o
879 +obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
880 +
881 +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
882 diff --git a/arch/arm/mach-qcom/board.c b/arch/arm/mach-qcom/board.c
883 new file mode 100644
884 index 0000000..4529f6b
885 --- /dev/null
886 +++ b/arch/arm/mach-qcom/board.c
887 @@ -0,0 +1,40 @@
888 +/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
889 + *
890 + * This program is free software; you can redistribute it and/or modify
891 + * it under the terms of the GNU General Public License version 2 and
892 + * only version 2 as published by the Free Software Foundation.
893 + *
894 + * This program is distributed in the hope that it will be useful,
895 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
896 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
897 + * GNU General Public License for more details.
898 + */
899 +
900 +#include <linux/init.h>
901 +#include <linux/of.h>
902 +#include <linux/of_platform.h>
903 +
904 +#include <asm/mach/arch.h>
905 +#include <asm/mach/map.h>
906 +
907 +extern struct smp_operations msm_smp_ops;
908 +
909 +static const char * const qcom_dt_match[] __initconst = {
910 + "qcom,msm8660-surf",
911 + "qcom,msm8960-cdp",
912 + NULL
913 +};
914 +
915 +static const char * const apq8074_dt_match[] __initconst = {
916 + "qcom,apq8074-dragonboard",
917 + NULL
918 +};
919 +
920 +DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
921 + .smp = smp_ops(msm_smp_ops),
922 + .dt_compat = qcom_dt_match,
923 +MACHINE_END
924 +
925 +DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)")
926 + .dt_compat = apq8074_dt_match,
927 +MACHINE_END
928 diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
929 new file mode 100644
930 index 0000000..67823a7
931 --- /dev/null
932 +++ b/arch/arm/mach-qcom/platsmp.c
933 @@ -0,0 +1,137 @@
934 +/*
935 + * Copyright (C) 2002 ARM Ltd.
936 + * All Rights Reserved
937 + * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
938 + * Copyright (c) 2014 The Linux Foundation. All rights reserved.
939 + *
940 + * This program is free software; you can redistribute it and/or modify
941 + * it under the terms of the GNU General Public License version 2 as
942 + * published by the Free Software Foundation.
943 + */
944 +
945 +#include <linux/init.h>
946 +#include <linux/errno.h>
947 +#include <linux/delay.h>
948 +#include <linux/device.h>
949 +#include <linux/smp.h>
950 +#include <linux/io.h>
951 +
952 +#include <asm/cputype.h>
953 +#include <asm/smp_plat.h>
954 +
955 +#include "scm-boot.h"
956 +
957 +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
958 +#define SCSS_CPU1CORE_RESET 0xD80
959 +#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
960 +
961 +extern void secondary_startup(void);
962 +
963 +static DEFINE_SPINLOCK(boot_lock);
964 +
965 +#ifdef CONFIG_HOTPLUG_CPU
966 +static void __ref msm_cpu_die(unsigned int cpu)
967 +{
968 + wfi();
969 +}
970 +#endif
971 +
972 +static inline int get_core_count(void)
973 +{
974 + /* 1 + the PART[1:0] field of MIDR */
975 + return ((read_cpuid_id() >> 4) & 3) + 1;
976 +}
977 +
978 +static void msm_secondary_init(unsigned int cpu)
979 +{
980 + /*
981 + * Synchronise with the boot thread.
982 + */
983 + spin_lock(&boot_lock);
984 + spin_unlock(&boot_lock);
985 +}
986 +
987 +static void prepare_cold_cpu(unsigned int cpu)
988 +{
989 + int ret;
990 + ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
991 + SCM_FLAG_COLDBOOT_CPU1);
992 + if (ret == 0) {
993 + void __iomem *sc1_base_ptr;
994 + sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
995 + if (sc1_base_ptr) {
996 + writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
997 + writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
998 + writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
999 + iounmap(sc1_base_ptr);
1000 + }
1001 + } else
1002 + printk(KERN_DEBUG "Failed to set secondary core boot "
1003 + "address\n");
1004 +}
1005 +
1006 +static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
1007 +{
1008 + static int cold_boot_done;
1009 +
1010 + /* Only need to bring cpu out of reset this way once */
1011 + if (cold_boot_done == false) {
1012 + prepare_cold_cpu(cpu);
1013 + cold_boot_done = true;
1014 + }
1015 +
1016 + /*
1017 + * set synchronisation state between this boot processor
1018 + * and the secondary one
1019 + */
1020 + spin_lock(&boot_lock);
1021 +
1022 + /*
1023 + * Send the secondary CPU a soft interrupt, thereby causing
1024 + * the boot monitor to read the system wide flags register,
1025 + * and branch to the address found there.
1026 + */
1027 + arch_send_wakeup_ipi_mask(cpumask_of(cpu));
1028 +
1029 + /*
1030 + * now the secondary core is starting up let it run its
1031 + * calibrations, then wait for it to finish
1032 + */
1033 + spin_unlock(&boot_lock);
1034 +
1035 + return 0;
1036 +}
1037 +
1038 +/*
1039 + * Initialise the CPU possible map early - this describes the CPUs
1040 + * which may be present or become present in the system. The msm8x60
1041 + * does not support the ARM SCU, so just set the possible cpu mask to
1042 + * NR_CPUS.
1043 + */
1044 +static void __init msm_smp_init_cpus(void)
1045 +{
1046 + unsigned int i, ncores = get_core_count();
1047 +
1048 + if (ncores > nr_cpu_ids) {
1049 + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
1050 + ncores, nr_cpu_ids);
1051 + ncores = nr_cpu_ids;
1052 + }
1053 +
1054 + for (i = 0; i < ncores; i++)
1055 + set_cpu_possible(i, true);
1056 +}
1057 +
1058 +static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
1059 +{
1060 +}
1061 +
1062 +struct smp_operations msm_smp_ops __initdata = {
1063 + .smp_init_cpus = msm_smp_init_cpus,
1064 + .smp_prepare_cpus = msm_smp_prepare_cpus,
1065 + .smp_secondary_init = msm_secondary_init,
1066 + .smp_boot_secondary = msm_boot_secondary,
1067 +#ifdef CONFIG_HOTPLUG_CPU
1068 + .cpu_die = msm_cpu_die,
1069 +#endif
1070 +};
1071 diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c
1072 new file mode 100644
1073 index 0000000..45cee3e
1074 --- /dev/null
1075 +++ b/arch/arm/mach-qcom/scm-boot.c
1076 @@ -0,0 +1,39 @@
1077 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
1078 + *
1079 + * This program is free software; you can redistribute it and/or modify
1080 + * it under the terms of the GNU General Public License version 2 and
1081 + * only version 2 as published by the Free Software Foundation.
1082 + *
1083 + * This program is distributed in the hope that it will be useful,
1084 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1085 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1086 + * GNU General Public License for more details.
1087 + *
1088 + * You should have received a copy of the GNU General Public License
1089 + * along with this program; if not, write to the Free Software
1090 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1091 + * 02110-1301, USA.
1092 + */
1093 +
1094 +#include <linux/module.h>
1095 +#include <linux/slab.h>
1096 +
1097 +#include "scm.h"
1098 +#include "scm-boot.h"
1099 +
1100 +/*
1101 + * Set the cold/warm boot address for one of the CPU cores.
1102 + */
1103 +int scm_set_boot_addr(phys_addr_t addr, int flags)
1104 +{
1105 + struct {
1106 + unsigned int flags;
1107 + phys_addr_t addr;
1108 + } cmd;
1109 +
1110 + cmd.addr = addr;
1111 + cmd.flags = flags;
1112 + return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
1113 + &cmd, sizeof(cmd), NULL, 0);
1114 +}
1115 +EXPORT_SYMBOL(scm_set_boot_addr);
1116 diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h
1117 new file mode 100644
1118 index 0000000..7be32ff
1119 --- /dev/null
1120 +++ b/arch/arm/mach-qcom/scm-boot.h
1121 @@ -0,0 +1,22 @@
1122 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
1123 + *
1124 + * This program is free software; you can redistribute it and/or modify
1125 + * it under the terms of the GNU General Public License version 2 and
1126 + * only version 2 as published by the Free Software Foundation.
1127 + *
1128 + * This program is distributed in the hope that it will be useful,
1129 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1130 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1131 + * GNU General Public License for more details.
1132 + */
1133 +#ifndef __MACH_SCM_BOOT_H
1134 +#define __MACH_SCM_BOOT_H
1135 +
1136 +#define SCM_BOOT_ADDR 0x1
1137 +#define SCM_FLAG_COLDBOOT_CPU1 0x1
1138 +#define SCM_FLAG_WARMBOOT_CPU1 0x2
1139 +#define SCM_FLAG_WARMBOOT_CPU0 0x4
1140 +
1141 +int scm_set_boot_addr(phys_addr_t addr, int flags);
1142 +
1143 +#endif
1144 diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
1145 new file mode 100644
1146 index 0000000..c536fd6
1147 --- /dev/null
1148 +++ b/arch/arm/mach-qcom/scm.c
1149 @@ -0,0 +1,299 @@
1150 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
1151 + *
1152 + * This program is free software; you can redistribute it and/or modify
1153 + * it under the terms of the GNU General Public License version 2 and
1154 + * only version 2 as published by the Free Software Foundation.
1155 + *
1156 + * This program is distributed in the hope that it will be useful,
1157 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1158 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1159 + * GNU General Public License for more details.
1160 + *
1161 + * You should have received a copy of the GNU General Public License
1162 + * along with this program; if not, write to the Free Software
1163 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1164 + * 02110-1301, USA.
1165 + */
1166 +
1167 +#include <linux/slab.h>
1168 +#include <linux/io.h>
1169 +#include <linux/module.h>
1170 +#include <linux/mutex.h>
1171 +#include <linux/errno.h>
1172 +#include <linux/err.h>
1173 +
1174 +#include <asm/cacheflush.h>
1175 +
1176 +#include "scm.h"
1177 +
1178 +/* Cache line size for msm8x60 */
1179 +#define CACHELINESIZE 32
1180 +
1181 +#define SCM_ENOMEM -5
1182 +#define SCM_EOPNOTSUPP -4
1183 +#define SCM_EINVAL_ADDR -3
1184 +#define SCM_EINVAL_ARG -2
1185 +#define SCM_ERROR -1
1186 +#define SCM_INTERRUPTED 1
1187 +
1188 +static DEFINE_MUTEX(scm_lock);
1189 +
1190 +/**
1191 + * struct scm_command - one SCM command buffer
1192 + * @len: total available memory for command and response
1193 + * @buf_offset: start of command buffer
1194 + * @resp_hdr_offset: start of response buffer
1195 + * @id: command to be executed
1196 + * @buf: buffer returned from scm_get_command_buffer()
1197 + *
1198 + * An SCM command is laid out in memory as follows:
1199 + *
1200 + * ------------------- <--- struct scm_command
1201 + * | command header |
1202 + * ------------------- <--- scm_get_command_buffer()
1203 + * | command buffer |
1204 + * ------------------- <--- struct scm_response and
1205 + * | response header | scm_command_to_response()
1206 + * ------------------- <--- scm_get_response_buffer()
1207 + * | response buffer |
1208 + * -------------------
1209 + *
1210 + * There can be arbitrary padding between the headers and buffers so
1211 + * you should always use the appropriate scm_get_*_buffer() routines
1212 + * to access the buffers in a safe manner.
1213 + */
1214 +struct scm_command {
1215 + u32 len;
1216 + u32 buf_offset;
1217 + u32 resp_hdr_offset;
1218 + u32 id;
1219 + u32 buf[0];
1220 +};
1221 +
1222 +/**
1223 + * struct scm_response - one SCM response buffer
1224 + * @len: total available memory for response
1225 + * @buf_offset: start of response data relative to start of scm_response
1226 + * @is_complete: indicates if the command has finished processing
1227 + */
1228 +struct scm_response {
1229 + u32 len;
1230 + u32 buf_offset;
1231 + u32 is_complete;
1232 +};
1233 +
1234 +/**
1235 + * alloc_scm_command() - Allocate an SCM command
1236 + * @cmd_size: size of the command buffer
1237 + * @resp_size: size of the response buffer
1238 + *
1239 + * Allocate an SCM command, including enough room for the command
1240 + * and response headers as well as the command and response buffers.
1241 + *
1242 + * Returns a valid &scm_command on success or %NULL if the allocation fails.
1243 + */
1244 +static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
1245 +{
1246 + struct scm_command *cmd;
1247 + size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
1248 + resp_size;
1249 +
1250 + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
1251 + if (cmd) {
1252 + cmd->len = len;
1253 + cmd->buf_offset = offsetof(struct scm_command, buf);
1254 + cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
1255 + }
1256 + return cmd;
1257 +}
1258 +
1259 +/**
1260 + * free_scm_command() - Free an SCM command
1261 + * @cmd: command to free
1262 + *
1263 + * Free an SCM command.
1264 + */
1265 +static inline void free_scm_command(struct scm_command *cmd)
1266 +{
1267 + kfree(cmd);
1268 +}
1269 +
1270 +/**
1271 + * scm_command_to_response() - Get a pointer to a scm_response
1272 + * @cmd: command
1273 + *
1274 + * Returns a pointer to a response for a command.
1275 + */
1276 +static inline struct scm_response *scm_command_to_response(
1277 + const struct scm_command *cmd)
1278 +{
1279 + return (void *)cmd + cmd->resp_hdr_offset;
1280 +}
1281 +
1282 +/**
1283 + * scm_get_command_buffer() - Get a pointer to a command buffer
1284 + * @cmd: command
1285 + *
1286 + * Returns a pointer to the command buffer of a command.
1287 + */
1288 +static inline void *scm_get_command_buffer(const struct scm_command *cmd)
1289 +{
1290 + return (void *)cmd->buf;
1291 +}
1292 +
1293 +/**
1294 + * scm_get_response_buffer() - Get a pointer to a response buffer
1295 + * @rsp: response
1296 + *
1297 + * Returns a pointer to a response buffer of a response.
1298 + */
1299 +static inline void *scm_get_response_buffer(const struct scm_response *rsp)
1300 +{
1301 + return (void *)rsp + rsp->buf_offset;
1302 +}
1303 +
1304 +static int scm_remap_error(int err)
1305 +{
1306 + switch (err) {
1307 + case SCM_ERROR:
1308 + return -EIO;
1309 + case SCM_EINVAL_ADDR:
1310 + case SCM_EINVAL_ARG:
1311 + return -EINVAL;
1312 + case SCM_EOPNOTSUPP:
1313 + return -EOPNOTSUPP;
1314 + case SCM_ENOMEM:
1315 + return -ENOMEM;
1316 + }
1317 + return -EINVAL;
1318 +}
1319 +
1320 +static u32 smc(u32 cmd_addr)
1321 +{
1322 + int context_id;
1323 + register u32 r0 asm("r0") = 1;
1324 + register u32 r1 asm("r1") = (u32)&context_id;
1325 + register u32 r2 asm("r2") = cmd_addr;
1326 + do {
1327 + asm volatile(
1328 + __asmeq("%0", "r0")
1329 + __asmeq("%1", "r0")
1330 + __asmeq("%2", "r1")
1331 + __asmeq("%3", "r2")
1332 +#ifdef REQUIRES_SEC
1333 + ".arch_extension sec\n"
1334 +#endif
1335 + "smc #0 @ switch to secure world\n"
1336 + : "=r" (r0)
1337 + : "r" (r0), "r" (r1), "r" (r2)
1338 + : "r3");
1339 + } while (r0 == SCM_INTERRUPTED);
1340 +
1341 + return r0;
1342 +}
1343 +
1344 +static int __scm_call(const struct scm_command *cmd)
1345 +{
1346 + int ret;
1347 + u32 cmd_addr = virt_to_phys(cmd);
1348 +
1349 + /*
1350 + * Flush the entire cache here so callers don't have to remember
1351 + * to flush the cache when passing physical addresses to the secure
1352 + * side in the buffer.
1353 + */
1354 + flush_cache_all();
1355 + ret = smc(cmd_addr);
1356 + if (ret < 0)
1357 + ret = scm_remap_error(ret);
1358 +
1359 + return ret;
1360 +}
1361 +
1362 +/**
1363 + * scm_call() - Send an SCM command
1364 + * @svc_id: service identifier
1365 + * @cmd_id: command identifier
1366 + * @cmd_buf: command buffer
1367 + * @cmd_len: length of the command buffer
1368 + * @resp_buf: response buffer
1369 + * @resp_len: length of the response buffer
1370 + *
1371 + * Sends a command to the SCM and waits for the command to finish processing.
1372 + */
1373 +int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
1374 + void *resp_buf, size_t resp_len)
1375 +{
1376 + int ret;
1377 + struct scm_command *cmd;
1378 + struct scm_response *rsp;
1379 +
1380 + cmd = alloc_scm_command(cmd_len, resp_len);
1381 + if (!cmd)
1382 + return -ENOMEM;
1383 +
1384 + cmd->id = (svc_id << 10) | cmd_id;
1385 + if (cmd_buf)
1386 + memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
1387 +
1388 + mutex_lock(&scm_lock);
1389 + ret = __scm_call(cmd);
1390 + mutex_unlock(&scm_lock);
1391 + if (ret)
1392 + goto out;
1393 +
1394 + rsp = scm_command_to_response(cmd);
1395 + do {
1396 + u32 start = (u32)rsp;
1397 + u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
1398 + start &= ~(CACHELINESIZE - 1);
1399 + while (start < end) {
1400 + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
1401 + : "memory");
1402 + start += CACHELINESIZE;
1403 + }
1404 + } while (!rsp->is_complete);
1405 +
1406 + if (resp_buf)
1407 + memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
1408 +out:
1409 + free_scm_command(cmd);
1410 + return ret;
1411 +}
1412 +EXPORT_SYMBOL(scm_call);
1413 +
1414 +u32 scm_get_version(void)
1415 +{
1416 + int context_id;
1417 + static u32 version = -1;
1418 + register u32 r0 asm("r0");
1419 + register u32 r1 asm("r1");
1420 +
1421 + if (version != -1)
1422 + return version;
1423 +
1424 + mutex_lock(&scm_lock);
1425 +
1426 + r0 = 0x1 << 8;
1427 + r1 = (u32)&context_id;
1428 + do {
1429 + asm volatile(
1430 + __asmeq("%0", "r0")
1431 + __asmeq("%1", "r1")
1432 + __asmeq("%2", "r0")
1433 + __asmeq("%3", "r1")
1434 +#ifdef REQUIRES_SEC
1435 + ".arch_extension sec\n"
1436 +#endif
1437 + "smc #0 @ switch to secure world\n"
1438 + : "=r" (r0), "=r" (r1)
1439 + : "r" (r0), "r" (r1)
1440 + : "r2", "r3");
1441 + } while (r0 == SCM_INTERRUPTED);
1442 +
1443 + version = r1;
1444 + mutex_unlock(&scm_lock);
1445 +
1446 + return version;
1447 +}
1448 +EXPORT_SYMBOL(scm_get_version);
1449 diff --git a/arch/arm/mach-qcom/scm.h b/arch/arm/mach-qcom/scm.h
1450 new file mode 100644
1451 index 0000000..00b31ea
1452 --- /dev/null
1453 +++ b/arch/arm/mach-qcom/scm.h
1454 @@ -0,0 +1,25 @@
1455 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
1456 + *
1457 + * This program is free software; you can redistribute it and/or modify
1458 + * it under the terms of the GNU General Public License version 2 and
1459 + * only version 2 as published by the Free Software Foundation.
1460 + *
1461 + * This program is distributed in the hope that it will be useful,
1462 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1463 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1464 + * GNU General Public License for more details.
1465 + */
1466 +#ifndef __MACH_SCM_H
1467 +#define __MACH_SCM_H
1468 +
1469 +#define SCM_SVC_BOOT 0x1
1470 +#define SCM_SVC_PIL 0x2
1471 +
1472 +extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
1473 + void *resp_buf, size_t resp_len);
1474 +
1475 +#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
1476 +
1477 +extern u32 scm_get_version(void);
1478 +
1479 +#endif
1480 --
1481 1.7.10.4
1482