From patchwork Tue Oct 29 19:40:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5377B13BD for ; Tue, 29 Oct 2019 19:42:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1D31C21721 for ; Tue, 29 Oct 2019 19:42:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="R3Sb9hiF"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="AIc8Kums" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732602AbfJ2TlQ (ORCPT ); Tue, 29 Oct 2019 15:41:16 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58600 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732226AbfJ2TlO (ORCPT ); Tue, 29 Oct 2019 15:41:14 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 049C760F7A; Tue, 29 Oct 2019 19:41:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378073; bh=jsn3Enh9ZO06Gy9rzGazEy3RVnLJoylO96UzI0UWFqA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R3Sb9hiFw+dxETpHk0zMwEtR/GMRY4GxBKQuHvxtcNWiAvwxl+93O6lM/PbqulJuU NNhGxf4dkW3KVnCEsG66UiCmrwnoeizOJvCEa33k1DYucvgzFEJabZG/JzQ69aRUql oUuOOTV43aKqY8MIQkLDOIQJjX5AXdfAR6/vdiew= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 600ED60D86; Tue, 29 Oct 2019 19:41:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378071; bh=jsn3Enh9ZO06Gy9rzGazEy3RVnLJoylO96UzI0UWFqA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AIc8Kumsk70zZUb+faGt5RuzfGC4jAWVUAf5NwmkhhNz0qAVOgycPnhXbJJA8NM07 wGHxyJelsB7lrQ8+EDMJ7V8pYUTvBx1+0ELK/Zq6VRk3SXHozPmBrtq0t5FgIZH2DN 0bUjBumC/bPmFdMylQgDDHovQs43RRVbjUUhpz/c= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 600ED60D86 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 01/17] firmware: qcom_scm: Rename macros and structures Date: Tue, 29 Oct 2019 12:40:49 -0700 Message-Id: <1572378065-4490-2-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org - Rename legacy-specific structures and macros with "legacy_" prefix. - Rename smccc-specific structures and macros with "smccc_" prefix. - Flip calculation of SMCCC_N_EXT_ARGS to be a function of N_REG_ARGS (not the other way around). N_REG_ARGS is fixed based off the SMC instruction and shouldn't be computed from the SCM abstraction. - Move SMCCC_FUNCNUM closer to other smccc-specific macros. - Add LEGACY_FUNCNUM macro to qcom_scm-32.c Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 72 ++++++++++++++++++++++-------------------- drivers/firmware/qcom_scm-64.c | 54 +++++++++++++++---------------- drivers/firmware/qcom_scm.c | 2 +- drivers/firmware/qcom_scm.h | 2 +- include/linux/qcom_scm.h | 2 +- 5 files changed, 67 insertions(+), 65 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index bee8729..d416efc 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2010,2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd. */ @@ -38,23 +38,25 @@ static struct qcom_scm_entry qcom_scm_wb[] = { static DEFINE_MUTEX(qcom_scm_lock); +#define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) + /** - * struct qcom_scm_command - one SCM command buffer + * struct legacy_command - one SCM command buffer * @len: total available memory for command and response * @buf_offset: start of command buffer * @resp_hdr_offset: start of response buffer * @id: command to be executed - * @buf: buffer returned from qcom_scm_get_command_buffer() + * @buf: buffer returned from legacy_get_command_buffer() * * An SCM command is laid out in memory as follows: * - * ------------------- <--- struct qcom_scm_command + * ------------------- <--- struct legacy_command * | command header | - * ------------------- <--- qcom_scm_get_command_buffer() + * ------------------- <--- legacy_get_command_buffer() * | command buffer | - * ------------------- <--- struct qcom_scm_response and - * | response header | qcom_scm_command_to_response() - * ------------------- <--- qcom_scm_get_response_buffer() + * ------------------- <--- struct legacy_response and + * | response header | legacy_command_to_response() + * ------------------- <--- legacy_get_response_buffer() * | response buffer | * ------------------- * @@ -62,7 +64,7 @@ static DEFINE_MUTEX(qcom_scm_lock); * you should always use the appropriate qcom_scm_get_*_buffer() routines * to access the buffers in a safe manner. */ -struct qcom_scm_command { +struct legacy_command { __le32 len; __le32 buf_offset; __le32 resp_hdr_offset; @@ -71,52 +73,52 @@ struct qcom_scm_command { }; /** - * struct qcom_scm_response - one SCM response buffer + * struct legacy_response - one SCM response buffer * @len: total available memory for response - * @buf_offset: start of response data relative to start of qcom_scm_response + * @buf_offset: start of response data relative to start of legacy_response * @is_complete: indicates if the command has finished processing */ -struct qcom_scm_response { +struct legacy_response { __le32 len; __le32 buf_offset; __le32 is_complete; }; /** - * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response + * legacy_command_to_response() - Get a pointer to a legacy_response * @cmd: command * * Returns a pointer to a response for a command. */ -static inline struct qcom_scm_response *qcom_scm_command_to_response( - const struct qcom_scm_command *cmd) +static inline struct legacy_response *legacy_command_to_response( + const struct legacy_command *cmd) { return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); } /** - * qcom_scm_get_command_buffer() - Get a pointer to a command buffer + * legacy_get_command_buffer() - Get a pointer to a command buffer * @cmd: command * * Returns a pointer to the command buffer of a command. */ -static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd) +static inline void *legacy_get_command_buffer(const struct legacy_command *cmd) { return (void *)cmd->buf; } /** - * qcom_scm_get_response_buffer() - Get a pointer to a response buffer + * legacy_get_response_buffer() - Get a pointer to a response buffer * @rsp: response * * Returns a pointer to a response buffer of a response. */ -static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp) +static inline void *legacy_get_response_buffer(const struct legacy_response *rsp) { return (void *)rsp + le32_to_cpu(rsp->buf_offset); } -static u32 smc(u32 cmd_addr) +static u32 __qcom_scm_call_do(u32 cmd_addr) { int context_id; register u32 r0 asm("r0") = 1; @@ -164,8 +166,8 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, size_t resp_len) { int ret; - struct qcom_scm_command *cmd; - struct qcom_scm_response *rsp; + struct legacy_command *cmd; + struct legacy_response *rsp; size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; dma_addr_t cmd_phys; @@ -177,11 +179,11 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); - cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); + cmd->id = cpu_to_le32(LEGACY_FUNCNUM(svc_id, cmd_id)); if (cmd_buf) - memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len); + memcpy(legacy_get_command_buffer(cmd), cmd_buf, cmd_len); - rsp = qcom_scm_command_to_response(cmd); + rsp = legacy_command_to_response(cmd); cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); if (dma_mapping_error(dev, cmd_phys)) { @@ -190,7 +192,7 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, } mutex_lock(&qcom_scm_lock); - ret = smc(cmd_phys); + ret = __qcom_scm_call_do(cmd_phys); if (ret < 0) ret = qcom_scm_remap_error(ret); mutex_unlock(&qcom_scm_lock); @@ -206,7 +208,7 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + le32_to_cpu(rsp->buf_offset), resp_len, DMA_FROM_DEVICE); - memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), + memcpy(resp_buf, legacy_get_response_buffer(rsp), resp_len); } out: @@ -215,12 +217,12 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, return ret; } -#define SCM_CLASS_REGISTER (0x2 << 8) -#define SCM_MASK_IRQS BIT(5) -#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \ - SCM_CLASS_REGISTER | \ - SCM_MASK_IRQS | \ - (n & 0xf)) +#define LEGACY_CLASS_REGISTER (0x2 << 8) +#define LEGACY_MASK_IRQS BIT(5) +#define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ + LEGACY_CLASS_REGISTER | \ + LEGACY_MASK_IRQS | \ + (n & 0xf)) /** * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument @@ -235,7 +237,7 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1); + register u32 r0 asm("r0") = LEGACY_ATOMIC(svc, cmd, 1); register u32 r1 asm("r1") = (u32)&context_id; register u32 r2 asm("r2") = arg1; @@ -268,7 +270,7 @@ static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2); + register u32 r0 asm("r0") = LEGACY_ATOMIC(svc, cmd, 2); register u32 r1 asm("r1") = (u32)&context_id; register u32 r2 asm("r2") = arg1; register u32 r3 asm("r3") = arg2; diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 7686786..e6721b5 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved. */ #include @@ -14,8 +14,6 @@ #include "qcom_scm.h" -#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) - #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 @@ -58,11 +56,12 @@ static DEFINE_MUTEX(qcom_scm_lock); #define QCOM_SCM_EBUSY_WAIT_MS 30 #define QCOM_SCM_EBUSY_MAX_RETRY 20 -#define N_EXT_QCOM_SCM_ARGS 7 -#define FIRST_EXT_ARG_IDX 3 -#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1) +#define SMCCC_FUNCNUM(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) +#define SMCCC_N_REG_ARGS 4 +#define SMCCC_FIRST_REG_IDX 2 +#define SMCCC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SMCCC_N_REG_ARGS + 1) -static void __qcom_scm_call_do(const struct qcom_scm_desc *desc, +static void __qcom_scm_call_do_quirk(const struct qcom_scm_desc *desc, struct arm_smccc_res *res, u32 fn_id, u64 x5, u32 type) { @@ -85,22 +84,23 @@ static void __qcom_scm_call_do(const struct qcom_scm_desc *desc, } while (res->a0 == QCOM_SCM_INTERRUPTED); } -static void qcom_scm_call_do(const struct qcom_scm_desc *desc, +static void qcom_scm_call_do_smccc(const struct qcom_scm_desc *desc, struct arm_smccc_res *res, u32 fn_id, u64 x5, bool atomic) { int retry_count = 0; if (atomic) { - __qcom_scm_call_do(desc, res, fn_id, x5, ARM_SMCCC_FAST_CALL); + __qcom_scm_call_do_quirk(desc, res, fn_id, x5, + ARM_SMCCC_FAST_CALL); return; } do { mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do(desc, res, fn_id, x5, - ARM_SMCCC_STD_CALL); + __qcom_scm_call_do_quirk(desc, res, fn_id, x5, + ARM_SMCCC_STD_CALL); mutex_unlock(&qcom_scm_lock); @@ -112,21 +112,21 @@ static void qcom_scm_call_do(const struct qcom_scm_desc *desc, } while (res->a0 == QCOM_SCM_V2_EBUSY); } -static int ___qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, - const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, bool atomic) +static int ___qcom_scm_call_smccc(struct device *dev, u32 svc_id, u32 cmd_id, + const struct qcom_scm_desc *desc, + struct arm_smccc_res *res, bool atomic) { int arglen = desc->arginfo & 0xf; int i; - u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id); - u64 x5 = desc->args[FIRST_EXT_ARG_IDX]; + u32 fn_id = SMCCC_FUNCNUM(svc_id, cmd_id); + u64 x5 = desc->args[SMCCC_N_REG_ARGS - 1]; dma_addr_t args_phys = 0; void *args_virt = NULL; size_t alloc_len; gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL; - if (unlikely(arglen > N_REGISTER_ARGS)) { - alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64); + if (unlikely(arglen > SMCCC_N_REG_ARGS)) { + alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64); args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag); if (!args_virt) @@ -135,15 +135,15 @@ static int ___qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, if (qcom_smccc_convention == ARM_SMCCC_SMC_32) { __le32 *args = args_virt; - for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++) + for (i = 0; i < SMCCC_N_EXT_ARGS; i++) args[i] = cpu_to_le32(desc->args[i + - FIRST_EXT_ARG_IDX]); + SMCCC_N_REG_ARGS - 1]); } else { __le64 *args = args_virt; - for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++) + for (i = 0; i < SMCCC_N_EXT_ARGS; i++) args[i] = cpu_to_le64(desc->args[i + - FIRST_EXT_ARG_IDX]); + SMCCC_N_REG_ARGS - 1]); } args_phys = dma_map_single(dev, args_virt, alloc_len, @@ -157,7 +157,7 @@ static int ___qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, x5 = args_phys; } - qcom_scm_call_do(desc, res, fn_id, x5, atomic); + qcom_scm_call_do_smccc(desc, res, fn_id, x5, atomic); if (args_virt) { dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); @@ -185,7 +185,7 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, struct arm_smccc_res *res) { might_sleep(); - return ___qcom_scm_call(dev, svc_id, cmd_id, desc, res, false); + return ___qcom_scm_call_smccc(dev, svc_id, cmd_id, desc, res, false); } /** @@ -203,7 +203,7 @@ static int qcom_scm_call_atomic(struct device *dev, u32 svc_id, u32 cmd_id, const struct qcom_scm_desc *desc, struct arm_smccc_res *res) { - return ___qcom_scm_call(dev, svc_id, cmd_id, desc, res, true); + return ___qcom_scm_call_smccc(dev, svc_id, cmd_id, desc, res, true); } /** @@ -253,7 +253,7 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) struct arm_smccc_res res; desc.arginfo = QCOM_SCM_ARGS(1); - desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) | + desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, @@ -295,7 +295,7 @@ void __qcom_scm_init(void) { u64 cmd; struct arm_smccc_res res; - u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD); + u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD); /* First try a SMC64 call */ cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index a729e05..f83b94d 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -2,7 +2,7 @@ /* * Qualcomm SCM driver * - * Copyright (c) 2010,2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd. */ #include diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index baee744..3c7b74d 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015,2019 The Linux Foundation. All rights reserved. */ #ifndef __QCOM_SCM_INT_H #define __QCOM_SCM_INT_H diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ffd72b3..122cca6 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015,2019 The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd. */ #ifndef __QCOM_SCM_H From patchwork Tue Oct 29 19:40:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218481 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 93460139A for ; Tue, 29 Oct 2019 19:42:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5377921721 for ; Tue, 29 Oct 2019 19:42:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="StUhbhL3"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="IBvEVzh/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732590AbfJ2TlP (ORCPT ); Tue, 29 Oct 2019 15:41:15 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58654 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731976AbfJ2TlP (ORCPT ); Tue, 29 Oct 2019 15:41:15 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id D7BDF60FA9; Tue, 29 Oct 2019 19:41:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378073; bh=922G0voN26Gzv/BX5PphlwvlCSF8WlfwTI1/E0/Rm3w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=StUhbhL3u8LVf9JURpT9jZNyh4Zm0d+C6nLcjke9qWc+7bbUFKo+WlTov05iAuA28 PiSqTJ2M22cc78IDnSmYG6AFvO0LuLGAMXfFZsE28bGjtg2eHV4/NY5LEoAjdg/D2m 5KPA3ICLOrSQbvpTs3gXYBeZxlnC2icaDborMqiE= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id E96A360F36; Tue, 29 Oct 2019 19:41:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378072; bh=922G0voN26Gzv/BX5PphlwvlCSF8WlfwTI1/E0/Rm3w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IBvEVzh/oaV9SD14WnBENjWzj51wFq4IxbnXG5vYZ1683IIXG68jyrFkggnwAvyYO tZYCOmMo7uQRe0H4mwFfqXmqQ13DEmpZPZjssHkVn9uLiiEzWVG4udjr34vEl2RUDs BELmX2E+U3uFAlwxQENGe5VvcOaFEqUWvMDAs+hs= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org E96A360F36 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 02/17] firmware: qcom_scm: Apply consistent naming scheme to command IDs Date: Tue, 29 Oct 2019 12:40:50 -0700 Message-Id: <1572378065-4490-3-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Create a consistent naming scheme for command IDs. The scheme is QCOM_SCM_##svc_##cmd. Remove unused macros QCOM_SCM_FLAG_HLOS, QCOM_SCM_FLAG_COLDBOOT_MC, QCOM_SCM_FLAG_WARMBOOT_MC, QCOM_SCM_CMD_CORE_HOTPLUGGED, and QCOM_SCM_BOOT_ADDR_MC. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 28 ++++++++++++++-------------- drivers/firmware/qcom_scm-64.c | 38 +++++++++++++++++++------------------- drivers/firmware/qcom_scm.c | 8 ++++---- drivers/firmware/qcom_scm.h | 41 ++++++++++++++++++----------------------- 4 files changed, 55 insertions(+), 60 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index d416efc..dee2129 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -356,7 +356,7 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) set_cpu_present(cpu, false); } - return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR, + return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_ADDR, flags, virt_to_phys(entry)); } @@ -395,7 +395,7 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, cmd.addr = cpu_to_le32(virt_to_phys(entry)); cmd.flags = cpu_to_le32(flags); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_ADDR, &cmd, sizeof(cmd), NULL, 0); if (!ret) { for_each_cpu(cpu, cpus) @@ -415,7 +415,7 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, */ void __qcom_scm_cpu_power_down(u32 flags) { - qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, + qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_TERMINATE_PC, flags & QCOM_SCM_FLUSH_FLAG_MASK); } @@ -425,7 +425,7 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id); __le32 ret_val = 0; - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, &svc_cmd, sizeof(svc_cmd), &ret_val, sizeof(ret_val)); if (ret) @@ -440,7 +440,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) return -ERANGE; - return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, + return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, req, req_cnt * sizeof(*req), resp, sizeof(*resp)); } @@ -456,7 +456,7 @@ bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) in = cpu_to_le32(peripheral); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_IS_SUPPORTED_CMD, + QCOM_SCM_PIL_PAS_IS_SUPPORTED, &in, sizeof(in), &out, sizeof(out)); @@ -477,7 +477,7 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, request.image_addr = cpu_to_le32(metadata_phys); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_INIT_IMAGE_CMD, + QCOM_SCM_PIL_PAS_INIT_IMAGE, &request, sizeof(request), &scm_ret, sizeof(scm_ret)); @@ -500,7 +500,7 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, request.len = cpu_to_le32(size); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_MEM_SETUP_CMD, + QCOM_SCM_PIL_PAS_MEM_SETUP, &request, sizeof(request), &scm_ret, sizeof(scm_ret)); @@ -515,7 +515,7 @@ int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) in = cpu_to_le32(peripheral); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_AUTH_AND_RESET_CMD, + QCOM_SCM_PIL_PAS_AUTH_AND_RESET, &in, sizeof(in), &out, sizeof(out)); @@ -530,7 +530,7 @@ int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) in = cpu_to_le32(peripheral); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_SHUTDOWN_CMD, + QCOM_SCM_PIL_PAS_SHUTDOWN, &in, sizeof(in), &out, sizeof(out)); @@ -543,7 +543,7 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) __le32 in = cpu_to_le32(reset); int ret; - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MSS_RESET, &in, sizeof(in), &out, sizeof(out)); @@ -552,8 +552,8 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { - return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE, - enable ? QCOM_SCM_SET_DLOAD_MODE : 0, 0); + return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, + enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0, 0); } int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) @@ -568,7 +568,7 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) req.state = cpu_to_le32(state); req.id = cpu_to_le32(id); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, &req, sizeof(req), &scm_ret, sizeof(scm_ret)); return ret ? : le32_to_cpu(scm_ret); diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index e6721b5..520925d 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -256,7 +256,7 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, &desc, &res); return ret ? : res.a1; @@ -284,7 +284,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, desc.args[9] = req[4].val; desc.arginfo = QCOM_SCM_ARGS(10); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, &desc, &res); *resp = res.a1; @@ -295,7 +295,7 @@ void __qcom_scm_init(void) { u64 cmd; struct arm_smccc_res res; - u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD); + u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL); /* First try a SMC64 call */ cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, @@ -320,7 +320,7 @@ bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) desc.arginfo = QCOM_SCM_ARGS(1); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_IS_SUPPORTED_CMD, + QCOM_SCM_PIL_PAS_IS_SUPPORTED, &desc, &res); return ret ? false : !!res.a1; @@ -337,7 +337,7 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, desc.args[1] = metadata_phys; desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_INIT_IMAGE, &desc, &res); return ret ? : res.a1; @@ -355,7 +355,7 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, desc.args[2] = size; desc.arginfo = QCOM_SCM_ARGS(3); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MEM_SETUP, &desc, &res); return ret ? : res.a1; @@ -371,7 +371,7 @@ int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) desc.arginfo = QCOM_SCM_ARGS(1); ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_AUTH_AND_RESET_CMD, + QCOM_SCM_PIL_PAS_AUTH_AND_RESET, &desc, &res); return ret ? : res.a1; @@ -386,7 +386,7 @@ int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_SHUTDOWN, &desc, &res); return ret ? : res.a1; @@ -402,7 +402,7 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) desc.args[1] = 0; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET, &desc, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MSS_RESET, &desc, &res); return ret ? : res.a1; @@ -418,7 +418,7 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) desc.args[1] = id; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, &desc, &res); return ret ? : res.a1; @@ -445,7 +445,7 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, QCOM_SCM_VAL, QCOM_SCM_VAL); ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_MEM_PROT_ASSIGN_ID, + QCOM_MP_ASSIGN, &desc, &res); return ret ? : res.a1; @@ -461,7 +461,7 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) desc.args[1] = spare; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_MP_RESTORE_SEC_CFG, &desc, &res); return ret ? : res.a1; @@ -478,7 +478,7 @@ int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, desc.arginfo = QCOM_SCM_ARGS(1); ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res); + QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, &desc, &res); if (size) *size = res.a1; @@ -500,7 +500,7 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, QCOM_SCM_VAL); ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res); + QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, &desc, &res); /* the pg table has been initialized already, ignore the error */ if (ret == -EPERM) @@ -514,11 +514,11 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - desc.args[0] = QCOM_SCM_SET_DLOAD_MODE; - desc.args[1] = enable ? QCOM_SCM_SET_DLOAD_MODE : 0; + desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; + desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE, + return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, &desc, &res); } @@ -558,10 +558,10 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - desc.args[0] = QCOM_SCM_CONFIG_ERRATA1_CLIENT_ALL; + desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL; desc.args[1] = en; desc.arginfo = QCOM_SCM_ARGS(2); return qcom_scm_call_atomic(dev, QCOM_SCM_SVC_SMMU_PROGRAM, - QCOM_SCM_CONFIG_ERRATA1, &desc, &res); + QCOM_SCM_SMMU_CONFIG_ERRATA1, &desc, &res); } diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index f83b94d..0fc5c94 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -142,7 +142,7 @@ bool qcom_scm_hdcp_available(void) return ret; ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, - QCOM_SCM_CMD_HDCP); + QCOM_SCM_HDCP_INVOKE); qcom_scm_clk_disable(); @@ -183,7 +183,7 @@ bool qcom_scm_pas_supported(u32 peripheral) int ret; ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PAS_IS_SUPPORTED_CMD); + QCOM_SCM_PIL_PAS_IS_SUPPORTED); if (ret <= 0) return false; @@ -370,12 +370,12 @@ static void qcom_scm_set_download_mode(bool enable) avail = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, - QCOM_SCM_SET_DLOAD_MODE); + QCOM_SCM_BOOT_SET_DLOAD_MODE); if (avail) { ret = __qcom_scm_set_dload_mode(__scm->dev, enable); } else if (__scm->dload_mode_addr) { ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr, - enable ? QCOM_SCM_SET_DLOAD_MODE : 0); + enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0); } else { dev_err(__scm->dev, "No available mechanism for setting download mode\n"); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 3c7b74d..7bc8566 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -5,23 +5,18 @@ #define __QCOM_SCM_INT_H #define QCOM_SCM_SVC_BOOT 0x1 -#define QCOM_SCM_BOOT_ADDR 0x1 -#define QCOM_SCM_SET_DLOAD_MODE 0x10 -#define QCOM_SCM_BOOT_ADDR_MC 0x11 -#define QCOM_SCM_SET_REMOTE_STATE 0xa +#define QCOM_SCM_BOOT_SET_ADDR 0x1 +#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0xa extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); -#define QCOM_SCM_FLAG_HLOS 0x01 -#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02 -#define QCOM_SCM_FLAG_WARMBOOT_MC 0x04 extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); -#define QCOM_SCM_CMD_TERMINATE_PC 0x2 +#define QCOM_SCM_BOOT_TERMINATE_PC 0x2 #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 -#define QCOM_SCM_CMD_CORE_HOTPLUGGED 0x10 extern void __qcom_scm_cpu_power_down(u32 flags); #define QCOM_SCM_SVC_IO 0x5 @@ -31,24 +26,24 @@ extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned in extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val); #define QCOM_SCM_SVC_INFO 0x6 -#define QCOM_IS_CALL_AVAIL_CMD 0x1 +#define QCOM_INFO_IS_CALL_AVAIL 0x1 extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id); #define QCOM_SCM_SVC_HDCP 0x11 -#define QCOM_SCM_CMD_HDCP 0x01 +#define QCOM_SCM_HDCP_INVOKE 0x01 extern int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); extern void __qcom_scm_init(void); #define QCOM_SCM_SVC_PIL 0x2 -#define QCOM_SCM_PAS_INIT_IMAGE_CMD 0x1 -#define QCOM_SCM_PAS_MEM_SETUP_CMD 0x2 -#define QCOM_SCM_PAS_AUTH_AND_RESET_CMD 0x5 -#define QCOM_SCM_PAS_SHUTDOWN_CMD 0x6 -#define QCOM_SCM_PAS_IS_SUPPORTED_CMD 0x7 -#define QCOM_SCM_PAS_MSS_RESET 0xa +#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x1 +#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x2 +#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x5 +#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x6 +#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x7 +#define QCOM_SCM_PIL_PAS_MSS_RESET 0xa extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral); extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, dma_addr_t metadata_phys); @@ -86,21 +81,21 @@ static inline int qcom_scm_remap_error(int err) } #define QCOM_SCM_SVC_MP 0xc -#define QCOM_SCM_RESTORE_SEC_CFG 2 +#define QCOM_SCM_MP_RESTORE_SEC_CFG 2 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); -#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE 3 -#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT 4 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 3 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 4 #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 -#define QCOM_SCM_CONFIG_ERRATA1 0x3 -#define QCOM_SCM_CONFIG_ERRATA1_CLIENT_ALL 0x2 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size); extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable); -#define QCOM_MEM_PROT_ASSIGN_ID 0x16 +#define QCOM_MP_ASSIGN 0x16 extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, size_t mem_sz, phys_addr_t src, size_t src_sz, From patchwork Tue Oct 29 19:40:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218479 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8A849139A for ; Tue, 29 Oct 2019 19:42:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5CEF221D56 for ; Tue, 29 Oct 2019 19:42:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="HPyAtj1Y"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="BdHdK83c" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733186AbfJ2TmN (ORCPT ); Tue, 29 Oct 2019 15:42:13 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58696 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732589AbfJ2TlQ (ORCPT ); Tue, 29 Oct 2019 15:41:16 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 9E9BF60EC7; Tue, 29 Oct 2019 19:41:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378075; bh=mwG0otl1m0KkcBEjjWxO1Pt2VtjKrDfNrsPsF8LcWBA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HPyAtj1YJ2tu83KUibMeFKj5EqawoX5ordew7lkZMFBKmhxSd/Lf4RJzgpkHwAHIk wP6NVuv1h2TKLj7H/P8GXhBNQZ/avRqZKiU/EWeZ3pHDygKLr2doSy52loPVuQsnnr 5C8rePp214aDrGcrguezxv82vZ39PWInJXF/OwhQ= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 8386E60EC7; Tue, 29 Oct 2019 19:41:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378072; bh=mwG0otl1m0KkcBEjjWxO1Pt2VtjKrDfNrsPsF8LcWBA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BdHdK83c6+8sEy8b2akFoLw2YWsJsR3GIE5+WxLknd0iu7nreMBCKkE+VF1+WQq3W 5fE79OR9CgBqsrZU9sBlqTvfEd4XS/tuWvUBWB/ux6tuccgrExlHnf/k3r3iyT48+O Bmb1adN4bL8fdP58oZoT2/l0u9Avns6ZBh9jg8C0= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 8386E60EC7 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 03/17] firmware: qcom_scm: Order functions, definitions by service/command Date: Tue, 29 Oct 2019 12:40:51 -0700 Message-Id: <1572378065-4490-4-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Definitions throughout qcom_scm are loosely grouped and loosely ordered. Sort all the functions/definitions by service ID/command ID to improve sanity when needing to add new functionality to this driver. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 104 +++++++++---------- drivers/firmware/qcom_scm-64.c | 192 +++++++++++++++++------------------ drivers/firmware/qcom_scm.c | 224 ++++++++++++++++++++--------------------- drivers/firmware/qcom_scm.h | 107 ++++++++++---------- include/linux/qcom_scm.h | 72 ++++++------- 5 files changed, 350 insertions(+), 349 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index dee2129..240adfd 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -419,33 +419,28 @@ void __qcom_scm_cpu_power_down(u32 flags) flags & QCOM_SCM_FLUSH_FLAG_MASK); } -int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) +int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { + struct { + __le32 state; + __le32 id; + } req; + __le32 scm_ret = 0; int ret; - __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id); - __le32 ret_val = 0; - - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, - &svc_cmd, sizeof(svc_cmd), &ret_val, - sizeof(ret_val)); - if (ret) - return ret; - return le32_to_cpu(ret_val); -} + req.state = cpu_to_le32(state); + req.id = cpu_to_le32(id); -int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, - u32 req_cnt, u32 *resp) -{ - if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) - return -ERANGE; + ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, + &req, sizeof(req), &scm_ret, sizeof(scm_ret)); - return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, - req, req_cnt * sizeof(*req), resp, sizeof(*resp)); + return ret ? : le32_to_cpu(scm_ret); } -void __qcom_scm_init(void) +int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { + return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, + enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0, 0); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -550,35 +545,37 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) return ret ? : le32_to_cpu(out); } -int __qcom_scm_set_dload_mode(struct device *dev, bool enable) -{ - return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, - enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0, 0); -} - -int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) +int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, + unsigned int *val) { - struct { - __le32 state; - __le32 id; - } req; - __le32 scm_ret = 0; int ret; - req.state = cpu_to_le32(state); - req.id = cpu_to_le32(id); + ret = qcom_scm_call_atomic1(QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, addr); + if (ret >= 0) + *val = ret; - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, - &req, sizeof(req), &scm_ret, sizeof(scm_ret)); + return ret < 0 ? ret : 0; +} - return ret ? : le32_to_cpu(scm_ret); +int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) +{ + return qcom_scm_call_atomic2(QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, + addr, val); } -int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, - size_t mem_sz, phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz) +int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) { - return -ENODEV; + int ret; + __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id); + __le32 ret_val = 0; + + ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, + &svc_cmd, sizeof(svc_cmd), &ret_val, + sizeof(ret_val)); + if (ret) + return ret; + + return le32_to_cpu(ret_val); } int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, @@ -599,25 +596,28 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, return -ENODEV; } -int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, - unsigned int *val) +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, + size_t mem_sz, phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz) { - int ret; - - ret = qcom_scm_call_atomic1(QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, addr); - if (ret >= 0) - *val = ret; - - return ret < 0 ? ret : 0; + return -ENODEV; } -int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) +int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, + u32 req_cnt, u32 *resp) { - return qcom_scm_call_atomic2(QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, - addr, val); + if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) + return -ERANGE; + + return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, + req, req_cnt * sizeof(*req), resp, sizeof(*resp)); } int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable) { return -ENODEV; } + +void __qcom_scm_init(void) +{ +} \ No newline at end of file diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 520925d..ee0c950 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -246,68 +246,33 @@ void __qcom_scm_cpu_power_down(u32 flags) { } -int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) +int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { - int ret; struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; + int ret; - desc.arginfo = QCOM_SCM_ARGS(1); - desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | - (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + desc.args[0] = state; + desc.args[1] = id; + desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, &desc, &res); return ret ? : res.a1; } -int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, - u32 req_cnt, u32 *resp) +int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { - int ret; struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) - return -ERANGE; - - desc.args[0] = req[0].addr; - desc.args[1] = req[0].val; - desc.args[2] = req[1].addr; - desc.args[3] = req[1].val; - desc.args[4] = req[2].addr; - desc.args[5] = req[2].val; - desc.args[6] = req[3].addr; - desc.args[7] = req[3].val; - desc.args[8] = req[4].addr; - desc.args[9] = req[4].val; - desc.arginfo = QCOM_SCM_ARGS(10); - - ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, &desc, - &res); - *resp = res.a1; - - return ret; -} - -void __qcom_scm_init(void) -{ - u64 cmd; - struct arm_smccc_res res; - u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL); - - /* First try a SMC64 call */ - cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, - ARM_SMCCC_OWNER_SIP, function); - - arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)), - 0, 0, 0, 0, 0, &res); + desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; + desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; + desc.arginfo = QCOM_SCM_ARGS(2); - if (!res.a0 && res.a1) - qcom_smccc_convention = ARM_SMCCC_SMC_64; - else - qcom_smccc_convention = ARM_SMCCC_SMC_32; + return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, + &desc, &res); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -408,44 +373,48 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) return ret ? : res.a1; } -int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) +int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, + unsigned int *val) { struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; int ret; - desc.args[0] = state; - desc.args[1] = id; - desc.arginfo = QCOM_SCM_ARGS(2); + desc.args[0] = addr; + desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, &desc, &res); + if (ret >= 0) + *val = res.a1; - return ret ? : res.a1; + return ret < 0 ? ret : 0; } -int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, - size_t mem_sz, phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz) +int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) { - int ret; struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - desc.args[0] = mem_region; - desc.args[1] = mem_sz; - desc.args[2] = src; - desc.args[3] = src_sz; - desc.args[4] = dest; - desc.args[5] = dest_sz; - desc.args[6] = 0; + desc.args[0] = addr; + desc.args[1] = val; + desc.arginfo = QCOM_SCM_ARGS(2); - desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, - QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, - QCOM_SCM_VAL, QCOM_SCM_VAL); + return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, + &desc, &res); +} - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_MP_ASSIGN, +int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) +{ + int ret; + struct qcom_scm_desc desc = {0}; + struct arm_smccc_res res; + + desc.arginfo = QCOM_SCM_ARGS(1); + desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + + ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, &desc, &res); return ret ? : res.a1; @@ -509,48 +478,60 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, return ret; } -int __qcom_scm_set_dload_mode(struct device *dev, bool enable) +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, + size_t mem_sz, phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz) { + int ret; struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; - desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, - &desc, &res); -} - -int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, - unsigned int *val) -{ - struct qcom_scm_desc desc = {0}; - struct arm_smccc_res res; - int ret; + desc.args[0] = mem_region; + desc.args[1] = mem_sz; + desc.args[2] = src; + desc.args[3] = src_sz; + desc.args[4] = dest; + desc.args[5] = dest_sz; + desc.args[6] = 0; - desc.args[0] = addr; - desc.arginfo = QCOM_SCM_ARGS(1); + desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_VAL); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, + ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, + QCOM_MP_ASSIGN, &desc, &res); - if (ret >= 0) - *val = res.a1; - return ret < 0 ? ret : 0; + return ret ? : res.a1; } -int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) +int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, + u32 req_cnt, u32 *resp) { + int ret; struct qcom_scm_desc desc = {0}; struct arm_smccc_res res; - desc.args[0] = addr; - desc.args[1] = val; - desc.arginfo = QCOM_SCM_ARGS(2); + if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) + return -ERANGE; - return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, - &desc, &res); + desc.args[0] = req[0].addr; + desc.args[1] = req[0].val; + desc.args[2] = req[1].addr; + desc.args[3] = req[1].val; + desc.args[4] = req[2].addr; + desc.args[5] = req[2].val; + desc.args[6] = req[3].addr; + desc.args[7] = req[3].val; + desc.args[8] = req[4].addr; + desc.args[9] = req[4].val; + desc.arginfo = QCOM_SCM_ARGS(10); + + ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, &desc, + &res); + *resp = res.a1; + + return ret; } int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) @@ -565,3 +546,22 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) return qcom_scm_call_atomic(dev, QCOM_SCM_SVC_SMMU_PROGRAM, QCOM_SCM_SMMU_CONFIG_ERRATA1, &desc, &res); } + +void __qcom_scm_init(void) +{ + u64 cmd; + struct arm_smccc_res res; + u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL); + + /* First try a SMC64 call */ + cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, + ARM_SMCCC_OWNER_SIP, function); + + arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)), + 0, 0, 0, 0, 0, &res); + + if (!res.a0 && res.a1) + qcom_smccc_convention = ARM_SMCCC_SMC_64; + else + qcom_smccc_convention = ARM_SMCCC_SMC_32; +} diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 0fc5c94..7244236 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -129,47 +129,33 @@ void qcom_scm_cpu_power_down(u32 flags) } EXPORT_SYMBOL(qcom_scm_cpu_power_down); -/** - * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. - * - * Return true if HDCP is supported, false if not. - */ -bool qcom_scm_hdcp_available(void) +int qcom_scm_set_remote_state(u32 state, u32 id) { - int ret = qcom_scm_clk_enable(); - - if (ret) - return ret; - - ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, - QCOM_SCM_HDCP_INVOKE); - - qcom_scm_clk_disable(); - - return ret > 0 ? true : false; + return __qcom_scm_set_remote_state(__scm->dev, state, id); } -EXPORT_SYMBOL(qcom_scm_hdcp_available); +EXPORT_SYMBOL(qcom_scm_set_remote_state); -/** - * qcom_scm_hdcp_req() - Send HDCP request. - * @req: HDCP request array - * @req_cnt: HDCP request array count - * @resp: response buffer passed to SCM - * - * Write HDCP register(s) through SCM. - */ -int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) +static void qcom_scm_set_download_mode(bool enable) { - int ret = qcom_scm_clk_enable(); + bool avail; + int ret = 0; - if (ret) - return ret; + avail = __qcom_scm_is_call_available(__scm->dev, + QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SET_DLOAD_MODE); + if (avail) { + ret = __qcom_scm_set_dload_mode(__scm->dev, enable); + } else if (__scm->dload_mode_addr) { + ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr, + enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0); + } else { + dev_err(__scm->dev, + "No available mechanism for setting download mode\n"); + } - ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp); - qcom_scm_clk_disable(); - return ret; + if (ret) + dev_err(__scm->dev, "failed to set download mode: %d\n", ret); } -EXPORT_SYMBOL(qcom_scm_hdcp_req); /** * qcom_scm_pas_supported() - Check if the peripheral authentication service is @@ -327,30 +313,6 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = { .deassert = qcom_scm_pas_reset_deassert, }; -int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) -{ - return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare); -} -EXPORT_SYMBOL(qcom_scm_restore_sec_cfg); - -int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) -{ - return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size); -} -EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size); - -int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) -{ - return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare); -} -EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); - -int qcom_scm_qsmmu500_wait_safe_toggle(bool en) -{ - return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); -} -EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); - int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return __qcom_scm_io_readl(__scm->dev, addr, val); @@ -363,68 +325,23 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) } EXPORT_SYMBOL(qcom_scm_io_writel); -static void qcom_scm_set_download_mode(bool enable) -{ - bool avail; - int ret = 0; - - avail = __qcom_scm_is_call_available(__scm->dev, - QCOM_SCM_SVC_BOOT, - QCOM_SCM_BOOT_SET_DLOAD_MODE); - if (avail) { - ret = __qcom_scm_set_dload_mode(__scm->dev, enable); - } else if (__scm->dload_mode_addr) { - ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr, - enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0); - } else { - dev_err(__scm->dev, - "No available mechanism for setting download mode\n"); - } - - if (ret) - dev_err(__scm->dev, "failed to set download mode: %d\n", ret); -} - -static int qcom_scm_find_dload_address(struct device *dev, u64 *addr) +int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { - struct device_node *tcsr; - struct device_node *np = dev->of_node; - struct resource res; - u32 offset; - int ret; - - tcsr = of_parse_phandle(np, "qcom,dload-mode", 0); - if (!tcsr) - return 0; - - ret = of_address_to_resource(tcsr, 0, &res); - of_node_put(tcsr); - if (ret) - return ret; - - ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset); - if (ret < 0) - return ret; - - *addr = res.start + offset; - - return 0; + return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare); } +EXPORT_SYMBOL(qcom_scm_restore_sec_cfg); -/** - * qcom_scm_is_available() - Checks if SCM is available - */ -bool qcom_scm_is_available(void) +int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { - return !!__scm; + return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size); } -EXPORT_SYMBOL(qcom_scm_is_available); +EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size); -int qcom_scm_set_remote_state(u32 state, u32 id) +int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { - return __qcom_scm_set_remote_state(__scm->dev, state, id); + return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare); } -EXPORT_SYMBOL(qcom_scm_set_remote_state); +EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); /** * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership @@ -508,6 +425,89 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, } EXPORT_SYMBOL(qcom_scm_assign_mem); +/** + * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. + * + * Return true if HDCP is supported, false if not. + */ +bool qcom_scm_hdcp_available(void) +{ + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; + + ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, + QCOM_SCM_HDCP_INVOKE); + + qcom_scm_clk_disable(); + + return ret > 0 ? true : false; +} +EXPORT_SYMBOL(qcom_scm_hdcp_available); + +/** + * qcom_scm_hdcp_req() - Send HDCP request. + * @req: HDCP request array + * @req_cnt: HDCP request array count + * @resp: response buffer passed to SCM + * + * Write HDCP register(s) through SCM. + */ +int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) +{ + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; + + ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp); + qcom_scm_clk_disable(); + return ret; +} +EXPORT_SYMBOL(qcom_scm_hdcp_req); + +int qcom_scm_qsmmu500_wait_safe_toggle(bool en) +{ + return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); +} +EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); + +/** + * qcom_scm_is_available() - Checks if SCM is available + */ +bool qcom_scm_is_available(void) +{ + return !!__scm; +} +EXPORT_SYMBOL(qcom_scm_is_available); + +static int qcom_scm_find_dload_address(struct device *dev, u64 *addr) +{ + struct device_node *tcsr; + struct device_node *np = dev->of_node; + struct resource res; + u32 offset; + int ret; + + tcsr = of_parse_phandle(np, "qcom,dload-mode", 0); + if (!tcsr) + return 0; + + ret = of_address_to_resource(tcsr, 0, &res); + of_node_put(tcsr); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset); + if (ret < 0) + return ret; + + *addr = res.start + offset; + + return 0; +} + static int qcom_scm_probe(struct platform_device *pdev) { struct qcom_scm *scm; diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 7bc8566..6f63ca6 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -4,54 +4,74 @@ #ifndef __QCOM_SCM_INT_H #define __QCOM_SCM_INT_H -#define QCOM_SCM_SVC_BOOT 0x1 -#define QCOM_SCM_BOOT_SET_ADDR 0x1 +#define QCOM_SCM_SVC_BOOT 0x01 +#define QCOM_SCM_BOOT_SET_ADDR 0x01 +#define QCOM_SCM_BOOT_TERMINATE_PC 0x02 +#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 -#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0xa -extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); -extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); - +extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); -extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); - -#define QCOM_SCM_BOOT_TERMINATE_PC 0x2 -#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 extern void __qcom_scm_cpu_power_down(u32 flags); +extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); +extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); +#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 + +#define QCOM_SCM_SVC_PIL 0x02 +#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 +#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x02 +#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x05 +#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06 +#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 +#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a +extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, + dma_addr_t metadata_phys); +extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, + phys_addr_t addr, phys_addr_t size); +extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral); +extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); -#define QCOM_SCM_SVC_IO 0x5 -#define QCOM_SCM_IO_READ 0x1 -#define QCOM_SCM_IO_WRITE 0x2 +#define QCOM_SCM_SVC_IO 0x05 +#define QCOM_SCM_IO_READ 0x01 +#define QCOM_SCM_IO_WRITE 0x02 extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val); extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val); -#define QCOM_SCM_SVC_INFO 0x6 -#define QCOM_INFO_IS_CALL_AVAIL 0x1 +#define QCOM_SCM_SVC_INFO 0x06 +#define QCOM_INFO_IS_CALL_AVAIL 0x01 extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id); -#define QCOM_SCM_SVC_HDCP 0x11 -#define QCOM_SCM_HDCP_INVOKE 0x01 +#define QCOM_SCM_SVC_MP 0x0c +#define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 +#define QCOM_MP_ASSIGN 0x16 +extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, + u32 spare); +extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, + size_t *size); +extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, + u32 size, u32 spare); +extern int __qcom_scm_assign_mem(struct device *dev, + phys_addr_t mem_region, size_t mem_sz, + phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz); + +#define QCOM_SCM_SVC_HDCP 0x11 +#define QCOM_SCM_HDCP_INVOKE 0x01 extern int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); -extern void __qcom_scm_init(void); +#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 +extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, + bool enable); +#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 -#define QCOM_SCM_SVC_PIL 0x2 -#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x1 -#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x2 -#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x5 -#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x6 -#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x7 -#define QCOM_SCM_PIL_PAS_MSS_RESET 0xa -extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, - dma_addr_t metadata_phys); -extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, - phys_addr_t addr, phys_addr_t size); -extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral); -extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); +extern void __qcom_scm_init(void); /* common error codes */ #define QCOM_SCM_V2_EBUSY -12 @@ -80,25 +100,4 @@ static inline int qcom_scm_remap_error(int err) return -EINVAL; } -#define QCOM_SCM_SVC_MP 0xc -#define QCOM_SCM_MP_RESTORE_SEC_CFG 2 -extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, - u32 spare); -#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 3 -#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 4 -#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 -extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, - size_t *size); -extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, - u32 size, u32 spare); -extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, - bool enable); -#define QCOM_MP_ASSIGN 0x16 -extern int __qcom_scm_assign_mem(struct device *dev, - phys_addr_t mem_region, size_t mem_sz, - phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz); - #endif diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 122cca6..a4dfab0 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -37,10 +37,8 @@ struct qcom_scm_vmperm { #if IS_ENABLED(CONFIG_QCOM_SCM) extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); -extern bool qcom_scm_is_available(void); -extern bool qcom_scm_hdcp_available(void); -extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, - u32 *resp); +extern void qcom_scm_cpu_power_down(u32 flags); +extern int qcom_scm_set_remote_state(u32 state, u32 id); extern bool qcom_scm_pas_supported(u32 peripheral); extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size); @@ -48,58 +46,62 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size); extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); -extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *src, - const struct qcom_scm_vmperm *newvm, - unsigned int dest_cnt); -extern void qcom_scm_cpu_power_down(u32 flags); -extern u32 qcom_scm_get_version(void); -extern int qcom_scm_set_remote_state(u32 state, u32 id); +extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); +extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); +extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, + unsigned int *src, + const struct qcom_scm_vmperm *newvm, + int dest_cnt); +extern bool qcom_scm_hdcp_available(void); +extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, + u32 *resp); extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); -extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); -extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); +extern u32 qcom_scm_get_version(void); +extern bool qcom_scm_is_available(void); #else #include static inline int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) -{ - return -ENODEV; -} + { return -ENODEV; } static inline int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) -{ - return -ENODEV; -} -static inline bool qcom_scm_is_available(void) { return false; } -static inline bool qcom_scm_hdcp_available(void) { return false; } -static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, - u32 *resp) { return -ENODEV; } + { return -ENODEV; } +static inline void qcom_scm_cpu_power_down(u32 flags) {} +static inline u32 qcom_scm_set_remote_state(u32 state, u32 id) + { return -ENODEV; } static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) { return -ENODEV; } static inline int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) { return -ENODEV; } -static inline int -qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; } +static inline int qcom_scm_pas_auth_and_reset(u32 peripheral) + { return -ENODEV; } static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } +static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) + { return -ENODEV; } +static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) + { return -ENODEV; } +static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) + { return -ENODEV; } +static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) + { return -ENODEV; } +static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) + { return -ENODEV; } static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, - unsigned int dest_cnt) { return -ENODEV; } -static inline void qcom_scm_cpu_power_down(u32 flags) {} + int dest_cnt) { return -ENODEV; } +static inline bool qcom_scm_hdcp_available(void) { return false; } +static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, + u32 *resp) { return -ENODEV; } +static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) + { return -ENODEV; } static inline u32 qcom_scm_get_version(void) { return 0; } -static inline u32 -qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; } -static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; } -static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } -static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } -static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } -static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; } -static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; } +static inline bool qcom_scm_is_available(void) { return false; } #endif #endif From patchwork Tue Oct 29 19:40:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218449 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 13BDB13B1 for ; Tue, 29 Oct 2019 19:41:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E4FE52086A for ; Tue, 29 Oct 2019 19:41:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="odBp+D5l"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="ligHr7qZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732611AbfJ2TlQ (ORCPT ); Tue, 29 Oct 2019 15:41:16 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58696 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732575AbfJ2TlO (ORCPT ); Tue, 29 Oct 2019 15:41:14 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 429C060FB8; Tue, 29 Oct 2019 19:41:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378074; bh=t69mBPbZYNAMCASUyLYBudWH7IjtKYXFXxCoBN9u+8Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=odBp+D5lQWi+QA7xwN8upvMonzXLV21kGY642XPQT4UBpzUC9SXJQWxCpa1FeP3k0 X51hNJL1b4bBGYKSNcHbTka3900jGzDd06bBwrmsd1aWzZRm2XW6iR/0WsuflAxRnV s/bCyMNakh1ZV/sWSEHMxHeoA6XkDSvCOtziLPXM= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 1B96460F83; Tue, 29 Oct 2019 19:41:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378073; bh=t69mBPbZYNAMCASUyLYBudWH7IjtKYXFXxCoBN9u+8Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ligHr7qZt+n0YX8isu2wwEtMB6yq+5rPRidiG4EMI55KSNpukuy4+nXtJeDqEm4GF qTQR4KVeTkTq8RY01f45emr9iWXSwxntOJgz6NDE6yfKTjGAu1xBHxEMjR9MlBDyhq KialMglO4VhMyM7+gUfYsQhMhTZUnxjB9kp/DE4E= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 1B96460F83 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 04/17] firmware: qcom_scm: Remove unused qcom_scm_get_version Date: Tue, 29 Oct 2019 12:40:52 -0700 Message-Id: <1572378065-4490-5-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Remove unused qcom_scm_get_version. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 36 ------------------------------------ include/linux/qcom_scm.h | 2 -- 2 files changed, 38 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index 240adfd..b2805de 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -291,42 +291,6 @@ static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) return r0; } -u32 qcom_scm_get_version(void) -{ - int context_id; - static u32 version = -1; - register u32 r0 asm("r0"); - register u32 r1 asm("r1"); - - if (version != -1) - return version; - - mutex_lock(&qcom_scm_lock); - - r0 = 0x1 << 8; - r1 = (u32)&context_id; - do { - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r1") - __asmeq("%2", "r0") - __asmeq("%3", "r1") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0), "=r" (r1) - : "r" (r0), "r" (r1) - : "r2", "r3", "r12"); - } while (r0 == QCOM_SCM_INTERRUPTED); - - version = r1; - mutex_unlock(&qcom_scm_lock); - - return version; -} -EXPORT_SYMBOL(qcom_scm_get_version); - /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index a4dfab0..1e95080 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -59,7 +59,6 @@ extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); -extern u32 qcom_scm_get_version(void); extern bool qcom_scm_is_available(void); #else @@ -101,7 +100,6 @@ static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } -static inline u32 qcom_scm_get_version(void) { return 0; } static inline bool qcom_scm_is_available(void) { return false; } #endif #endif From patchwork Tue Oct 29 19:40:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218471 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B8988139A for ; Tue, 29 Oct 2019 19:42:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 78D5D217F9 for ; Tue, 29 Oct 2019 19:42:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="nnqQAgiX"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="nuLGT1TW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732659AbfJ2TlR (ORCPT ); Tue, 29 Oct 2019 15:41:17 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58774 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732585AbfJ2TlR (ORCPT ); Tue, 29 Oct 2019 15:41:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 4F6C860FFC; Tue, 29 Oct 2019 19:41:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378075; bh=zWihqYztVsqgFVR7ZPnz4KrGiPGHYbaWgOmI99WzC7g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nnqQAgiXD9GAXLTF/4XKaLC/oGXI4mpT27Z+y8baJvYFd/Uppf2mgmOAevjmzZ1CQ JQ2dttuGt+NHhpgzveF61BgvTPIgkNMiSj/bHjU1I17Q9fAMODAMffZqEzEjGsc5vn Am3KaO0NEx0ZNAQn/RdDzNDxqyIH+cjXLPA6EB2M= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id A2FD860F8D; Tue, 29 Oct 2019 19:41:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378074; bh=zWihqYztVsqgFVR7ZPnz4KrGiPGHYbaWgOmI99WzC7g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nuLGT1TWMPcivfVvv1qOe66NtvlyCyNWRybIzdFWq9iamFz3y+Fhz8sdilg2yi2qc fVqw2O2+aaiojb6ita/4f54UDigBxuK9uQ2N+Sy70DR8WUtrEOOIt98Q2g2c8M0eJq UeS234YT1DL1Q9ji+4T/vnbI+tduetBePRxsG4gQ= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org A2FD860F8D Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 05/17] firmware: qcom_scm-64: Move svc/cmd/owner into qcom_scm_desc Date: Tue, 29 Oct 2019 12:40:53 -0700 Message-Id: <1572378065-4490-6-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Service, command, and owner IDs are all part of qcom_scm_desc struct and have no special reason to be a function argument (or hard-coded in the case of owner). Moving them to be part of qcom_scm_desc struct improves readability. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 191 ++++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 71 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index ee0c950..2fcbfac 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -46,8 +46,11 @@ enum qcom_scm_arg_types { * @res: The values returned by the secure syscall */ struct qcom_scm_desc { + u32 svc; + u32 cmd; u32 arginfo; u64 args[MAX_QCOM_SCM_ARGS]; + u32 owner; }; static u64 qcom_smccc_convention = -1; @@ -62,14 +65,16 @@ static DEFINE_MUTEX(qcom_scm_lock); #define SMCCC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SMCCC_N_REG_ARGS + 1) static void __qcom_scm_call_do_quirk(const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, u32 fn_id, - u64 x5, u32 type) + struct arm_smccc_res *res, u64 x5, u32 type) { u64 cmd; struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; - cmd = ARM_SMCCC_CALL_VAL(type, qcom_smccc_convention, - ARM_SMCCC_OWNER_SIP, fn_id); + cmd = ARM_SMCCC_CALL_VAL( + type, + qcom_smccc_convention, + desc->owner, + SMCCC_FUNCNUM(desc->svc, desc->cmd)); quirk.state.a6 = 0; @@ -85,22 +90,19 @@ static void __qcom_scm_call_do_quirk(const struct qcom_scm_desc *desc, } static void qcom_scm_call_do_smccc(const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, u32 fn_id, - u64 x5, bool atomic) + struct arm_smccc_res *res, u64 x5, bool atomic) { int retry_count = 0; if (atomic) { - __qcom_scm_call_do_quirk(desc, res, fn_id, x5, - ARM_SMCCC_FAST_CALL); + __qcom_scm_call_do_quirk(desc, res, x5, ARM_SMCCC_FAST_CALL); return; } do { mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do_quirk(desc, res, fn_id, x5, - ARM_SMCCC_STD_CALL); + __qcom_scm_call_do_quirk(desc, res, x5, ARM_SMCCC_STD_CALL); mutex_unlock(&qcom_scm_lock); @@ -112,7 +114,7 @@ static void qcom_scm_call_do_smccc(const struct qcom_scm_desc *desc, } while (res->a0 == QCOM_SCM_V2_EBUSY); } -static int ___qcom_scm_call_smccc(struct device *dev, u32 svc_id, u32 cmd_id, +static int ___qcom_scm_call_smccc(struct device *dev, const struct qcom_scm_desc *desc, struct arm_smccc_res *res, bool atomic) { @@ -157,7 +159,7 @@ static int ___qcom_scm_call_smccc(struct device *dev, u32 svc_id, u32 cmd_id, x5 = args_phys; } - qcom_scm_call_do_smccc(desc, res, fn_id, x5, atomic); + qcom_scm_call_do_smccc(desc, res, x5, atomic); if (args_virt) { dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); @@ -180,12 +182,11 @@ static int ___qcom_scm_call_smccc(struct device *dev, u32 svc_id, u32 cmd_id, * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. */ -static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, - const struct qcom_scm_desc *desc, +static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc, struct arm_smccc_res *res) { might_sleep(); - return ___qcom_scm_call_smccc(dev, svc_id, cmd_id, desc, res, false); + return ___qcom_scm_call_smccc(dev, desc, res, false); } /** @@ -199,11 +200,11 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, * Sends a command to the SCM and waits for the command to finish processing. * This can be called in atomic context. */ -static int qcom_scm_call_atomic(struct device *dev, u32 svc_id, u32 cmd_id, +static int qcom_scm_call_atomic(struct device *dev, const struct qcom_scm_desc *desc, struct arm_smccc_res *res) { - return ___qcom_scm_call_smccc(dev, svc_id, cmd_id, desc, res, true); + return ___qcom_scm_call_smccc(dev, desc, res, true); } /** @@ -248,7 +249,11 @@ void __qcom_scm_cpu_power_down(u32 flags) int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; @@ -256,37 +261,41 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) desc.args[1] = id; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, - &desc, &res); + return qcom_scm_call(dev, &desc, &res); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_IS_SUPPORTED, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? false : !!res.a1; } @@ -295,15 +304,18 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, dma_addr_t metadata_phys) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = peripheral; desc.args[1] = metadata_phys; desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_INIT_IMAGE, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -312,7 +324,11 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, phys_addr_t addr, phys_addr_t size) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = peripheral; @@ -320,8 +336,7 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, desc.args[2] = size; desc.arginfo = QCOM_SCM_ARGS(3); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MEM_SETUP, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -329,15 +344,17 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_AUTH_AND_RESET, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -345,21 +362,28 @@ int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_SHUTDOWN, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; @@ -367,8 +391,7 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) desc.args[1] = 0; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MSS_RESET, &desc, - &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -376,15 +399,18 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_READ, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; desc.args[0] = addr; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); if (ret >= 0) *val = res.a1; @@ -393,36 +419,46 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_WRITE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = addr; desc.args[1] = val; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, - &desc, &res); + return qcom_scm_call(dev, &desc, &res); } int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_INFO, + .cmd = QCOM_INFO_IS_CALL_AVAIL, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.arginfo = QCOM_SCM_ARGS(1); desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_RESTORE_SEC_CFG, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; @@ -430,8 +466,7 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) desc.args[1] = spare; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_MP_RESTORE_SEC_CFG, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -439,15 +474,18 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; desc.args[0] = spare; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); if (size) *size = res.a1; @@ -458,7 +496,11 @@ int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; int ret; @@ -468,8 +510,7 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); /* the pg table has been initialized already, ignore the error */ if (ret == -EPERM) @@ -483,7 +524,11 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, phys_addr_t dest, size_t dest_sz) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_MP_ASSIGN, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = mem_region; @@ -498,9 +543,7 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, - QCOM_MP_ASSIGN, - &desc, &res); + ret = qcom_scm_call(dev, &desc, &res); return ret ? : res.a1; } @@ -509,7 +552,11 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { int ret; - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_HDCP, + .cmd = QCOM_SCM_HDCP_INVOKE, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) @@ -527,8 +574,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, desc.args[9] = req[4].val; desc.arginfo = QCOM_SCM_ARGS(10); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, &desc, - &res); + ret = qcom_scm_call(dev, &desc, &res); *resp = res.a1; return ret; @@ -536,15 +582,18 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) { - struct qcom_scm_desc desc = {0}; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, + .owner = ARM_SMCCC_OWNER_SIP, + }; struct arm_smccc_res res; desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL; desc.args[1] = en; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call_atomic(dev, QCOM_SCM_SVC_SMMU_PROGRAM, - QCOM_SCM_SMMU_CONFIG_ERRATA1, &desc, &res); + return qcom_scm_call_atomic(dev, &desc, &res); } void __qcom_scm_init(void) From patchwork Tue Oct 29 19:40:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218465 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ACA67139A for ; Tue, 29 Oct 2019 19:41:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 76E0F20663 for ; Tue, 29 Oct 2019 19:41:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="ANV/xoJ+"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="arylRVTb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732679AbfJ2TlS (ORCPT ); Tue, 29 Oct 2019 15:41:18 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58876 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732612AbfJ2TlR (ORCPT ); Tue, 29 Oct 2019 15:41:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 233CB60F82; Tue, 29 Oct 2019 19:41:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378076; bh=wRc4oZA0jLUxAV4m32HDOgO/xGFZxj797A7lyWawo9E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ANV/xoJ+ZQs6rNpE9Lb+YgnKPbwuptAVaGm4Zz9BuMgLQEYHr3DpogWKjfHEzNMwB PwVr6PO2X66ZsQFWsY8ApISdTYRM6iIjp76hij2MU6Hb0/HIZbyzqug5iM2Dq4K8ZC UdPm+pq1QGGs2wLhjPzqAcKmC1/ZMVBQK4yFEdJA= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 40C5960F82; Tue, 29 Oct 2019 19:41:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378074; bh=wRc4oZA0jLUxAV4m32HDOgO/xGFZxj797A7lyWawo9E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=arylRVTbZBL3C6nLxFl8q58pI85Px1RyDgw5jYFlPc8/rNDVf4iBaFtxV0i15KsMu dbOAsrPWnOFzujpO7I2ERpydRT5zz8KJbBnIiCXazS6tPbs7VnDi+k8jbq/g2tKK4m lnENbPxf8qWBUiYdnR7XXidgYbSnGeIug2zm/jKA= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 40C5960F82 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 06/17] firmware: qcom_scm-64: Add SCM results to descriptor Date: Tue, 29 Oct 2019 12:40:54 -0700 Message-Id: <1572378065-4490-7-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Remove knowledge of arm_smccc_res struct from client wrappers so that client wrappers only work QCOM SCM data structures. SCM calls may have up to 3 arguments, so qcom_scm_call_smccc is responsible now for filling those 3 arguments accordingly. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 101 +++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 2fcbfac..cd694a2 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -50,6 +50,7 @@ struct qcom_scm_desc { u32 cmd; u32 arginfo; u64 args[MAX_QCOM_SCM_ARGS]; + u64 res[MAX_QCOM_SCM_RETS]; u32 owner; }; @@ -115,8 +116,7 @@ static void qcom_scm_call_do_smccc(const struct qcom_scm_desc *desc, } static int ___qcom_scm_call_smccc(struct device *dev, - const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, bool atomic) + struct qcom_scm_desc *desc, bool atomic) { int arglen = desc->arginfo & 0xf; int i; @@ -126,6 +126,7 @@ static int ___qcom_scm_call_smccc(struct device *dev, void *args_virt = NULL; size_t alloc_len; gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL; + struct arm_smccc_res res; if (unlikely(arglen > SMCCC_N_REG_ARGS)) { alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64); @@ -159,15 +160,15 @@ static int ___qcom_scm_call_smccc(struct device *dev, x5 = args_phys; } - qcom_scm_call_do_smccc(desc, res, x5, atomic); + qcom_scm_call_do_smccc(desc, &res, x5, atomic); if (args_virt) { dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); kfree(args_virt); } - if (res->a0 < 0) - return qcom_scm_remap_error(res->a0); + if (res.a0 < 0) + return qcom_scm_remap_error(res.a0); return 0; } @@ -182,11 +183,10 @@ static int ___qcom_scm_call_smccc(struct device *dev, * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. */ -static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc, - struct arm_smccc_res *res) +static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { might_sleep(); - return ___qcom_scm_call_smccc(dev, desc, res, false); + return ___qcom_scm_call_smccc(dev, desc, false); } /** @@ -200,11 +200,9 @@ static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc, * Sends a command to the SCM and waits for the command to finish processing. * This can be called in atomic context. */ -static int qcom_scm_call_atomic(struct device *dev, - const struct qcom_scm_desc *desc, - struct arm_smccc_res *res) +static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) { - return ___qcom_scm_call_smccc(dev, desc, res, true); + return ___qcom_scm_call_smccc(dev, desc, true); } /** @@ -254,16 +252,15 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = state; desc.args[1] = id; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_set_dload_mode(struct device *dev, bool enable) @@ -273,13 +270,12 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, &desc, &res); + return qcom_scm_call(dev, &desc); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -290,14 +286,13 @@ bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? false : !!res.a1; + return ret ? false : !!desc.res[0]; } int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, @@ -309,15 +304,14 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = peripheral; desc.args[1] = metadata_phys; desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, @@ -329,16 +323,15 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = peripheral; desc.args[1] = addr; desc.args[2] = size; desc.arginfo = QCOM_SCM_ARGS(3); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) @@ -349,14 +342,13 @@ int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) @@ -367,14 +359,13 @@ int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = peripheral; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) @@ -384,16 +375,15 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = reset; desc.args[1] = 0; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, @@ -404,15 +394,14 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, .cmd = QCOM_SCM_IO_READ, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = addr; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); if (ret >= 0) - *val = res.a1; + *val = desc.res[0]; return ret < 0 ? ret : 0; } @@ -424,13 +413,12 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) .cmd = QCOM_SCM_IO_WRITE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = addr; desc.args[1] = val; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, &desc, &res); + return qcom_scm_call(dev, &desc); } int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) @@ -441,15 +429,14 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) .cmd = QCOM_INFO_IS_CALL_AVAIL, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.arginfo = QCOM_SCM_ARGS(1); desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) @@ -459,16 +446,15 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) .cmd = QCOM_SCM_MP_RESTORE_SEC_CFG, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = device_id; desc.args[1] = spare; desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, @@ -479,18 +465,17 @@ int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = spare; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); if (size) - *size = res.a1; + *size = desc.res[0]; - return ret ? : res.a2; + return ret ? : desc.res[1]; } int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, @@ -501,7 +486,6 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; int ret; desc.args[0] = addr; @@ -510,7 +494,7 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); /* the pg table has been initialized already, ignore the error */ if (ret == -EPERM) @@ -529,7 +513,6 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, .cmd = QCOM_MP_ASSIGN, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = mem_region; desc.args[1] = mem_sz; @@ -543,9 +526,9 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL); - ret = qcom_scm_call(dev, &desc, &res); + ret = qcom_scm_call(dev, &desc); - return ret ? : res.a1; + return ret ? : desc.res[0]; } int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, @@ -557,7 +540,6 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, .cmd = QCOM_SCM_HDCP_INVOKE, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) return -ERANGE; @@ -574,8 +556,8 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, desc.args[9] = req[4].val; desc.arginfo = QCOM_SCM_ARGS(10); - ret = qcom_scm_call(dev, &desc, &res); - *resp = res.a1; + ret = qcom_scm_call(dev, &desc); + *resp = desc.res[0]; return ret; } @@ -587,13 +569,12 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, .owner = ARM_SMCCC_OWNER_SIP, }; - struct arm_smccc_res res; desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL; desc.args[1] = en; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call_atomic(dev, &desc, &res); + return qcom_scm_call_atomic(dev, &desc); } void __qcom_scm_init(void) From patchwork Tue Oct 29 19:40:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218475 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 98B4D13B1 for ; Tue, 29 Oct 2019 19:42:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 75F8721721 for ; Tue, 29 Oct 2019 19:42:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="TUkMbbya"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="TUkMbbya" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731976AbfJ2TmJ (ORCPT ); Tue, 29 Oct 2019 15:42:09 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58654 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732597AbfJ2TlQ (ORCPT ); Tue, 29 Oct 2019 15:41:16 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E03BC60FB4; Tue, 29 Oct 2019 19:41:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378075; bh=cLTTSZkKBie5f/YXYt3hhrbvgdG2klqOpAdCVB1WzPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TUkMbbyaVOliAENbFOcbI+CSd9C4j5L0FFGLQ8hkCypDTZOGuoNOFUHFll9WAyvLF kOe24UTQqafXhP11DrlwgwJAB5K4EBw3QTq3udp7qhfGh065c0yf8r8z6GKWZOO+qG VUUm+VeZSLpZlEmqZ9Wu5bKCh54C/XO2xAtj6eRs= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id D131960FB4; Tue, 29 Oct 2019 19:41:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378075; bh=cLTTSZkKBie5f/YXYt3hhrbvgdG2klqOpAdCVB1WzPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TUkMbbyaVOliAENbFOcbI+CSd9C4j5L0FFGLQ8hkCypDTZOGuoNOFUHFll9WAyvLF kOe24UTQqafXhP11DrlwgwJAB5K4EBw3QTq3udp7qhfGh065c0yf8r8z6GKWZOO+qG VUUm+VeZSLpZlEmqZ9Wu5bKCh54C/XO2xAtj6eRs= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org D131960FB4 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 07/17] firmware: qcom_scm-64: Remove qcom_scm_call_do_smccc Date: Tue, 29 Oct 2019 12:40:55 -0700 Message-Id: <1572378065-4490-8-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Remove thin wrapper to qcom_scm_call_do_smccc because it doesn't do enough of anything interesting to dedicate its own function. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 46 ++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index cd694a2..6660539 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -90,31 +90,6 @@ static void __qcom_scm_call_do_quirk(const struct qcom_scm_desc *desc, } while (res->a0 == QCOM_SCM_INTERRUPTED); } -static void qcom_scm_call_do_smccc(const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, u64 x5, bool atomic) -{ - int retry_count = 0; - - if (atomic) { - __qcom_scm_call_do_quirk(desc, res, x5, ARM_SMCCC_FAST_CALL); - return; - } - - do { - mutex_lock(&qcom_scm_lock); - - __qcom_scm_call_do_quirk(desc, res, x5, ARM_SMCCC_STD_CALL); - - mutex_unlock(&qcom_scm_lock); - - if (res->a0 == QCOM_SCM_V2_EBUSY) { - if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) - break; - msleep(QCOM_SCM_EBUSY_WAIT_MS); - } - } while (res->a0 == QCOM_SCM_V2_EBUSY); -} - static int ___qcom_scm_call_smccc(struct device *dev, struct qcom_scm_desc *desc, bool atomic) { @@ -160,7 +135,26 @@ static int ___qcom_scm_call_smccc(struct device *dev, x5 = args_phys; } - qcom_scm_call_do_smccc(desc, &res, x5, atomic); + if (atomic) { + __qcom_scm_call_do_quirk(desc, &res, x5, ARM_SMCCC_FAST_CALL); + } else { + int retry_count = 0; + + do { + mutex_lock(&qcom_scm_lock); + + __qcom_scm_call_do_quirk(desc, &res, x5, + ARM_SMCCC_STD_CALL); + + mutex_unlock(&qcom_scm_lock); + + if (res.a0 == QCOM_SCM_V2_EBUSY) { + if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) + break; + msleep(QCOM_SCM_EBUSY_WAIT_MS); + } + } while (res.a0 == QCOM_SCM_V2_EBUSY); + } if (args_virt) { dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); From patchwork Tue Oct 29 19:40:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218469 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BB59313BD for ; Tue, 29 Oct 2019 19:42:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9647421479 for ; Tue, 29 Oct 2019 19:42:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Yy3E8WCe"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="CLXSWkGw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733086AbfJ2TmA (ORCPT ); Tue, 29 Oct 2019 15:42:00 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58696 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732644AbfJ2TlR (ORCPT ); Tue, 29 Oct 2019 15:41:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id BA94861068; Tue, 29 Oct 2019 19:41:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378076; bh=m7MUjWZqECuFAZSrGENljHlPPOvtxA98b4PK/BdQI2A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Yy3E8WCewoEMwzJN9fKJqB3fhpyV89Xh0D870sCOlnkS4D8JLiCd5NMVoXiEMv+tM +Ema3IILxqf0cxvmXYR2sun2Fq8vgDBR2LpikcLfamy504hgsdOFNWb99j3aYVmehb /Q38ZvmIARSekErTCAI36qRx4h27agySyU3WwI6A= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 75E2E61018; Tue, 29 Oct 2019 19:41:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378075; bh=m7MUjWZqECuFAZSrGENljHlPPOvtxA98b4PK/BdQI2A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CLXSWkGwXKk7jEN4oKqwoH1ZkdcLv+WBOBJAGqPbgKCeqo46O0v7+uzUDLrpVBfnL 52iNmhWFkZPwCki3ks7IRhHnb8hPVEnwrvtF7e/FqNDwV25rMdgEt9afF2YPt5zzkS eGcJ90ddBPUs6wup307YTpao9r8SqBsw4ziqmlEo= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 75E2E61018 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 08/17] firmware: qcom_scm-64: Move SMC register filling to qcom_scm_call_smccc Date: Tue, 29 Oct 2019 12:40:56 -0700 Message-Id: <1572378065-4490-9-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org qcom_scm_call_smccc should be responsible for converting qcom_scm_desc into arguments for smc call. Consolidate the dispersed logic to convert qcom_scm_desc into smc arguments inside qcom_scm_call_smccc. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 44 ++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 6660539..c83eb1d 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -54,6 +54,10 @@ struct qcom_scm_desc { u32 owner; }; +struct arm_smccc_args { + unsigned long a[8]; +}; + static u64 qcom_smccc_convention = -1; static DEFINE_MUTEX(qcom_scm_lock); @@ -64,28 +68,23 @@ static DEFINE_MUTEX(qcom_scm_lock); #define SMCCC_N_REG_ARGS 4 #define SMCCC_FIRST_REG_IDX 2 #define SMCCC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SMCCC_N_REG_ARGS + 1) +#define SMCCC_LAST_REG_IDX (SMCCC_FIRST_REG_IDX + SMCCC_N_REG_ARGS - 1) -static void __qcom_scm_call_do_quirk(const struct qcom_scm_desc *desc, - struct arm_smccc_res *res, u64 x5, u32 type) +static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, + struct arm_smccc_res *res) { - u64 cmd; + unsigned long a0 = smc->a[0]; struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; - cmd = ARM_SMCCC_CALL_VAL( - type, - qcom_smccc_convention, - desc->owner, - SMCCC_FUNCNUM(desc->svc, desc->cmd)); - quirk.state.a6 = 0; do { - arm_smccc_smc_quirk(cmd, desc->arginfo, desc->args[0], - desc->args[1], desc->args[2], x5, - quirk.state.a6, 0, res, &quirk); + arm_smccc_smc_quirk(a0, smc->a[1], smc->a[2], smc->a[3], + smc->a[4], smc->a[5], quirk.state.a6, + smc->a[7], res, &quirk); if (res->a0 == QCOM_SCM_INTERRUPTED) - cmd = res->a0; + a0 = res->a0; } while (res->a0 == QCOM_SCM_INTERRUPTED); } @@ -95,13 +94,21 @@ static int ___qcom_scm_call_smccc(struct device *dev, { int arglen = desc->arginfo & 0xf; int i; - u32 fn_id = SMCCC_FUNCNUM(svc_id, cmd_id); - u64 x5 = desc->args[SMCCC_N_REG_ARGS - 1]; dma_addr_t args_phys = 0; void *args_virt = NULL; size_t alloc_len; gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL; struct arm_smccc_res res; + struct arm_smccc_args smc = {0}; + + smc.a[0] = ARM_SMCCC_CALL_VAL( + atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL, + qcom_smccc_convention, + desc->owner, + SMCCC_FUNCNUM(desc->svc, desc->cmd)); + smc.a[1] = desc->arginfo; + for (i = 0; i < SMCCC_N_REG_ARGS; i++) + smc.a[i + SMCCC_FIRST_REG_IDX] = desc->args[i]; if (unlikely(arglen > SMCCC_N_REG_ARGS)) { alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64); @@ -132,19 +139,18 @@ static int ___qcom_scm_call_smccc(struct device *dev, return -ENOMEM; } - x5 = args_phys; + smc.a[SMCCC_LAST_REG_IDX] = args_phys; } if (atomic) { - __qcom_scm_call_do_quirk(desc, &res, x5, ARM_SMCCC_FAST_CALL); + __qcom_scm_call_do_quirk(&smc, &res); } else { int retry_count = 0; do { mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do_quirk(desc, &res, x5, - ARM_SMCCC_STD_CALL); + __qcom_scm_call_do_quirk(&smc, &res); mutex_unlock(&qcom_scm_lock); From patchwork Tue Oct 29 19:40:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218473 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9E4E7139A for ; Tue, 29 Oct 2019 19:42:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7AA7821721 for ; Tue, 29 Oct 2019 19:42:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Ob/h5JsR"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Ob/h5JsR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732644AbfJ2TmD (ORCPT ); Tue, 29 Oct 2019 15:42:03 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58654 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731976AbfJ2TlR (ORCPT ); Tue, 29 Oct 2019 15:41:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id DAB776101A; Tue, 29 Oct 2019 19:41:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378076; bh=xqAqpfTz0MYS2QzAykQoW/gQ3PLb9xPmN77DGBErdDY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ob/h5JsRgpLBR3aGNUS0GcT65eRkobT2Qns6KK8kN4r6YoYmlQI6KxRWGNFxbLAsG FvCTBKysBsI92mWYxweuvSY6zXMg3GykpUhaervTnI93FAHjQqSmXCSjzMlNC1DsdS ZX/SQLcd73wZTbVU20opJ7a3zlP36RO7SqxJFrkQ= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 180DE61066; Tue, 29 Oct 2019 19:41:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378076; bh=xqAqpfTz0MYS2QzAykQoW/gQ3PLb9xPmN77DGBErdDY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ob/h5JsRgpLBR3aGNUS0GcT65eRkobT2Qns6KK8kN4r6YoYmlQI6KxRWGNFxbLAsG FvCTBKysBsI92mWYxweuvSY6zXMg3GykpUhaervTnI93FAHjQqSmXCSjzMlNC1DsdS ZX/SQLcd73wZTbVU20opJ7a3zlP36RO7SqxJFrkQ= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 180DE61066 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 09/17] firmware: qcom_scm-64: Improve SMC convention detection Date: Tue, 29 Oct 2019 12:40:57 -0700 Message-Id: <1572378065-4490-10-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org - Use enum to describe SMC convention. - Improve SMC convention detection to use __qcom_scm_is_call_available instead of circumventing qcom_scm_call_smccc. - Improve SMC convention detection to check that SMCCC-32 works, instead of just assuming it does of SMCCC-64 does not. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index c83eb1d..4d7fd3e 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -58,7 +58,13 @@ struct arm_smccc_args { unsigned long a[8]; }; -static u64 qcom_smccc_convention = -1; +enum qcom_smc_convention { + SMC_CONVENTION_UNKNOWN, + SMC_CONVENTION_ARM_32, + SMC_CONVENTION_ARM_64, +}; + +static enum qcom_smc_convention qcom_smc_convention = SMC_CONVENTION_UNKNOWN; static DEFINE_MUTEX(qcom_scm_lock); #define QCOM_SCM_EBUSY_WAIT_MS 30 @@ -103,7 +109,9 @@ static int ___qcom_scm_call_smccc(struct device *dev, smc.a[0] = ARM_SMCCC_CALL_VAL( atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL, - qcom_smccc_convention, + (qcom_smc_convention == SMC_CONVENTION_ARM_64) ? + ARM_SMCCC_SMC_64 : + ARM_SMCCC_SMC_32, desc->owner, SMCCC_FUNCNUM(desc->svc, desc->cmd)); smc.a[1] = desc->arginfo; @@ -117,7 +125,7 @@ static int ___qcom_scm_call_smccc(struct device *dev, if (!args_virt) return -ENOMEM; - if (qcom_smccc_convention == ARM_SMCCC_SMC_32) { + if (qcom_smc_convention == SMC_CONVENTION_ARM_32) { __le32 *args = args_virt; for (i = 0; i < SMCCC_N_EXT_ARGS; i++) @@ -579,19 +587,15 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) void __qcom_scm_init(void) { - u64 cmd; - struct arm_smccc_res res; - u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL); - /* First try a SMC64 call */ - cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, - ARM_SMCCC_OWNER_SIP, function); - - arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)), - 0, 0, 0, 0, 0, &res); - - if (!res.a0 && res.a1) - qcom_smccc_convention = ARM_SMCCC_SMC_64; - else - qcom_smccc_convention = ARM_SMCCC_SMC_32; + qcom_smc_convention = SMC_CONVENTION_ARM_64; + if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, + QCOM_INFO_IS_CALL_AVAIL) <= 0) { + /* Now try a SMC32 call */ + qcom_smc_convention = SMC_CONVENTION_ARM_32; + if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, + QCOM_INFO_IS_CALL_AVAIL) <= 0) { + qcom_smc_convention = SMC_CONVENTION_UNKNOWN; + } + } } From patchwork Tue Oct 29 19:40:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 401C9139A for ; Tue, 29 Oct 2019 19:42:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1C7C321479 for ; Tue, 29 Oct 2019 19:42:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Op9Sz4NN"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Op9Sz4NN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733050AbfJ2Tlz (ORCPT ); Tue, 29 Oct 2019 15:41:55 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:58774 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732670AbfJ2TlS (ORCPT ); Tue, 29 Oct 2019 15:41:18 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 87CFF6110B; Tue, 29 Oct 2019 19:41:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378077; bh=hP900jZPuqDXv7f9uVqPcMmFzU4ziySueGkarLvTxSQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Op9Sz4NNHxwz3Tihx4YY592WBRRznVagwGtIk0StZzQZMgYRP3v7Ew/Zoi85/Kiwg EUrSKsi0temk2g6mlII8pclfg2zoWy3XHOjoWM3syIv3XiDiFxeSbrrlI6hWT1Qlm3 109IUm1dvV7z3oHBR19DaxkWusIe8vh0AwOpFeoM= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id A18FA61067; Tue, 29 Oct 2019 19:41:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378077; bh=hP900jZPuqDXv7f9uVqPcMmFzU4ziySueGkarLvTxSQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Op9Sz4NNHxwz3Tihx4YY592WBRRznVagwGtIk0StZzQZMgYRP3v7Ew/Zoi85/Kiwg EUrSKsi0temk2g6mlII8pclfg2zoWy3XHOjoWM3syIv3XiDiFxeSbrrlI6hWT1Qlm3 109IUm1dvV7z3oHBR19DaxkWusIe8vh0AwOpFeoM= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org A18FA61067 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 10/17] firmware: qcom_scm-32: Use SMC arch wrappers Date: Tue, 29 Oct 2019 12:40:58 -0700 Message-Id: <1572378065-4490-11-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Use SMC arch wrappers instead of inline assembly. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 71 ++++++++++-------------------------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index b2805de..e6d0a87 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "qcom_scm.h" @@ -121,25 +122,13 @@ static inline void *legacy_get_response_buffer(const struct legacy_response *rsp static u32 __qcom_scm_call_do(u32 cmd_addr) { int context_id; - register u32 r0 asm("r0") = 1; - register u32 r1 asm("r1") = (u32)&context_id; - register u32 r2 asm("r2") = cmd_addr; + struct arm_smccc_res res; do { - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0) - : "r" (r0), "r" (r1), "r" (r2) - : "r3", "r12"); - } while (r0 == QCOM_SCM_INTERRUPTED); - - return r0; + arm_smccc_smc(1, (unsigned long)&context_id, cmd_addr, + 0, 0, 0, 0, 0, &res); + } while (res.a0 == QCOM_SCM_INTERRUPTED); + + return res.a0; } /** @@ -236,24 +225,12 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) { int context_id; + struct arm_smccc_res res; + + arm_smccc_smc(LEGACY_ATOMIC(svc, cmd, 1), (unsigned long)&context_id, + arg1, 0, 0, 0, 0, 0, &res); - register u32 r0 asm("r0") = LEGACY_ATOMIC(svc, cmd, 1); - register u32 r1 asm("r1") = (u32)&context_id; - register u32 r2 asm("r2") = arg1; - - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0) - : "r" (r0), "r" (r1), "r" (r2) - : "r3", "r12"); - return r0; + return res.a0; } /** @@ -269,26 +246,12 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) { int context_id; + struct arm_smccc_res res; + + arm_smccc_smc(LEGACY_ATOMIC(svc, cmd, 2), (unsigned long)&context_id, + arg1, arg2, 0, 0, 0, 0, &res); - register u32 r0 asm("r0") = LEGACY_ATOMIC(svc, cmd, 2); - register u32 r1 asm("r1") = (u32)&context_id; - register u32 r2 asm("r2") = arg1; - register u32 r3 asm("r3") = arg2; - - asm volatile( - __asmeq("%0", "r0") - __asmeq("%1", "r0") - __asmeq("%2", "r1") - __asmeq("%3", "r2") - __asmeq("%4", "r3") -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0 @ switch to secure world\n" - : "=r" (r0) - : "r" (r0), "r" (r1), "r" (r2), "r" (r3) - : "r12"); - return r0; + return res.a0; } /** From patchwork Tue Oct 29 19:40:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218461 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8C32A13B1 for ; Tue, 29 Oct 2019 19:41:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 560622053B for ; Tue, 29 Oct 2019 19:41:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="CXB26qoa"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="HGk6aN1I" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732787AbfJ2Tlo (ORCPT ); Tue, 29 Oct 2019 15:41:44 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59112 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732703AbfJ2TlU (ORCPT ); Tue, 29 Oct 2019 15:41:20 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 7C9E46110C; Tue, 29 Oct 2019 19:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378078; bh=6hAW82zTf4/8Hm1v5YB/ziDkcsI/FWYzJZE3FBg5a0g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CXB26qoadX+fJlc8BbrmwlrdKOv1fGEbH2T7z/JJbFs3akDK3faTRloay4fcmuyfB EiS1mLNl07EbengbZ3CiJXVp9sDOODhyBubKh42M49qAv+mvFGJLVaepr+R3C8vpx+ syrmXktnepKZV4euxTSPnl/rzYaoEHo+s9tNQk6k= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 3130F610DB; Tue, 29 Oct 2019 19:41:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378077; bh=6hAW82zTf4/8Hm1v5YB/ziDkcsI/FWYzJZE3FBg5a0g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HGk6aN1I9MAlvf79lXW1/kf0Y6s5J7KmlRmZCt68mA2rc/c1TsWEW7NSS+h36kVYa chLlrya18mOPS5YFX2ejpfoTPi0S3fUdOyTvD5rpmCH1ecsIxup9raR0SqJ4tn9CHX DD+HG7CFcV8bd8iADwfhdaV566ohRLpj5CRribY4= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 3130F610DB Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 11/17] firmware: qcom_scm-32: Use qcom_scm_desc in non-atomic calls Date: Tue, 29 Oct 2019 12:40:59 -0700 Message-Id: <1572378065-4490-12-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Use qcom_scm_desc in non-atomic calls to remove legacy convention details from every SCM wrapper function. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 270 ++++++++++++++++++++++++++--------------- 1 file changed, 169 insertions(+), 101 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index e6d0a87..46ae76d 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -39,6 +39,46 @@ static struct qcom_scm_entry qcom_scm_wb[] = { static DEFINE_MUTEX(qcom_scm_lock); +#define MAX_QCOM_SCM_ARGS 10 +#define MAX_QCOM_SCM_RETS 3 + +enum qcom_scm_arg_types { + QCOM_SCM_VAL, + QCOM_SCM_RO, + QCOM_SCM_RW, + QCOM_SCM_BUFVAL, +}; + +#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ + (((a) & 0x3) << 4) | \ + (((b) & 0x3) << 6) | \ + (((c) & 0x3) << 8) | \ + (((d) & 0x3) << 10) | \ + (((e) & 0x3) << 12) | \ + (((f) & 0x3) << 14) | \ + (((g) & 0x3) << 16) | \ + (((h) & 0x3) << 18) | \ + (((i) & 0x3) << 20) | \ + (((j) & 0x3) << 22) | \ + ((num) & 0xf)) + +#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +/** + * struct qcom_scm_desc + * @arginfo: Metadata describing the arguments in args[] + * @args: The array of arguments for the secure syscall + * @res: The values returned by the secure syscall + */ +struct qcom_scm_desc { + u32 svc; + u32 cmd; + u32 arginfo; + u64 args[MAX_QCOM_SCM_ARGS]; + u64 res[MAX_QCOM_SCM_RETS]; + u32 owner; +}; + #define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) /** @@ -150,15 +190,19 @@ static u32 __qcom_scm_call_do(u32 cmd_addr) * and response buffers is taken care of by qcom_scm_call; however, callers are * responsible for any other cached buffers passed over to the secure world. */ -static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, - const void *cmd_buf, size_t cmd_len, void *resp_buf, - size_t resp_len) +static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { + int arglen = desc->arginfo & 0xf; int ret; + size_t i; struct legacy_command *cmd; struct legacy_response *rsp; + const size_t cmd_len = arglen * sizeof(__le32); + const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; dma_addr_t cmd_phys; + __le32 *arg_buf; + __le32 *res_buf; cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); if (!cmd) @@ -167,10 +211,11 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, cmd->len = cpu_to_le32(alloc_len); cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); + cmd->id = cpu_to_le32(LEGACY_FUNCNUM(desc->svc, desc->cmd)); - cmd->id = cpu_to_le32(LEGACY_FUNCNUM(svc_id, cmd_id)); - if (cmd_buf) - memcpy(legacy_get_command_buffer(cmd), cmd_buf, cmd_len); + arg_buf = legacy_get_command_buffer(cmd); + for (i = 0; i < arglen; i++) + arg_buf[i] = cpu_to_le32(desc->args[i]); rsp = legacy_command_to_response(cmd); @@ -193,13 +238,13 @@ static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id, sizeof(*rsp), DMA_FROM_DEVICE); } while (!rsp->is_complete); - if (resp_buf) { - dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + - le32_to_cpu(rsp->buf_offset), - resp_len, DMA_FROM_DEVICE); - memcpy(resp_buf, legacy_get_response_buffer(rsp), - resp_len); - } + dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + + le32_to_cpu(rsp->buf_offset), + resp_len, DMA_FROM_DEVICE); + + res_buf = legacy_get_response_buffer(rsp); + for (i = 0; i < MAX_QCOM_SCM_RETS; i++) + desc->res[i] = le32_to_cpu(res_buf[i]); out: dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); kfree(cmd); @@ -301,10 +346,10 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, int ret; int flags = 0; int cpu; - struct { - __le32 flags; - __le32 addr; - } cmd; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + }; /* * Reassign only if we are switching from hotplug entry point @@ -320,10 +365,9 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, if (!flags) return 0; - cmd.addr = cpu_to_le32(virt_to_phys(entry)); - cmd.flags = cpu_to_le32(flags); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_ADDR, - &cmd, sizeof(cmd), NULL, 0); + desc.args[0] = virt_to_phys(entry); + desc.args[1] = flags; + ret = qcom_scm_call(dev, &desc); if (!ret) { for_each_cpu(cpu, cpus) qcom_scm_wb[cpu].entry = entry; @@ -348,20 +392,20 @@ void __qcom_scm_cpu_power_down(u32 flags) int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { - struct { - __le32 state; - __le32 id; - } req; - __le32 scm_ret = 0; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, + .owner = ARM_SMCCC_OWNER_SIP, + }; int ret; - req.state = cpu_to_le32(state); - req.id = cpu_to_le32(id); + desc.args[0] = state; + desc.args[1] = id; + desc.arginfo = QCOM_SCM_ARGS(2); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_REMOTE_STATE, - &req, sizeof(req), &scm_ret, sizeof(scm_ret)); + ret = qcom_scm_call(dev, &desc); - return ret ? : le32_to_cpu(scm_ret); + return ret ? : desc.res[0]; } int __qcom_scm_set_dload_mode(struct device *dev, bool enable) @@ -372,104 +416,107 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) { - __le32 out; - __le32 in; int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, + .owner = ARM_SMCCC_OWNER_SIP, + }; - in = cpu_to_le32(peripheral); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_IS_SUPPORTED, - &in, sizeof(in), - &out, sizeof(out)); + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); - return ret ? false : !!out; + ret = qcom_scm_call(dev, &desc); + + return ret ? false : !!desc.res[0]; } int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, dma_addr_t metadata_phys) { - __le32 scm_ret; int ret; - struct { - __le32 proc; - __le32 image_addr; - } request; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, + .owner = ARM_SMCCC_OWNER_SIP, + }; - request.proc = cpu_to_le32(peripheral); - request.image_addr = cpu_to_le32(metadata_phys); + desc.args[0] = peripheral; + desc.args[1] = metadata_phys; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_INIT_IMAGE, - &request, sizeof(request), - &scm_ret, sizeof(scm_ret)); + ret = qcom_scm_call(dev, &desc); - return ret ? : le32_to_cpu(scm_ret); + return ret ? : desc.res[0]; } int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, - phys_addr_t addr, phys_addr_t size) + phys_addr_t addr, phys_addr_t size) { - __le32 scm_ret; int ret; - struct { - __le32 proc; - __le32 addr; - __le32 len; - } request; - - request.proc = cpu_to_le32(peripheral); - request.addr = cpu_to_le32(addr); - request.len = cpu_to_le32(size); - - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_MEM_SETUP, - &request, sizeof(request), - &scm_ret, sizeof(scm_ret)); - - return ret ? : le32_to_cpu(scm_ret); + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.args[1] = addr; + desc.args[2] = size; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; } int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) { - __le32 out; - __le32 in; int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; - in = cpu_to_le32(peripheral); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_AUTH_AND_RESET, - &in, sizeof(in), - &out, sizeof(out)); + ret = qcom_scm_call(dev, &desc); - return ret ? : le32_to_cpu(out); + return ret ? : desc.res[0]; } int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) { - __le32 out; - __le32 in; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, + .owner = ARM_SMCCC_OWNER_SIP, + }; int ret; - in = cpu_to_le32(peripheral); - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_SHUTDOWN, - &in, sizeof(in), - &out, sizeof(out)); + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(dev, &desc); - return ret ? : le32_to_cpu(out); + return ret ? : desc.res[0]; } int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) { - __le32 out; - __le32 in = cpu_to_le32(reset); + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; int ret; - ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PIL_PAS_MSS_RESET, - &in, sizeof(in), - &out, sizeof(out)); + desc.args[0] = reset; + desc.args[1] = 0; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); - return ret ? : le32_to_cpu(out); + return ret ? : desc.res[0]; } int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, @@ -493,16 +540,16 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) { int ret; - __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id); - __le32 ret_val = 0; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_INFO, + .cmd = QCOM_INFO_IS_CALL_AVAIL, + .args[0] = (svc_id << 10) | cmd_id, + .arginfo = QCOM_SCM_ARGS(1), + }; - ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL, - &svc_cmd, sizeof(svc_cmd), &ret_val, - sizeof(ret_val)); - if (ret) - return ret; + ret = qcom_scm_call(dev, &desc); - return le32_to_cpu(ret_val); + return ret ? : desc.res[0]; } int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, @@ -533,11 +580,32 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_HDCP, + .cmd = QCOM_SCM_HDCP_INVOKE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) return -ERANGE; - return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE, - req, req_cnt * sizeof(*req), resp, sizeof(*resp)); + desc.args[0] = req[0].addr; + desc.args[1] = req[0].val; + desc.args[2] = req[1].addr; + desc.args[3] = req[1].val; + desc.args[4] = req[2].addr; + desc.args[5] = req[2].val; + desc.args[6] = req[3].addr; + desc.args[7] = req[3].val; + desc.args[8] = req[4].addr; + desc.args[9] = req[4].val; + desc.arginfo = QCOM_SCM_ARGS(req_cnt * 2); + + ret = qcom_scm_call(dev, &desc); + *resp = desc.res[0]; + + return ret; } int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable) From patchwork Tue Oct 29 19:41:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218463 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B63C413B1 for ; Tue, 29 Oct 2019 19:41:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 938F220663 for ; Tue, 29 Oct 2019 19:41:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="QURQeMfn"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="QURQeMfn" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732703AbfJ2Tls (ORCPT ); Tue, 29 Oct 2019 15:41:48 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59172 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732715AbfJ2TlT (ORCPT ); Tue, 29 Oct 2019 15:41:19 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E3DB461160; Tue, 29 Oct 2019 19:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378078; bh=CwJ1xO95Cs4fGMidt4macPUsbwV1O9OFYHlVup1ElfY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QURQeMfnvL6OZOaCA4D4E50PYmS9TBT9yJ9eC2mXzGYkN7fRuV5jMZ/ag7BtVtkH0 OkiGHLRlmnBniWAuHMehq6K6H+RJBPt+c9BcWycSpmPdmywxxb8BRM43NNhjT0Y1ic xSXcgaZu+W8jXoVfQ+lvi/5/5TXO8WRfq8AxaI8A= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id BBD1361132; Tue, 29 Oct 2019 19:41:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378078; bh=CwJ1xO95Cs4fGMidt4macPUsbwV1O9OFYHlVup1ElfY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QURQeMfnvL6OZOaCA4D4E50PYmS9TBT9yJ9eC2mXzGYkN7fRuV5jMZ/ag7BtVtkH0 OkiGHLRlmnBniWAuHMehq6K6H+RJBPt+c9BcWycSpmPdmywxxb8BRM43NNhjT0Y1ic xSXcgaZu+W8jXoVfQ+lvi/5/5TXO8WRfq8AxaI8A= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org BBD1361132 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 12/17] firmware: qcom_scm-32: Move SMCCC register filling to qcom_scm_call Date: Tue, 29 Oct 2019 12:41:00 -0700 Message-Id: <1572378065-4490-13-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org - Move SMCCC register filling to qcom_scm_call so that qcom_scm_call_do only needs to concern itself with retry mechanism. - Use arm_smccc_args struct in atomic variants as well. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 47 ++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index 46ae76d..88d1755 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -78,6 +78,9 @@ struct qcom_scm_desc { u64 res[MAX_QCOM_SCM_RETS]; u32 owner; }; +struct arm_smccc_args { + unsigned long a[8]; +}; #define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) @@ -159,16 +162,13 @@ static inline void *legacy_get_response_buffer(const struct legacy_response *rsp return (void *)rsp + le32_to_cpu(rsp->buf_offset); } -static u32 __qcom_scm_call_do(u32 cmd_addr) +static void __qcom_scm_call_do(const struct arm_smccc_args *smc, + struct arm_smccc_res *res) { - int context_id; - struct arm_smccc_res res; do { - arm_smccc_smc(1, (unsigned long)&context_id, cmd_addr, - 0, 0, 0, 0, 0, &res); - } while (res.a0 == QCOM_SCM_INTERRUPTED); - - return res.a0; + arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], + smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); + } while (res->a0 == QCOM_SCM_INTERRUPTED); } /** @@ -193,10 +193,12 @@ static u32 __qcom_scm_call_do(u32 cmd_addr) static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { int arglen = desc->arginfo & 0xf; - int ret; + int ret = 0, context_id; size_t i; struct legacy_command *cmd; struct legacy_response *rsp; + struct arm_smccc_args smc = {0}; + struct arm_smccc_res res; const size_t cmd_len = arglen * sizeof(__le32); const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; @@ -225,10 +227,14 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) return -ENOMEM; } + smc.a[0] = 1; + smc.a[1] = (unsigned long)&context_id; + smc.a[2] = cmd_phys; + mutex_lock(&qcom_scm_lock); - ret = __qcom_scm_call_do(cmd_phys); - if (ret < 0) - ret = qcom_scm_remap_error(ret); + __qcom_scm_call_do(&smc, &res); + if (res.a0 < 0) + ret = qcom_scm_remap_error(res.a0); mutex_unlock(&qcom_scm_lock); if (ret) goto out; @@ -270,10 +276,14 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) { int context_id; + struct arm_smccc_args smc = {0}; struct arm_smccc_res res; - arm_smccc_smc(LEGACY_ATOMIC(svc, cmd, 1), (unsigned long)&context_id, - arg1, 0, 0, 0, 0, 0, &res); + smc.a[0] = LEGACY_ATOMIC(svc, cmd, 1); + smc.a[1] = (unsigned long)&context_id; + smc.a[2] = arg1; + arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], + smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); return res.a0; } @@ -291,10 +301,15 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) { int context_id; + struct arm_smccc_args smc = {0}; struct arm_smccc_res res; - arm_smccc_smc(LEGACY_ATOMIC(svc, cmd, 2), (unsigned long)&context_id, - arg1, arg2, 0, 0, 0, 0, &res); + smc.a[0] = LEGACY_ATOMIC(svc, cmd, 2); + smc.a[1] = (unsigned long)&context_id; + smc.a[2] = arg1; + smc.a[3] = arg2; + arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], + smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); return res.a0; } From patchwork Tue Oct 29 19:41:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218451 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BBE98139A for ; Tue, 29 Oct 2019 19:41:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9000221734 for ; Tue, 29 Oct 2019 19:41:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="AiPMPQYp"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="GYnyQvtu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732820AbfJ2TlX (ORCPT ); Tue, 29 Oct 2019 15:41:23 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59296 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732783AbfJ2TlV (ORCPT ); Tue, 29 Oct 2019 15:41:21 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 7E7E261189; Tue, 29 Oct 2019 19:41:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378080; bh=tL2BbrwGwu9blREkX8o8jK47L1GFoM99Ft8aXjCPPf0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AiPMPQYpjCwJbifYmnGWGnmh7XBynRom/+jR2d/RvkMc1K2g4rmZT/2DWSaceIS4q /JuKLXjnKG7uTU2W4hWaAhWFei/PiS0Bbjfp13kqZBzNnBLQTS475FhtdmpAhczaoR dwzdwf96nemcKU72Tl6u/mM7DA4bgtV2IGjOYL0g= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 4D3796110D; Tue, 29 Oct 2019 19:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378078; bh=tL2BbrwGwu9blREkX8o8jK47L1GFoM99Ft8aXjCPPf0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GYnyQvtukMKvKRZDzo14KMWDakHXwwg5wgrq7BB6gAlJlED4HT/isixfq/+FldtzB HPJ8TAmSrdYMH87y7VcuPu4n9dfndYf9306wKyZp9dDJOHVimvRrEGLENiYXLgveru OgHM3inLKKeoobuSY1C1ftjs1h8aK246+omGGiV0= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 4D3796110D Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 13/17] firmware: qcom_scm-32: Create common legacy atomic call Date: Tue, 29 Oct 2019 12:41:01 -0700 Message-Id: <1572378065-4490-14-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Per [1], legacy calling convention supports up to 5 arguments and 3 return values. Create one function to support this combination. [1]: https://source.codeaurora.org/quic/la/kernel/msm-4.9/tree/drivers/soc/qcom/scm.c?h=kernel.lnx.4.9.r28-rel#n1024 Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 107 +++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 41 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index 88d1755..f9eb490 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -257,6 +257,8 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) return ret; } +#define LEGACY_ATOMIC_N_REG_ARGS 5 +#define LEGACY_ATOMIC_FIRST_REG_IDX 2 #define LEGACY_CLASS_REGISTER (0x2 << 8) #define LEGACY_MASK_IRQS BIT(5) #define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ @@ -265,52 +267,34 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) (n & 0xf)) /** - * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument - * @svc_id: service identifier - * @cmd_id: command identifier - * @arg1: first argument + * qcom_scm_call_atomic() - Send an atomic SCM command with up to 5 arguments + * and 3 return values * * This shall only be used with commands that are guaranteed to be * uninterruptable, atomic and SMP safe. */ -static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) +static int qcom_scm_call_atomic(struct qcom_scm_desc *desc) { int context_id; struct arm_smccc_args smc = {0}; struct arm_smccc_res res; + size_t i, arglen = desc->arginfo & 0xf; - smc.a[0] = LEGACY_ATOMIC(svc, cmd, 1); + BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); + + smc.a[0] = LEGACY_ATOMIC(desc->svc, desc->cmd, arglen); smc.a[1] = (unsigned long)&context_id; - smc.a[2] = arg1; - arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], - smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); - return res.a0; -} + for(i = 0; i < arglen; i++) + smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; -/** - * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments - * @svc_id: service identifier - * @cmd_id: command identifier - * @arg1: first argument - * @arg2: second argument - * - * This shall only be used with commands that are guaranteed to be - * uninterruptable, atomic and SMP safe. - */ -static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) -{ - int context_id; - struct arm_smccc_args smc = {0}; - struct arm_smccc_res res; - - smc.a[0] = LEGACY_ATOMIC(svc, cmd, 2); - smc.a[1] = (unsigned long)&context_id; - smc.a[2] = arg1; - smc.a[3] = arg2; arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); + desc->res[0] = res.a1; + desc->res[1] = res.a2; + desc->res[2] = res.a3; + return res.a0; } @@ -332,6 +316,11 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) QCOM_SCM_FLAG_COLDBOOT_CPU2, QCOM_SCM_FLAG_COLDBOOT_CPU3, }; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + .owner = ARM_SMCCC_OWNER_SIP, + }; if (!cpus || (cpus && cpumask_empty(cpus))) return -EINVAL; @@ -343,8 +332,11 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) set_cpu_present(cpu, false); } - return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_ADDR, - flags, virt_to_phys(entry)); + desc.args[0] = flags; + desc.args[1] = virt_to_phys(entry); + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(&desc); } /** @@ -401,8 +393,15 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, */ void __qcom_scm_cpu_power_down(u32 flags) { - qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_TERMINATE_PC, - flags & QCOM_SCM_FLUSH_FLAG_MASK); + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_TERMINATE_PC, + .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK, + .arginfo = QCOM_SCM_ARGS(1), + .owner = ARM_SMCCC_OWNER_SIP, + }; + + qcom_scm_call_atomic(&desc); } int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) @@ -425,8 +424,17 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { - return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_SET_DLOAD_MODE, - enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0, 0); + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; + desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(&desc); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -538,18 +546,35 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val) { int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_READ, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = addr; + desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call_atomic1(QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, addr); + ret = qcom_scm_call_atomic(&desc); if (ret >= 0) - *val = ret; + *val = desc.res[0]; return ret < 0 ? ret : 0; } int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) { - return qcom_scm_call_atomic2(QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE, - addr, val); + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_WRITE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = addr; + desc.args[1] = val; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(&desc); } int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) From patchwork Tue Oct 29 19:41:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218453 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E735513BD for ; Tue, 29 Oct 2019 19:41:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C476321734 for ; Tue, 29 Oct 2019 19:41:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="BDZJSyXG"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="BDZJSyXG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732612AbfJ2TlX (ORCPT ); Tue, 29 Oct 2019 15:41:23 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59250 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732749AbfJ2TlV (ORCPT ); Tue, 29 Oct 2019 15:41:21 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id ED10761178; Tue, 29 Oct 2019 19:41:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378079; bh=uK6ASzZpPsIeZzDNRRMhT8EKcsUfWE3Mf4A1ExJ+xZ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BDZJSyXGiYOpewo4vEKD8uxKLA0VXaotuaAdNLiIcO1FPcqefpScSAkpxn63fEMnk uIA/SqMxpcuusgrym5eXHm7y9mG5YdcsgZwvF9KxzToJaqdn98GfOgtrR3/Fb6xfVd yaGoXy0KCqyk+FHSafcFSjjLeLPwHjF5xM/6Liaw= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id D96806115E; Tue, 29 Oct 2019 19:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378079; bh=uK6ASzZpPsIeZzDNRRMhT8EKcsUfWE3Mf4A1ExJ+xZ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BDZJSyXGiYOpewo4vEKD8uxKLA0VXaotuaAdNLiIcO1FPcqefpScSAkpxn63fEMnk uIA/SqMxpcuusgrym5eXHm7y9mG5YdcsgZwvF9KxzToJaqdn98GfOgtrR3/Fb6xfVd yaGoXy0KCqyk+FHSafcFSjjLeLPwHjF5xM/6Liaw= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org D96806115E Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 14/17] firmware: qcom_scm-32: Add device argument to atomic calls Date: Tue, 29 Oct 2019 12:41:02 -0700 Message-Id: <1572378065-4490-15-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add this unused parameter to reduce merge friction between SMCCC and legacy based conventions. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-32.c | 18 ++++++++++-------- drivers/firmware/qcom_scm-64.c | 5 +++-- drivers/firmware/qcom_scm.c | 4 ++-- drivers/firmware/qcom_scm.h | 5 +++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index f9eb490..a33fdf1 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -273,7 +273,7 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) * This shall only be used with commands that are guaranteed to be * uninterruptable, atomic and SMP safe. */ -static int qcom_scm_call_atomic(struct qcom_scm_desc *desc) +static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) { int context_id; struct arm_smccc_args smc = {0}; @@ -306,7 +306,8 @@ static int qcom_scm_call_atomic(struct qcom_scm_desc *desc) * Set the cold boot address of the cpus. Any cpu outside the supported * range would be removed from the cpu present mask. */ -int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) +int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, + const cpumask_t *cpus) { int flags = 0; int cpu; @@ -336,7 +337,7 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) desc.args[1] = virt_to_phys(entry); desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call_atomic(&desc); + return qcom_scm_call_atomic(dev, &desc); } /** @@ -391,7 +392,7 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, * the control would return from this function, otherwise, the cpu jumps to the * warm boot entry point set for this cpu upon reset. */ -void __qcom_scm_cpu_power_down(u32 flags) +void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) { struct qcom_scm_desc desc = { .svc = QCOM_SCM_SVC_BOOT, @@ -401,7 +402,7 @@ void __qcom_scm_cpu_power_down(u32 flags) .owner = ARM_SMCCC_OWNER_SIP, }; - qcom_scm_call_atomic(&desc); + qcom_scm_call_atomic(dev, &desc); } int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) @@ -434,7 +435,7 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call_atomic(&desc); + return qcom_scm_call_atomic(dev, &desc); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -555,11 +556,12 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, desc.args[0] = addr; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call_atomic(&desc); + ret = qcom_scm_call_atomic(dev, &desc); if (ret >= 0) *val = desc.res[0]; return ret < 0 ? ret : 0; + } int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) @@ -574,7 +576,7 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) desc.args[1] = val; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call_atomic(&desc); + return qcom_scm_call_atomic(dev, &desc); } int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 4d7fd3e..9f39483 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -221,7 +221,8 @@ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) * Set the cold boot address of the cpus. Any cpu outside the supported * range would be removed from the cpu present mask. */ -int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) +int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, + const cpumask_t *cpus) { return -ENOTSUPP; } @@ -249,7 +250,7 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, * the control would return from this function, otherwise, the cpu jumps to the * warm boot entry point set for this cpu upon reset. */ -void __qcom_scm_cpu_power_down(u32 flags) +void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) { } diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 7244236..bb57fad 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -97,7 +97,7 @@ static void qcom_scm_clk_disable(void) */ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) { - return __qcom_scm_set_cold_boot_addr(entry, cpus); + return __qcom_scm_set_cold_boot_addr(__scm->dev, entry, cpus); } EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); @@ -125,7 +125,7 @@ EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); */ void qcom_scm_cpu_power_down(u32 flags) { - __qcom_scm_cpu_power_down(flags); + __qcom_scm_cpu_power_down(__scm->dev, flags); } EXPORT_SYMBOL(qcom_scm_cpu_power_down); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 6f63ca6..ce2c396 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -9,10 +9,11 @@ #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 -extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); +extern int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, + const cpumask_t *cpus); extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); -extern void __qcom_scm_cpu_power_down(u32 flags); +extern void __qcom_scm_cpu_power_down(struct device *dev, u32 flags); extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 From patchwork Tue Oct 29 19:41:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218459 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9E2CB139A for ; Tue, 29 Oct 2019 19:41:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 679FF21734 for ; Tue, 29 Oct 2019 19:41:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="e6HrFTSy"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="ooc/JVz7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732952AbfJ2Tli (ORCPT ); Tue, 29 Oct 2019 15:41:38 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59332 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732787AbfJ2TlW (ORCPT ); Tue, 29 Oct 2019 15:41:22 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E1ABE6119B; Tue, 29 Oct 2019 19:41:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378080; bh=sHg38L+FKPh+SKEIc+nBDiMf56kEXlg1XkzK9aIWflM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e6HrFTSymF9uaDNrVQB8XKXgmyzcvgP5PtbvLbtOGsuhSlvpBIGPMSs41WSijDZ01 qtKkg0SD1RbNHD4FOSKcH4B58iyJFG0Bv3uglOMKIFhBMtapyYdP51f5243K/luUpY eXPDz4UpTmqhnn/UswATckE7yT3NW3qNu2U13JmA= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 6B84361150; Tue, 29 Oct 2019 19:41:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378079; bh=sHg38L+FKPh+SKEIc+nBDiMf56kEXlg1XkzK9aIWflM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ooc/JVz71ixTnkXFne1pYe/cp8hgYYrdwSucMUMA6HMvN48h3RpBGn+OwhTtuGcwb j0uFabyzZF+ML+Cr2d98WNW9vSzFX2sDK0mMU1wbHnwmGhOqDJrgAmZH6HYWVUjd1x SzSr0evkojHSo7Kd7M8mvZ5QHRXyN4SWW9ToNbVI= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 6B84361150 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 15/17] firmware: qcom_scm: Merge legacy and SMCCC conventions Date: Tue, 29 Oct 2019 12:41:03 -0700 Message-Id: <1572378065-4490-16-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Copy/paste legacy SCM driver into qcom_scm-64 with the following notes: - Renamed qcom_scm_call in qcom_scm-32 to qcom_scm_call_legacy in the copy. - Renamed qcom_scm_call_atomic in qcom_scm 32 to qcom_scm_call_atomic_legacy in the copy. - Rename __qcom_scm_call_smccc to qcom_scm_call_smccc. - Filled in implementations set_cold_boot_addr, set_warm_boot_addr, and cpu_power_down from qcom_scm-32.c. - set_dload_mode, io_writel, io_readl now use atomic variants as in qcom_scm-32. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 322 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 314 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 9f39483..71b07b8 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -95,7 +95,7 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, } while (res->a0 == QCOM_SCM_INTERRUPTED); } -static int ___qcom_scm_call_smccc(struct device *dev, +static int qcom_scm_call_smccc(struct device *dev, struct qcom_scm_desc *desc, bool atomic) { int arglen = desc->arginfo & 0xf; @@ -181,6 +181,223 @@ static int ___qcom_scm_call_smccc(struct device *dev, return 0; } +#define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) + +/** + * struct legacy_command - one SCM command buffer + * @len: total available memory for command and response + * @buf_offset: start of command buffer + * @resp_hdr_offset: start of response buffer + * @id: command to be executed + * @buf: buffer returned from legacy_get_command_buffer() + * + * An SCM command is laid out in memory as follows: + * + * ------------------- <--- struct legacy_command + * | command header | + * ------------------- <--- legacy_get_command_buffer() + * | command buffer | + * ------------------- <--- struct legacy_response and + * | response header | legacy_command_to_response() + * ------------------- <--- legacy_get_response_buffer() + * | response buffer | + * ------------------- + * + * There can be arbitrary padding between the headers and buffers so + * you should always use the appropriate qcom_scm_get_*_buffer() routines + * to access the buffers in a safe manner. + */ +struct legacy_command { + __le32 len; + __le32 buf_offset; + __le32 resp_hdr_offset; + __le32 id; + __le32 buf[0]; +}; + +/** + * struct legacy_response - one SCM response buffer + * @len: total available memory for response + * @buf_offset: start of response data relative to start of legacy_response + * @is_complete: indicates if the command has finished processing + */ +struct legacy_response { + __le32 len; + __le32 buf_offset; + __le32 is_complete; +}; + +/** + * legacy_command_to_response() - Get a pointer to a legacy_response + * @cmd: command + * + * Returns a pointer to a response for a command. + */ +static inline struct legacy_response *legacy_command_to_response( + const struct legacy_command *cmd) +{ + return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); +} + +/** + * legacy_get_command_buffer() - Get a pointer to a command buffer + * @cmd: command + * + * Returns a pointer to the command buffer of a command. + */ +static inline void *legacy_get_command_buffer(const struct legacy_command *cmd) +{ + return (void *)cmd->buf; +} + +/** + * legacy_get_response_buffer() - Get a pointer to a response buffer + * @rsp: response + * + * Returns a pointer to a response buffer of a response. + */ +static inline void *legacy_get_response_buffer(const struct legacy_response *rsp) +{ + return (void *)rsp + le32_to_cpu(rsp->buf_offset); +} + +static void __qcom_scm_call_do(const struct arm_smccc_args *smc, + struct arm_smccc_res *res) +{ + do { + arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], + smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); + } while (res->a0 == QCOM_SCM_INTERRUPTED); +} + +/** + * qcom_scm_call_legacy() - Send an SCM command + * @dev: struct device + * @svc_id: service identifier + * @cmd_id: command identifier + * @cmd_buf: command buffer + * @cmd_len: length of the command buffer + * @resp_buf: response buffer + * @resp_len: length of the response buffer + * + * Sends a command to the SCM and waits for the command to finish processing. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking qcom_scm_call and invalidated in the cache + * immediately after qcom_scm_call returns. Cache maintenance on the command + * and response buffers is taken care of by qcom_scm_call; however, callers are + * responsible for any other cached buffers passed over to the secure world. + */ +static int qcom_scm_call_legacy(struct device *dev, struct qcom_scm_desc *desc) +{ + int arglen = desc->arginfo & 0xf; + int ret = 0, context_id; + size_t i; + struct legacy_command *cmd; + struct legacy_response *rsp; + struct arm_smccc_args smc = {0}; + struct arm_smccc_res res; + const size_t cmd_len = arglen * sizeof(__le32); + const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); + size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; + dma_addr_t cmd_phys; + __le32 *arg_buf; + __le32 *res_buf; + + cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->len = cpu_to_le32(alloc_len); + cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); + cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); + cmd->id = cpu_to_le32(LEGACY_FUNCNUM(desc->svc, desc->cmd)); + + arg_buf = legacy_get_command_buffer(cmd); + for (i = 0; i < arglen; i++) + arg_buf[i] = cpu_to_le32(desc->args[i]); + + rsp = legacy_command_to_response(cmd); + + cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, cmd_phys)) { + kfree(cmd); + return -ENOMEM; + } + + smc.a[0] = 1; + smc.a[1] = (unsigned long)&context_id; + smc.a[2] = cmd_phys; + + mutex_lock(&qcom_scm_lock); + __qcom_scm_call_do(&smc, &res); + if (res.a0 < 0) + ret = qcom_scm_remap_error(res.a0); + mutex_unlock(&qcom_scm_lock); + if (ret) + goto out; + + do { + dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, + sizeof(*rsp), DMA_FROM_DEVICE); + } while (!rsp->is_complete); + + dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + + le32_to_cpu(rsp->buf_offset), + resp_len, DMA_FROM_DEVICE); + + res_buf = legacy_get_response_buffer(rsp); + for (i = 0; i < MAX_QCOM_SCM_RETS; i++) + desc->res[i] = le32_to_cpu(res_buf[i]); +out: + dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); + kfree(cmd); + return ret; +} + +#define LEGACY_ATOMIC_N_REG_ARGS 5 +#define LEGACY_ATOMIC_FIRST_REG_IDX 2 +#define LEGACY_CLASS_REGISTER (0x2 << 8) +#define LEGACY_MASK_IRQS BIT(5) +#define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ + LEGACY_CLASS_REGISTER | \ + LEGACY_MASK_IRQS | \ + (n & 0xf)) + +/** + * qcom_scm_call_atomic_legacy() - Send an atomic SCM command with up to + * 5 arguments and 3 return values + * + * This shall only be used with commands that are guaranteed to be + * uninterruptable, atomic and SMP safe. + */ +static int qcom_scm_call_atomic_legacy(struct device *dev, + struct qcom_scm_desc *desc) +{ + int context_id; + struct arm_smccc_args smc = {0}; + struct arm_smccc_res res; + size_t i, arglen = desc->arginfo & 0xf; + + BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); + + smc.a[0] = LEGACY_ATOMIC(desc->svc, desc->cmd, arglen); + smc.a[1] = (unsigned long)&context_id; + + for(i = 0; i < arglen; i++) + smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; + + arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], + smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); + + desc->res[0] = res.a1; + desc->res[1] = res.a2; + desc->res[2] = res.a3; + + return res.a0; +} + /** * qcom_scm_call() - Invoke a syscall in the secure world * @dev: device @@ -194,7 +411,7 @@ static int ___qcom_scm_call_smccc(struct device *dev, static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { might_sleep(); - return ___qcom_scm_call_smccc(dev, desc, false); + return qcom_scm_call_smccc(dev, desc, false); } /** @@ -210,9 +427,14 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) */ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) { - return ___qcom_scm_call_smccc(dev, desc, true); + return qcom_scm_call_smccc(dev, desc, true); } +#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 +#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 +#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 +#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 + /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus @@ -224,9 +446,54 @@ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus) { - return -ENOTSUPP; + int flags = 0; + int cpu; + int scm_cb_flags[] = { + QCOM_SCM_FLAG_COLDBOOT_CPU0, + QCOM_SCM_FLAG_COLDBOOT_CPU1, + QCOM_SCM_FLAG_COLDBOOT_CPU2, + QCOM_SCM_FLAG_COLDBOOT_CPU3, + }; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + if (!cpus || (cpus && cpumask_empty(cpus))) + return -EINVAL; + + for_each_cpu(cpu, cpus) { + if (cpu < ARRAY_SIZE(scm_cb_flags)) + flags |= scm_cb_flags[cpu]; + else + set_cpu_present(cpu, false); + } + + desc.args[0] = flags; + desc.args[1] = virt_to_phys(entry); + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); } +#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 +#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 +#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 +#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 + +struct qcom_scm_entry { + int flag; + void *entry; +}; + +static struct qcom_scm_entry qcom_scm_wb[] = { + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, +}; + /** * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus * @dev: Device pointer @@ -239,7 +506,37 @@ int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus) { - return -ENOTSUPP; + int ret; + int flags = 0; + int cpu; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + }; + + /* + * Reassign only if we are switching from hotplug entry point + * to cpuidle entry point or vice versa. + */ + for_each_cpu(cpu, cpus) { + if (entry == qcom_scm_wb[cpu].entry) + continue; + flags |= qcom_scm_wb[cpu].flag; + } + + /* No change in entry function */ + if (!flags) + return 0; + + desc.args[0] = virt_to_phys(entry); + desc.args[1] = flags; + ret = qcom_scm_call(dev, &desc); + if (!ret) { + for_each_cpu(cpu, cpus) + qcom_scm_wb[cpu].entry = entry; + } + + return ret; } /** @@ -252,6 +549,15 @@ int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, */ void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) { + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_TERMINATE_PC, + .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK, + .arginfo = QCOM_SCM_ARGS(1), + .owner = ARM_SMCCC_OWNER_SIP, + }; + + qcom_scm_call_atomic(dev, &desc); } int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) @@ -284,7 +590,7 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, &desc); + return qcom_scm_call_atomic(dev, &desc); } bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) @@ -408,7 +714,7 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, desc.args[0] = addr; desc.arginfo = QCOM_SCM_ARGS(1); - ret = qcom_scm_call(dev, &desc); + ret = qcom_scm_call_atomic(dev, &desc); if (ret >= 0) *val = desc.res[0]; @@ -427,7 +733,7 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) desc.args[1] = val; desc.arginfo = QCOM_SCM_ARGS(2); - return qcom_scm_call(dev, &desc); + return qcom_scm_call_atomic(dev, &desc); } int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) From patchwork Tue Oct 29 19:41:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218457 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8A2A0139A for ; Tue, 29 Oct 2019 19:41:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 688DC21906 for ; Tue, 29 Oct 2019 19:41:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="iToUY6Se"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="luNjpd7I" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732835AbfJ2TlY (ORCPT ); Tue, 29 Oct 2019 15:41:24 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59398 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732813AbfJ2TlX (ORCPT ); Tue, 29 Oct 2019 15:41:23 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 1C047611A0; Tue, 29 Oct 2019 19:41:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378081; bh=g2U8HWLTIcekjOXCUmt1PvmKhBgWatSqjqtl7Sh96/c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iToUY6SeLIwMv78MRsEbxKKBAd2N81tJlTkNsNpawarlMCO8Ekwax/YxI8C8HuJKJ tfUaukE18qwT3hnjczhbICOpnEi6fQws6yH3tGpiq4VSri/8fFmBK/x0VNY8BBMgCd 6gLjIZKw7LQUIPQs3KnN/yPin5ly0TdEXM28CGtI= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 0485661139; Tue, 29 Oct 2019 19:41:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378080; bh=g2U8HWLTIcekjOXCUmt1PvmKhBgWatSqjqtl7Sh96/c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=luNjpd7IdsggE167WpwVUkiHvGvW9j9UOea6z0DSIV+QsqLF7bhTxyRefVgYOluaC y9FGxbRLrxord6yXY97O3R2YDGyfI75rJrqeoubJhL72Y8goEGp3VGQaCaWLVk92Kz fAHDmRvSfxQ0/Y4wOiRhQNjJf1+TSyEcwcv62SxE= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 0485661139 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 16/17] firmware: qcom_scm: Enable legacy calling convention in qcom_scm-64.c Date: Tue, 29 Oct 2019 12:41:04 -0700 Message-Id: <1572378065-4490-17-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Enable legacy calling convention in qcom_scm-64. Update is_call_available to use legacy function numbers when using legacy convention. Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 71b07b8..18f0bf5 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -60,6 +60,7 @@ struct arm_smccc_args { enum qcom_smc_convention { SMC_CONVENTION_UNKNOWN, + SMC_CONVENTION_LEGACY, SMC_CONVENTION_ARM_32, SMC_CONVENTION_ARM_64, }; @@ -411,7 +412,16 @@ static int qcom_scm_call_atomic_legacy(struct device *dev, static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { might_sleep(); - return qcom_scm_call_smccc(dev, desc, false); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, false); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } } /** @@ -427,7 +437,16 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) */ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) { - return qcom_scm_call_smccc(dev, desc, true); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, true); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_atomic_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } } #define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 @@ -746,8 +765,19 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) }; desc.arginfo = QCOM_SCM_ARGS(1); - desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | - (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + break; + case SMC_CONVENTION_LEGACY: + desc.args[0] = LEGACY_FUNCNUM(svc_id, cmd_id); + break; + default: + pr_err("Unknown SMC convention being used\n"); + return -EINVAL; + } ret = qcom_scm_call(dev, &desc); @@ -902,7 +932,7 @@ void __qcom_scm_init(void) qcom_smc_convention = SMC_CONVENTION_ARM_32; if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, QCOM_INFO_IS_CALL_AVAIL) <= 0) { - qcom_smc_convention = SMC_CONVENTION_UNKNOWN; + qcom_smc_convention = SMC_CONVENTION_LEGACY; } } } From patchwork Tue Oct 29 19:41:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 11218455 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA2AB139A for ; Tue, 29 Oct 2019 19:41:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5D53421734 for ; Tue, 29 Oct 2019 19:41:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="TN41HYzP"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="Ms/Ph8nT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732905AbfJ2Tlc (ORCPT ); Tue, 29 Oct 2019 15:41:32 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:59526 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732899AbfJ2Tlb (ORCPT ); Tue, 29 Oct 2019 15:41:31 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 143D2611AC; Tue, 29 Oct 2019 19:41:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378088; bh=FOTd+jxX3k6GS7w6oDnwVBoTFr/+nIMVlWr0I4Q1zjE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TN41HYzP4X8rgwF6mrxJTsQPhSDw8Ce4+ph/3a/ge+8UCD3EugHSmcc6ezoOrT8Lw rlmNDT5EAg0H0khkG6EIQNwAhAZcMqdftfWw08FYuCUQp1BNqFITUKNBCnpSpi+mAc m5pOYoIpKH3UNmIyQJAlGs6uSGZzYA6I/gV25zC0= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_INVALID,DKIM_SIGNED,SPF_NONE autolearn=no autolearn_force=no version=3.4.0 Received: from eberman-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: eberman@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 8D57161151; Tue, 29 Oct 2019 19:41:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572378081; bh=FOTd+jxX3k6GS7w6oDnwVBoTFr/+nIMVlWr0I4Q1zjE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ms/Ph8nT6l/SdVGA/fh6AWN9aeVRPxRp6qE1OvHU/s0OQhJvhtIJZrR+pqjeq6NY3 zkB2A4f2704ZGwQtw+NOF3F234CbaXhcZ3oMS09/9jFhDI3DbAHuBQesbMd42xhCfJ 3RfSHIvreyRx7acHrnHnOEs9j90/naVjs7HQPmIg= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 8D57161151 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=eberman@codeaurora.org From: Elliot Berman To: bjorn.andersson@linaro.org, saipraka@codeaurora.org, agross@kernel.org Cc: tsoni@codeaurora.org, sidgup@codeaurora.org, psodagud@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, Elliot Berman Subject: [RFC 17/17] firmware: qcom_scm: Rename -64 -> -smc, remove -32 Date: Tue, 29 Oct 2019 12:41:05 -0700 Message-Id: <1572378065-4490-18-git-send-email-eberman@codeaurora.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> References: <1572378065-4490-1-git-send-email-eberman@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org - Rename qcom_scm-64.c to qcom_scm-smc as it supports SMC-based calling conventions for 32 and 64-bit targets - Remove qcom_scm-32.c as it has been superceded by qcom_scm-smc.c - Update Kconfig to select QCOM_SCM_TRANSPORT_SMC on ARM and ARM64 targets Signed-off-by: Elliot Berman --- drivers/firmware/Kconfig | 18 +- drivers/firmware/Makefile | 4 +- drivers/firmware/qcom_scm-32.c | 660 ---------------------------- drivers/firmware/qcom_scm-64.c | 938 ---------------------------------------- drivers/firmware/qcom_scm-smc.c | 938 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 950 insertions(+), 1608 deletions(-) delete mode 100644 drivers/firmware/qcom_scm-32.c delete mode 100644 drivers/firmware/qcom_scm-64.c create mode 100644 drivers/firmware/qcom_scm-smc.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index e40a77b..ad477ca 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -236,16 +236,20 @@ config INTEL_STRATIX10_RSU config QCOM_SCM bool - depends on ARM || ARM64 + depends on QCOM_SCM_TRANSPORT_SMC select RESET_CONTROLLER + help + This option enables support for communicating with + Qualcomm secure worlds. -config QCOM_SCM_32 - def_bool y - depends on QCOM_SCM && ARM - -config QCOM_SCM_64 +config QCOM_SCM_TRANSPORT_SMC def_bool y - depends on QCOM_SCM && ARM64 + depends on ARM || ARM64 + help + This option enables support for communicating with + Qualcomm secure worlds via the SMC instruction, using + either ARM SMCCC or legacy calling convention by querying + the Qualcomm secure world. config QCOM_SCM_DOWNLOAD_MODE_DEFAULT bool "Qualcomm download mode enabled by default" diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 3fcb919..fc250f0 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -18,9 +18,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o obj-$(CONFIG_QCOM_SCM) += qcom_scm.o -obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o -obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o -CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a +obj-$(CONFIG_QCOM_SCM_TRANSPORT_SMC) += qcom_scm-smc.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c deleted file mode 100644 index a33fdf1..0000000 --- a/drivers/firmware/qcom_scm-32.c +++ /dev/null @@ -1,660 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved. - * Copyright (C) 2015 Linaro Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qcom_scm.h" - -#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 -#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 -#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 -#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 - -#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 -#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 -#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 -#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 - -struct qcom_scm_entry { - int flag; - void *entry; -}; - -static struct qcom_scm_entry qcom_scm_wb[] = { - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, -}; - -static DEFINE_MUTEX(qcom_scm_lock); - -#define MAX_QCOM_SCM_ARGS 10 -#define MAX_QCOM_SCM_RETS 3 - -enum qcom_scm_arg_types { - QCOM_SCM_VAL, - QCOM_SCM_RO, - QCOM_SCM_RW, - QCOM_SCM_BUFVAL, -}; - -#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ - (((a) & 0x3) << 4) | \ - (((b) & 0x3) << 6) | \ - (((c) & 0x3) << 8) | \ - (((d) & 0x3) << 10) | \ - (((e) & 0x3) << 12) | \ - (((f) & 0x3) << 14) | \ - (((g) & 0x3) << 16) | \ - (((h) & 0x3) << 18) | \ - (((i) & 0x3) << 20) | \ - (((j) & 0x3) << 22) | \ - ((num) & 0xf)) - -#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - -/** - * struct qcom_scm_desc - * @arginfo: Metadata describing the arguments in args[] - * @args: The array of arguments for the secure syscall - * @res: The values returned by the secure syscall - */ -struct qcom_scm_desc { - u32 svc; - u32 cmd; - u32 arginfo; - u64 args[MAX_QCOM_SCM_ARGS]; - u64 res[MAX_QCOM_SCM_RETS]; - u32 owner; -}; -struct arm_smccc_args { - unsigned long a[8]; -}; - -#define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) - -/** - * struct legacy_command - one SCM command buffer - * @len: total available memory for command and response - * @buf_offset: start of command buffer - * @resp_hdr_offset: start of response buffer - * @id: command to be executed - * @buf: buffer returned from legacy_get_command_buffer() - * - * An SCM command is laid out in memory as follows: - * - * ------------------- <--- struct legacy_command - * | command header | - * ------------------- <--- legacy_get_command_buffer() - * | command buffer | - * ------------------- <--- struct legacy_response and - * | response header | legacy_command_to_response() - * ------------------- <--- legacy_get_response_buffer() - * | response buffer | - * ------------------- - * - * There can be arbitrary padding between the headers and buffers so - * you should always use the appropriate qcom_scm_get_*_buffer() routines - * to access the buffers in a safe manner. - */ -struct legacy_command { - __le32 len; - __le32 buf_offset; - __le32 resp_hdr_offset; - __le32 id; - __le32 buf[0]; -}; - -/** - * struct legacy_response - one SCM response buffer - * @len: total available memory for response - * @buf_offset: start of response data relative to start of legacy_response - * @is_complete: indicates if the command has finished processing - */ -struct legacy_response { - __le32 len; - __le32 buf_offset; - __le32 is_complete; -}; - -/** - * legacy_command_to_response() - Get a pointer to a legacy_response - * @cmd: command - * - * Returns a pointer to a response for a command. - */ -static inline struct legacy_response *legacy_command_to_response( - const struct legacy_command *cmd) -{ - return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); -} - -/** - * legacy_get_command_buffer() - Get a pointer to a command buffer - * @cmd: command - * - * Returns a pointer to the command buffer of a command. - */ -static inline void *legacy_get_command_buffer(const struct legacy_command *cmd) -{ - return (void *)cmd->buf; -} - -/** - * legacy_get_response_buffer() - Get a pointer to a response buffer - * @rsp: response - * - * Returns a pointer to a response buffer of a response. - */ -static inline void *legacy_get_response_buffer(const struct legacy_response *rsp) -{ - return (void *)rsp + le32_to_cpu(rsp->buf_offset); -} - -static void __qcom_scm_call_do(const struct arm_smccc_args *smc, - struct arm_smccc_res *res) -{ - do { - arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], - smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); - } while (res->a0 == QCOM_SCM_INTERRUPTED); -} - -/** - * qcom_scm_call() - Send an SCM command - * @dev: struct device - * @svc_id: service identifier - * @cmd_id: command identifier - * @cmd_buf: command buffer - * @cmd_len: length of the command buffer - * @resp_buf: response buffer - * @resp_len: length of the response buffer - * - * Sends a command to the SCM and waits for the command to finish processing. - * - * A note on cache maintenance: - * Note that any buffers that are expected to be accessed by the secure world - * must be flushed before invoking qcom_scm_call and invalidated in the cache - * immediately after qcom_scm_call returns. Cache maintenance on the command - * and response buffers is taken care of by qcom_scm_call; however, callers are - * responsible for any other cached buffers passed over to the secure world. - */ -static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) -{ - int arglen = desc->arginfo & 0xf; - int ret = 0, context_id; - size_t i; - struct legacy_command *cmd; - struct legacy_response *rsp; - struct arm_smccc_args smc = {0}; - struct arm_smccc_res res; - const size_t cmd_len = arglen * sizeof(__le32); - const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); - size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; - dma_addr_t cmd_phys; - __le32 *arg_buf; - __le32 *res_buf; - - cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->len = cpu_to_le32(alloc_len); - cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); - cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); - cmd->id = cpu_to_le32(LEGACY_FUNCNUM(desc->svc, desc->cmd)); - - arg_buf = legacy_get_command_buffer(cmd); - for (i = 0; i < arglen; i++) - arg_buf[i] = cpu_to_le32(desc->args[i]); - - rsp = legacy_command_to_response(cmd); - - cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); - if (dma_mapping_error(dev, cmd_phys)) { - kfree(cmd); - return -ENOMEM; - } - - smc.a[0] = 1; - smc.a[1] = (unsigned long)&context_id; - smc.a[2] = cmd_phys; - - mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do(&smc, &res); - if (res.a0 < 0) - ret = qcom_scm_remap_error(res.a0); - mutex_unlock(&qcom_scm_lock); - if (ret) - goto out; - - do { - dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, - sizeof(*rsp), DMA_FROM_DEVICE); - } while (!rsp->is_complete); - - dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + - le32_to_cpu(rsp->buf_offset), - resp_len, DMA_FROM_DEVICE); - - res_buf = legacy_get_response_buffer(rsp); - for (i = 0; i < MAX_QCOM_SCM_RETS; i++) - desc->res[i] = le32_to_cpu(res_buf[i]); -out: - dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); - kfree(cmd); - return ret; -} - -#define LEGACY_ATOMIC_N_REG_ARGS 5 -#define LEGACY_ATOMIC_FIRST_REG_IDX 2 -#define LEGACY_CLASS_REGISTER (0x2 << 8) -#define LEGACY_MASK_IRQS BIT(5) -#define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ - LEGACY_CLASS_REGISTER | \ - LEGACY_MASK_IRQS | \ - (n & 0xf)) - -/** - * qcom_scm_call_atomic() - Send an atomic SCM command with up to 5 arguments - * and 3 return values - * - * This shall only be used with commands that are guaranteed to be - * uninterruptable, atomic and SMP safe. - */ -static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) -{ - int context_id; - struct arm_smccc_args smc = {0}; - struct arm_smccc_res res; - size_t i, arglen = desc->arginfo & 0xf; - - BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); - - smc.a[0] = LEGACY_ATOMIC(desc->svc, desc->cmd, arglen); - smc.a[1] = (unsigned long)&context_id; - - for(i = 0; i < arglen; i++) - smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; - - arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], - smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); - - desc->res[0] = res.a1; - desc->res[1] = res.a2; - desc->res[2] = res.a3; - - return res.a0; -} - -/** - * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus - * @entry: Entry point function for the cpus - * @cpus: The cpumask of cpus that will use the entry point - * - * Set the cold boot address of the cpus. Any cpu outside the supported - * range would be removed from the cpu present mask. - */ -int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, - const cpumask_t *cpus) -{ - int flags = 0; - int cpu; - int scm_cb_flags[] = { - QCOM_SCM_FLAG_COLDBOOT_CPU0, - QCOM_SCM_FLAG_COLDBOOT_CPU1, - QCOM_SCM_FLAG_COLDBOOT_CPU2, - QCOM_SCM_FLAG_COLDBOOT_CPU3, - }; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_ADDR, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - if (!cpus || (cpus && cpumask_empty(cpus))) - return -EINVAL; - - for_each_cpu(cpu, cpus) { - if (cpu < ARRAY_SIZE(scm_cb_flags)) - flags |= scm_cb_flags[cpu]; - else - set_cpu_present(cpu, false); - } - - desc.args[0] = flags; - desc.args[1] = virt_to_phys(entry); - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -/** - * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus - * @entry: Entry point function for the cpus - * @cpus: The cpumask of cpus that will use the entry point - * - * Set the Linux entry point for the SCM to transfer control to when coming - * out of a power down. CPU power down may be executed on cpuidle or hotplug. - */ -int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, - const cpumask_t *cpus) -{ - int ret; - int flags = 0; - int cpu; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_ADDR, - }; - - /* - * Reassign only if we are switching from hotplug entry point - * to cpuidle entry point or vice versa. - */ - for_each_cpu(cpu, cpus) { - if (entry == qcom_scm_wb[cpu].entry) - continue; - flags |= qcom_scm_wb[cpu].flag; - } - - /* No change in entry function */ - if (!flags) - return 0; - - desc.args[0] = virt_to_phys(entry); - desc.args[1] = flags; - ret = qcom_scm_call(dev, &desc); - if (!ret) { - for_each_cpu(cpu, cpus) - qcom_scm_wb[cpu].entry = entry; - } - - return ret; -} - -/** - * qcom_scm_cpu_power_down() - Power down the cpu - * @flags - Flags to flush cache - * - * This is an end point to power down cpu. If there was a pending interrupt, - * the control would return from this function, otherwise, the cpu jumps to the - * warm boot entry point set for this cpu upon reset. - */ -void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_TERMINATE_PC, - .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK, - .arginfo = QCOM_SCM_ARGS(1), - .owner = ARM_SMCCC_OWNER_SIP, - }; - - qcom_scm_call_atomic(dev, &desc); -} - -int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = state; - desc.args[1] = id; - desc.arginfo = QCOM_SCM_ARGS(2); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_set_dload_mode(struct device *dev, bool enable) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; - desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - return ret ? false : !!desc.res[0]; -} - -int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, - dma_addr_t metadata_phys) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.args[1] = metadata_phys; - desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, - phys_addr_t addr, phys_addr_t size) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.args[1] = addr; - desc.args[2] = size; - desc.arginfo = QCOM_SCM_ARGS(3); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = peripheral; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = reset; - desc.args[1] = 0; - desc.arginfo = QCOM_SCM_ARGS(2); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, - unsigned int *val) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_IO, - .cmd = QCOM_SCM_IO_READ, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = addr; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call_atomic(dev, &desc); - if (ret >= 0) - *val = desc.res[0]; - - return ret < 0 ? ret : 0; - -} - -int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_IO, - .cmd = QCOM_SCM_IO_WRITE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = addr; - desc.args[1] = val; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_INFO, - .cmd = QCOM_INFO_IS_CALL_AVAIL, - .args[0] = (svc_id << 10) | cmd_id, - .arginfo = QCOM_SCM_ARGS(1), - }; - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, - u32 spare) -{ - return -ENODEV; -} - -int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, - size_t *size) -{ - return -ENODEV; -} - -int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, - u32 spare) -{ - return -ENODEV; -} - -int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, - size_t mem_sz, phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz) -{ - return -ENODEV; -} - -int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, - u32 req_cnt, u32 *resp) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_HDCP, - .cmd = QCOM_SCM_HDCP_INVOKE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) - return -ERANGE; - - desc.args[0] = req[0].addr; - desc.args[1] = req[0].val; - desc.args[2] = req[1].addr; - desc.args[3] = req[1].val; - desc.args[4] = req[2].addr; - desc.args[5] = req[2].val; - desc.args[6] = req[3].addr; - desc.args[7] = req[3].val; - desc.args[8] = req[4].addr; - desc.args[9] = req[4].val; - desc.arginfo = QCOM_SCM_ARGS(req_cnt * 2); - - ret = qcom_scm_call(dev, &desc); - *resp = desc.res[0]; - - return ret; -} - -int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable) -{ - return -ENODEV; -} - -void __qcom_scm_init(void) -{ -} \ No newline at end of file diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c deleted file mode 100644 index 18f0bf5..0000000 --- a/drivers/firmware/qcom_scm-64.c +++ /dev/null @@ -1,938 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qcom_scm.h" - -#define MAX_QCOM_SCM_ARGS 10 -#define MAX_QCOM_SCM_RETS 3 - -enum qcom_scm_arg_types { - QCOM_SCM_VAL, - QCOM_SCM_RO, - QCOM_SCM_RW, - QCOM_SCM_BUFVAL, -}; - -#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ - (((a) & 0x3) << 4) | \ - (((b) & 0x3) << 6) | \ - (((c) & 0x3) << 8) | \ - (((d) & 0x3) << 10) | \ - (((e) & 0x3) << 12) | \ - (((f) & 0x3) << 14) | \ - (((g) & 0x3) << 16) | \ - (((h) & 0x3) << 18) | \ - (((i) & 0x3) << 20) | \ - (((j) & 0x3) << 22) | \ - ((num) & 0xf)) - -#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - -/** - * struct qcom_scm_desc - * @arginfo: Metadata describing the arguments in args[] - * @args: The array of arguments for the secure syscall - * @res: The values returned by the secure syscall - */ -struct qcom_scm_desc { - u32 svc; - u32 cmd; - u32 arginfo; - u64 args[MAX_QCOM_SCM_ARGS]; - u64 res[MAX_QCOM_SCM_RETS]; - u32 owner; -}; - -struct arm_smccc_args { - unsigned long a[8]; -}; - -enum qcom_smc_convention { - SMC_CONVENTION_UNKNOWN, - SMC_CONVENTION_LEGACY, - SMC_CONVENTION_ARM_32, - SMC_CONVENTION_ARM_64, -}; - -static enum qcom_smc_convention qcom_smc_convention = SMC_CONVENTION_UNKNOWN; -static DEFINE_MUTEX(qcom_scm_lock); - -#define QCOM_SCM_EBUSY_WAIT_MS 30 -#define QCOM_SCM_EBUSY_MAX_RETRY 20 - -#define SMCCC_FUNCNUM(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) -#define SMCCC_N_REG_ARGS 4 -#define SMCCC_FIRST_REG_IDX 2 -#define SMCCC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SMCCC_N_REG_ARGS + 1) -#define SMCCC_LAST_REG_IDX (SMCCC_FIRST_REG_IDX + SMCCC_N_REG_ARGS - 1) - -static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, - struct arm_smccc_res *res) -{ - unsigned long a0 = smc->a[0]; - struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; - - quirk.state.a6 = 0; - - do { - arm_smccc_smc_quirk(a0, smc->a[1], smc->a[2], smc->a[3], - smc->a[4], smc->a[5], quirk.state.a6, - smc->a[7], res, &quirk); - - if (res->a0 == QCOM_SCM_INTERRUPTED) - a0 = res->a0; - - } while (res->a0 == QCOM_SCM_INTERRUPTED); -} - -static int qcom_scm_call_smccc(struct device *dev, - struct qcom_scm_desc *desc, bool atomic) -{ - int arglen = desc->arginfo & 0xf; - int i; - dma_addr_t args_phys = 0; - void *args_virt = NULL; - size_t alloc_len; - gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL; - struct arm_smccc_res res; - struct arm_smccc_args smc = {0}; - - smc.a[0] = ARM_SMCCC_CALL_VAL( - atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL, - (qcom_smc_convention == SMC_CONVENTION_ARM_64) ? - ARM_SMCCC_SMC_64 : - ARM_SMCCC_SMC_32, - desc->owner, - SMCCC_FUNCNUM(desc->svc, desc->cmd)); - smc.a[1] = desc->arginfo; - for (i = 0; i < SMCCC_N_REG_ARGS; i++) - smc.a[i + SMCCC_FIRST_REG_IDX] = desc->args[i]; - - if (unlikely(arglen > SMCCC_N_REG_ARGS)) { - alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64); - args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag); - - if (!args_virt) - return -ENOMEM; - - if (qcom_smc_convention == SMC_CONVENTION_ARM_32) { - __le32 *args = args_virt; - - for (i = 0; i < SMCCC_N_EXT_ARGS; i++) - args[i] = cpu_to_le32(desc->args[i + - SMCCC_N_REG_ARGS - 1]); - } else { - __le64 *args = args_virt; - - for (i = 0; i < SMCCC_N_EXT_ARGS; i++) - args[i] = cpu_to_le64(desc->args[i + - SMCCC_N_REG_ARGS - 1]); - } - - args_phys = dma_map_single(dev, args_virt, alloc_len, - DMA_TO_DEVICE); - - if (dma_mapping_error(dev, args_phys)) { - kfree(args_virt); - return -ENOMEM; - } - - smc.a[SMCCC_LAST_REG_IDX] = args_phys; - } - - if (atomic) { - __qcom_scm_call_do_quirk(&smc, &res); - } else { - int retry_count = 0; - - do { - mutex_lock(&qcom_scm_lock); - - __qcom_scm_call_do_quirk(&smc, &res); - - mutex_unlock(&qcom_scm_lock); - - if (res.a0 == QCOM_SCM_V2_EBUSY) { - if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) - break; - msleep(QCOM_SCM_EBUSY_WAIT_MS); - } - } while (res.a0 == QCOM_SCM_V2_EBUSY); - } - - if (args_virt) { - dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); - kfree(args_virt); - } - - if (res.a0 < 0) - return qcom_scm_remap_error(res.a0); - - return 0; -} - -#define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) - -/** - * struct legacy_command - one SCM command buffer - * @len: total available memory for command and response - * @buf_offset: start of command buffer - * @resp_hdr_offset: start of response buffer - * @id: command to be executed - * @buf: buffer returned from legacy_get_command_buffer() - * - * An SCM command is laid out in memory as follows: - * - * ------------------- <--- struct legacy_command - * | command header | - * ------------------- <--- legacy_get_command_buffer() - * | command buffer | - * ------------------- <--- struct legacy_response and - * | response header | legacy_command_to_response() - * ------------------- <--- legacy_get_response_buffer() - * | response buffer | - * ------------------- - * - * There can be arbitrary padding between the headers and buffers so - * you should always use the appropriate qcom_scm_get_*_buffer() routines - * to access the buffers in a safe manner. - */ -struct legacy_command { - __le32 len; - __le32 buf_offset; - __le32 resp_hdr_offset; - __le32 id; - __le32 buf[0]; -}; - -/** - * struct legacy_response - one SCM response buffer - * @len: total available memory for response - * @buf_offset: start of response data relative to start of legacy_response - * @is_complete: indicates if the command has finished processing - */ -struct legacy_response { - __le32 len; - __le32 buf_offset; - __le32 is_complete; -}; - -/** - * legacy_command_to_response() - Get a pointer to a legacy_response - * @cmd: command - * - * Returns a pointer to a response for a command. - */ -static inline struct legacy_response *legacy_command_to_response( - const struct legacy_command *cmd) -{ - return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); -} - -/** - * legacy_get_command_buffer() - Get a pointer to a command buffer - * @cmd: command - * - * Returns a pointer to the command buffer of a command. - */ -static inline void *legacy_get_command_buffer(const struct legacy_command *cmd) -{ - return (void *)cmd->buf; -} - -/** - * legacy_get_response_buffer() - Get a pointer to a response buffer - * @rsp: response - * - * Returns a pointer to a response buffer of a response. - */ -static inline void *legacy_get_response_buffer(const struct legacy_response *rsp) -{ - return (void *)rsp + le32_to_cpu(rsp->buf_offset); -} - -static void __qcom_scm_call_do(const struct arm_smccc_args *smc, - struct arm_smccc_res *res) -{ - do { - arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], - smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); - } while (res->a0 == QCOM_SCM_INTERRUPTED); -} - -/** - * qcom_scm_call_legacy() - Send an SCM command - * @dev: struct device - * @svc_id: service identifier - * @cmd_id: command identifier - * @cmd_buf: command buffer - * @cmd_len: length of the command buffer - * @resp_buf: response buffer - * @resp_len: length of the response buffer - * - * Sends a command to the SCM and waits for the command to finish processing. - * - * A note on cache maintenance: - * Note that any buffers that are expected to be accessed by the secure world - * must be flushed before invoking qcom_scm_call and invalidated in the cache - * immediately after qcom_scm_call returns. Cache maintenance on the command - * and response buffers is taken care of by qcom_scm_call; however, callers are - * responsible for any other cached buffers passed over to the secure world. - */ -static int qcom_scm_call_legacy(struct device *dev, struct qcom_scm_desc *desc) -{ - int arglen = desc->arginfo & 0xf; - int ret = 0, context_id; - size_t i; - struct legacy_command *cmd; - struct legacy_response *rsp; - struct arm_smccc_args smc = {0}; - struct arm_smccc_res res; - const size_t cmd_len = arglen * sizeof(__le32); - const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); - size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; - dma_addr_t cmd_phys; - __le32 *arg_buf; - __le32 *res_buf; - - cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->len = cpu_to_le32(alloc_len); - cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); - cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); - cmd->id = cpu_to_le32(LEGACY_FUNCNUM(desc->svc, desc->cmd)); - - arg_buf = legacy_get_command_buffer(cmd); - for (i = 0; i < arglen; i++) - arg_buf[i] = cpu_to_le32(desc->args[i]); - - rsp = legacy_command_to_response(cmd); - - cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); - if (dma_mapping_error(dev, cmd_phys)) { - kfree(cmd); - return -ENOMEM; - } - - smc.a[0] = 1; - smc.a[1] = (unsigned long)&context_id; - smc.a[2] = cmd_phys; - - mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do(&smc, &res); - if (res.a0 < 0) - ret = qcom_scm_remap_error(res.a0); - mutex_unlock(&qcom_scm_lock); - if (ret) - goto out; - - do { - dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, - sizeof(*rsp), DMA_FROM_DEVICE); - } while (!rsp->is_complete); - - dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + - le32_to_cpu(rsp->buf_offset), - resp_len, DMA_FROM_DEVICE); - - res_buf = legacy_get_response_buffer(rsp); - for (i = 0; i < MAX_QCOM_SCM_RETS; i++) - desc->res[i] = le32_to_cpu(res_buf[i]); -out: - dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); - kfree(cmd); - return ret; -} - -#define LEGACY_ATOMIC_N_REG_ARGS 5 -#define LEGACY_ATOMIC_FIRST_REG_IDX 2 -#define LEGACY_CLASS_REGISTER (0x2 << 8) -#define LEGACY_MASK_IRQS BIT(5) -#define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ - LEGACY_CLASS_REGISTER | \ - LEGACY_MASK_IRQS | \ - (n & 0xf)) - -/** - * qcom_scm_call_atomic_legacy() - Send an atomic SCM command with up to - * 5 arguments and 3 return values - * - * This shall only be used with commands that are guaranteed to be - * uninterruptable, atomic and SMP safe. - */ -static int qcom_scm_call_atomic_legacy(struct device *dev, - struct qcom_scm_desc *desc) -{ - int context_id; - struct arm_smccc_args smc = {0}; - struct arm_smccc_res res; - size_t i, arglen = desc->arginfo & 0xf; - - BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); - - smc.a[0] = LEGACY_ATOMIC(desc->svc, desc->cmd, arglen); - smc.a[1] = (unsigned long)&context_id; - - for(i = 0; i < arglen; i++) - smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; - - arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], - smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); - - desc->res[0] = res.a1; - desc->res[1] = res.a2; - desc->res[2] = res.a3; - - return res.a0; -} - -/** - * qcom_scm_call() - Invoke a syscall in the secure world - * @dev: device - * @svc_id: service identifier - * @cmd_id: command identifier - * @desc: Descriptor structure containing arguments and return values - * - * Sends a command to the SCM and waits for the command to finish processing. - * This should *only* be called in pre-emptible context. - */ -static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) -{ - might_sleep(); - switch (qcom_smc_convention) { - case SMC_CONVENTION_ARM_32: - case SMC_CONVENTION_ARM_64: - return qcom_scm_call_smccc(dev, desc, false); - case SMC_CONVENTION_LEGACY: - return qcom_scm_call_legacy(dev, desc); - default: - pr_err("Unknown current SCM calling convention.\n"); - return -EINVAL; - } -} - -/** - * qcom_scm_call_atomic() - atomic variation of qcom_scm_call() - * @dev: device - * @svc_id: service identifier - * @cmd_id: command identifier - * @desc: Descriptor structure containing arguments and return values - * @res: Structure containing results from SMC/HVC call - * - * Sends a command to the SCM and waits for the command to finish processing. - * This can be called in atomic context. - */ -static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) -{ - switch (qcom_smc_convention) { - case SMC_CONVENTION_ARM_32: - case SMC_CONVENTION_ARM_64: - return qcom_scm_call_smccc(dev, desc, true); - case SMC_CONVENTION_LEGACY: - return qcom_scm_call_atomic_legacy(dev, desc); - default: - pr_err("Unknown current SCM calling convention.\n"); - return -EINVAL; - } -} - -#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 -#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 -#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 -#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 - -/** - * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus - * @entry: Entry point function for the cpus - * @cpus: The cpumask of cpus that will use the entry point - * - * Set the cold boot address of the cpus. Any cpu outside the supported - * range would be removed from the cpu present mask. - */ -int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, - const cpumask_t *cpus) -{ - int flags = 0; - int cpu; - int scm_cb_flags[] = { - QCOM_SCM_FLAG_COLDBOOT_CPU0, - QCOM_SCM_FLAG_COLDBOOT_CPU1, - QCOM_SCM_FLAG_COLDBOOT_CPU2, - QCOM_SCM_FLAG_COLDBOOT_CPU3, - }; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_ADDR, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - if (!cpus || (cpus && cpumask_empty(cpus))) - return -EINVAL; - - for_each_cpu(cpu, cpus) { - if (cpu < ARRAY_SIZE(scm_cb_flags)) - flags |= scm_cb_flags[cpu]; - else - set_cpu_present(cpu, false); - } - - desc.args[0] = flags; - desc.args[1] = virt_to_phys(entry); - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 -#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 -#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 -#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 - -struct qcom_scm_entry { - int flag; - void *entry; -}; - -static struct qcom_scm_entry qcom_scm_wb[] = { - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, -}; - -/** - * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus - * @dev: Device pointer - * @entry: Entry point function for the cpus - * @cpus: The cpumask of cpus that will use the entry point - * - * Set the Linux entry point for the SCM to transfer control to when coming - * out of a power down. CPU power down may be executed on cpuidle or hotplug. - */ -int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, - const cpumask_t *cpus) -{ - int ret; - int flags = 0; - int cpu; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_ADDR, - }; - - /* - * Reassign only if we are switching from hotplug entry point - * to cpuidle entry point or vice versa. - */ - for_each_cpu(cpu, cpus) { - if (entry == qcom_scm_wb[cpu].entry) - continue; - flags |= qcom_scm_wb[cpu].flag; - } - - /* No change in entry function */ - if (!flags) - return 0; - - desc.args[0] = virt_to_phys(entry); - desc.args[1] = flags; - ret = qcom_scm_call(dev, &desc); - if (!ret) { - for_each_cpu(cpu, cpus) - qcom_scm_wb[cpu].entry = entry; - } - - return ret; -} - -/** - * qcom_scm_cpu_power_down() - Power down the cpu - * @flags - Flags to flush cache - * - * This is an end point to power down cpu. If there was a pending interrupt, - * the control would return from this function, otherwise, the cpu jumps to the - * warm boot entry point set for this cpu upon reset. - */ -void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_TERMINATE_PC, - .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK, - .arginfo = QCOM_SCM_ARGS(1), - .owner = ARM_SMCCC_OWNER_SIP, - }; - - qcom_scm_call_atomic(dev, &desc); -} - -int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = state; - desc.args[1] = id; - desc.arginfo = QCOM_SCM_ARGS(2); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_set_dload_mode(struct device *dev, bool enable) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_BOOT, - .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; - desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - return ret ? false : !!desc.res[0]; -} - -int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, - dma_addr_t metadata_phys) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.args[1] = metadata_phys; - desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, - phys_addr_t addr, phys_addr_t size) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.args[1] = addr; - desc.args[2] = size; - desc.arginfo = QCOM_SCM_ARGS(3); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = peripheral; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_PIL, - .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = reset; - desc.args[1] = 0; - desc.arginfo = QCOM_SCM_ARGS(2); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, - unsigned int *val) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_IO, - .cmd = QCOM_SCM_IO_READ, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = addr; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call_atomic(dev, &desc); - if (ret >= 0) - *val = desc.res[0]; - - return ret < 0 ? ret : 0; -} - -int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_IO, - .cmd = QCOM_SCM_IO_WRITE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = addr; - desc.args[1] = val; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_INFO, - .cmd = QCOM_INFO_IS_CALL_AVAIL, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.arginfo = QCOM_SCM_ARGS(1); - switch (qcom_smc_convention) { - case SMC_CONVENTION_ARM_32: - case SMC_CONVENTION_ARM_64: - desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | - (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); - break; - case SMC_CONVENTION_LEGACY: - desc.args[0] = LEGACY_FUNCNUM(svc_id, cmd_id); - break; - default: - pr_err("Unknown SMC convention being used\n"); - return -EINVAL; - } - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_MP, - .cmd = QCOM_SCM_MP_RESTORE_SEC_CFG, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = device_id; - desc.args[1] = spare; - desc.arginfo = QCOM_SCM_ARGS(2); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, - size_t *size) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_MP, - .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = spare; - desc.arginfo = QCOM_SCM_ARGS(1); - - ret = qcom_scm_call(dev, &desc); - - if (size) - *size = desc.res[0]; - - return ret ? : desc.res[1]; -} - -int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, - u32 spare) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_MP, - .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, - .owner = ARM_SMCCC_OWNER_SIP, - }; - int ret; - - desc.args[0] = addr; - desc.args[1] = size; - desc.args[2] = spare; - desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, - QCOM_SCM_VAL); - - ret = qcom_scm_call(dev, &desc); - - /* the pg table has been initialized already, ignore the error */ - if (ret == -EPERM) - ret = 0; - - return ret; -} - -int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, - size_t mem_sz, phys_addr_t src, size_t src_sz, - phys_addr_t dest, size_t dest_sz) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_MP, - .cmd = QCOM_MP_ASSIGN, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = mem_region; - desc.args[1] = mem_sz; - desc.args[2] = src; - desc.args[3] = src_sz; - desc.args[4] = dest; - desc.args[5] = dest_sz; - desc.args[6] = 0; - - desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, - QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, - QCOM_SCM_VAL, QCOM_SCM_VAL); - - ret = qcom_scm_call(dev, &desc); - - return ret ? : desc.res[0]; -} - -int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, - u32 req_cnt, u32 *resp) -{ - int ret; - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_HDCP, - .cmd = QCOM_SCM_HDCP_INVOKE, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) - return -ERANGE; - - desc.args[0] = req[0].addr; - desc.args[1] = req[0].val; - desc.args[2] = req[1].addr; - desc.args[3] = req[1].val; - desc.args[4] = req[2].addr; - desc.args[5] = req[2].val; - desc.args[6] = req[3].addr; - desc.args[7] = req[3].val; - desc.args[8] = req[4].addr; - desc.args[9] = req[4].val; - desc.arginfo = QCOM_SCM_ARGS(10); - - ret = qcom_scm_call(dev, &desc); - *resp = desc.res[0]; - - return ret; -} - -int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) -{ - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_SMMU_PROGRAM, - .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, - .owner = ARM_SMCCC_OWNER_SIP, - }; - - desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL; - desc.args[1] = en; - desc.arginfo = QCOM_SCM_ARGS(2); - - return qcom_scm_call_atomic(dev, &desc); -} - -void __qcom_scm_init(void) -{ - /* First try a SMC64 call */ - qcom_smc_convention = SMC_CONVENTION_ARM_64; - if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, - QCOM_INFO_IS_CALL_AVAIL) <= 0) { - /* Now try a SMC32 call */ - qcom_smc_convention = SMC_CONVENTION_ARM_32; - if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, - QCOM_INFO_IS_CALL_AVAIL) <= 0) { - qcom_smc_convention = SMC_CONVENTION_LEGACY; - } - } -} diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c new file mode 100644 index 0000000..18f0bf5 --- /dev/null +++ b/drivers/firmware/qcom_scm-smc.c @@ -0,0 +1,938 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcom_scm.h" + +#define MAX_QCOM_SCM_ARGS 10 +#define MAX_QCOM_SCM_RETS 3 + +enum qcom_scm_arg_types { + QCOM_SCM_VAL, + QCOM_SCM_RO, + QCOM_SCM_RW, + QCOM_SCM_BUFVAL, +}; + +#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ + (((a) & 0x3) << 4) | \ + (((b) & 0x3) << 6) | \ + (((c) & 0x3) << 8) | \ + (((d) & 0x3) << 10) | \ + (((e) & 0x3) << 12) | \ + (((f) & 0x3) << 14) | \ + (((g) & 0x3) << 16) | \ + (((h) & 0x3) << 18) | \ + (((i) & 0x3) << 20) | \ + (((j) & 0x3) << 22) | \ + ((num) & 0xf)) + +#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +/** + * struct qcom_scm_desc + * @arginfo: Metadata describing the arguments in args[] + * @args: The array of arguments for the secure syscall + * @res: The values returned by the secure syscall + */ +struct qcom_scm_desc { + u32 svc; + u32 cmd; + u32 arginfo; + u64 args[MAX_QCOM_SCM_ARGS]; + u64 res[MAX_QCOM_SCM_RETS]; + u32 owner; +}; + +struct arm_smccc_args { + unsigned long a[8]; +}; + +enum qcom_smc_convention { + SMC_CONVENTION_UNKNOWN, + SMC_CONVENTION_LEGACY, + SMC_CONVENTION_ARM_32, + SMC_CONVENTION_ARM_64, +}; + +static enum qcom_smc_convention qcom_smc_convention = SMC_CONVENTION_UNKNOWN; +static DEFINE_MUTEX(qcom_scm_lock); + +#define QCOM_SCM_EBUSY_WAIT_MS 30 +#define QCOM_SCM_EBUSY_MAX_RETRY 20 + +#define SMCCC_FUNCNUM(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) +#define SMCCC_N_REG_ARGS 4 +#define SMCCC_FIRST_REG_IDX 2 +#define SMCCC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SMCCC_N_REG_ARGS + 1) +#define SMCCC_LAST_REG_IDX (SMCCC_FIRST_REG_IDX + SMCCC_N_REG_ARGS - 1) + +static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, + struct arm_smccc_res *res) +{ + unsigned long a0 = smc->a[0]; + struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; + + quirk.state.a6 = 0; + + do { + arm_smccc_smc_quirk(a0, smc->a[1], smc->a[2], smc->a[3], + smc->a[4], smc->a[5], quirk.state.a6, + smc->a[7], res, &quirk); + + if (res->a0 == QCOM_SCM_INTERRUPTED) + a0 = res->a0; + + } while (res->a0 == QCOM_SCM_INTERRUPTED); +} + +static int qcom_scm_call_smccc(struct device *dev, + struct qcom_scm_desc *desc, bool atomic) +{ + int arglen = desc->arginfo & 0xf; + int i; + dma_addr_t args_phys = 0; + void *args_virt = NULL; + size_t alloc_len; + gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL; + struct arm_smccc_res res; + struct arm_smccc_args smc = {0}; + + smc.a[0] = ARM_SMCCC_CALL_VAL( + atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL, + (qcom_smc_convention == SMC_CONVENTION_ARM_64) ? + ARM_SMCCC_SMC_64 : + ARM_SMCCC_SMC_32, + desc->owner, + SMCCC_FUNCNUM(desc->svc, desc->cmd)); + smc.a[1] = desc->arginfo; + for (i = 0; i < SMCCC_N_REG_ARGS; i++) + smc.a[i + SMCCC_FIRST_REG_IDX] = desc->args[i]; + + if (unlikely(arglen > SMCCC_N_REG_ARGS)) { + alloc_len = SMCCC_N_EXT_ARGS * sizeof(u64); + args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag); + + if (!args_virt) + return -ENOMEM; + + if (qcom_smc_convention == SMC_CONVENTION_ARM_32) { + __le32 *args = args_virt; + + for (i = 0; i < SMCCC_N_EXT_ARGS; i++) + args[i] = cpu_to_le32(desc->args[i + + SMCCC_N_REG_ARGS - 1]); + } else { + __le64 *args = args_virt; + + for (i = 0; i < SMCCC_N_EXT_ARGS; i++) + args[i] = cpu_to_le64(desc->args[i + + SMCCC_N_REG_ARGS - 1]); + } + + args_phys = dma_map_single(dev, args_virt, alloc_len, + DMA_TO_DEVICE); + + if (dma_mapping_error(dev, args_phys)) { + kfree(args_virt); + return -ENOMEM; + } + + smc.a[SMCCC_LAST_REG_IDX] = args_phys; + } + + if (atomic) { + __qcom_scm_call_do_quirk(&smc, &res); + } else { + int retry_count = 0; + + do { + mutex_lock(&qcom_scm_lock); + + __qcom_scm_call_do_quirk(&smc, &res); + + mutex_unlock(&qcom_scm_lock); + + if (res.a0 == QCOM_SCM_V2_EBUSY) { + if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) + break; + msleep(QCOM_SCM_EBUSY_WAIT_MS); + } + } while (res.a0 == QCOM_SCM_V2_EBUSY); + } + + if (args_virt) { + dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE); + kfree(args_virt); + } + + if (res.a0 < 0) + return qcom_scm_remap_error(res.a0); + + return 0; +} + +#define LEGACY_FUNCNUM(s, c) (((s) << 10) | ((c) & 0x3ff)) + +/** + * struct legacy_command - one SCM command buffer + * @len: total available memory for command and response + * @buf_offset: start of command buffer + * @resp_hdr_offset: start of response buffer + * @id: command to be executed + * @buf: buffer returned from legacy_get_command_buffer() + * + * An SCM command is laid out in memory as follows: + * + * ------------------- <--- struct legacy_command + * | command header | + * ------------------- <--- legacy_get_command_buffer() + * | command buffer | + * ------------------- <--- struct legacy_response and + * | response header | legacy_command_to_response() + * ------------------- <--- legacy_get_response_buffer() + * | response buffer | + * ------------------- + * + * There can be arbitrary padding between the headers and buffers so + * you should always use the appropriate qcom_scm_get_*_buffer() routines + * to access the buffers in a safe manner. + */ +struct legacy_command { + __le32 len; + __le32 buf_offset; + __le32 resp_hdr_offset; + __le32 id; + __le32 buf[0]; +}; + +/** + * struct legacy_response - one SCM response buffer + * @len: total available memory for response + * @buf_offset: start of response data relative to start of legacy_response + * @is_complete: indicates if the command has finished processing + */ +struct legacy_response { + __le32 len; + __le32 buf_offset; + __le32 is_complete; +}; + +/** + * legacy_command_to_response() - Get a pointer to a legacy_response + * @cmd: command + * + * Returns a pointer to a response for a command. + */ +static inline struct legacy_response *legacy_command_to_response( + const struct legacy_command *cmd) +{ + return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); +} + +/** + * legacy_get_command_buffer() - Get a pointer to a command buffer + * @cmd: command + * + * Returns a pointer to the command buffer of a command. + */ +static inline void *legacy_get_command_buffer(const struct legacy_command *cmd) +{ + return (void *)cmd->buf; +} + +/** + * legacy_get_response_buffer() - Get a pointer to a response buffer + * @rsp: response + * + * Returns a pointer to a response buffer of a response. + */ +static inline void *legacy_get_response_buffer(const struct legacy_response *rsp) +{ + return (void *)rsp + le32_to_cpu(rsp->buf_offset); +} + +static void __qcom_scm_call_do(const struct arm_smccc_args *smc, + struct arm_smccc_res *res) +{ + do { + arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], + smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); + } while (res->a0 == QCOM_SCM_INTERRUPTED); +} + +/** + * qcom_scm_call_legacy() - Send an SCM command + * @dev: struct device + * @svc_id: service identifier + * @cmd_id: command identifier + * @cmd_buf: command buffer + * @cmd_len: length of the command buffer + * @resp_buf: response buffer + * @resp_len: length of the response buffer + * + * Sends a command to the SCM and waits for the command to finish processing. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking qcom_scm_call and invalidated in the cache + * immediately after qcom_scm_call returns. Cache maintenance on the command + * and response buffers is taken care of by qcom_scm_call; however, callers are + * responsible for any other cached buffers passed over to the secure world. + */ +static int qcom_scm_call_legacy(struct device *dev, struct qcom_scm_desc *desc) +{ + int arglen = desc->arginfo & 0xf; + int ret = 0, context_id; + size_t i; + struct legacy_command *cmd; + struct legacy_response *rsp; + struct arm_smccc_args smc = {0}; + struct arm_smccc_res res; + const size_t cmd_len = arglen * sizeof(__le32); + const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32); + size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len; + dma_addr_t cmd_phys; + __le32 *arg_buf; + __le32 *res_buf; + + cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->len = cpu_to_le32(alloc_len); + cmd->buf_offset = cpu_to_le32(sizeof(*cmd)); + cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len); + cmd->id = cpu_to_le32(LEGACY_FUNCNUM(desc->svc, desc->cmd)); + + arg_buf = legacy_get_command_buffer(cmd); + for (i = 0; i < arglen; i++) + arg_buf[i] = cpu_to_le32(desc->args[i]); + + rsp = legacy_command_to_response(cmd); + + cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, cmd_phys)) { + kfree(cmd); + return -ENOMEM; + } + + smc.a[0] = 1; + smc.a[1] = (unsigned long)&context_id; + smc.a[2] = cmd_phys; + + mutex_lock(&qcom_scm_lock); + __qcom_scm_call_do(&smc, &res); + if (res.a0 < 0) + ret = qcom_scm_remap_error(res.a0); + mutex_unlock(&qcom_scm_lock); + if (ret) + goto out; + + do { + dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, + sizeof(*rsp), DMA_FROM_DEVICE); + } while (!rsp->is_complete); + + dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + + le32_to_cpu(rsp->buf_offset), + resp_len, DMA_FROM_DEVICE); + + res_buf = legacy_get_response_buffer(rsp); + for (i = 0; i < MAX_QCOM_SCM_RETS; i++) + desc->res[i] = le32_to_cpu(res_buf[i]); +out: + dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); + kfree(cmd); + return ret; +} + +#define LEGACY_ATOMIC_N_REG_ARGS 5 +#define LEGACY_ATOMIC_FIRST_REG_IDX 2 +#define LEGACY_CLASS_REGISTER (0x2 << 8) +#define LEGACY_MASK_IRQS BIT(5) +#define LEGACY_ATOMIC(svc, cmd, n) ((LEGACY_FUNCNUM(svc, cmd) << 12) | \ + LEGACY_CLASS_REGISTER | \ + LEGACY_MASK_IRQS | \ + (n & 0xf)) + +/** + * qcom_scm_call_atomic_legacy() - Send an atomic SCM command with up to + * 5 arguments and 3 return values + * + * This shall only be used with commands that are guaranteed to be + * uninterruptable, atomic and SMP safe. + */ +static int qcom_scm_call_atomic_legacy(struct device *dev, + struct qcom_scm_desc *desc) +{ + int context_id; + struct arm_smccc_args smc = {0}; + struct arm_smccc_res res; + size_t i, arglen = desc->arginfo & 0xf; + + BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); + + smc.a[0] = LEGACY_ATOMIC(desc->svc, desc->cmd, arglen); + smc.a[1] = (unsigned long)&context_id; + + for(i = 0; i < arglen; i++) + smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; + + arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], + smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); + + desc->res[0] = res.a1; + desc->res[1] = res.a2; + desc->res[2] = res.a3; + + return res.a0; +} + +/** + * qcom_scm_call() - Invoke a syscall in the secure world + * @dev: device + * @svc_id: service identifier + * @cmd_id: command identifier + * @desc: Descriptor structure containing arguments and return values + * + * Sends a command to the SCM and waits for the command to finish processing. + * This should *only* be called in pre-emptible context. + */ +static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) +{ + might_sleep(); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, false); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } +} + +/** + * qcom_scm_call_atomic() - atomic variation of qcom_scm_call() + * @dev: device + * @svc_id: service identifier + * @cmd_id: command identifier + * @desc: Descriptor structure containing arguments and return values + * @res: Structure containing results from SMC/HVC call + * + * Sends a command to the SCM and waits for the command to finish processing. + * This can be called in atomic context. + */ +static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) +{ + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, true); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_atomic_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } +} + +#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 +#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 +#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 +#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 + +/** + * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus + * @entry: Entry point function for the cpus + * @cpus: The cpumask of cpus that will use the entry point + * + * Set the cold boot address of the cpus. Any cpu outside the supported + * range would be removed from the cpu present mask. + */ +int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, + const cpumask_t *cpus) +{ + int flags = 0; + int cpu; + int scm_cb_flags[] = { + QCOM_SCM_FLAG_COLDBOOT_CPU0, + QCOM_SCM_FLAG_COLDBOOT_CPU1, + QCOM_SCM_FLAG_COLDBOOT_CPU2, + QCOM_SCM_FLAG_COLDBOOT_CPU3, + }; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + if (!cpus || (cpus && cpumask_empty(cpus))) + return -EINVAL; + + for_each_cpu(cpu, cpus) { + if (cpu < ARRAY_SIZE(scm_cb_flags)) + flags |= scm_cb_flags[cpu]; + else + set_cpu_present(cpu, false); + } + + desc.args[0] = flags; + desc.args[1] = virt_to_phys(entry); + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + +#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 +#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 +#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 +#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 + +struct qcom_scm_entry { + int flag; + void *entry; +}; + +static struct qcom_scm_entry qcom_scm_wb[] = { + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, + { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, +}; + +/** + * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus + * @dev: Device pointer + * @entry: Entry point function for the cpus + * @cpus: The cpumask of cpus that will use the entry point + * + * Set the Linux entry point for the SCM to transfer control to when coming + * out of a power down. CPU power down may be executed on cpuidle or hotplug. + */ +int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, + const cpumask_t *cpus) +{ + int ret; + int flags = 0; + int cpu; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_ADDR, + }; + + /* + * Reassign only if we are switching from hotplug entry point + * to cpuidle entry point or vice versa. + */ + for_each_cpu(cpu, cpus) { + if (entry == qcom_scm_wb[cpu].entry) + continue; + flags |= qcom_scm_wb[cpu].flag; + } + + /* No change in entry function */ + if (!flags) + return 0; + + desc.args[0] = virt_to_phys(entry); + desc.args[1] = flags; + ret = qcom_scm_call(dev, &desc); + if (!ret) { + for_each_cpu(cpu, cpus) + qcom_scm_wb[cpu].entry = entry; + } + + return ret; +} + +/** + * qcom_scm_cpu_power_down() - Power down the cpu + * @flags - Flags to flush cache + * + * This is an end point to power down cpu. If there was a pending interrupt, + * the control would return from this function, otherwise, the cpu jumps to the + * warm boot entry point set for this cpu upon reset. + */ +void __qcom_scm_cpu_power_down(struct device *dev, u32 flags) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_TERMINATE_PC, + .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK, + .arginfo = QCOM_SCM_ARGS(1), + .owner = ARM_SMCCC_OWNER_SIP, + }; + + qcom_scm_call_atomic(dev, &desc); +} + +int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = state; + desc.args[1] = id; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_set_dload_mode(struct device *dev, bool enable) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE; + desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + +bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(dev, &desc); + + return ret ? false : !!desc.res[0]; +} + +int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral, + dma_addr_t metadata_phys) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.args[1] = metadata_phys; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral, + phys_addr_t addr, phys_addr_t size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.args[1] = addr; + desc.args[2] = size; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_PIL_PAS_MSS_RESET, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = reset; + desc.args[1] = 0; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, + unsigned int *val) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_READ, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = addr; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call_atomic(dev, &desc); + if (ret >= 0) + *val = desc.res[0]; + + return ret < 0 ? ret : 0; +} + +int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_WRITE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = addr; + desc.args[1] = val; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + +int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_INFO, + .cmd = QCOM_INFO_IS_CALL_AVAIL, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.arginfo = QCOM_SCM_ARGS(1); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + break; + case SMC_CONVENTION_LEGACY: + desc.args[0] = LEGACY_FUNCNUM(svc_id, cmd_id); + break; + default: + pr_err("Unknown SMC convention being used\n"); + return -EINVAL; + } + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_RESTORE_SEC_CFG, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = device_id; + desc.args[1] = spare; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, + size_t *size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = spare; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(dev, &desc); + + if (size) + *size = desc.res[0]; + + return ret ? : desc.res[1]; +} + +int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, + u32 spare) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + desc.args[0] = addr; + desc.args[1] = size; + desc.args[2] = spare; + desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + /* the pg table has been initialized already, ignore the error */ + if (ret == -EPERM) + ret = 0; + + return ret; +} + +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, + size_t mem_sz, phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_MP_ASSIGN, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = mem_region; + desc.args[1] = mem_sz; + desc.args[2] = src; + desc.args[3] = src_sz; + desc.args[4] = dest; + desc.args[5] = dest_sz; + desc.args[6] = 0; + + desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, + u32 req_cnt, u32 *resp) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_HDCP, + .cmd = QCOM_SCM_HDCP_INVOKE, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) + return -ERANGE; + + desc.args[0] = req[0].addr; + desc.args[1] = req[0].val; + desc.args[2] = req[1].addr; + desc.args[3] = req[1].val; + desc.args[4] = req[2].addr; + desc.args[5] = req[2].val; + desc.args[6] = req[3].addr; + desc.args[7] = req[3].val; + desc.args[8] = req[4].addr; + desc.args[9] = req[4].val; + desc.arginfo = QCOM_SCM_ARGS(10); + + ret = qcom_scm_call(dev, &desc); + *resp = desc.res[0]; + + return ret; +} + +int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL; + desc.args[1] = en; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + +void __qcom_scm_init(void) +{ + /* First try a SMC64 call */ + qcom_smc_convention = SMC_CONVENTION_ARM_64; + if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, + QCOM_INFO_IS_CALL_AVAIL) <= 0) { + /* Now try a SMC32 call */ + qcom_smc_convention = SMC_CONVENTION_ARM_32; + if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, + QCOM_INFO_IS_CALL_AVAIL) <= 0) { + qcom_smc_convention = SMC_CONVENTION_LEGACY; + } + } +}