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