aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJorge Ramirez-Ortiz <jorge@foundries.io>2020-06-15 15:11:31 +0200
committerJérôme Forissier <jerome@forissier.org>2020-08-11 17:08:51 +0200
commit30c53a72426366d0a4eb4aa396c37b8fd048a82a (patch)
treec3420ced402773adaf8ebbedb7d21378236c69f6 /core
parent6ee9f66689c712fa8783785e9e7f2964bcf136e9 (diff)
core: arm: rpc i2c trampoline driver
Gives OP-TEE access to the i2c buses initialized and controlled by the REE kernel. This is done by memory mapping a buffer from the thread's cache where the input or output data is transferred. Using this mechanism, OP-TEE clients do not have to worry about REE RUNTIME_PM features switching off clocks from the controllers or collisions with other bus masters. This driver assumes that the I2C chip is on a REE statically assigned bus which value is known to OP-TEE (it will not query/probe the REE). The slave address can be either seven or ten bits. When using a ten bit address, the corresponding flag needs to be set in the command and the REE adapter must support the requested addressing mode. Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'core')
-rw-r--r--core/arch/arm/kernel/rpc_io_i2c.c61
-rw-r--r--core/arch/arm/kernel/sub.mk1
-rw-r--r--core/include/kernel/rpc_io_i2c.h38
-rw-r--r--core/include/optee_rpc_cmd.h22
4 files changed, 122 insertions, 0 deletions
diff --git a/core/arch/arm/kernel/rpc_io_i2c.c b/core/arch/arm/kernel/rpc_io_i2c.c
new file mode 100644
index 00000000..b48320ad
--- /dev/null
+++ b/core/arch/arm/kernel/rpc_io_i2c.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2020 Foundries Ltd <jorge@foundries.io>
+ */
+#include <kernel/rpc_io_i2c.h>
+#include <kernel/thread.h>
+#include <mm/mobj.h>
+#include <string.h>
+
+/*
+ * @brief: I2C master transfer request to an I2C slave device.
+ * It is the responsibility of the caller to validate the number of bytes
+ * processed by the REE.
+ *
+ * @param req: the secure world I2C master request
+ * @param len: the number of bytes processed by REE
+ * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error.
+ */
+TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *req, size_t *len)
+{
+ struct thread_param p[4] = { };
+ TEE_Result res = TEE_SUCCESS;
+ struct mobj *mobj = NULL;
+ uint8_t *va = NULL;
+
+ assert(req);
+
+ if (!len)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_KERNEL_PRIVATE,
+ req->buffer_len, &mobj);
+ if (!va)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ if (req->mode == RPC_I2C_MODE_WRITE)
+ memcpy(va, req->buffer, req->buffer_len);
+
+ p[0] = THREAD_PARAM_VALUE(IN, req->mode, req->bus, req->chip);
+ p[1] = THREAD_PARAM_VALUE(IN, req->flags, 0, 0);
+ p[2] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, req->buffer_len);
+ p[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0);
+
+ res = thread_rpc_cmd(OPTEE_RPC_CMD_I2C_TRANSFER, ARRAY_SIZE(p), p);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /*
+ * Reporting more bytes than supplied or requested from the I2C chip is
+ * an REE error
+ */
+ if (p[2].u.value.a > req->buffer_len)
+ return TEE_ERROR_EXCESS_DATA;
+
+ *len = p[2].u.value.a;
+
+ if (req->mode == RPC_I2C_MODE_READ)
+ memcpy(req->buffer, va, *len);
+
+ return TEE_SUCCESS;
+}
diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk
index 4190a0c5..71a89553 100644
--- a/core/arch/arm/kernel/sub.mk
+++ b/core/arch/arm/kernel/sub.mk
@@ -6,6 +6,7 @@ srcs-$(CFG_SECSTOR_TA) += secstor_ta.c
endif
srcs-y += pseudo_ta.c
srcs-y += tee_time.c
+srcs-y += rpc_io_i2c.c
srcs-y += otp_stubs.c
srcs-y += delay.c
diff --git a/core/include/kernel/rpc_io_i2c.h b/core/include/kernel/rpc_io_i2c.h
new file mode 100644
index 00000000..010f8922
--- /dev/null
+++ b/core/include/kernel/rpc_io_i2c.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2020 Foundries Ltd <jorge@foundries.io>
+ */
+
+#ifndef __RPC_IO_I2C_H
+#define __RPC_IO_I2C_H
+
+#include <optee_rpc_cmd.h>
+#include <tee_api_types.h>
+
+/* I2C master transfer mode */
+enum rpc_i2c_mode {
+ RPC_I2C_MODE_WRITE = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR,
+ RPC_I2C_MODE_READ = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD,
+};
+
+/* I2C master transfer control flags */
+#define RPC_I2C_FLAGS_TEN_BIT OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT
+
+/*
+ * The bus identifier defines an implicit ABI with the REE.
+ * Using this service to access I2C slaves on REE dynamically assigned buses is
+ * not recommended unless there is a guarantee that the bus identifier will
+ * persist across reboots.
+ */
+struct rpc_i2c_request {
+ enum rpc_i2c_mode mode;
+ uint16_t bus; /* bus identifier used by the REE [0..n] */
+ uint16_t chip; /* slave identifier from its data sheet */
+ uint16_t flags; /* transfer flags (ie: ten bit chip address) */
+ uint8_t *buffer;
+ size_t buffer_len;
+};
+
+TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes);
+
+#endif /* __RPC_IO_I2C_H */
diff --git a/core/include/optee_rpc_cmd.h b/core/include/optee_rpc_cmd.h
index 03f80323..3b8d0290 100644
--- a/core/include/optee_rpc_cmd.h
+++ b/core/include/optee_rpc_cmd.h
@@ -149,6 +149,28 @@
#define OPTEE_RPC_CMD_BENCH_REG 20
/*
+ * Issue master requests (read and write operations) to an I2C chip.
+ *
+ * [in] value[0].a Transfer mode (OPTEE_MSG_RPC_CMD_I2C_TRANSFER_*)
+ * [in] value[0].b The I2C bus (a.k.a adapter).
+ * 16 bit field.
+ * [in] value[0].c The I2C chip (a.k.a address).
+ * 16 bit field (either 7 or 10 bit effective).
+ * [in] value[1].a The I2C master control flags (ie, 10 bit address).
+ * 16 bit field.
+ * [in/out] memref[2] Buffer used for data transfers.
+ * [out] value[3].a Number of bytes transferred by the REE.
+ */
+#define OPTEE_RPC_CMD_I2C_TRANSFER 21
+
+/* I2C master transfer modes */
+#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0
+#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1
+
+/* I2C master control flags */
+#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0)
+
+/*
* Definition of protocol for command OPTEE_RPC_CMD_FS
*/