summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAmir Samuelov <amirs@codeaurora.org>2015-11-25 11:34:17 +0200
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:12:11 -0700
commit09e5b188695cf2eb58a8fdac761e40d596d48840 (patch)
tree0f5ac2ea06c4d4ab4c8ea867856bd488cfaafc95 /include
parent876012215c2e801a0ca07c6c59578df7bab22623 (diff)
soc: qcom: add secure processor communication (spcom) driver
This driver supports communication with secure processor subsystem over glink transport layer. The communication is based on using shared memory and interrupts. This driver exposes interface to both kernel and user space. Change-Id: Iec5fc78c8370002643b549e43015c06b09d8ab8b Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
Diffstat (limited to 'include')
-rw-r--r--include/soc/qcom/spcom.h266
-rw-r--r--include/uapi/linux/spcom.h89
2 files changed, 355 insertions, 0 deletions
diff --git a/include/soc/qcom/spcom.h b/include/soc/qcom/spcom.h
new file mode 100644
index 000000000000..e7302cad39cd
--- /dev/null
+++ b/include/soc/qcom/spcom.h
@@ -0,0 +1,266 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SPCOM_H_
+#define _SPCOM_H_
+
+#include <linux/types.h> /* uint32_t ,bool */
+
+/**
+ * @brief - Secure Processor Communication API
+ *
+ * This API should be used by Linux Kernel drivers,
+ * similar API is provided to user space applications
+ * via spcomlib.h API file.
+ * Sending Request and receiving Response is synchronous, only one at a time.
+ * The API is based on Client/Server model.
+ * The API resemble the trustzone QSEECOM API.
+ * In most cases, the Secure Processor side has servers and the HLOS
+ * side has clients. Request is initiated by the client and responded by the
+ * server.
+ */
+
+/*===========================================================================*/
+/* defines, enums , types */
+/*===========================================================================*/
+
+/* Maximum size (including null) for channel names - match glink */
+#define SPCOM_CHANNEL_NAME_SIZE 32
+
+/**
+ * Request buffer size.
+ * Any large data (multiply of 4KB) is provided by temp buffer in DDR.
+ * Request shall provide the temp buffer physical address (align to 4KB).
+ * Maximum request/response size of 268 is used to accommodate APDU size.
+ * From kernel spcom driver perspective a PAGE_SIZE of 4K
+ * is the actual maximum size for a single read/write file operation.
+ */
+#define SPCOM_MAX_REQUEST_SIZE 268
+#define SPCOM_MAX_RESPONSE_SIZE 268
+
+/**
+ * Abstract spcom handle.
+ * The actual struct definition is internal to the spcom driver.
+ */
+struct spcom_client; /* Forward declaration */
+struct spcom_server; /* Forward declaration */
+
+/**
+ * Client registration info
+ *
+ * @ch_name: glink logical channel name
+ * @notify_ssr_cb: callback when the remote SP side reset (power down).
+ * This is likely to happen due to remote subsystem restart (SSR).
+ * NULL callback means no notification required.
+ * Upon ssr callback, the user should unregister,
+ * Poll for link up and then register again.
+ */
+struct spcom_client_info {
+ const char *ch_name;
+ void (*notify_ssr_cb)(void);
+};
+
+/**
+ * Server registration info
+ *
+ * @ch_name: glink logical channel name
+ * @notify_ssr_cb: callback when the remote SP side reset (power down).
+ * This is likely to happen due to remote subsystem restart (SSR).
+ * NULL callback means no notification required.
+ * Upon ssr callback, the user should unregister,
+ * Poll for link up and then register again.
+ */
+struct spcom_service_info {
+ const char *ch_name;
+ void (*notify_ssr_cb)(void);
+};
+
+/*===========================================================================*/
+/* RESET */
+/*===========================================================================*/
+
+
+/**
+ * spcom_reset_sp_subsystem() - send reset command to secure processor.
+ *
+ * Gracefully ask the remote SP to reset itself.
+ * SP will probably initiate a Watch-Dog-Bite.
+ *
+ * return: 0 on success, negative error code on failure.
+ */
+int spcom_reset_sp_subsystem(void);
+
+/**
+ * spcom_is_sp_subsystem_link_up() - check if SPSS link is up.
+ *
+ * return: true if link is up, false if link is down.
+ */
+bool spcom_is_sp_subsystem_link_up(void);
+
+/*===========================================================================*/
+/* Client LOAD SP Application */
+/*===========================================================================*/
+
+/**
+ * spcom_is_app_loaded() - check if the SP App is already loaded.
+ *
+ * This shall be useful when the HLOS app restarts.
+ * This API will check if logical channel node has been created.
+ *
+ * @ch_name: glink logical channel name
+ *
+ * @note: This API is available only on HLOS.
+ *
+ * return: true if loaded,false otherwise.
+ */
+bool spcom_is_app_loaded(const char *ch_name);
+
+/**
+ * spcom_load_app() - Load Secure Processor Application.
+ *
+ * @ch_name: glink logical channel name
+ * spcom shall open channel file node after application is loaded.
+ *
+ * @file_path: Path to the encrypted file containing the application.
+ *
+ * @note: This API is available only on HLOS.
+ *
+ * return: 0 on success, negative error code on failure.
+ */
+int spcom_load_app(const char *ch_name, const char *file_path);
+
+/*===========================================================================*/
+/* Client Send Message */
+/*===========================================================================*/
+/**
+ * spcom_register_client() - register client for channel
+ *
+ * Only one client/Server can register on each side of a channel.
+ * Server on remote side is expected to be running and connected,
+ * therefore connection expected within the provided timeout.
+ * Handle is returned even if timeout expired.
+ * use spcom_client_is_server_connected() to check fully connected.
+ *
+ * @info: Client configuration info (input).
+ *
+ * return: client handle on success, NULL on failure.
+ */
+struct spcom_client *spcom_register_client(struct spcom_client_info *info);
+
+/**
+ * spcom_unregister_client() - unregister client for channel
+ *
+ * @client: Client Handle.
+ *
+ * return: 0 on success, negative error code on failure (see errno.h)
+ */
+int spcom_unregister_client(struct spcom_client *client);
+
+/**
+ * spcom_client_send_message_sync() - Send a synchronous request and response
+ *
+ * @client: a pointer to spcom client
+ * @req_ptr: a pointer to the request C struct representation
+ * @req_size: size of the request C struct
+ * @resp_ptr: a pointer to the response C struct representation
+ * @resp_size: size of the response C struct
+ * @timeout_msec: Timeout in msec between command and response, 0=no timeout.
+ *
+ * return: number of rx bytes on success, negative value on failure.
+ */
+int spcom_client_send_message_sync(struct spcom_client *client,
+ void *req_ptr,
+ uint32_t req_size,
+ void *resp_ptr,
+ uint32_t resp_size,
+ uint32_t timeout_msec);
+
+/**
+ * spcom_client_is_server_connected() - Check if remote server connected.
+ *
+ * This API checks that the logical channel is fully connected between
+ * the client and the server.
+ * Normally, the server should be up first and connect first.
+ *
+ * @client: a pointer to spcom client
+ *
+ * return: true if server connected, false otherwise.
+ */
+bool spcom_client_is_server_connected(struct spcom_client *client);
+
+/*===========================================================================*/
+/* Service */
+/*===========================================================================*/
+
+/**
+ * spcom_register_service() - register server for channel
+ *
+ * Only one client/Server can register on each side of a channel.
+ *
+ * @info: Server configuration info (input).
+ *
+ * return: server handle on success, NULL on failure.
+ */
+struct spcom_server *spcom_register_service(struct spcom_service_info *info);
+
+/**
+ * spcom_unregister_service() - unregister server for channel
+ *
+ * @server: server Handle.
+ *
+ * return: 0 on success, negative error code on failure (see errno.h)
+ */
+int spcom_unregister_service(struct spcom_server *server);
+
+/**
+ * spcom_server_get_next_request_size() - get the size of the
+ * next request
+ *
+ * This API MUST be called before calling spcom_server_wait_for_request().
+ * The server should allocate the relevant buffer size.
+ *
+ * @server: a pointer to spcom server
+ *
+ * return: size of request in bytes on success, negative value on failure.
+ */
+int spcom_server_get_next_request_size(struct spcom_server *server);
+
+/**
+ * spcom_server_wait_for_request() - server wait for request
+ *
+ * @server: a pointer to spcom server
+ * @req_ptr: a pointer to the request buffer
+ * @req_size: size of the buffer provided.
+ * The server should provide a buffer of at least the size
+ * returned by spcom_server_get_next_request_size() and up to
+ * SPCOM_MAX_REQUEST_SIZE.
+ *
+ * return: size of request on success, negative value on failure (see errno.h)
+ */
+int spcom_server_wait_for_request(struct spcom_server *server,
+ void *req_ptr,
+ uint32_t req_size);
+
+/**
+ * spcom_server_send_response() - Send a the response to request
+ *
+ * @server: a pointer to spcom server
+ * @resp_ptr: a pointer to the response C struct representation
+ * @resp_size: size of the response C struct
+ *
+ * return: sent data size on success, negative value on failure (see errno.h)
+ */
+int spcom_server_send_response(struct spcom_server *server,
+ void *resp_ptr,
+ uint32_t resp_size);
+
+#endif /* _SPCOM_H_ */
diff --git a/include/uapi/linux/spcom.h b/include/uapi/linux/spcom.h
new file mode 100644
index 000000000000..eb09d72ce21b
--- /dev/null
+++ b/include/uapi/linux/spcom.h
@@ -0,0 +1,89 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _UAPI_SPCOM_H_
+#define _UAPI_SPCOM_H_
+
+#include <linux/types.h> /* uint32_t, bool */
+#include <linux/bitops.h> /* BIT() */
+
+/**
+ * @brief - Secure Processor Communication interface to user space spcomlib.
+ *
+ * Sending data and control commands by write() file operation.
+ * Receiving data by read() file operation.
+ * Getting the next request size by read() file operation,
+ * with special size SPCOM_GET_NEXT_REQUEST_SIZE.
+ */
+
+/* Maximum size (including null) for channel names */
+#define SPCOM_CHANNEL_NAME_SIZE 32
+
+/*
+ * file read(fd, buf, size) with this size,
+ * hints the kernel that user space wants to read the next-req-size.
+ * This size is bigger than both SPCOM_MAX_REQUEST_SIZE and
+ * SPCOM_MAX_RESPONSE_SIZE , so it is not a valid data size.
+ */
+#define SPCOM_GET_NEXT_REQUEST_SIZE (PAGE_SIZE-1)
+
+/* Command Id between spcomlib and spcom driver, on write() */
+enum spcom_cmd_id {
+ SPCOM_CMD_LOAD_APP = 0x4C4F4144, /* "LOAD" = 0x4C4F4144 */
+ SPCOM_CMD_RESET_SP = 0x52455354, /* "REST" = 0x52455354 */
+ SPCOM_CMD_SEND = 0x53454E44, /* "SEND" = 0x53454E44 */
+ SPCOM_CMD_FSSR = 0x46535352, /* "FSSR" = 0x46535352 */
+ SPCOM_CMD_CREATE_CHANNEL = 0x43524554, /* "CRET" = 0x43524554 */
+};
+
+/*
+ * @note: Event types that are always implicitly polled:
+ * POLLERR=0x08 | POLLHUP=0x10 | POLLNVAL=0x20
+ * so bits 3,4,5 can't be used
+ */
+enum spcom_poll_events {
+ SPCOM_POLL_LINK_STATE = BIT(1),
+ SPCOM_POLL_CH_CONNECT = BIT(2),
+ SPCOM_POLL_READY_FLAG = BIT(14), /* output */
+ SPCOM_POLL_WAIT_FLAG = BIT(15), /* if set , wait for the event */
+};
+
+/* Common Command structure between User Space and spcom driver, on write() */
+struct spcom_user_command {
+ enum spcom_cmd_id cmd_id;
+ uint32_t arg;
+} __packed;
+
+/* Command structure between userspace spcomlib and spcom driver, on write() */
+struct spcom_user_load_app_command {
+ enum spcom_cmd_id cmd_id;
+ char ch_name[SPCOM_CHANNEL_NAME_SIZE];
+ uint32_t app_image_size;
+ char *app_buf_ptr;
+ uint32_t app_buf_size;
+} __packed;
+
+/* Command structure between User Space and spcom driver, on write() */
+struct spcom_send_command {
+ enum spcom_cmd_id cmd_id;
+ uint32_t timeout_msec;
+ uint32_t buf_size;
+ char buf[0]; /* Variable buffer size - must be last field */
+} __packed;
+
+/* Command structure between userspace spcomlib and spcom driver, on write() */
+struct spcom_user_create_channel_command {
+ enum spcom_cmd_id cmd_id;
+ char ch_name[SPCOM_CHANNEL_NAME_SIZE];
+} __packed;
+
+#endif /* _UAPI_SPCOM_H_ */