kernel: update 3.14 to 3.14.18
[openwrt/staging/stintel.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