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
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.
11 As part of this, we move support for MSM8X60, MSM8960 and MSM8974 over
14 Signed-off-by: Kumar Gala <galak@codeaurora.org>
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
55 @@ -1168,6 +1168,14 @@ L: linux-arm-kernel@lists.infradead.org
56 W: http://www.arm.linux.org.uk/
60 +M: Kumar Gala <galak@codeaurora.org>
61 +M: David Brown <davidb@codeaurora.org>
62 +L: linux-arm-msm@vger.kernel.org
64 +F: arch/arm/mach-qcom/
65 +T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
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
74 Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
80 + bool "Qualcomm MSM (non-multiplatform)"
81 select ARCH_REQUIRE_GPIOLIB
83 select GENERIC_CLOCKEVENTS
84 @@ -1006,6 +1005,8 @@ source "arch/arm/plat-pxa/Kconfig"
86 source "arch/arm/mach-mmp/Kconfig"
88 +source "arch/arm/mach-qcom/Kconfig"
90 source "arch/arm/mach-realview/Kconfig"
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
100 + depends on ARCH_MSM || ARCH_QCOM
102 config DEBUG_LL_INCLUDE
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
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
143 - bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7
145 - select ARCH_REQUIRE_GPIOLIB
147 - select GENERIC_CLOCKEVENTS
149 - Support for Qualcomm's devicetree based MSM systems.
153 -menu "Qualcomm MSM SoC Selection"
154 - depends on ARCH_MSM_DT
157 - bool "Enable support for MSM8X60"
161 - select MSM_SCM if SMP
165 - bool "Enable support for MSM8960"
169 - select MSM_SCM if SMP
173 - bool "Enable support for MSM8974"
176 - select HAVE_ARM_ARCH_TIMER
178 - select MSM_SCM if SMP
183 prompt "Qualcomm MSM SoC Type"
184 default ARCH_MSM7X00A
185 - depends on ARCH_MSM_NODT
186 + depends on ARCH_MSM
189 bool "MSM7x00A / MSM7x01A"
190 @@ -99,7 +58,7 @@ config MSM_VIC
193 menu "Qualcomm MSM Board Type"
194 - depends on ARCH_MSM_NODT
195 + 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
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
207 -CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
209 -obj-$(CONFIG_SMP) += platsmp.o
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
222 -/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved.
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.
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.
234 -#include <linux/init.h>
235 -#include <linux/of.h>
236 -#include <linux/of_platform.h>
238 -#include <asm/mach/arch.h>
239 -#include <asm/mach/map.h>
243 -static const char * const msm_dt_match[] __initconst = {
244 - "qcom,msm8660-fluid",
245 - "qcom,msm8660-surf",
246 - "qcom,msm8960-cdp",
250 -static const char * const apq8074_dt_match[] __initconst = {
251 - "qcom,apq8074-dragonboard",
255 -DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
256 - .smp = smp_ops(msm_smp_ops),
257 - .dt_compat = msm_dt_match,
260 -DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)")
261 - .dt_compat = apq8074_dt_match,
263 --- a/arch/arm/mach-msm/platsmp.c
267 - * Copyright (C) 2002 ARM Ltd.
268 - * All Rights Reserved
269 - * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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>
283 -#include <asm/cputype.h>
284 -#include <asm/smp_plat.h>
286 -#include "scm-boot.h"
289 -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
290 -#define SCSS_CPU1CORE_RESET 0xD80
291 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
293 -extern void secondary_startup(void);
295 -static DEFINE_SPINLOCK(boot_lock);
297 -#ifdef CONFIG_HOTPLUG_CPU
298 -static void __ref msm_cpu_die(unsigned int cpu)
304 -static inline int get_core_count(void)
306 - /* 1 + the PART[1:0] field of MIDR */
307 - return ((read_cpuid_id() >> 4) & 3) + 1;
310 -static void msm_secondary_init(unsigned int cpu)
313 - * Synchronise with the boot thread.
315 - spin_lock(&boot_lock);
316 - spin_unlock(&boot_lock);
319 -static void prepare_cold_cpu(unsigned int cpu)
322 - ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
323 - SCM_FLAG_COLDBOOT_CPU1);
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);
334 - printk(KERN_DEBUG "Failed to set secondary core boot "
338 -static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
340 - static int cold_boot_done;
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;
349 - * set synchronisation state between this boot processor
350 - * and the secondary one
352 - spin_lock(&boot_lock);
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.
359 - arch_send_wakeup_ipi_mask(cpumask_of(cpu));
362 - * now the secondary core is starting up let it run its
363 - * calibrations, then wait for it to finish
365 - spin_unlock(&boot_lock);
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
376 -static void __init msm_smp_init_cpus(void)
378 - unsigned int i, ncores = get_core_count();
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;
386 - for (i = 0; i < ncores; i++)
387 - set_cpu_possible(i, true);
390 -static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
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,
403 --- a/arch/arm/mach-msm/scm-boot.c
406 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
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
423 -#include <linux/module.h>
424 -#include <linux/slab.h>
427 -#include "scm-boot.h"
430 - * Set the cold/warm boot address for one of the CPU cores.
432 -int scm_set_boot_addr(phys_addr_t addr, int flags)
435 - unsigned int flags;
441 - return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
442 - &cmd, sizeof(cmd), NULL, 0);
444 -EXPORT_SYMBOL(scm_set_boot_addr);
445 --- a/arch/arm/mach-msm/scm-boot.h
448 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
459 -#ifndef __MACH_SCM_BOOT_H
460 -#define __MACH_SCM_BOOT_H
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
467 -int scm_set_boot_addr(phys_addr_t addr, int flags);
470 --- a/arch/arm/mach-msm/scm.c
473 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
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
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>
497 -#include <asm/cacheflush.h>
501 -/* Cache line size for msm8x60 */
502 -#define CACHELINESIZE 32
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
511 -static DEFINE_MUTEX(scm_lock);
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()
521 - * An SCM command is laid out in memory as follows:
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 - * -------------------
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.
537 -struct scm_command {
540 - u32 resp_hdr_offset;
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
551 -struct scm_response {
558 - * alloc_scm_command() - Allocate an SCM command
559 - * @cmd_size: size of the command buffer
560 - * @resp_size: size of the response buffer
562 - * Allocate an SCM command, including enough room for the command
563 - * and response headers as well as the command and response buffers.
565 - * Returns a valid &scm_command on success or %NULL if the allocation fails.
567 -static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
569 - struct scm_command *cmd;
570 - size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
573 - cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
576 - cmd->buf_offset = offsetof(struct scm_command, buf);
577 - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
583 - * free_scm_command() - Free an SCM command
584 - * @cmd: command to free
586 - * Free an SCM command.
588 -static inline void free_scm_command(struct scm_command *cmd)
594 - * scm_command_to_response() - Get a pointer to a scm_response
597 - * Returns a pointer to a response for a command.
599 -static inline struct scm_response *scm_command_to_response(
600 - const struct scm_command *cmd)
602 - return (void *)cmd + cmd->resp_hdr_offset;
606 - * scm_get_command_buffer() - Get a pointer to a command buffer
609 - * Returns a pointer to the command buffer of a command.
611 -static inline void *scm_get_command_buffer(const struct scm_command *cmd)
613 - return (void *)cmd->buf;
617 - * scm_get_response_buffer() - Get a pointer to a response buffer
620 - * Returns a pointer to a response buffer of a response.
622 -static inline void *scm_get_response_buffer(const struct scm_response *rsp)
624 - return (void *)rsp + rsp->buf_offset;
627 -static int scm_remap_error(int err)
632 - case SCM_EINVAL_ADDR:
633 - case SCM_EINVAL_ARG:
635 - case SCM_EOPNOTSUPP:
636 - return -EOPNOTSUPP;
643 -static u32 smc(u32 cmd_addr)
646 - register u32 r0 asm("r0") = 1;
647 - register u32 r1 asm("r1") = (u32)&context_id;
648 - register u32 r2 asm("r2") = cmd_addr;
651 - __asmeq("%0", "r0")
652 - __asmeq("%1", "r0")
653 - __asmeq("%2", "r1")
654 - __asmeq("%3", "r2")
656 - ".arch_extension sec\n"
658 - "smc #0 @ switch to secure world\n"
660 - : "r" (r0), "r" (r1), "r" (r2)
662 - } while (r0 == SCM_INTERRUPTED);
667 -static int __scm_call(const struct scm_command *cmd)
670 - u32 cmd_addr = virt_to_phys(cmd);
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.
678 - ret = smc(cmd_addr);
680 - ret = scm_remap_error(ret);
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
694 - * Sends a command to the SCM and waits for the command to finish processing.
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)
700 - struct scm_command *cmd;
701 - struct scm_response *rsp;
703 - cmd = alloc_scm_command(cmd_len, resp_len);
707 - cmd->id = (svc_id << 10) | cmd_id;
709 - memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
711 - mutex_lock(&scm_lock);
712 - ret = __scm_call(cmd);
713 - mutex_unlock(&scm_lock);
717 - rsp = scm_command_to_response(cmd);
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)
725 - start += CACHELINESIZE;
727 - } while (!rsp->is_complete);
730 - memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
732 - free_scm_command(cmd);
735 -EXPORT_SYMBOL(scm_call);
737 -u32 scm_get_version(void)
740 - static u32 version = -1;
741 - register u32 r0 asm("r0");
742 - register u32 r1 asm("r1");
747 - mutex_lock(&scm_lock);
750 - r1 = (u32)&context_id;
753 - __asmeq("%0", "r0")
754 - __asmeq("%1", "r1")
755 - __asmeq("%2", "r0")
756 - __asmeq("%3", "r1")
758 - ".arch_extension sec\n"
760 - "smc #0 @ switch to secure world\n"
761 - : "=r" (r0), "=r" (r1)
762 - : "r" (r0), "r" (r1)
764 - } while (r0 == SCM_INTERRUPTED);
767 - mutex_unlock(&scm_lock);
771 -EXPORT_SYMBOL(scm_get_version);
772 --- a/arch/arm/mach-msm/scm.h
775 -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
786 -#ifndef __MACH_SCM_H
787 -#define __MACH_SCM_H
789 -#define SCM_SVC_BOOT 0x1
790 -#define SCM_SVC_PIL 0x2
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);
795 -#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
797 -extern u32 scm_get_version(void);
801 +++ b/arch/arm/mach-qcom/Kconfig
804 + bool "Qualcomm Support" if ARCH_MULTI_V7
805 + select ARCH_REQUIRE_GPIOLIB
808 + select GENERIC_CLOCKEVENTS
810 + select QCOM_SCM if SMP
812 + Support for Qualcomm's devicetree based systems.
816 +menu "Qualcomm SoC Selection"
819 + bool "Enable support for MSM8X60"
823 + bool "Enable support for MSM8960"
827 + bool "Enable support for MSM8974"
828 + select HAVE_ARM_ARCH_TIMER
837 +++ b/arch/arm/mach-qcom/Makefile
840 +obj-$(CONFIG_SMP) += platsmp.o
841 +obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
843 +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
845 +++ b/arch/arm/mach-qcom/board.c
847 +/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
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.
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.
859 +#include <linux/init.h>
860 +#include <linux/of.h>
861 +#include <linux/of_platform.h>
863 +#include <asm/mach/arch.h>
864 +#include <asm/mach/map.h>
866 +extern struct smp_operations msm_smp_ops;
868 +static const char * const qcom_dt_match[] __initconst = {
869 + "qcom,msm8660-surf",
870 + "qcom,msm8960-cdp",
874 +static const char * const apq8074_dt_match[] __initconst = {
875 + "qcom,apq8074-dragonboard",
879 +DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
880 + .smp = smp_ops(msm_smp_ops),
881 + .dt_compat = qcom_dt_match,
884 +DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)")
885 + .dt_compat = apq8074_dt_match,
888 +++ b/arch/arm/mach-qcom/platsmp.c
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.
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.
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>
908 +#include <asm/cputype.h>
909 +#include <asm/smp_plat.h>
911 +#include "scm-boot.h"
913 +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
914 +#define SCSS_CPU1CORE_RESET 0xD80
915 +#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
917 +extern void secondary_startup(void);
919 +static DEFINE_SPINLOCK(boot_lock);
921 +#ifdef CONFIG_HOTPLUG_CPU
922 +static void __ref msm_cpu_die(unsigned int cpu)
928 +static inline int get_core_count(void)
930 + /* 1 + the PART[1:0] field of MIDR */
931 + return ((read_cpuid_id() >> 4) & 3) + 1;
934 +static void msm_secondary_init(unsigned int cpu)
937 + * Synchronise with the boot thread.
939 + spin_lock(&boot_lock);
940 + spin_unlock(&boot_lock);
943 +static void prepare_cold_cpu(unsigned int cpu)
946 + ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
947 + SCM_FLAG_COLDBOOT_CPU1);
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);
958 + printk(KERN_DEBUG "Failed to set secondary core boot "
962 +static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
964 + static int cold_boot_done;
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;
973 + * set synchronisation state between this boot processor
974 + * and the secondary one
976 + spin_lock(&boot_lock);
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.
983 + arch_send_wakeup_ipi_mask(cpumask_of(cpu));
986 + * now the secondary core is starting up let it run its
987 + * calibrations, then wait for it to finish
989 + spin_unlock(&boot_lock);
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
1000 +static void __init msm_smp_init_cpus(void)
1002 + unsigned int i, ncores = get_core_count();
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;
1010 + for (i = 0; i < ncores; i++)
1011 + set_cpu_possible(i, true);
1014 +static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
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,
1028 +++ b/arch/arm/mach-qcom/scm-boot.c
1030 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
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.
1047 +#include <linux/module.h>
1048 +#include <linux/slab.h>
1051 +#include "scm-boot.h"
1054 + * Set the cold/warm boot address for one of the CPU cores.
1056 +int scm_set_boot_addr(phys_addr_t addr, int flags)
1059 + unsigned int flags;
1064 + cmd.flags = flags;
1065 + return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
1066 + &cmd, sizeof(cmd), NULL, 0);
1068 +EXPORT_SYMBOL(scm_set_boot_addr);
1070 +++ b/arch/arm/mach-qcom/scm-boot.h
1072 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
1083 +#ifndef __MACH_SCM_BOOT_H
1084 +#define __MACH_SCM_BOOT_H
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
1091 +int scm_set_boot_addr(phys_addr_t addr, int flags);
1095 +++ b/arch/arm/mach-qcom/scm.c
1097 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
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.
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>
1121 +#include <asm/cacheflush.h>
1125 +/* Cache line size for msm8x60 */
1126 +#define CACHELINESIZE 32
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
1135 +static DEFINE_MUTEX(scm_lock);
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()
1145 + * An SCM command is laid out in memory as follows:
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 + * -------------------
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.
1161 +struct scm_command {
1164 + u32 resp_hdr_offset;
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
1175 +struct scm_response {
1182 + * alloc_scm_command() - Allocate an SCM command
1183 + * @cmd_size: size of the command buffer
1184 + * @resp_size: size of the response buffer
1186 + * Allocate an SCM command, including enough room for the command
1187 + * and response headers as well as the command and response buffers.
1189 + * Returns a valid &scm_command on success or %NULL if the allocation fails.
1191 +static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
1193 + struct scm_command *cmd;
1194 + size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
1197 + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
1200 + cmd->buf_offset = offsetof(struct scm_command, buf);
1201 + cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
1207 + * free_scm_command() - Free an SCM command
1208 + * @cmd: command to free
1210 + * Free an SCM command.
1212 +static inline void free_scm_command(struct scm_command *cmd)
1218 + * scm_command_to_response() - Get a pointer to a scm_response
1221 + * Returns a pointer to a response for a command.
1223 +static inline struct scm_response *scm_command_to_response(
1224 + const struct scm_command *cmd)
1226 + return (void *)cmd + cmd->resp_hdr_offset;
1230 + * scm_get_command_buffer() - Get a pointer to a command buffer
1233 + * Returns a pointer to the command buffer of a command.
1235 +static inline void *scm_get_command_buffer(const struct scm_command *cmd)
1237 + return (void *)cmd->buf;
1241 + * scm_get_response_buffer() - Get a pointer to a response buffer
1244 + * Returns a pointer to a response buffer of a response.
1246 +static inline void *scm_get_response_buffer(const struct scm_response *rsp)
1248 + return (void *)rsp + rsp->buf_offset;
1251 +static int scm_remap_error(int err)
1256 + case SCM_EINVAL_ADDR:
1257 + case SCM_EINVAL_ARG:
1259 + case SCM_EOPNOTSUPP:
1260 + return -EOPNOTSUPP;
1267 +static u32 smc(u32 cmd_addr)
1270 + register u32 r0 asm("r0") = 1;
1271 + register u32 r1 asm("r1") = (u32)&context_id;
1272 + register u32 r2 asm("r2") = cmd_addr;
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"
1282 + "smc #0 @ switch to secure world\n"
1284 + : "r" (r0), "r" (r1), "r" (r2)
1286 + } while (r0 == SCM_INTERRUPTED);
1291 +static int __scm_call(const struct scm_command *cmd)
1294 + u32 cmd_addr = virt_to_phys(cmd);
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.
1301 + flush_cache_all();
1302 + ret = smc(cmd_addr);
1304 + ret = scm_remap_error(ret);
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
1318 + * Sends a command to the SCM and waits for the command to finish processing.
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)
1324 + struct scm_command *cmd;
1325 + struct scm_response *rsp;
1327 + cmd = alloc_scm_command(cmd_len, resp_len);
1331 + cmd->id = (svc_id << 10) | cmd_id;
1333 + memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
1335 + mutex_lock(&scm_lock);
1336 + ret = __scm_call(cmd);
1337 + mutex_unlock(&scm_lock);
1341 + rsp = scm_command_to_response(cmd);
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)
1349 + start += CACHELINESIZE;
1351 + } while (!rsp->is_complete);
1354 + memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
1356 + free_scm_command(cmd);
1359 +EXPORT_SYMBOL(scm_call);
1361 +u32 scm_get_version(void)
1364 + static u32 version = -1;
1365 + register u32 r0 asm("r0");
1366 + register u32 r1 asm("r1");
1368 + if (version != -1)
1371 + mutex_lock(&scm_lock);
1374 + r1 = (u32)&context_id;
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"
1384 + "smc #0 @ switch to secure world\n"
1385 + : "=r" (r0), "=r" (r1)
1386 + : "r" (r0), "r" (r1)
1388 + } while (r0 == SCM_INTERRUPTED);
1391 + mutex_unlock(&scm_lock);
1395 +EXPORT_SYMBOL(scm_get_version);
1397 +++ b/arch/arm/mach-qcom/scm.h
1399 +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
1410 +#ifndef __MACH_SCM_H
1411 +#define __MACH_SCM_H
1413 +#define SCM_SVC_BOOT 0x1
1414 +#define SCM_SVC_PIL 0x2
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);
1419 +#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
1421 +extern u32 scm_get_version(void);