drivers: sip_svc: Add driver for SiP Supervisory call
Add driver for communicating with EL3/EL2 layer using smc/hvc call for Silicon vendor Provided services for INTEL AGILEX SOC FPGA. Signed-off-by: Mahesh Rao <mahesh.rao@intel.com>
This commit is contained in:
parent
4c66ac81fd
commit
1a7576ce9e
10 changed files with 943 additions and 0 deletions
|
@ -76,3 +76,4 @@ add_subdirectory_ifdef(CONFIG_W1 w1)
|
||||||
add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
|
add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
|
||||||
add_subdirectory_ifdef(CONFIG_WIFI wifi)
|
add_subdirectory_ifdef(CONFIG_WIFI wifi)
|
||||||
add_subdirectory_ifdef(CONFIG_RTC rtc)
|
add_subdirectory_ifdef(CONFIG_RTC rtc)
|
||||||
|
add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_DRIVER sip_svc)
|
||||||
|
|
|
@ -79,5 +79,6 @@ source "drivers/w1/Kconfig"
|
||||||
source "drivers/watchdog/Kconfig"
|
source "drivers/watchdog/Kconfig"
|
||||||
source "drivers/wifi/Kconfig"
|
source "drivers/wifi/Kconfig"
|
||||||
source "drivers/xen/Kconfig"
|
source "drivers/xen/Kconfig"
|
||||||
|
source "drivers/sip_svc/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
5
drivers/sip_svc/CMakeLists.txt
Normal file
5
drivers/sip_svc/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (c) 2023 Intel Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
zephyr_library()
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_ARM_SIP_SVC_HAS_INTEL_SDM_MAILBOX_FIFO sip_smc_intel_socfpga.c)
|
31
drivers/sip_svc/Kconfig
Normal file
31
drivers/sip_svc/Kconfig
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Silicon vendor Provided Supervisory call driver for sip_svc subsystem
|
||||||
|
|
||||||
|
# Copyright (c) 2023 Intel Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
menuconfig ARM_SIP_SVC_DRIVER
|
||||||
|
bool "ARM SIP SVC driver"
|
||||||
|
depends on ARM64
|
||||||
|
help
|
||||||
|
ARM supervisory call driver for communicating with EL2 or EL3 firmware
|
||||||
|
|
||||||
|
if ARM_SIP_SVC_DRIVER
|
||||||
|
|
||||||
|
module = ARM_SIP_SVC_DRIVER
|
||||||
|
module-str = arm_sip_svc_driver
|
||||||
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
||||||
|
config ARM_SIP_SVC_DRIVER_INIT_PRIORITY
|
||||||
|
int "Initialization priority"
|
||||||
|
default 50
|
||||||
|
|
||||||
|
config ARM_SIP_SVC_HAS_DRIVER
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
This is an option to be enabled by individual sip svc driver
|
||||||
|
to signal that there is a sip svc driver. This is used by other
|
||||||
|
modules which depends on sip svc driver.
|
||||||
|
|
||||||
|
source "drivers/sip_svc/Kconfig.sip_smc_agilex"
|
||||||
|
|
||||||
|
endif # ARM_SIP_SVC_DRIVER
|
26
drivers/sip_svc/Kconfig.sip_smc_agilex
Normal file
26
drivers/sip_svc/Kconfig.sip_smc_agilex
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Copyright (c) 2023 Intel Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config ARM_SIP_SVC_HAS_INTEL_SDM_MAILBOX_FIFO
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_INTEL_AGILEX_SOCFPGA_SIP_SMC_ENABLED
|
||||||
|
imply ARM_SIP_SVC_HAS_DRIVER
|
||||||
|
help
|
||||||
|
Support for SDM mailbox fifo in Intel SoC FPGA Agilex via SMC calls.
|
||||||
|
|
||||||
|
config ARM_SIP_SVC_EL3_MAILBOX_RESPONSE_SIZE
|
||||||
|
int "Size of response buffer used for ASYNC transactions."
|
||||||
|
default 4096
|
||||||
|
depends on ARM_SIP_SVC_HAS_INTEL_SDM_MAILBOX_FIFO
|
||||||
|
help
|
||||||
|
Size of response buffer used for ASYNC transactions.For Intel Agilex platform
|
||||||
|
the maximum size of response buffer size is 4096 and minimum is 4 bytes.
|
||||||
|
Also it should be multiple of 4 bytes.
|
||||||
|
|
||||||
|
config ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS
|
||||||
|
int "Maximum allowable ongoing transactions."
|
||||||
|
default 16
|
||||||
|
depends on ARM_SIP_SVC_HAS_INTEL_SDM_MAILBOX_FIFO
|
||||||
|
help
|
||||||
|
Allowed number of active transactions in sip_svc subsystem for this driver.
|
227
drivers/sip_svc/sip_smc_intel_socfpga.c
Normal file
227
drivers/sip_svc/sip_smc_intel_socfpga.c
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Intel SoC FPGA platform specific functions used by ARM SiP Services for
|
||||||
|
* supporting EL3 communication from zephyr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h>
|
||||||
|
#include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
|
||||||
|
#include <zephyr/drivers/sip_svc/sip_svc_driver.h>
|
||||||
|
#include <zephyr/syscall_handler.h>
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(intel_agilex_socfpga_sip_smc, CONFIG_ARM_SIP_SVC_DRIVER_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT intel_agilex_socfpga_sip_smc
|
||||||
|
|
||||||
|
#define DT_SIP_SMC DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
|
static bool intel_sip_smc_plat_func_id_valid(const struct device *dev, uint32_t command,
|
||||||
|
uint32_t func_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if (command > SIP_SVC_PROTO_CMD_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == SIP_SVC_PROTO_CMD_SYNC) {
|
||||||
|
/* Synchronous SMC Function IDs */
|
||||||
|
switch (func_id) {
|
||||||
|
case SMC_FUNC_ID_GET_SVC_VERSION:
|
||||||
|
case SMC_FUNC_ID_REG_READ:
|
||||||
|
case SMC_FUNC_ID_REG_WRITE:
|
||||||
|
case SMC_FUNC_ID_REG_UPDATE:
|
||||||
|
case SMC_FUNC_ID_SET_HPS_BRIDGES:
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (command == SIP_SVC_PROTO_CMD_ASYNC) {
|
||||||
|
/* Asynchronous SMC Function IDs */
|
||||||
|
switch (func_id) {
|
||||||
|
case SMC_FUNC_ID_MAILBOX_SEND_COMMAND:
|
||||||
|
case SMC_FUNC_ID_MAILBOX_POLL_RESPONSE:
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t intel_sip_smc_plat_format_trans_id(const struct device *dev, uint32_t client_idx,
|
||||||
|
uint32_t trans_idx)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
/*combine the transaction id and client id to get the job id*/
|
||||||
|
return (((client_idx & 0xF) << 4) | (trans_idx & 0xF));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t intel_sip_smc_plat_get_trans_idx(const struct device *dev, uint32_t trans_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
return (trans_id & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intel_sip_smc_plat_update_trans_id(const struct device *dev,
|
||||||
|
struct sip_svc_request *request, uint32_t trans_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
uint32_t *data;
|
||||||
|
|
||||||
|
if (request == NULL) {
|
||||||
|
LOG_ERR("request is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign the trans id into intel smc header a1 */
|
||||||
|
SMC_PLAT_PROTO_HEADER_SET_TRANS_ID(request->a1, trans_id);
|
||||||
|
|
||||||
|
/* Assign the trans id into mailbox header */
|
||||||
|
if ((void *)request->a2 != NULL) {
|
||||||
|
data = (uint32_t *)request->a2;
|
||||||
|
SIP_SVC_MB_HEADER_SET_TRANS_ID(data[0], trans_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intel_sip_smc_plat_free_async_memory(const struct device *dev,
|
||||||
|
struct sip_svc_request *request)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
/* Free mailbox command data dynamic memory space,
|
||||||
|
* this function will be called after sip_svc service
|
||||||
|
* process the async request.
|
||||||
|
*/
|
||||||
|
if (request->a2) {
|
||||||
|
k_free((void *)request->a2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intel_sip_smc_plat_async_res_req(const struct device *dev, unsigned long *a0,
|
||||||
|
unsigned long *a1, unsigned long *a2, unsigned long *a3,
|
||||||
|
unsigned long *a4, unsigned long *a5, unsigned long *a6,
|
||||||
|
unsigned long *a7, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
/* Fill in SMC parameter to read mailbox response */
|
||||||
|
*a0 = SMC_FUNC_ID_MAILBOX_POLL_RESPONSE;
|
||||||
|
*a1 = 0;
|
||||||
|
*a2 = (unsigned long)buf;
|
||||||
|
*a3 = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intel_sip_smc_plat_async_res_res(const struct device *dev, struct arm_smccc_res *res,
|
||||||
|
char *buf, size_t *size, uint32_t *trans_id)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
uint32_t *resp = (uint32_t *)buf;
|
||||||
|
|
||||||
|
__ASSERT((res && buf && size && trans_id), "invalid parameters\n");
|
||||||
|
|
||||||
|
if (((long)res->a0) <= SMC_STATUS_OKAY) {
|
||||||
|
/* Extract transaction id from mailbox response header */
|
||||||
|
*trans_id = SIP_SVC_MB_HEADER_GET_TRANS_ID(resp[0]);
|
||||||
|
/* The final length should include both header and body */
|
||||||
|
*size = (SIP_SVC_MB_HEADER_GET_LENGTH(resp[0]) + 1) * 4;
|
||||||
|
} else {
|
||||||
|
LOG_INF("There is no valid polling response %ld", (long)res->a0);
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Got a valid polling response");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t intel_sip_smc_plat_get_error_code(const struct device *dev,
|
||||||
|
struct arm_smccc_res *res)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
if (res != NULL) {
|
||||||
|
return res->a0;
|
||||||
|
} else {
|
||||||
|
return SIP_SVC_ID_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intel_sip_secure_monitor_call(const struct device *dev, unsigned long function_id,
|
||||||
|
unsigned long arg0, unsigned long arg1,
|
||||||
|
unsigned long arg2, unsigned long arg3,
|
||||||
|
unsigned long arg4, unsigned long arg5,
|
||||||
|
unsigned long arg6, struct arm_smccc_res *res)
|
||||||
|
{
|
||||||
|
__ASSERT_NO_MSG(dev != NULL);
|
||||||
|
__ASSERT_NO_MSG(res != NULL);
|
||||||
|
|
||||||
|
LOG_INF("Before %s call", DT_PROP(DT_SIP_SMC, method));
|
||||||
|
LOG_DBG("\tfunction_id %08lx", function_id);
|
||||||
|
LOG_DBG("\targ0 %08lx", arg0);
|
||||||
|
LOG_DBG("\targ1 %08lx", arg1);
|
||||||
|
LOG_DBG("\targ2 %08lx", arg2);
|
||||||
|
LOG_DBG("\targ3 %08lx", arg3);
|
||||||
|
LOG_DBG("\targ4 %08lx", arg4);
|
||||||
|
LOG_DBG("\targ5 %08lx", arg5);
|
||||||
|
LOG_DBG("\targ6 %08lx", arg6);
|
||||||
|
|
||||||
|
arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res);
|
||||||
|
|
||||||
|
LOG_INF("After %s call", DT_PROP(DT_SIP_SMC, method));
|
||||||
|
LOG_DBG("\tres->a0 %08lx", res->a0);
|
||||||
|
LOG_DBG("\tres->a1 %08lx", res->a1);
|
||||||
|
LOG_DBG("\tres->a2 %08lx", res->a2);
|
||||||
|
LOG_DBG("\tres->a3 %08lx", res->a3);
|
||||||
|
LOG_DBG("\tres->a4 %08lx", res->a4);
|
||||||
|
LOG_DBG("\tres->a5 %08lx", res->a5);
|
||||||
|
LOG_DBG("\tres->a6 %08lx", res->a6);
|
||||||
|
LOG_DBG("\tres->a7 %08lx", res->a7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arm_sip_smc_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
LOG_INF("Supervisory call %s registered successfully", DT_PROP(DT_SIP_SMC, method));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct svc_driver_api api = {
|
||||||
|
.sip_supervisory_call = intel_sip_secure_monitor_call,
|
||||||
|
.sip_svc_plat_get_trans_idx = intel_sip_smc_plat_get_trans_idx,
|
||||||
|
.sip_svc_plat_format_trans_id = intel_sip_smc_plat_format_trans_id,
|
||||||
|
.sip_svc_plat_func_id_valid = intel_sip_smc_plat_func_id_valid,
|
||||||
|
.sip_svc_plat_update_trans_id = intel_sip_smc_plat_update_trans_id,
|
||||||
|
.sip_svc_plat_get_error_code = intel_sip_smc_plat_get_error_code,
|
||||||
|
.sip_svc_plat_async_res_req = intel_sip_smc_plat_async_res_req,
|
||||||
|
.sip_svc_plat_async_res_res = intel_sip_smc_plat_async_res_res,
|
||||||
|
.sip_svc_plat_free_async_memory = intel_sip_smc_plat_free_async_memory};
|
||||||
|
|
||||||
|
BUILD_ASSERT((DT_PROP(DT_SIP_SMC, zephyr_num_clients) != 0), "num-clients should not be zero");
|
||||||
|
BUILD_ASSERT((CONFIG_ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS > 0),
|
||||||
|
"CONFIG_ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS should be greater than 0");
|
||||||
|
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
|
DEVICE_DT_DEFINE(DT_SIP_SMC, arm_sip_smc_init, NULL, NULL, NULL, POST_KERNEL,
|
||||||
|
CONFIG_ARM_SIP_SVC_DRIVER_INIT_PRIORITY, &api);
|
||||||
|
|
||||||
|
#endif
|
42
include/zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h
Normal file
42
include/zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_SIP_SVC_AGILEX_MB_H_
|
||||||
|
#define ZEPHYR_INCLUDE_SIP_SVC_AGILEX_MB_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Intel SoC FPGA Agilex customized SDM Mailbox communication
|
||||||
|
* protocol handler. SDM Mailbox protocol will be embedded in
|
||||||
|
* Arm SiP Services SMC protocol and sent to/from SDM via Arm
|
||||||
|
* SiP Services.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIP_SVP_MB_MAX_WORD_SIZE 1024
|
||||||
|
#define SIP_SVP_MB_HEADER_TRANS_ID_OFFSET 24
|
||||||
|
#define SIP_SVP_MB_HEADER_TRANS_ID_MASK 0xFF
|
||||||
|
#define SIP_SVP_MB_HEADER_LENGTH_OFFSET 12
|
||||||
|
#define SIP_SVP_MB_HEADER_LENGTH_MASK 0x7FF
|
||||||
|
|
||||||
|
#define SIP_SVC_MB_HEADER_GET_CLIENT_ID(header) \
|
||||||
|
((header) >> SIP_SVP_MB_HEADER_CLIENT_ID_OFFSET & \
|
||||||
|
SIP_SVP_MB_HEADER_CLIENT_ID_MASK)
|
||||||
|
|
||||||
|
#define SIP_SVC_MB_HEADER_GET_TRANS_ID(header) \
|
||||||
|
((header) >> SIP_SVP_MB_HEADER_TRANS_ID_OFFSET & \
|
||||||
|
SIP_SVP_MB_HEADER_TRANS_ID_MASK)
|
||||||
|
|
||||||
|
#define SIP_SVC_MB_HEADER_SET_TRANS_ID(header, id) \
|
||||||
|
(header) &= ~(SIP_SVP_MB_HEADER_TRANS_ID_MASK << \
|
||||||
|
SIP_SVP_MB_HEADER_TRANS_ID_OFFSET); \
|
||||||
|
(header) |= (((id) & SIP_SVP_MB_HEADER_TRANS_ID_MASK) << \
|
||||||
|
SIP_SVP_MB_HEADER_TRANS_ID_OFFSET);
|
||||||
|
|
||||||
|
#define SIP_SVC_MB_HEADER_GET_LENGTH(header) \
|
||||||
|
((header) >> SIP_SVP_MB_HEADER_LENGTH_OFFSET & \
|
||||||
|
SIP_SVP_MB_HEADER_LENGTH_MASK)
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_SIP_SVC_AGILEX_MB_H_ */
|
69
include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h
Normal file
69
include/zephyr/drivers/sip_svc/sip_svc_agilex_smc.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_SIP_SVC_AGILEX_SMC_H_
|
||||||
|
#define ZEPHYR_INCLUDE_SIP_SVC_AGILEX_SMC_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Intel SoC FPGA Agilex customized Arm SiP Services
|
||||||
|
* SMC protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @brief SMC return status
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SMC_STATUS_INVALID 0xFFFFFFFF
|
||||||
|
#define SMC_STATUS_OKAY 0
|
||||||
|
#define SMC_STATUS_BUSY 1
|
||||||
|
#define SMC_STATUS_REJECT 2
|
||||||
|
#define SMC_STATUS_NO_RESPONSE 3
|
||||||
|
#define SMC_STATUS_ERROR 4
|
||||||
|
|
||||||
|
/* @brief SMC Intel Header at a1
|
||||||
|
*
|
||||||
|
* bit
|
||||||
|
* 7: 0 Transaction ID
|
||||||
|
* 59: 8 Reserved
|
||||||
|
* 63:60 Version
|
||||||
|
*/
|
||||||
|
#define SMC_PLAT_PROTO_VER 0x0
|
||||||
|
|
||||||
|
#define SMC_PLAT_PROTO_HEADER_TRANS_ID_OFFSET 0
|
||||||
|
#define SMC_PLAT_PROTO_HEADER_TRANS_ID_MASK 0xFF
|
||||||
|
|
||||||
|
#define SMC_PLAT_PROTO_HEADER_VER_OFFSET 60
|
||||||
|
#define SMC_PLAT_PROTO_HEADER_VER_MASK 0xF
|
||||||
|
|
||||||
|
#define SMC_PLAT_PROTO_HEADER \
|
||||||
|
((SMC_PLAT_PROTO_VER & SMC_PLAT_PROTO_HEADER_VER_MASK) << SMC_PLAT_PROTO_HEADER_VER_OFFSET)
|
||||||
|
|
||||||
|
#define SMC_PLAT_PROTO_HEADER_SET_TRANS_ID(header, trans_id) \
|
||||||
|
(header) &= \
|
||||||
|
~(SMC_PLAT_PROTO_HEADER_TRANS_ID_MASK << SMC_PLAT_PROTO_HEADER_TRANS_ID_OFFSET); \
|
||||||
|
(header) |= (((trans_id)&SMC_PLAT_PROTO_HEADER_TRANS_ID_MASK) \
|
||||||
|
<< SMC_PLAT_PROTO_HEADER_TRANS_ID_OFFSET);
|
||||||
|
|
||||||
|
/* @brief SYNC SMC Function IDs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SMC_FUNC_ID_GET_SVC_VERSION 0xC2000400
|
||||||
|
#define SMC_FUNC_ID_REG_READ 0xC2000401
|
||||||
|
#define SMC_FUNC_ID_REG_WRITE 0xC2000402
|
||||||
|
#define SMC_FUNC_ID_REG_UPDATE 0xC2000403
|
||||||
|
#define SMC_FUNC_ID_SET_HPS_BRIDGES 0xC2000404
|
||||||
|
|
||||||
|
/* @brief ASYNC SMC Function IDs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SMC_FUNC_ID_MAILBOX_SEND_COMMAND 0xC2000420
|
||||||
|
#define SMC_FUNC_ID_MAILBOX_POLL_RESPONSE 0xC2000421
|
||||||
|
|
||||||
|
/* @brief SDM mailbox CANCEL command
|
||||||
|
*/
|
||||||
|
#define MAILBOX_CANCEL_COMMAND 0x03
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_SIP_SVC_AGILEX_SMC_H_ */
|
353
include/zephyr/drivers/sip_svc/sip_svc_driver.h
Normal file
353
include/zephyr/drivers/sip_svc/sip_svc_driver.h
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_
|
||||||
|
#define ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/arch/arm64/arm-smccc.h>
|
||||||
|
#include <zephyr/drivers/sip_svc/sip_svc_proto.h>
|
||||||
|
|
||||||
|
#define DEV_API(dev) ((struct svc_driver_api *)(dev)->api)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Length of SVC conduit name.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define SVC_CONDUIT_NAME_LENGTH (4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for executing the supervisory call
|
||||||
|
* See @a sip_supervisory_call() for argument description
|
||||||
|
*/
|
||||||
|
typedef void (*sip_supervisory_call_t)(const struct device *dev, unsigned long function_id,
|
||||||
|
unsigned long arg0, unsigned long arg1, unsigned long arg2,
|
||||||
|
unsigned long arg3, unsigned long arg4, unsigned long arg5,
|
||||||
|
unsigned long arg6, struct arm_smccc_res *res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for validating function id for the supervisory call.
|
||||||
|
* See @a sip_svc_plat_func_id_valid() for argument description
|
||||||
|
*/
|
||||||
|
typedef bool (*sip_svc_plat_func_id_valid_t)(const struct device *dev, uint32_t command,
|
||||||
|
uint32_t func_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for generating the transaction id from client id.
|
||||||
|
* See @a sip_svc_plat_format_trans_id() for argument description
|
||||||
|
*/
|
||||||
|
typedef uint32_t (*sip_svc_plat_format_trans_id_t)(const struct device *dev, uint32_t client_idx,
|
||||||
|
uint32_t trans_idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for retrieving client transaction id from transaction id
|
||||||
|
* See @a sip_svc_plat_get_trans_idx() for argument description
|
||||||
|
*/
|
||||||
|
typedef uint32_t (*sip_svc_plat_get_trans_idx_t)(const struct device *dev, uint32_t trans_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for updating transaction id for request packet for lower layer
|
||||||
|
* See @a sip_svc_plat_update_trans_id() for argument description
|
||||||
|
*/
|
||||||
|
typedef void (*sip_svc_plat_update_trans_id_t)(const struct device *dev,
|
||||||
|
struct sip_svc_request *request, uint32_t trans_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for freeing command buffer in ASYNC packets
|
||||||
|
* See @a sip_svc_plat_free_async_memory() for argument description
|
||||||
|
*/
|
||||||
|
typedef void (*sip_svc_plat_free_async_memory_t)(const struct device *dev,
|
||||||
|
struct sip_svc_request *request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API to construct Polling packet for ASYNC transaction.
|
||||||
|
* See @a sip_svc_plat_async_res_req() for argument description
|
||||||
|
*/
|
||||||
|
typedef int (*sip_svc_plat_async_res_req_t)(const struct device *dev, unsigned long *a0,
|
||||||
|
unsigned long *a1, unsigned long *a2, unsigned long *a3,
|
||||||
|
unsigned long *a4, unsigned long *a5, unsigned long *a6,
|
||||||
|
unsigned long *a7, char *buf, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API to check the response of polling request
|
||||||
|
* See @a sip_svc_plat_async_res_res() for argument description
|
||||||
|
*/
|
||||||
|
typedef int (*sip_svc_plat_async_res_res_t)(const struct device *dev, struct arm_smccc_res *res,
|
||||||
|
char *buf, size_t *size, uint32_t *trans_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback API for retrieving error code from a supervisory call response.
|
||||||
|
* See @a sip_svc_plat_get_error_code() for argument description.
|
||||||
|
*/
|
||||||
|
typedef uint32_t (*sip_svc_plat_get_error_code_t)(const struct device *dev,
|
||||||
|
struct arm_smccc_res *res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief API structure for sip_svc driver.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
__subsystem struct svc_driver_api {
|
||||||
|
sip_supervisory_call_t sip_supervisory_call;
|
||||||
|
sip_svc_plat_func_id_valid_t sip_svc_plat_func_id_valid;
|
||||||
|
sip_svc_plat_format_trans_id_t sip_svc_plat_format_trans_id;
|
||||||
|
sip_svc_plat_get_trans_idx_t sip_svc_plat_get_trans_idx;
|
||||||
|
sip_svc_plat_update_trans_id_t sip_svc_plat_update_trans_id;
|
||||||
|
sip_svc_plat_free_async_memory_t sip_svc_plat_free_async_memory;
|
||||||
|
sip_svc_plat_async_res_req_t sip_svc_plat_async_res_req;
|
||||||
|
sip_svc_plat_async_res_res_t sip_svc_plat_async_res_res;
|
||||||
|
sip_svc_plat_get_error_code_t sip_svc_plat_get_error_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief supervisory call function which will execute the smc/hvc call
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param function_id Function identifier for the supervisory call.
|
||||||
|
* @param arg0 Argument 0 for supervisory call.
|
||||||
|
* @param arg1 Argument 1 for supervisory call.
|
||||||
|
* @param arg2 Argument 2 for supervisory call.
|
||||||
|
* @param arg3 Argument 3 for supervisory call.
|
||||||
|
* @param arg4 Argument 4 for supervisory call.
|
||||||
|
* @param arg5 Argument 5 for supervisory call.
|
||||||
|
* @param arg6 Argument 6 for supervisory call.
|
||||||
|
* @param res Pointer to response buffer for supervisory call.
|
||||||
|
*/
|
||||||
|
__syscall void sip_supervisory_call(const struct device *dev, unsigned long function_id,
|
||||||
|
unsigned long arg0, unsigned long arg1, unsigned long arg2,
|
||||||
|
unsigned long arg3, unsigned long arg4, unsigned long arg5,
|
||||||
|
unsigned long arg6, struct arm_smccc_res *res);
|
||||||
|
static inline void z_impl_sip_supervisory_call(const struct device *dev, unsigned long function_id,
|
||||||
|
unsigned long arg0, unsigned long arg1,
|
||||||
|
unsigned long arg2, unsigned long arg3,
|
||||||
|
unsigned long arg4, unsigned long arg5,
|
||||||
|
unsigned long arg6, struct arm_smccc_res *res)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_supervisory_call, "sip_supervisory_call shouldn't be NULL");
|
||||||
|
__ASSERT(res, "response pointer shouldn't be NULL");
|
||||||
|
|
||||||
|
api->sip_supervisory_call(dev, function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate the function id for the supervisory call.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param command Command which specify if the call is SYNC or ASYNC.
|
||||||
|
* @param func_id Function identifier
|
||||||
|
*
|
||||||
|
* @retval true if command and function identifiers are valid.
|
||||||
|
* @retval false if command and function identifiers are invalid.
|
||||||
|
*/
|
||||||
|
__syscall bool sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command,
|
||||||
|
uint32_t func_id);
|
||||||
|
static inline bool z_impl_sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command,
|
||||||
|
uint32_t func_id)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_func_id_valid,
|
||||||
|
"sip_svc_plat_func_id_valid func shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_func_id_valid(dev, command, func_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats and generates the transaction id from client id.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param client_idx client index.
|
||||||
|
* @param trans_idx transaction index.
|
||||||
|
*
|
||||||
|
* @retval transaction id, which is used for tracking each transaction.
|
||||||
|
*/
|
||||||
|
__syscall uint32_t sip_svc_plat_format_trans_id(const struct device *dev, uint32_t client_idx,
|
||||||
|
uint32_t trans_idx);
|
||||||
|
static inline uint32_t z_impl_sip_svc_plat_format_trans_id(const struct device *dev,
|
||||||
|
uint32_t client_idx, uint32_t trans_idx)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_format_trans_id,
|
||||||
|
"sip_svc_plat_format_trans_id func shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_format_trans_id(dev, client_idx, trans_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve client transaction id from packet transaction id.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param trans_id transaction identifier if for a transaction.
|
||||||
|
*
|
||||||
|
* @retval client transaction id form Transaction id.
|
||||||
|
*/
|
||||||
|
__syscall uint32_t sip_svc_plat_get_trans_idx(const struct device *dev, uint32_t trans_id);
|
||||||
|
static inline uint32_t z_impl_sip_svc_plat_get_trans_idx(const struct device *dev,
|
||||||
|
uint32_t trans_id)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_get_trans_idx,
|
||||||
|
"sip_svc_plat_get_trans_idx func shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_get_trans_idx(dev, trans_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Update transaction id for sip_svc_request for lower layer.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param request Pointer to sip_svc_request structure.
|
||||||
|
* @param trans_id Transaction id.
|
||||||
|
*/
|
||||||
|
__syscall void sip_svc_plat_update_trans_id(const struct device *dev,
|
||||||
|
struct sip_svc_request *request, uint32_t trans_id);
|
||||||
|
static inline void z_impl_sip_svc_plat_update_trans_id(const struct device *dev,
|
||||||
|
struct sip_svc_request *request,
|
||||||
|
uint32_t trans_id)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_update_trans_id,
|
||||||
|
"sip_svc_plat_update_trans_id func shouldn't be NULL");
|
||||||
|
__ASSERT(request, "request shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_update_trans_id(dev, request, trans_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve the error code from arm_smccc_res response.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param res Pointer to struct arm_smccc_res response.
|
||||||
|
*
|
||||||
|
* @retval 0 on success.
|
||||||
|
* @retval SIP_SVC_ID_INVALID on failure
|
||||||
|
*/
|
||||||
|
__syscall uint32_t sip_svc_plat_get_error_code(const struct device *dev, struct arm_smccc_res *res);
|
||||||
|
static inline uint32_t z_impl_sip_svc_plat_get_error_code(const struct device *dev,
|
||||||
|
struct arm_smccc_res *res)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_get_error_code,
|
||||||
|
"sip_svc_plat_get_error_code func shouldn't be NULL");
|
||||||
|
__ASSERT(res, "res shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_get_error_code(dev, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set arguments for polling supervisory call. For ASYNC polling of response.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param a0 Argument 0 for supervisory call.
|
||||||
|
* @param a1 Argument 1 for supervisory call.
|
||||||
|
* @param a2 Argument 2 for supervisory call.
|
||||||
|
* @param a3 Argument 3 for supervisory call.
|
||||||
|
* @param a4 Argument 4 for supervisory call.
|
||||||
|
* @param a5 Argument 5 for supervisory call.
|
||||||
|
* @param a6 Argument 6 for supervisory call.
|
||||||
|
* @param a7 Argument 7 for supervisory call.
|
||||||
|
* @param buf Pointer for response buffer.
|
||||||
|
* @param size Size of response buffer.
|
||||||
|
*
|
||||||
|
* @retval 0 on success
|
||||||
|
*/
|
||||||
|
__syscall int sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0,
|
||||||
|
unsigned long *a1, unsigned long *a2, unsigned long *a3,
|
||||||
|
unsigned long *a4, unsigned long *a5, unsigned long *a6,
|
||||||
|
unsigned long *a7, char *buf, size_t size);
|
||||||
|
static inline int z_impl_sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0,
|
||||||
|
unsigned long *a1, unsigned long *a2,
|
||||||
|
unsigned long *a3, unsigned long *a4,
|
||||||
|
unsigned long *a5, unsigned long *a6,
|
||||||
|
unsigned long *a7, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_async_res_req,
|
||||||
|
"sip_svc_plat_async_res_req func shouldn't be NULL");
|
||||||
|
__ASSERT(a0, "a0 shouldn't be NULL");
|
||||||
|
__ASSERT(a1, "a1 shouldn't be NULL");
|
||||||
|
__ASSERT(a2, "a2 shouldn't be NULL");
|
||||||
|
__ASSERT(a3, "a3 shouldn't be NULL");
|
||||||
|
__ASSERT(a4, "a4 shouldn't be NULL");
|
||||||
|
__ASSERT(a5, "a5 shouldn't be NULL");
|
||||||
|
__ASSERT(a6, "a6 shouldn't be NULL");
|
||||||
|
__ASSERT(a7, "a7 shouldn't be NULL");
|
||||||
|
__ASSERT(((buf == NULL && size == 0) || (buf != NULL && size != 0)),
|
||||||
|
"buf and size should represent a buffer");
|
||||||
|
return api->sip_svc_plat_async_res_req(dev, a0, a1, a2, a3, a4, a5, a6, a7, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check the response of polling supervisory call and retrieve the response
|
||||||
|
* size and transaction id.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param res Pointer to struct arm_smccc_res response.
|
||||||
|
* @param buf Pointer to response buffer.
|
||||||
|
* @param size Size of response in response buffer
|
||||||
|
* @param trans_id Transaction id of the response.
|
||||||
|
*
|
||||||
|
* @retval 0 on getting a valid polling response from supervisory call.
|
||||||
|
* @retval -EINPROGRESS on no valid polling response from supervisory call.
|
||||||
|
*/
|
||||||
|
__syscall int sip_svc_plat_async_res_res(const struct device *dev, struct arm_smccc_res *res,
|
||||||
|
char *buf, size_t *size, uint32_t *trans_id);
|
||||||
|
static inline int z_impl_sip_svc_plat_async_res_res(const struct device *dev,
|
||||||
|
struct arm_smccc_res *res, char *buf,
|
||||||
|
size_t *size, uint32_t *trans_id)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_async_res_res,
|
||||||
|
"sip_svc_plat_async_res_res func shouldn't be NULL");
|
||||||
|
__ASSERT(res, "res shouldn't be NULL");
|
||||||
|
__ASSERT(buf, "buf shouldn't be NULL");
|
||||||
|
__ASSERT(size, "size shouldn't be NULL");
|
||||||
|
__ASSERT(trans_id, "buf shouldn't be NULL");
|
||||||
|
|
||||||
|
return api->sip_svc_plat_async_res_res(dev, res, buf, size, trans_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free the command buffer used for ASYNC packet after sending it to lower layers.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param request Pointer to sip_svc_request packet.
|
||||||
|
*/
|
||||||
|
__syscall void sip_svc_plat_free_async_memory(const struct device *dev,
|
||||||
|
struct sip_svc_request *request);
|
||||||
|
static inline void z_impl_sip_svc_plat_free_async_memory(const struct device *dev,
|
||||||
|
struct sip_svc_request *request)
|
||||||
|
{
|
||||||
|
__ASSERT(dev, "dev shouldn't be NULL");
|
||||||
|
const struct svc_driver_api *api = DEV_API(dev);
|
||||||
|
|
||||||
|
__ASSERT(api->sip_svc_plat_free_async_memory,
|
||||||
|
"sip_svc_plat_free_async_memory func shouldn't be NULL");
|
||||||
|
__ASSERT(request, "request shouldn't be NULL");
|
||||||
|
|
||||||
|
api->sip_svc_plat_free_async_memory(dev, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <syscalls/sip_svc_driver.h>
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ */
|
188
include/zephyr/drivers/sip_svc/sip_svc_proto.h
Normal file
188
include/zephyr/drivers/sip_svc/sip_svc_proto.h
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_SIP_SVC_PROTO_H_
|
||||||
|
#define ZEPHYR_INCLUDE_SIP_SVC_PROTO_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Arm SiP services communication protocol
|
||||||
|
* between service provider and client.
|
||||||
|
*
|
||||||
|
* Client to fill in the input data in struct sip_svc_request format
|
||||||
|
* when requesting SMC/HVC service via 'send' function.
|
||||||
|
*
|
||||||
|
* Service to fill in the SMC/HVC return value in struct sip_svc_response
|
||||||
|
* format and pass to client via Callback.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invalid id value
|
||||||
|
*/
|
||||||
|
#define SIP_SVC_ID_INVALID 0xFFFFFFFF
|
||||||
|
|
||||||
|
/** @brief Header format
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_VER 0x0
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_CODE_OFFSET 0
|
||||||
|
#define SIP_SVC_PROTO_HEADER_CODE_MASK 0xFFFF
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_TRANS_ID_OFFSET 16
|
||||||
|
#define SIP_SVC_PROTO_HEADER_TRANS_ID_MASK 0xFF
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_VER_OFFSET 30
|
||||||
|
#define SIP_SVC_PROTO_HEADER_VER_MASK 0x3
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER(code, trans_id) \
|
||||||
|
((((code)&SIP_SVC_PROTO_HEADER_CODE_MASK) << SIP_SVC_PROTO_HEADER_CODE_OFFSET) | \
|
||||||
|
(((trans_id)&SIP_SVC_PROTO_HEADER_TRANS_ID_MASK) \
|
||||||
|
<< SIP_SVC_PROTO_HEADER_TRANS_ID_OFFSET) | \
|
||||||
|
((SIP_SVC_PROTO_VER & SIP_SVC_PROTO_HEADER_VER_MASK) << SIP_SVC_PROTO_HEADER_VER_OFFSET))
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_GET_CODE(header) \
|
||||||
|
(((header) >> SIP_SVC_PROTO_HEADER_CODE_OFFSET) & SIP_SVC_PROTO_HEADER_CODE_MASK)
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_GET_TRANS_ID(header) \
|
||||||
|
(((header) >> SIP_SVC_PROTO_HEADER_TRANS_ID_OFFSET) & SIP_SVC_PROTO_HEADER_TRANS_ID_MASK)
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_HEADER_SET_TRANS_ID(header, trans_id) \
|
||||||
|
(header) &= ~(SIP_SVC_PROTO_HEADER_TRANS_ID_MASK << SIP_SVC_PROTO_HEADER_TRANS_ID_OFFSET); \
|
||||||
|
(header) |= (((trans_id)&SIP_SVC_PROTO_HEADER_TRANS_ID_MASK) \
|
||||||
|
<< SIP_SVC_PROTO_HEADER_TRANS_ID_OFFSET);
|
||||||
|
|
||||||
|
/** @brief Arm SiP services command code in request header
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_CMD_SYNC
|
||||||
|
* - Typical flow, synchronous request. Service expects EL3/EL2 firmware to
|
||||||
|
* return the result immediately during SMC/HVC call.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_CMD_ASYNC
|
||||||
|
* - Asynchronous request. Service is required to poll the response via a
|
||||||
|
* separate SMC/HVC call. Use this method if the request requires longer
|
||||||
|
* processing in EL3/EL2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_CMD_SYNC 0x0
|
||||||
|
#define SIP_SVC_PROTO_CMD_ASYNC 0x1
|
||||||
|
#define SIP_SVC_PROTO_CMD_MAX SIP_SVC_PROTO_CMD_ASYNC
|
||||||
|
|
||||||
|
/** @brief Error code in response header
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_OK
|
||||||
|
* - Successfully execute the request.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_UNKNOWN
|
||||||
|
* - Unrecognized SMC/HVC Function ID.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_BUSY
|
||||||
|
* - The request is still in progress. Please try again.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_REJECT
|
||||||
|
* - The request have been rejected due to improper input data.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_NO_RESPONSE
|
||||||
|
* - No response from target hardware yet.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_ERROR
|
||||||
|
* - Error occurred when executing the request.
|
||||||
|
*
|
||||||
|
* SIP_SVC_PROTO_STATUS_NOT_SUPPORT
|
||||||
|
* - Unsupported Arm SiP services command code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIP_SVC_PROTO_STATUS_OK 0x0
|
||||||
|
#define SIP_SVC_PROTO_STATUS_UNKNOWN 0xFFFF
|
||||||
|
#define SIP_SVC_PROTO_STATUS_BUSY 0x1
|
||||||
|
#define SIP_SVC_PROTO_STATUS_REJECT 0x2
|
||||||
|
#define SIP_SVC_PROTO_STATUS_NO_RESPONSE 0x3
|
||||||
|
#define SIP_SVC_PROTO_STATUS_ERROR 0x4
|
||||||
|
|
||||||
|
/** @brief SiP Service communication protocol
|
||||||
|
* request format.
|
||||||
|
*
|
||||||
|
* request header
|
||||||
|
* - bits [15: 0] Arm SiP services command code
|
||||||
|
* - bits [23:16] Transaction ID (Filled in by sip_svc service)
|
||||||
|
* - bits [29:24] Unused. Reserved.
|
||||||
|
* - bits [31:30] Arm SiP services communication protocol version
|
||||||
|
*
|
||||||
|
* a0 - a7
|
||||||
|
* - User input data to be filled into a0-a7 registers when trigger
|
||||||
|
* SMC/HVC
|
||||||
|
*
|
||||||
|
* resp_data_addr
|
||||||
|
* - This parameter only used by asynchronous command.
|
||||||
|
* - Dynamic memory address for service to put the asynchronous response
|
||||||
|
* data. The service will free this memory space if the client has
|
||||||
|
* cancelled the transaction.
|
||||||
|
*
|
||||||
|
* resp_data_size
|
||||||
|
* - This parameter only used by asynchronous command.
|
||||||
|
* - Maximum memory size in bytes of resp_data_addr
|
||||||
|
*
|
||||||
|
* priv_data
|
||||||
|
* - Memory address to client context. Service will pass this address back
|
||||||
|
* to client in response format via callback.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct sip_svc_request {
|
||||||
|
uint32_t header;
|
||||||
|
unsigned long a0;
|
||||||
|
unsigned long a1;
|
||||||
|
unsigned long a2;
|
||||||
|
unsigned long a3;
|
||||||
|
unsigned long a4;
|
||||||
|
unsigned long a5;
|
||||||
|
unsigned long a6;
|
||||||
|
unsigned long a7;
|
||||||
|
uint64_t resp_data_addr;
|
||||||
|
uint32_t resp_data_size;
|
||||||
|
void *priv_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief SiP Services service communication protocol
|
||||||
|
* response format.
|
||||||
|
*
|
||||||
|
* response header
|
||||||
|
* - bits [15: 0] Error code
|
||||||
|
* - bits [23:16] Transaction ID
|
||||||
|
* - bits [29:24] Unused. Reserved.
|
||||||
|
* - bits [31:30] Arm SiP services communication protocol version
|
||||||
|
*
|
||||||
|
* a0 - a3
|
||||||
|
* - SMC/HVC return value
|
||||||
|
*
|
||||||
|
* resp_data_addr
|
||||||
|
* - This parameter only used by asynchronous command.
|
||||||
|
* - Dynamic memory address that put the asynchronous response data.
|
||||||
|
* This address is provided by client during request. Client is responsible
|
||||||
|
* to free the memory space when receive the callback of a asynchronous
|
||||||
|
* command transaction.The memory needs to be dynamically allocated,
|
||||||
|
* the framework will free the allocated memory if the channel is in ABORT
|
||||||
|
* state.
|
||||||
|
*
|
||||||
|
* resp_data_size
|
||||||
|
* - This parameter only used by asynchronous command.
|
||||||
|
* - Valid data size in bytes of resp_data_addr
|
||||||
|
*
|
||||||
|
* priv_data
|
||||||
|
* - Memory address to client context which given during request.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct sip_svc_response {
|
||||||
|
uint32_t header;
|
||||||
|
unsigned long a0;
|
||||||
|
unsigned long a1;
|
||||||
|
unsigned long a2;
|
||||||
|
unsigned long a3;
|
||||||
|
uint64_t resp_data_addr;
|
||||||
|
uint32_t resp_data_size;
|
||||||
|
void *priv_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_SIP_SVC_PROTO_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue